aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml21
-rw-r--r--.github/codeql-cpp.yml4
-rw-r--r--.github/codeql-python.yml4
-rw-r--r--.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql59
-rw-r--r--.github/codeql/custom-queries/cpp/qlpack.yml4
-rw-r--r--.github/workflows/README.md61
-rw-r--r--.github/workflows/build-dependencies.txt12
-rw-r--r--.github/workflows/checkstyle-dependencies.txt5
-rw-r--r--.github/workflows/checkstyle.yaml13
-rw-r--r--.github/workflows/codeql.yml41
-rwxr-xr-x.github/workflows/scripts/generate-summary.sh119
-rwxr-xr-x.github/workflows/scripts/reclaim_disk_space.sh20
-rwxr-xr-x.github/workflows/scripts/setup-dependencies.sh88
-rwxr-xr-x.github/workflows/scripts/setup-functional.sh24
-rw-r--r--.github/workflows/zfs-linux-tests.yml124
-rw-r--r--.github/workflows/zfs-linux.yml64
-rw-r--r--.github/workflows/zfs-tests-functional.yml82
-rw-r--r--.github/workflows/zfs-tests-sanity.yml78
-rw-r--r--.github/workflows/zloop.yml62
-rw-r--r--.gitignore4
-rw-r--r--.mailmap207
-rw-r--r--AUTHORS398
-rw-r--r--CODE_OF_CONDUCT.md2
-rw-r--r--META4
-rw-r--r--Makefile.am2
-rw-r--r--README.md2
-rwxr-xr-xautogen.sh2
-rw-r--r--cmd/Makefile.am9
-rwxr-xr-xcmd/arc_summary329
-rwxr-xr-xcmd/arcstat.in180
-rwxr-xr-xcmd/dbufstat.in22
-rw-r--r--cmd/mount_zfs.c4
-rw-r--r--cmd/raidz_test/raidz_bench.c14
-rw-r--r--cmd/raidz_test/raidz_test.c202
-rw-r--r--cmd/raidz_test/raidz_test.h5
-rw-r--r--cmd/zdb/Makefile.am4
-rw-r--r--cmd/zdb/zdb.c1067
-rw-r--r--cmd/zdb/zdb.h2
-rw-r--r--cmd/zdb/zdb_il.c100
-rw-r--r--cmd/zed/agents/fmd_api.c68
-rw-r--r--cmd/zed/agents/fmd_api.h5
-rw-r--r--cmd/zed/agents/fmd_serd.c24
-rw-r--r--cmd/zed/agents/fmd_serd.h4
-rw-r--r--cmd/zed/agents/zfs_agents.c67
-rw-r--r--cmd/zed/agents/zfs_diagnosis.c189
-rw-r--r--cmd/zed/agents/zfs_mod.c356
-rw-r--r--cmd/zed/agents/zfs_retire.c138
-rw-r--r--cmd/zed/zed.d/Makefile.am2
-rwxr-xr-xcmd/zed/zed.d/statechange-led.sh2
-rwxr-xr-xcmd/zed/zed.d/statechange-notify.sh4
-rwxr-xr-xcmd/zed/zed.d/statechange-slot_off.sh64
-rw-r--r--cmd/zed/zed.d/zed-functions.sh193
-rw-r--r--cmd/zed/zed.d/zed.rc48
-rw-r--r--cmd/zed/zed_conf.c20
-rw-r--r--cmd/zed/zed_conf.h1
-rw-r--r--cmd/zed/zed_disk_event.c72
-rw-r--r--cmd/zed/zed_event.c62
-rw-r--r--cmd/zed/zed_exec.c6
-rw-r--r--cmd/zed/zed_log.h1
-rw-r--r--cmd/zfs/zfs_iter.c76
-rw-r--r--cmd/zfs/zfs_iter.h13
-rw-r--r--cmd/zfs/zfs_main.c481
-rw-r--r--cmd/zfs/zfs_project.c2
-rw-r--r--cmd/zfs/zfs_projectutil.h2
-rw-r--r--cmd/zfs/zfs_util.h2
-rw-r--r--cmd/zfs_ids_to_path.c2
-rw-r--r--cmd/zgenhostid.c2
-rw-r--r--cmd/zhack.c523
-rwxr-xr-xcmd/zilstat.in551
-rw-r--r--cmd/zinject/translate.c10
-rw-r--r--cmd/zinject/zinject.c215
-rw-r--r--cmd/zinject/zinject.h2
-rw-r--r--cmd/zpool/Makefile.am11
-rw-r--r--cmd/zpool/compatibility.d/grub211
-rw-r--r--cmd/zpool/compatibility.d/openzfs-2.240
-rw-r--r--cmd/zpool/compatibility.d/openzfsonosx-1.8.11
-rw-r--r--cmd/zpool/os/freebsd/zpool_vdev_os.c23
-rw-r--r--cmd/zpool/os/linux/zpool_vdev_os.c257
-rwxr-xr-xcmd/zpool/zpool.d/ses12
-rw-r--r--cmd/zpool/zpool_iter.c43
-rw-r--r--cmd/zpool/zpool_main.c1340
-rw-r--r--cmd/zpool/zpool_util.c2
-rw-r--r--cmd/zpool/zpool_util.h9
-rw-r--r--cmd/zpool/zpool_vdev.c91
-rw-r--r--cmd/zpool_influxdb/zpool_influxdb.c20
-rw-r--r--cmd/zstream/Makefile.am1
-rw-r--r--cmd/zstream/zstream.c4
-rw-r--r--cmd/zstream/zstream.h1
-rw-r--r--cmd/zstream/zstream_decompress.c64
-rw-r--r--cmd/zstream/zstream_dump.c16
-rw-r--r--cmd/zstream/zstream_recompress.c376
-rw-r--r--cmd/zstream/zstream_redup.c22
-rw-r--r--cmd/zstream/zstream_token.c8
-rw-r--r--cmd/ztest.c1087
-rwxr-xr-xcmd/zvol_wait7
-rw-r--r--config/Rules.am18
-rw-r--r--config/Shellcheck.am4
-rw-r--r--config/Substfiles.am3
-rw-r--r--config/always-arch.m46
-rw-r--r--config/always-compiler-options.m487
-rw-r--r--config/always-pyzfs.m419
-rw-r--r--config/ax_python_devel.m4405
-rw-r--r--config/deb.am28
-rw-r--r--config/find_system_library.m44
-rw-r--r--config/kernel-acl.m480
-rw-r--r--config/kernel-automount.m42
-rw-r--r--config/kernel-bio.m42
-rw-r--r--config/kernel-blk-queue.m419
-rw-r--r--config/kernel-blkdev.m4424
-rw-r--r--config/kernel-block-device-operations.m441
-rw-r--r--config/kernel-commit-metadata.m42
-rw-r--r--config/kernel-cpu_has_feature.m429
-rw-r--r--config/kernel-current-time.m45
-rw-r--r--config/kernel-dentry-alias.m430
-rw-r--r--config/kernel-dentry-operations.m42
-rw-r--r--config/kernel-dirty-inode.m42
-rw-r--r--config/kernel-encode-fh-inode.m42
-rw-r--r--config/kernel-evict-inode.m42
-rw-r--r--config/kernel-fadvise.m423
-rw-r--r--config/kernel-fallocate.m42
-rw-r--r--config/kernel-filemap-splice-read.m425
-rw-r--r--config/kernel-filemap.m427
-rw-r--r--config/kernel-flush_dcache_page.m427
-rw-r--r--config/kernel-fpu.m423
-rw-r--r--config/kernel-fsync-bdev.m436
-rw-r--r--config/kernel-fsync.m44
-rw-r--r--config/kernel-generic_fadvise.m427
-rw-r--r--config/kernel-generic_fillattr.m454
-rw-r--r--config/kernel-generic_io_acct.m498
-rw-r--r--config/kernel-get-link.m48
-rw-r--r--config/kernel-iattr-vfsid.m424
-rw-r--r--config/kernel-idmap_mnt_api.m450
-rw-r--r--config/kernel-inode-create.m445
-rw-r--r--config/kernel-inode-getattr.m469
-rw-r--r--config/kernel-inode-lookup.m42
-rw-r--r--config/kernel-inode-permission.m439
-rw-r--r--config/kernel-inode-setattr.m487
-rw-r--r--config/kernel-inode-times.m4121
-rw-r--r--config/kernel-is_owner_or_cap.m425
-rw-r--r--config/kernel-make-request-fn.m461
-rw-r--r--config/kernel-mkdir.m459
-rw-r--r--config/kernel-mknod.m436
-rw-r--r--config/kernel-mm-page-size.m417
-rw-r--r--config/kernel-mod-param.m433
-rw-r--r--config/kernel-proc-operations.m410
-rw-r--r--config/kernel-put-link.m44
-rw-r--r--config/kernel-reclaim_state.m426
-rw-r--r--config/kernel-register_sysctl_table.m427
-rw-r--r--config/kernel-rename.m4109
-rw-r--r--config/kernel-setattr-prepare.m444
-rw-r--r--config/kernel-show-options.m42
-rw-r--r--config/kernel-shrink.m4151
-rw-r--r--config/kernel-strlcpy.m447
-rw-r--r--config/kernel-symlink.m435
-rw-r--r--config/kernel-timer.m44
-rw-r--r--config/kernel-tmpfile.m457
-rw-r--r--config/kernel-vfs-direct_IO.m48
-rw-r--r--config/kernel-vfs-extended-file_range.m450
-rw-r--r--config/kernel-vfs-file_range.m4191
-rw-r--r--config/kernel-vfs-iov_iter.m426
-rw-r--r--config/kernel-vfs-iterate.m46
-rw-r--r--config/kernel-vfs-rw-iterate.m44
-rw-r--r--config/kernel-writepage_t.m426
-rw-r--r--config/kernel-xattr-handler.m4140
-rw-r--r--config/kernel.m4117
-rw-r--r--config/rpm.am10
-rw-r--r--config/user-backtrace.m414
-rw-r--r--config/user-libunwind.m444
-rw-r--r--config/user.m46
-rw-r--r--config/zfs-build.m454
-rw-r--r--configure.ac7
-rw-r--r--contrib/bash_completion.d/Makefile.am2
-rw-r--r--contrib/bash_completion.d/zfs.in14
-rw-r--r--contrib/coverity/model.c654
-rw-r--r--contrib/debian/.gitignore1
-rw-r--r--contrib/debian/changelog.in19
-rw-r--r--contrib/debian/clean11
-rw-r--r--contrib/debian/control326
-rw-r--r--contrib/debian/control.modules.in33
-rw-r--r--contrib/debian/copyright19
-rw-r--r--contrib/debian/not-installed13
-rw-r--r--contrib/debian/openzfs-libnvpair3.docs2
-rw-r--r--contrib/debian/openzfs-libnvpair3.install.in1
-rw-r--r--contrib/debian/openzfs-libpam-zfs.install2
-rw-r--r--contrib/debian/openzfs-libpam-zfs.postinst8
-rw-r--r--contrib/debian/openzfs-libpam-zfs.prerm8
-rw-r--r--contrib/debian/openzfs-libuutil3.docs2
-rw-r--r--contrib/debian/openzfs-libuutil3.install.in1
-rw-r--r--contrib/debian/openzfs-libzfs-dev.docs2
-rw-r--r--contrib/debian/openzfs-libzfs-dev.install.in3
-rw-r--r--contrib/debian/openzfs-libzfs4.docs2
-rw-r--r--contrib/debian/openzfs-libzfs4.install.in2
-rw-r--r--contrib/debian/openzfs-libzfsbootenv1.docs2
-rw-r--r--contrib/debian/openzfs-libzfsbootenv1.install.in1
-rw-r--r--contrib/debian/openzfs-libzpool5.docs2
-rw-r--r--contrib/debian/openzfs-libzpool5.install.in1
-rw-r--r--contrib/debian/openzfs-python3-pyzfs.install1
-rw-r--r--contrib/debian/openzfs-zfs-dkms.config31
-rw-r--r--contrib/debian/openzfs-zfs-dkms.dkms1
-rw-r--r--contrib/debian/openzfs-zfs-dkms.docs2
-rw-r--r--contrib/debian/openzfs-zfs-dkms.install1
-rw-r--r--contrib/debian/openzfs-zfs-dkms.postinst51
-rw-r--r--contrib/debian/openzfs-zfs-dkms.prerm8
-rw-r--r--contrib/debian/openzfs-zfs-dkms.templates40
-rw-r--r--contrib/debian/openzfs-zfs-dkms.triggers1
-rw-r--r--contrib/debian/openzfs-zfs-dracut.install2
-rw-r--r--contrib/debian/openzfs-zfs-initramfs.install2
-rw-r--r--contrib/debian/openzfs-zfs-modules-_KVERS_-di.install.in2
-rw-r--r--contrib/debian/openzfs-zfs-modules-_KVERS_.install.in2
-rw-r--r--contrib/debian/openzfs-zfs-modules-_KVERS_.postinst.in16
-rw-r--r--contrib/debian/openzfs-zfs-modules-_KVERS_.postrm.in7
-rw-r--r--contrib/debian/openzfs-zfs-test.install13
-rw-r--r--contrib/debian/openzfs-zfs-zed.install5
-rw-r--r--contrib/debian/openzfs-zfs-zed.postinst13
-rw-r--r--contrib/debian/openzfs-zfs-zed.postrm17
l---------contrib/debian/openzfs-zfs-zed.zfs-zed.init1
-rw-r--r--contrib/debian/openzfs-zfsutils.docs2
-rw-r--r--contrib/debian/openzfs-zfsutils.examples5
-rw-r--r--contrib/debian/openzfs-zfsutils.install136
-rw-r--r--contrib/debian/openzfs-zfsutils.postinst13
l---------contrib/debian/openzfs-zfsutils.zfs-import.init1
l---------contrib/debian/openzfs-zfsutils.zfs-load-key.init1
l---------contrib/debian/openzfs-zfsutils.zfs-mount.init1
l---------contrib/debian/openzfs-zfsutils.zfs-share.init1
-rwxr-xr-xcontrib/debian/rules.in218
-rw-r--r--contrib/debian/source/format1
-rw-r--r--contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/conf.d/zfs8
-rwxr-xr-xcontrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/hooks/zdev67
-rwxr-xr-xcontrib/dracut/02zfsexpandknowledge/module-setup.sh.in18
-rwxr-xr-xcontrib/dracut/90zfs/module-setup.sh.in39
-rw-r--r--contrib/dracut/90zfs/zfs-env-bootfs.service.in16
-rwxr-xr-xcontrib/dracut/90zfs/zfs-generator.sh.in67
-rwxr-xr-xcontrib/dracut/90zfs/zfs-lib.sh.in2
-rwxr-xr-xcontrib/dracut/90zfs/zfs-load-key.sh.in2
-rw-r--r--contrib/dracut/90zfs/zfs-nonroot-necessities.service.in20
-rw-r--r--contrib/dracut/90zfs/zfs-rollback-bootfs.service.in5
-rw-r--r--contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in3
-rw-r--r--contrib/dracut/Makefile.am1
-rw-r--r--contrib/initramfs/README.md25
-rwxr-xr-xcontrib/initramfs/hooks/zfs.in3
-rw-r--r--contrib/initramfs/scripts/zfs105
-rw-r--r--contrib/pam_zfs_key/pam_zfs_key.c234
-rw-r--r--contrib/pyzfs/libzfs_core/__init__.py2
-rw-r--r--contrib/pyzfs/libzfs_core/_constants.py6
-rw-r--r--contrib/pyzfs/libzfs_core/_error_translation.py5
-rw-r--r--contrib/pyzfs/libzfs_core/_libzfs_core.py129
-rw-r--r--contrib/pyzfs/libzfs_core/bindings/libzfs_core.py4
-rw-r--r--contrib/pyzfs/libzfs_core/exceptions.py6
-rw-r--r--contrib/pyzfs/libzfs_core/test/test_libzfs_core.py21
-rw-r--r--etc/Makefile.am1
-rw-r--r--etc/init.d/README.md8
-rwxr-xr-xetc/init.d/zfs-import.in2
-rwxr-xr-xetc/init.d/zfs-load-key.in2
-rwxr-xr-xetc/init.d/zfs-mount.in7
-rwxr-xr-xetc/init.d/zfs-share.in3
-rwxr-xr-xetc/init.d/zfs-zed.in3
-rw-r--r--etc/systemd/system-generators/zfs-mount-generator.c9
-rw-r--r--etc/systemd/system/zfs-import-cache.service.in2
-rw-r--r--etc/systemd/system/zfs-import-scan.service.in2
-rw-r--r--etc/systemd/system/zfs-share.service.in2
-rw-r--r--etc/systemd/system/zfs-zed.service.in2
-rw-r--r--include/Makefile.am9
-rw-r--r--include/libnvpair.h13
-rw-r--r--include/libuutil.h35
-rw-r--r--include/libuutil_common.h2
-rw-r--r--include/libuutil_impl.h36
-rw-r--r--include/libzdb.h68
-rw-r--r--include/libzfs.h77
-rw-r--r--include/libzfs_core.h10
-rw-r--r--include/libzutil.h125
-rw-r--r--include/os/freebsd/Makefile.am11
-rw-r--r--include/os/freebsd/linux/compiler.h1
-rw-r--r--include/os/freebsd/spl/acl/acl_common.h4
-rw-r--r--include/os/freebsd/spl/rpc/xdr.h71
-rw-r--r--include/os/freebsd/spl/sys/acl.h2
-rw-r--r--include/os/freebsd/spl/sys/acl_impl.h2
-rw-r--r--include/os/freebsd/spl/sys/atomic.h10
-rw-r--r--include/os/freebsd/spl/sys/byteorder.h16
-rw-r--r--include/os/freebsd/spl/sys/callb.h2
-rw-r--r--include/os/freebsd/spl/sys/ccompat.h2
-rw-r--r--include/os/freebsd/spl/sys/ccompile.h2
-rw-r--r--include/os/freebsd/spl/sys/cmn_err.h37
-rw-r--r--include/os/freebsd/spl/sys/cred.h2
-rw-r--r--include/os/freebsd/spl/sys/ctype.h1
-rw-r--r--include/os/freebsd/spl/sys/debug.h194
-rw-r--r--include/os/freebsd/spl/sys/disp.h2
-rw-r--r--include/os/freebsd/spl/sys/dkio.h494
-rw-r--r--include/os/freebsd/spl/sys/extdirent.h71
-rw-r--r--include/os/freebsd/spl/sys/ia32/asm_linkage.h (renamed from module/icp/include/sys/ia32/asm_linkage.h)45
-rw-r--r--include/os/freebsd/spl/sys/idmap.h2
-rw-r--r--include/os/freebsd/spl/sys/isa_defs.h417
-rw-r--r--include/os/freebsd/spl/sys/kmem.h11
-rw-r--r--include/os/freebsd/spl/sys/kstat.h10
-rw-r--r--include/os/freebsd/spl/sys/list.h2
-rw-r--r--include/os/freebsd/spl/sys/list_impl.h3
-rw-r--r--include/os/freebsd/spl/sys/mod_os.h54
-rw-r--r--include/os/freebsd/spl/sys/mutex.h1
-rw-r--r--include/os/freebsd/spl/sys/processor.h2
-rw-r--r--include/os/freebsd/spl/sys/procfs_list.h2
-rw-r--r--include/os/freebsd/spl/sys/simd.h14
-rw-r--r--include/os/freebsd/spl/sys/simd_aarch64.h94
-rw-r--r--include/os/freebsd/spl/sys/simd_arm.h74
-rw-r--r--include/os/freebsd/spl/sys/simd_powerpc.h86
-rw-r--r--include/os/freebsd/spl/sys/simd_x86.h67
-rw-r--r--include/os/freebsd/spl/sys/spl_condvar.h2
-rw-r--r--include/os/freebsd/spl/sys/sysmacros.h42
-rw-r--r--include/os/freebsd/spl/sys/taskq.h26
-rw-r--r--include/os/freebsd/spl/sys/time.h4
-rw-r--r--include/os/freebsd/spl/sys/timer.h2
-rw-r--r--include/os/freebsd/spl/sys/types.h2
-rw-r--r--include/os/freebsd/spl/sys/uio.h2
-rw-r--r--include/os/freebsd/spl/sys/uuid.h2
-rw-r--r--include/os/freebsd/spl/sys/vfs.h6
-rw-r--r--include/os/freebsd/spl/sys/vnode.h21
-rw-r--r--include/os/freebsd/spl/sys/vnode_impl.h15
-rw-r--r--include/os/freebsd/spl/sys/zmod.h2
-rw-r--r--include/os/freebsd/zfs/sys/arc_os.h34
-rw-r--r--include/os/freebsd/zfs/sys/freebsd_event.h37
-rw-r--r--include/os/freebsd/zfs/sys/sha2.h197
-rw-r--r--include/os/freebsd/zfs/sys/vdev_os.h2
-rw-r--r--include/os/freebsd/zfs/sys/zfs_context_os.h4
-rw-r--r--include/os/freebsd/zfs/sys/zfs_ctldir.h2
-rw-r--r--include/os/freebsd/zfs/sys/zfs_dir.h2
-rw-r--r--include/os/freebsd/zfs/sys/zfs_ioctl_compat.h15
-rw-r--r--include/os/freebsd/zfs/sys/zfs_vfsops_os.h10
-rw-r--r--include/os/freebsd/zfs/sys/zfs_vnops_os.h13
-rw-r--r--include/os/freebsd/zfs/sys/zfs_znode_impl.h45
-rw-r--r--include/os/linux/Makefile.am10
-rw-r--r--include/os/linux/kernel/linux/blkdev_compat.h104
-rw-r--r--include/os/linux/kernel/linux/compiler_compat.h2
-rw-r--r--include/os/linux/kernel/linux/dcache_compat.h49
-rw-r--r--include/os/linux/kernel/linux/kmap_compat.h2
-rw-r--r--include/os/linux/kernel/linux/mm_compat.h (renamed from include/sys/spa_boot.h)26
-rw-r--r--include/os/linux/kernel/linux/mod_compat.h74
-rw-r--r--include/os/linux/kernel/linux/percpu_compat.h2
-rw-r--r--include/os/linux/kernel/linux/simd.h7
-rw-r--r--include/os/linux/kernel/linux/simd_aarch64.h84
-rw-r--r--include/os/linux/kernel/linux/simd_arm.h86
-rw-r--r--include/os/linux/kernel/linux/simd_powerpc.h120
-rw-r--r--include/os/linux/kernel/linux/simd_x86.h36
-rw-r--r--include/os/linux/kernel/linux/utsname_compat.h2
-rw-r--r--include/os/linux/kernel/linux/vfs_compat.h42
-rw-r--r--include/os/linux/kernel/linux/xattr_compat.h43
-rw-r--r--include/os/linux/spl/rpc/types.h (renamed from include/os/linux/spl/sys/dkio.h)25
-rw-r--r--include/os/linux/spl/rpc/xdr.h5
-rw-r--r--include/os/linux/spl/sys/byteorder.h15
-rw-r--r--include/os/linux/spl/sys/cmn_err.h19
-rw-r--r--include/os/linux/spl/sys/cred.h131
-rw-r--r--include/os/linux/spl/sys/debug.h234
-rw-r--r--include/os/linux/spl/sys/disp.h4
-rw-r--r--include/os/linux/spl/sys/errno.h2
-rw-r--r--include/os/linux/spl/sys/ia32/asm_linkage.h212
-rw-r--r--include/os/linux/spl/sys/isa_defs.h52
-rw-r--r--include/os/linux/spl/sys/kmem.h9
-rw-r--r--include/os/linux/spl/sys/kmem_cache.h15
-rw-r--r--include/os/linux/spl/sys/kstat.h10
-rw-r--r--include/os/linux/spl/sys/list.h4
-rw-r--r--include/os/linux/spl/sys/misc.h29
-rw-r--r--include/os/linux/spl/sys/mutex.h22
-rw-r--r--include/os/linux/spl/sys/procfs_list.h2
-rw-r--r--include/os/linux/spl/sys/shrinker.h62
-rw-r--r--include/os/linux/spl/sys/string.h49
-rw-r--r--include/os/linux/spl/sys/sysmacros.h10
-rw-r--r--include/os/linux/spl/sys/taskq.h3
-rw-r--r--include/os/linux/spl/sys/trace.h2
-rw-r--r--include/os/linux/spl/sys/trace_spl.h2
-rw-r--r--include/os/linux/spl/sys/trace_taskq.h2
-rw-r--r--include/os/linux/spl/sys/types.h29
-rw-r--r--include/os/linux/spl/sys/uio.h22
-rw-r--r--include/os/linux/spl/sys/vmem.h6
-rw-r--r--include/os/linux/spl/sys/vmsystm.h3
-rw-r--r--include/os/linux/zfs/sys/policy.h7
-rw-r--r--include/os/linux/zfs/sys/sha2.h148
-rw-r--r--include/os/linux/zfs/sys/trace_acl.h16
-rw-r--r--include/os/linux/zfs/sys/trace_arc.h20
-rw-r--r--include/os/linux/zfs/sys/trace_common.h14
-rw-r--r--include/os/linux/zfs/sys/trace_dbgmsg.h2
-rw-r--r--include/os/linux/zfs/sys/trace_dbuf.h10
-rw-r--r--include/os/linux/zfs/sys/trace_dmu.h2
-rw-r--r--include/os/linux/zfs/sys/trace_dnode.h2
-rw-r--r--include/os/linux/zfs/sys/trace_multilist.h2
-rw-r--r--include/os/linux/zfs/sys/trace_rrwlock.h2
-rw-r--r--include/os/linux/zfs/sys/trace_txg.h2
-rw-r--r--include/os/linux/zfs/sys/trace_vdev.h2
-rw-r--r--include/os/linux/zfs/sys/trace_zfs.h2
-rw-r--r--include/os/linux/zfs/sys/trace_zil.h58
-rw-r--r--include/os/linux/zfs/sys/trace_zio.h2
-rw-r--r--include/os/linux/zfs/sys/trace_zrlock.h2
-rw-r--r--include/os/linux/zfs/sys/zfs_context_os.h2
-rw-r--r--include/os/linux/zfs/sys/zfs_ctldir.h2
-rw-r--r--include/os/linux/zfs/sys/zfs_dir.h3
-rw-r--r--include/os/linux/zfs/sys/zfs_vfsops_os.h6
-rw-r--r--include/os/linux/zfs/sys/zfs_vnops_os.h28
-rw-r--r--include/os/linux/zfs/sys/zfs_znode_impl.h81
-rw-r--r--include/os/linux/zfs/sys/zpl.h113
-rw-r--r--include/sys/abd.h22
-rw-r--r--include/sys/abd_impl.h28
-rw-r--r--include/sys/arc.h20
-rw-r--r--include/sys/arc_impl.h135
-rw-r--r--include/sys/asm_linkage.h48
-rw-r--r--include/sys/avl.h2
-rw-r--r--include/sys/avl_impl.h2
-rw-r--r--include/sys/bitmap.h93
-rw-r--r--include/sys/bitops.h2
-rw-r--r--include/sys/blake3.h33
-rw-r--r--include/sys/bplist.h2
-rw-r--r--include/sys/bpobj.h5
-rw-r--r--include/sys/bptree.h2
-rw-r--r--include/sys/bqueue.h19
-rw-r--r--include/sys/brt.h63
-rw-r--r--include/sys/brt_impl.h199
-rw-r--r--include/sys/btree.h79
-rw-r--r--include/sys/crypto/api.h2
-rw-r--r--include/sys/crypto/common.h2
-rw-r--r--include/sys/crypto/icp.h2
-rw-r--r--include/sys/dataset_kstats.h11
-rw-r--r--include/sys/dbuf.h53
-rw-r--r--include/sys/ddt.h201
-rw-r--r--include/sys/ddt_impl.h95
-rw-r--r--include/sys/dmu.h52
-rw-r--r--include/sys/dmu_impl.h4
-rw-r--r--include/sys/dmu_objset.h10
-rw-r--r--include/sys/dmu_recv.h8
-rw-r--r--include/sys/dmu_redact.h2
-rw-r--r--include/sys/dmu_send.h2
-rw-r--r--include/sys/dmu_traverse.h2
-rw-r--r--include/sys/dmu_tx.h4
-rw-r--r--include/sys/dmu_zfetch.h20
-rw-r--r--include/sys/dnode.h55
-rw-r--r--include/sys/dsl_bookmark.h1
-rw-r--r--include/sys/dsl_crypt.h2
-rw-r--r--include/sys/dsl_dataset.h14
-rw-r--r--include/sys/dsl_deadlist.h4
-rw-r--r--include/sys/dsl_deleg.h2
-rw-r--r--include/sys/dsl_destroy.h2
-rw-r--r--include/sys/dsl_dir.h7
-rw-r--r--include/sys/dsl_pool.h16
-rw-r--r--include/sys/dsl_prop.h2
-rw-r--r--include/sys/dsl_scan.h31
-rw-r--r--include/sys/dsl_synctask.h2
-rw-r--r--include/sys/dsl_userhold.h2
-rw-r--r--include/sys/edonr.h41
-rw-r--r--include/sys/efi_partition.h2
-rw-r--r--include/sys/fm/fs/zfs.h12
-rw-r--r--include/sys/fm/protocol.h2
-rw-r--r--include/sys/fm/util.h4
-rw-r--r--include/sys/fs/zfs.h95
-rw-r--r--include/sys/metaslab.h6
-rw-r--r--include/sys/metaslab_impl.h9
-rw-r--r--include/sys/mmp.h2
-rw-r--r--include/sys/mntent.h5
-rw-r--r--include/sys/multilist.h5
-rw-r--r--include/sys/nvpair.h23
-rw-r--r--include/sys/nvpair_impl.h2
-rw-r--r--include/sys/pathname.h2
-rw-r--r--include/sys/qat.h2
-rw-r--r--include/sys/range_tree.h2
-rw-r--r--include/sys/rrwlock.h2
-rw-r--r--include/sys/sa.h2
-rw-r--r--include/sys/sa_impl.h2
-rw-r--r--include/sys/sha2.h127
-rw-r--r--include/sys/spa.h133
-rw-r--r--include/sys/spa_checkpoint.h2
-rw-r--r--include/sys/spa_checksum.h2
-rw-r--r--include/sys/spa_impl.h50
-rw-r--r--include/sys/spa_log_spacemap.h2
-rw-r--r--include/sys/space_map.h2
-rw-r--r--include/sys/space_reftree.h2
-rw-r--r--include/sys/sysevent.h2
-rw-r--r--include/sys/sysevent/dev.h5
-rw-r--r--include/sys/sysevent/eventdefs.h7
-rw-r--r--include/sys/txg.h4
-rw-r--r--include/sys/txg_impl.h5
-rw-r--r--include/sys/u8_textprep.h2
-rw-r--r--include/sys/u8_textprep_data.h2
-rw-r--r--include/sys/uberblock.h2
-rw-r--r--include/sys/uberblock_impl.h55
-rw-r--r--include/sys/uio_impl.h2
-rw-r--r--include/sys/unique.h2
-rw-r--r--include/sys/uuid.h2
-rw-r--r--include/sys/vdev.h29
-rw-r--r--include/sys/vdev_disk.h2
-rw-r--r--include/sys/vdev_draid.h2
-rw-r--r--include/sys/vdev_file.h2
-rw-r--r--include/sys/vdev_impl.h81
-rw-r--r--include/sys/vdev_initialize.h3
-rw-r--r--include/sys/vdev_raidz.h103
-rw-r--r--include/sys/vdev_raidz_impl.h55
-rw-r--r--include/sys/vdev_rebuild.h3
-rw-r--r--include/sys/vdev_removal.h2
-rw-r--r--include/sys/vdev_trim.h3
-rw-r--r--include/sys/xvattr.h2
-rw-r--r--include/sys/zap.h10
-rw-r--r--include/sys/zap_impl.h14
-rw-r--r--include/sys/zap_leaf.h12
-rw-r--r--include/sys/zcp.h4
-rw-r--r--include/sys/zcp_iter.h2
-rw-r--r--include/sys/zfeature.h2
-rw-r--r--include/sys/zfs_acl.h15
-rw-r--r--include/sys/zfs_chksum.h2
-rw-r--r--include/sys/zfs_context.h37
-rw-r--r--include/sys/zfs_debug.h4
-rw-r--r--include/sys/zfs_delay.h2
-rw-r--r--include/sys/zfs_file.h2
-rw-r--r--include/sys/zfs_fuid.h2
-rw-r--r--include/sys/zfs_impl.h69
-rw-r--r--include/sys/zfs_ioctl.h17
-rw-r--r--include/sys/zfs_ioctl_impl.h4
-rw-r--r--include/sys/zfs_onexit.h4
-rw-r--r--include/sys/zfs_project.h2
-rw-r--r--include/sys/zfs_quota.h2
-rw-r--r--include/sys/zfs_racct.h2
-rw-r--r--include/sys/zfs_refcount.h30
-rw-r--r--include/sys/zfs_rlock.h2
-rw-r--r--include/sys/zfs_sa.h2
-rw-r--r--include/sys/zfs_stat.h2
-rw-r--r--include/sys/zfs_sysfs.h2
-rw-r--r--include/sys/zfs_vfsops.h2
-rw-r--r--include/sys/zfs_vnops.h9
-rw-r--r--include/sys/zfs_znode.h46
-rw-r--r--include/sys/zil.h101
-rw-r--r--include/sys/zil_impl.h62
-rw-r--r--include/sys/zio.h157
-rw-r--r--include/sys/zio_checksum.h12
-rw-r--r--include/sys/zio_compress.h6
-rw-r--r--include/sys/zio_impl.h75
-rw-r--r--include/sys/zrlock.h5
-rw-r--r--include/sys/zvol.h7
-rw-r--r--include/sys/zvol_impl.h7
-rw-r--r--include/thread_pool.h2
-rw-r--r--include/zfeature_common.h6
-rw-r--r--include/zfs_comutil.h2
-rw-r--r--include/zfs_deleg.h2
-rw-r--r--include/zfs_fletcher.h29
-rw-r--r--include/zfs_namecheck.h2
-rw-r--r--include/zfs_prop.h2
-rw-r--r--lib/Makefile.am5
-rw-r--r--lib/libefi/rdwr_efi.c8
-rw-r--r--lib/libicp/Makefile.am29
-rw-r--r--lib/libnvpair/libnvpair.abi2928
-rw-r--r--lib/libnvpair/libnvpair.c60
-rw-r--r--lib/libnvpair/libnvpair_json.c4
-rw-r--r--lib/libnvpair/nvpair_alloc_system.c2
-rw-r--r--lib/libshare/libshare.c14
-rw-r--r--lib/libshare/libshare_impl.h5
-rw-r--r--lib/libshare/nfs.c40
-rw-r--r--lib/libshare/nfs.h4
-rw-r--r--lib/libshare/os/freebsd/nfs.c15
-rw-r--r--lib/libshare/os/freebsd/smb.c2
-rw-r--r--lib/libshare/os/linux/nfs.c78
-rw-r--r--lib/libshare/os/linux/smb.c19
-rw-r--r--lib/libshare/smb.h2
-rw-r--r--lib/libspl/Makefile.am4
-rw-r--r--lib/libspl/assert.c98
-rw-r--r--lib/libspl/atomic.c8
-rw-r--r--lib/libspl/getexecname.c2
-rw-r--r--lib/libspl/include/Makefile.am11
-rw-r--r--lib/libspl/include/assert.h131
-rw-r--r--lib/libspl/include/atomic.h9
-rw-r--r--lib/libspl/include/libgen.h2
-rw-r--r--lib/libspl/include/libshare.h5
-rw-r--r--lib/libspl/include/os/freebsd/sys/byteorder.h16
-rw-r--r--lib/libspl/include/os/freebsd/sys/file.h2
-rw-r--r--lib/libspl/include/os/freebsd/sys/ia32/asm_linkage.h184
-rw-r--r--lib/libspl/include/os/freebsd/sys/mnttab.h2
-rw-r--r--lib/libspl/include/os/freebsd/sys/mount.h2
-rw-r--r--lib/libspl/include/os/freebsd/sys/param.h4
-rw-r--r--lib/libspl/include/os/freebsd/sys/stat.h8
-rw-r--r--lib/libspl/include/os/linux/sys/byteorder.h16
-rw-r--r--lib/libspl/include/os/linux/sys/errno.h2
-rw-r--r--lib/libspl/include/os/linux/sys/ia32/asm_linkage.h211
-rw-r--r--lib/libspl/include/os/linux/sys/mnttab.h2
-rw-r--r--lib/libspl/include/os/linux/sys/mount.h2
-rw-r--r--lib/libspl/include/os/linux/sys/param.h2
-rw-r--r--lib/libspl/include/os/linux/sys/stat.h2
-rw-r--r--lib/libspl/include/os/linux/sys/sysmacros.h2
-rw-r--r--lib/libspl/include/os/linux/sys/zfs_context_os.h2
-rw-r--r--lib/libspl/include/rpc/xdr.h2
-rw-r--r--lib/libspl/include/statcommon.h2
-rw-r--r--lib/libspl/include/stdlib.h2
-rw-r--r--lib/libspl/include/string.h2
-rw-r--r--lib/libspl/include/sys/acl.h2
-rw-r--r--lib/libspl/include/sys/acl_impl.h2
-rw-r--r--lib/libspl/include/sys/asm_linkage.h (renamed from module/icp/include/sys/asm_linkage.h)2
-rw-r--r--lib/libspl/include/sys/callb.h2
-rw-r--r--lib/libspl/include/sys/cmn_err.h36
-rw-r--r--lib/libspl/include/sys/cred.h2
-rw-r--r--lib/libspl/include/sys/debug.h2
-rw-r--r--lib/libspl/include/sys/dkio.h2
-rw-r--r--lib/libspl/include/sys/dklabel.h2
-rw-r--r--lib/libspl/include/sys/dktp/fdisk.h2
-rw-r--r--lib/libspl/include/sys/feature_tests.h2
-rw-r--r--lib/libspl/include/sys/inttypes.h2
-rw-r--r--lib/libspl/include/sys/isa_defs.h26
-rw-r--r--lib/libspl/include/sys/kmem.h2
-rw-r--r--lib/libspl/include/sys/kstat.h2
-rw-r--r--lib/libspl/include/sys/list.h2
-rw-r--r--lib/libspl/include/sys/list_impl.h3
-rw-r--r--lib/libspl/include/sys/mhd.h2
-rw-r--r--lib/libspl/include/sys/mkdev.h2
-rw-r--r--lib/libspl/include/sys/policy.h2
-rw-r--r--lib/libspl/include/sys/poll.h2
-rw-r--r--lib/libspl/include/sys/priv.h2
-rw-r--r--lib/libspl/include/sys/processor.h2
-rw-r--r--lib/libspl/include/sys/sha2.h148
-rw-r--r--lib/libspl/include/sys/simd.h162
-rw-r--r--lib/libspl/include/sys/stack.h2
-rw-r--r--lib/libspl/include/sys/stdtypes.h2
-rw-r--r--lib/libspl/include/sys/sunddi.h2
-rw-r--r--lib/libspl/include/sys/systeminfo.h2
-rw-r--r--lib/libspl/include/sys/time.h4
-rw-r--r--lib/libspl/include/sys/types.h27
-rw-r--r--lib/libspl/include/sys/types32.h2
-rw-r--r--lib/libspl/include/sys/uio.h4
-rw-r--r--lib/libspl/include/sys/vnode.h2
-rw-r--r--lib/libspl/include/sys/zone.h2
-rw-r--r--lib/libspl/include/umem.h26
-rw-r--r--lib/libspl/include/unistd.h2
-rw-r--r--lib/libspl/include/zone.h2
-rw-r--r--lib/libspl/libspl_impl.h2
-rw-r--r--lib/libspl/list.c6
-rw-r--r--lib/libspl/mkdirp.c2
-rw-r--r--lib/libspl/os/freebsd/getexecname.c2
-rw-r--r--lib/libspl/os/freebsd/gethostid.c2
-rw-r--r--lib/libspl/os/freebsd/getmntany.c7
-rw-r--r--lib/libspl/os/freebsd/mnttab.c5
-rw-r--r--lib/libspl/os/linux/getexecname.c2
-rw-r--r--lib/libspl/os/linux/gethostid.c8
-rw-r--r--lib/libspl/os/linux/getmntany.c5
-rw-r--r--lib/libspl/os/linux/zone.c12
-rw-r--r--lib/libspl/page.c2
-rw-r--r--lib/libspl/strlcat.c2
-rw-r--r--lib/libspl/strlcpy.c2
-rw-r--r--lib/libspl/timestamp.c2
-rw-r--r--lib/libtpool/thread_pool.c3
-rw-r--r--lib/libtpool/thread_pool_impl.h2
-rw-r--r--lib/libuutil/Makefile.am1
-rw-r--r--lib/libuutil/libuutil.abi961
-rw-r--r--lib/libuutil/uu_alloc.c2
-rw-r--r--lib/libuutil/uu_avl.c32
-rw-r--r--lib/libuutil/uu_ident.c2
-rw-r--r--lib/libuutil/uu_list.c46
-rw-r--r--lib/libuutil/uu_misc.c2
-rw-r--r--lib/libuutil/uu_pname.c202
-rw-r--r--lib/libuutil/uu_string.c2
-rw-r--r--lib/libzdb/Makefile.am7
-rw-r--r--lib/libzdb/libzdb.c102
-rw-r--r--lib/libzfs/Makefile.am5
-rw-r--r--lib/libzfs/libzfs.abi7518
-rw-r--r--lib/libzfs/libzfs_changelist.c55
-rw-r--r--lib/libzfs/libzfs_config.c2
-rw-r--r--lib/libzfs/libzfs_crypto.c24
-rw-r--r--lib/libzfs/libzfs_dataset.c215
-rw-r--r--lib/libzfs/libzfs_diff.c67
-rw-r--r--lib/libzfs/libzfs_impl.h4
-rw-r--r--lib/libzfs/libzfs_import.c8
-rw-r--r--lib/libzfs/libzfs_iter.c94
-rw-r--r--lib/libzfs/libzfs_mount.c35
-rw-r--r--lib/libzfs/libzfs_pool.c642
-rw-r--r--lib/libzfs/libzfs_sendrecv.c487
-rw-r--r--lib/libzfs/libzfs_status.c7
-rw-r--r--lib/libzfs/libzfs_util.c282
-rw-r--r--lib/libzfs/os/freebsd/libzfs_compat.c10
-rw-r--r--lib/libzfs/os/freebsd/libzfs_zmount.c29
-rw-r--r--lib/libzfs/os/linux/libzfs_mount_os.c9
-rw-r--r--lib/libzfs/os/linux/libzfs_pool_os.c14
-rw-r--r--lib/libzfs/os/linux/libzfs_util_os.c6
-rw-r--r--lib/libzfs_core/libzfs_core.abi1589
-rw-r--r--lib/libzfs_core/libzfs_core.c76
-rw-r--r--lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c17
-rw-r--r--lib/libzfs_core/os/linux/libzfs_core_ioctl.c2
-rw-r--r--lib/libzfsbootenv/libzfsbootenv.abi507
-rw-r--r--lib/libzfsbootenv/lzbe_device.c22
-rw-r--r--lib/libzpool/Makefile.am7
-rw-r--r--lib/libzpool/kernel.c54
-rw-r--r--lib/libzpool/taskq.c42
-rw-r--r--lib/libzpool/util.c25
-rw-r--r--lib/libzutil/Makefile.am1
-rw-r--r--lib/libzutil/os/freebsd/zutil_device_path_os.c2
-rw-r--r--lib/libzutil/os/freebsd/zutil_import_os.c19
-rw-r--r--lib/libzutil/os/linux/zutil_device_path_os.c18
-rw-r--r--lib/libzutil/os/linux/zutil_import_os.c70
-rw-r--r--lib/libzutil/os/linux/zutil_setproctitle.c276
-rw-r--r--lib/libzutil/zutil_device_path.c2
-rw-r--r--lib/libzutil/zutil_import.c318
-rw-r--r--lib/libzutil/zutil_import.h21
-rw-r--r--lib/libzutil/zutil_nicenum.c2
-rw-r--r--lib/libzutil/zutil_pool.c33
-rw-r--r--man/Makefile.am20
-rw-r--r--man/man1/arcstat.188
-rw-r--r--man/man1/cstyle.12
-rw-r--r--man/man1/raidz_test.12
-rw-r--r--man/man1/test-runner.17
-rw-r--r--man/man1/zhack.124
-rw-r--r--man/man1/ztest.133
-rw-r--r--man/man4/spl.418
-rw-r--r--man/man4/zfs.4770
-rw-r--r--man/man7/dracut.zfs.728
-rw-r--r--man/man7/vdevprops.730
-rw-r--r--man/man7/zfsconcepts.745
-rw-r--r--man/man7/zfsprops.7140
-rw-r--r--man/man7/zpool-features.780
-rw-r--r--man/man7/zpoolconcepts.788
-rw-r--r--man/man7/zpoolprops.797
-rw-r--r--man/man8/.gitignore1
-rw-r--r--man/man8/fsck.zfs.85
-rw-r--r--man/man8/mount.zfs.82
-rw-r--r--man/man8/vdev_id.86
-rw-r--r--man/man8/zdb.869
-rw-r--r--man/man8/zed.8.in30
-rw-r--r--man/man8/zfs-allow.84
-rw-r--r--man/man8/zfs-bookmark.82
-rw-r--r--man/man8/zfs-clone.82
-rw-r--r--man/man8/zfs-create.815
-rw-r--r--man/man8/zfs-destroy.82
-rw-r--r--man/man8/zfs-diff.82
-rw-r--r--man/man8/zfs-hold.88
-rw-r--r--man/man8/zfs-jail.85
-rw-r--r--man/man8/zfs-list.813
-rw-r--r--man/man8/zfs-load-key.811
-rw-r--r--man/man8/zfs-mount-generator.8.in9
-rw-r--r--man/man8/zfs-mount.811
-rw-r--r--man/man8/zfs-program.813
-rw-r--r--man/man8/zfs-project.85
-rw-r--r--man/man8/zfs-promote.85
-rw-r--r--man/man8/zfs-receive.827
-rw-r--r--man/man8/zfs-rename.82
-rw-r--r--man/man8/zfs-rollback.82
-rw-r--r--man/man8/zfs-send.865
-rw-r--r--man/man8/zfs-set.820
-rw-r--r--man/man8/zfs-share.82
-rw-r--r--man/man8/zfs-snapshot.818
-rw-r--r--man/man8/zfs-upgrade.82
-rw-r--r--man/man8/zfs-userspace.85
-rw-r--r--man/man8/zfs-wait.82
-rw-r--r--man/man8/zfs-zone.82
-rw-r--r--man/man8/zfs.88
-rw-r--r--man/man8/zfs_ids_to_path.82
-rw-r--r--man/man8/zfs_prepare_disk.8.in70
-rw-r--r--man/man8/zgenhostid.82
-rw-r--r--man/man8/zinject.823
-rw-r--r--man/man8/zpool-add.820
-rw-r--r--man/man8/zpool-attach.855
-rw-r--r--man/man8/zpool-checkpoint.82
-rw-r--r--man/man8/zpool-clear.820
-rw-r--r--man/man8/zpool-create.87
-rw-r--r--man/man8/zpool-destroy.82
-rw-r--r--man/man8/zpool-detach.82
-rw-r--r--man/man8/zpool-events.886
-rw-r--r--man/man8/zpool-export.85
-rw-r--r--man/man8/zpool-get.82
-rw-r--r--man/man8/zpool-history.82
-rw-r--r--man/man8/zpool-import.82
-rw-r--r--man/man8/zpool-initialize.812
-rw-r--r--man/man8/zpool-iostat.89
-rw-r--r--man/man8/zpool-labelclear.82
-rw-r--r--man/man8/zpool-list.84
-rw-r--r--man/man8/zpool-offline.820
-rw-r--r--man/man8/zpool-reguid.82
-rw-r--r--man/man8/zpool-remove.812
-rw-r--r--man/man8/zpool-reopen.82
-rw-r--r--man/man8/zpool-replace.82
-rw-r--r--man/man8/zpool-resilver.85
-rw-r--r--man/man8/zpool-scrub.829
-rw-r--r--man/man8/zpool-split.85
-rw-r--r--man/man8/zpool-status.832
-rw-r--r--man/man8/zpool-sync.82
-rw-r--r--man/man8/zpool-trim.82
-rw-r--r--man/man8/zpool-upgrade.85
-rw-r--r--man/man8/zpool-wait.810
-rw-r--r--man/man8/zpool.894
-rw-r--r--man/man8/zstream.835
-rw-r--r--module/.gitignore1
-rw-r--r--module/Kbuild.in79
-rw-r--r--module/Makefile.bsd301
-rw-r--r--module/Makefile.in2
-rw-r--r--module/avl/avl.c8
-rw-r--r--module/icp/algs/aes/aes_impl.c10
-rw-r--r--module/icp/algs/aes/aes_impl_aesni.c11
-rw-r--r--module/icp/algs/aes/aes_impl_generic.c2
-rw-r--r--module/icp/algs/aes/aes_impl_x86-64.c2
-rw-r--r--module/icp/algs/aes/aes_modes.c2
-rw-r--r--module/icp/algs/blake3/blake3.c25
-rw-r--r--module/icp/algs/blake3/blake3_generic.c10
-rw-r--r--module/icp/algs/blake3/blake3_impl.c484
-rw-r--r--module/icp/algs/blake3/blake3_impl.h36
-rw-r--r--module/icp/algs/blake3/blake3_x86-64.c248
-rw-r--r--module/icp/algs/edonr/edonr.c781
-rw-r--r--module/icp/algs/edonr/edonr_byteorder.h216
-rw-r--r--module/icp/algs/modes/cbc.c2
-rw-r--r--module/icp/algs/modes/ccm.c5
-rw-r--r--module/icp/algs/modes/ctr.c3
-rw-r--r--module/icp/algs/modes/ecb.c2
-rw-r--r--module/icp/algs/modes/gcm.c255
-rw-r--r--module/icp/algs/modes/gcm_generic.c2
-rw-r--r--module/icp/algs/modes/gcm_pclmulqdq.c5
-rw-r--r--module/icp/algs/modes/modes.c59
-rw-r--r--module/icp/algs/sha2/sha2.c956
-rw-r--r--module/icp/algs/sha2/sha256_impl.c313
-rw-r--r--module/icp/algs/sha2/sha2_generic.c562
-rw-r--r--module/icp/algs/sha2/sha512_impl.c282
-rw-r--r--module/icp/algs/skein/skein_block.c2
-rw-r--r--module/icp/api/kcf_cipher.c2
-rw-r--r--module/icp/api/kcf_ctxops.c4
-rw-r--r--module/icp/api/kcf_mac.c2
-rw-r--r--module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S4173
-rw-r--r--module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S4415
-rw-r--r--module/icp/asm-aarch64/sha2/sha256-armv8.S2012
-rw-r--r--module/icp/asm-aarch64/sha2/sha512-armv8.S1570
-rw-r--r--module/icp/asm-arm/sha2/sha256-armv7.S2774
-rw-r--r--module/icp/asm-arm/sha2/sha512-armv7.S1827
-rw-r--r--module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S2
-rw-r--r--module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S2
-rw-r--r--module/icp/asm-ppc64/sha2/sha256-p8.S1520
-rw-r--r--module/icp/asm-ppc64/sha2/sha256-ppc.S2727
-rw-r--r--module/icp/asm-ppc64/sha2/sha512-p8.S1722
-rw-r--r--module/icp/asm-ppc64/sha2/sha512-ppc.S2973
-rw-r--r--module/icp/asm-x86_64/aes/aes_aesni.S16
-rw-r--r--module/icp/asm-x86_64/aes/aes_amd64.S62
-rw-r--r--module/icp/asm-x86_64/aes/aestab2.h2
-rw-r--r--module/icp/asm-x86_64/blake3/blake3_avx2.S27
-rw-r--r--module/icp/asm-x86_64/blake3/blake3_avx512.S48
-rw-r--r--module/icp/asm-x86_64/blake3/blake3_sse2.S50
-rw-r--r--module/icp/asm-x86_64/blake3/blake3_sse41.S49
-rw-r--r--module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S107
-rw-r--r--module/icp/asm-x86_64/modes/gcm_pclmulqdq.S6
-rw-r--r--module/icp/asm-x86_64/modes/ghash-x86_64.S70
-rw-r--r--module/icp/asm-x86_64/sha2/sha256-x86_64.S5104
-rw-r--r--module/icp/asm-x86_64/sha2/sha256_impl.S2089
-rw-r--r--module/icp/asm-x86_64/sha2/sha512-x86_64.S4011
-rw-r--r--module/icp/asm-x86_64/sha2/sha512_impl.S2114
-rw-r--r--module/icp/core/kcf_callprov.c4
-rw-r--r--module/icp/core/kcf_mech_tabs.c4
-rw-r--r--module/icp/core/kcf_prov_lib.c2
-rw-r--r--module/icp/core/kcf_prov_tabs.c4
-rw-r--r--module/icp/core/kcf_sched.c2
-rw-r--r--module/icp/illumos-crypto.c2
-rw-r--r--module/icp/include/aes/aes_impl.h11
-rw-r--r--module/icp/include/generic_impl.c233
-rw-r--r--module/icp/include/modes/gcm_impl.h2
-rw-r--r--module/icp/include/modes/modes.h4
-rw-r--r--module/icp/include/sha2/sha2_consts.h219
-rw-r--r--module/icp/include/sha2/sha2_impl.h29
-rw-r--r--module/icp/include/sys/crypto/impl.h44
-rw-r--r--module/icp/include/sys/crypto/sched_impl.h9
-rw-r--r--module/icp/include/sys/crypto/spi.h2
-rw-r--r--module/icp/include/sys/ia32/stack.h160
-rw-r--r--module/icp/include/sys/ia32/trap.h107
-rw-r--r--module/icp/include/sys/stack.h2
-rw-r--r--module/icp/include/sys/trap.h2
-rw-r--r--module/icp/io/aes.c27
-rw-r--r--module/icp/io/sha2_mod.c16
-rw-r--r--module/icp/io/skein_mod.c17
-rw-r--r--module/icp/spi/kcf_spi.c2
-rw-r--r--module/lua/lapi.c4
-rw-r--r--module/lua/ldebug.c7
-rw-r--r--module/lua/ldo.c18
-rw-r--r--module/lua/lfunc.h4
-rw-r--r--module/lua/lgc.c2
-rw-r--r--module/lua/lgc.h2
-rw-r--r--module/lua/lobject.c2
-rw-r--r--module/lua/lobject.h4
-rw-r--r--module/lua/lvm.c2
-rw-r--r--module/lua/setjmp/setjmp.S2
-rw-r--r--module/lua/setjmp/setjmp_aarch64.S2
-rw-r--r--module/lua/setjmp/setjmp_arm.S2
-rw-r--r--module/lua/setjmp/setjmp_i386.S4
-rw-r--r--module/lua/setjmp/setjmp_loongarch64.S82
-rw-r--r--module/lua/setjmp/setjmp_ppc.S4
-rw-r--r--module/lua/setjmp/setjmp_sparc64.S2
-rw-r--r--module/lua/setjmp/setjmp_x86_64.S27
-rw-r--r--module/nvpair/fnvpair.c14
-rw-r--r--module/nvpair/nvpair.c30
-rw-r--r--module/nvpair/nvpair_alloc_fixed.c2
-rw-r--r--module/nvpair/nvpair_alloc_spl.c2
-rw-r--r--module/os/freebsd/spl/acl_common.c6
-rw-r--r--module/os/freebsd/spl/callb.c9
-rw-r--r--module/os/freebsd/spl/list.c6
-rw-r--r--module/os/freebsd/spl/sha224.h96
-rw-r--r--module/os/freebsd/spl/sha256.h99
-rw-r--r--module/os/freebsd/spl/sha256c.c378
-rw-r--r--module/os/freebsd/spl/sha384.h96
-rw-r--r--module/os/freebsd/spl/sha512.h101
-rw-r--r--module/os/freebsd/spl/sha512c.c508
-rw-r--r--module/os/freebsd/spl/sha512t.h143
-rw-r--r--module/os/freebsd/spl/spl_acl.c3
-rw-r--r--module/os/freebsd/spl/spl_atomic.c3
-rw-r--r--module/os/freebsd/spl/spl_cmn_err.c2
-rw-r--r--module/os/freebsd/spl/spl_dtrace.c3
-rw-r--r--module/os/freebsd/spl/spl_kmem.c3
-rw-r--r--module/os/freebsd/spl/spl_kstat.c130
-rw-r--r--module/os/freebsd/spl/spl_misc.c5
-rw-r--r--module/os/freebsd/spl/spl_policy.c3
-rw-r--r--module/os/freebsd/spl/spl_procfs_list.c3
-rw-r--r--module/os/freebsd/spl/spl_string.c32
-rw-r--r--module/os/freebsd/spl/spl_sunddi.c3
-rw-r--r--module/os/freebsd/spl/spl_sysevent.c7
-rw-r--r--module/os/freebsd/spl/spl_taskq.c191
-rw-r--r--module/os/freebsd/spl/spl_uio.c2
-rw-r--r--module/os/freebsd/spl/spl_vfs.c24
-rw-r--r--module/os/freebsd/spl/spl_vm.c3
-rw-r--r--module/os/freebsd/spl/spl_zlib.c11
-rw-r--r--module/os/freebsd/spl/spl_zone.c3
-rw-r--r--module/os/freebsd/zfs/abd_os.c4
-rw-r--r--module/os/freebsd/zfs/arc_os.c95
-rw-r--r--module/os/freebsd/zfs/crypto_os.c3
-rw-r--r--module/os/freebsd/zfs/dmu_os.c7
-rw-r--r--module/os/freebsd/zfs/event_os.c83
-rw-r--r--module/os/freebsd/zfs/kmod_core.c52
-rw-r--r--module/os/freebsd/zfs/spa_os.c9
-rw-r--r--module/os/freebsd/zfs/sysctl_os.c680
-rw-r--r--module/os/freebsd/zfs/vdev_file.c21
-rw-r--r--module/os/freebsd/zfs/vdev_geom.c56
-rw-r--r--module/os/freebsd/zfs/vdev_label_os.c63
-rw-r--r--module/os/freebsd/zfs/zfs_acl.c51
-rw-r--r--module/os/freebsd/zfs/zfs_ctldir.c50
-rw-r--r--module/os/freebsd/zfs/zfs_debug.c22
-rw-r--r--module/os/freebsd/zfs/zfs_dir.c14
-rw-r--r--module/os/freebsd/zfs/zfs_file_os.c70
-rw-r--r--module/os/freebsd/zfs/zfs_ioctl_compat.c13
-rw-r--r--module/os/freebsd/zfs/zfs_ioctl_os.c7
-rw-r--r--module/os/freebsd/zfs/zfs_vfsops.c526
-rw-r--r--module/os/freebsd/zfs/zfs_vnops_os.c722
-rw-r--r--module/os/freebsd/zfs/zfs_znode.c142
-rw-r--r--module/os/freebsd/zfs/zio_crypt.c44
-rw-r--r--module/os/freebsd/zfs/zvol_os.c130
-rw-r--r--module/os/linux/spl/spl-condvar.c4
-rw-r--r--module/os/linux/spl/spl-cred.c12
-rw-r--r--module/os/linux/spl/spl-err.c5
-rw-r--r--module/os/linux/spl/spl-generic.c163
-rw-r--r--module/os/linux/spl/spl-kmem-cache.c49
-rw-r--r--module/os/linux/spl/spl-kstat.c9
-rw-r--r--module/os/linux/spl/spl-proc.c77
-rw-r--r--module/os/linux/spl/spl-procfs-list.c4
-rw-r--r--module/os/linux/spl/spl-shrinker.c115
-rw-r--r--module/os/linux/spl/spl-taskq.c110
-rw-r--r--module/os/linux/spl/spl-thread.c8
-rw-r--r--module/os/linux/spl/spl-trace.c2
-rw-r--r--module/os/linux/spl/spl-tsd.c2
-rw-r--r--module/os/linux/spl/spl-xdr.c1
-rw-r--r--module/os/linux/spl/spl-zlib.c2
-rw-r--r--module/os/linux/spl/spl-zone.c11
-rw-r--r--module/os/linux/zfs/abd_os.c202
-rw-r--r--module/os/linux/zfs/arc_os.c86
-rw-r--r--module/os/linux/zfs/mmp_os.c4
-rw-r--r--module/os/linux/zfs/policy.c21
-rw-r--r--module/os/linux/zfs/qat.c2
-rw-r--r--module/os/linux/zfs/qat_compress.c6
-rw-r--r--module/os/linux/zfs/qat_crypt.c2
-rw-r--r--module/os/linux/zfs/spa_misc_os.c18
-rw-r--r--module/os/linux/zfs/trace.c2
-rw-r--r--module/os/linux/zfs/vdev_disk.c1097
-rw-r--r--module/os/linux/zfs/vdev_file.c56
-rw-r--r--module/os/linux/zfs/vdev_label_os.c (renamed from module/zfs/spa_boot.c)41
-rw-r--r--module/os/linux/zfs/zfs_acl.c118
-rw-r--r--module/os/linux/zfs/zfs_ctldir.c97
-rw-r--r--module/os/linux/zfs/zfs_debug.c25
-rw-r--r--module/os/linux/zfs/zfs_dir.c115
-rw-r--r--module/os/linux/zfs/zfs_file_os.c4
-rw-r--r--module/os/linux/zfs/zfs_ioctl_os.c15
-rw-r--r--module/os/linux/zfs/zfs_sysfs.c8
-rw-r--r--module/os/linux/zfs/zfs_uio.c31
-rw-r--r--module/os/linux/zfs/zfs_vfsops.c179
-rw-r--r--module/os/linux/zfs/zfs_vnops_os.c931
-rw-r--r--module/os/linux/zfs/zfs_znode.c174
-rw-r--r--module/os/linux/zfs/zio_crypt.c64
-rw-r--r--module/os/linux/zfs/zpl_ctldir.c100
-rw-r--r--module/os/linux/zfs/zpl_export.c2
-rw-r--r--module/os/linux/zfs/zpl_file.c189
-rw-r--r--module/os/linux/zfs/zpl_file_range.c299
-rw-r--r--module/os/linux/zfs/zpl_inode.c234
-rw-r--r--module/os/linux/zfs/zpl_super.c63
-rw-r--r--module/os/linux/zfs/zpl_xattr.c82
-rw-r--r--module/os/linux/zfs/zvol_os.c225
-rw-r--r--module/unicode/u8_textprep.c23
-rw-r--r--module/unicode/uconv.c2
-rw-r--r--module/zcommon/zfeature_common.c31
-rw-r--r--module/zcommon/zfs_comutil.c6
-rw-r--r--module/zcommon/zfs_deleg.c6
-rw-r--r--module/zcommon/zfs_fletcher.c39
-rw-r--r--module/zcommon/zfs_fletcher_aarch64_neon.c19
-rw-r--r--module/zcommon/zfs_fletcher_avx512.c30
-rw-r--r--module/zcommon/zfs_fletcher_intel.c19
-rw-r--r--module/zcommon/zfs_fletcher_sse.c28
-rw-r--r--module/zcommon/zfs_fletcher_superscalar.c13
-rw-r--r--module/zcommon/zfs_fletcher_superscalar4.c13
-rw-r--r--module/zcommon/zfs_namecheck.c2
-rw-r--r--module/zcommon/zfs_prop.c60
-rw-r--r--module/zcommon/zpool_prop.c37
-rw-r--r--module/zcommon/zprop_common.c2
-rw-r--r--module/zfs/abd.c198
-rw-r--r--module/zfs/arc.c2759
-rw-r--r--module/zfs/blake3_zfs.c11
-rw-r--r--module/zfs/bplist.c10
-rw-r--r--module/zfs/bpobj.c124
-rw-r--r--module/zfs/bptree.c2
-rw-r--r--module/zfs/bqueue.c122
-rw-r--r--module/zfs/brt.c1673
-rw-r--r--module/zfs/btree.c82
-rw-r--r--module/zfs/dataset_kstats.c72
-rw-r--r--module/zfs/dbuf.c1109
-rw-r--r--module/zfs/dbuf_stats.c19
-rw-r--r--module/zfs/ddt.c652
-rw-r--r--module/zfs/ddt_stats.c212
-rw-r--r--module/zfs/ddt_zap.c151
-rw-r--r--module/zfs/dmu.c455
-rw-r--r--module/zfs/dmu_diff.c2
-rw-r--r--module/zfs/dmu_object.c10
-rw-r--r--module/zfs/dmu_objset.c228
-rw-r--r--module/zfs/dmu_recv.c557
-rw-r--r--module/zfs/dmu_redact.c27
-rw-r--r--module/zfs/dmu_send.c78
-rw-r--r--module/zfs/dmu_traverse.c47
-rw-r--r--module/zfs/dmu_tx.c175
-rw-r--r--module/zfs/dmu_zfetch.c344
-rw-r--r--module/zfs/dnode.c228
-rw-r--r--module/zfs/dnode_sync.c43
-rw-r--r--module/zfs/dsl_bookmark.c87
-rw-r--r--module/zfs/dsl_crypt.c75
-rw-r--r--module/zfs/dsl_dataset.c172
-rw-r--r--module/zfs/dsl_deadlist.c141
-rw-r--r--module/zfs/dsl_deleg.c2
-rw-r--r--module/zfs/dsl_destroy.c40
-rw-r--r--module/zfs/dsl_dir.c123
-rw-r--r--module/zfs/dsl_pool.c83
-rw-r--r--module/zfs/dsl_prop.c103
-rw-r--r--module/zfs/dsl_scan.c977
-rw-r--r--module/zfs/dsl_synctask.c2
-rw-r--r--module/zfs/dsl_userhold.c6
-rw-r--r--module/zfs/edonr_zfs.c8
-rw-r--r--module/zfs/fm.c25
-rw-r--r--module/zfs/gzip.c2
-rw-r--r--module/zfs/lzjb.c2
-rw-r--r--module/zfs/metaslab.c361
-rw-r--r--module/zfs/mmp.c30
-rw-r--r--module/zfs/multilist.c34
-rw-r--r--module/zfs/pathname.c2
-rw-r--r--module/zfs/range_tree.c21
-rw-r--r--module/zfs/refcount.c211
-rw-r--r--module/zfs/rrwlock.c2
-rw-r--r--module/zfs/sa.c10
-rw-r--r--module/zfs/sha2_zfs.c (renamed from module/zfs/sha256.c)16
-rw-r--r--module/zfs/spa.c1498
-rw-r--r--module/zfs/spa_checkpoint.c11
-rw-r--r--module/zfs/spa_config.c39
-rw-r--r--module/zfs/spa_errlog.c914
-rw-r--r--module/zfs/spa_history.c4
-rw-r--r--module/zfs/spa_log_spacemap.c62
-rw-r--r--module/zfs/spa_misc.c251
-rw-r--r--module/zfs/spa_stats.c14
-rw-r--r--module/zfs/space_map.c2
-rw-r--r--module/zfs/space_reftree.c2
-rw-r--r--module/zfs/txg.c32
-rw-r--r--module/zfs/uberblock.c4
-rw-r--r--module/zfs/unique.c2
-rw-r--r--module/zfs/vdev.c742
-rw-r--r--module/zfs/vdev_cache.c436
-rw-r--r--module/zfs/vdev_draid.c72
-rw-r--r--module/zfs/vdev_indirect.c49
-rw-r--r--module/zfs/vdev_initialize.c103
-rw-r--r--module/zfs/vdev_label.c194
-rw-r--r--module/zfs/vdev_mirror.c14
-rw-r--r--module/zfs/vdev_missing.c2
-rw-r--r--module/zfs/vdev_queue.c444
-rw-r--r--module/zfs/vdev_raidz.c2586
-rw-r--r--module/zfs/vdev_raidz_math.c33
-rw-r--r--module/zfs/vdev_raidz_math_aarch64_neon.c2
-rw-r--r--module/zfs/vdev_raidz_math_aarch64_neon_common.h2
-rw-r--r--module/zfs/vdev_raidz_math_aarch64_neonx2.c6
-rw-r--r--module/zfs/vdev_raidz_math_avx2.c2
-rw-r--r--module/zfs/vdev_raidz_math_avx512bw.c2
-rw-r--r--module/zfs/vdev_raidz_math_avx512f.c2
-rw-r--r--module/zfs/vdev_raidz_math_impl.h164
-rw-r--r--module/zfs/vdev_raidz_math_powerpc_altivec.c2
-rw-r--r--module/zfs/vdev_raidz_math_powerpc_altivec_common.h46
-rw-r--r--module/zfs/vdev_raidz_math_scalar.c2
-rw-r--r--module/zfs/vdev_raidz_math_sse2.c2
-rw-r--r--module/zfs/vdev_raidz_math_ssse3.c2
-rw-r--r--module/zfs/vdev_rebuild.c59
-rw-r--r--module/zfs/vdev_removal.c22
-rw-r--r--module/zfs/vdev_root.c2
-rw-r--r--module/zfs/vdev_trim.c134
-rw-r--r--module/zfs/zap.c385
-rw-r--r--module/zfs/zap_leaf.c85
-rw-r--r--module/zfs/zap_micro.c467
-rw-r--r--module/zfs/zcp.c26
-rw-r--r--module/zfs/zcp_get.c14
-rw-r--r--module/zfs/zcp_iter.c2
-rw-r--r--module/zfs/zcp_synctask.c37
-rw-r--r--module/zfs/zfeature.c2
-rw-r--r--module/zfs/zfs_byteswap.c2
-rw-r--r--module/zfs/zfs_chksum.c226
-rw-r--r--module/zfs/zfs_fm.c164
-rw-r--r--module/zfs/zfs_fuid.c14
-rw-r--r--module/zfs/zfs_impl.c61
-rw-r--r--module/zfs/zfs_ioctl.c263
-rw-r--r--module/zfs/zfs_log.c154
-rw-r--r--module/zfs/zfs_onexit.c9
-rw-r--r--module/zfs/zfs_quota.c5
-rw-r--r--module/zfs/zfs_ratelimit.c2
-rw-r--r--module/zfs/zfs_replay.c227
-rw-r--r--module/zfs/zfs_rlock.c2
-rw-r--r--module/zfs/zfs_sa.c2
-rw-r--r--module/zfs/zfs_vnops.c801
-rw-r--r--module/zfs/zil.c1879
-rw-r--r--module/zfs/zio.c802
-rw-r--r--module/zfs/zio_checksum.c35
-rw-r--r--module/zfs/zio_compress.c13
-rw-r--r--module/zfs/zio_inject.c152
-rw-r--r--module/zfs/zle.c2
-rw-r--r--module/zfs/zrlock.c10
-rw-r--r--module/zfs/zvol.c228
-rw-r--r--module/zstd/include/zstd_compat_wrapper.h2
-rw-r--r--module/zstd/lib/common/fse_decompress.c11
-rw-r--r--module/zstd/lib/compress/zstd_compress_superblock.c16
-rw-r--r--module/zstd/lib/compress/zstd_double_fast.c4
-rw-r--r--module/zstd/lib/compress/zstd_fast.c6
-rw-r--r--module/zstd/lib/compress/zstd_lazy.c12
-rw-r--r--module/zstd/lib/decompress/zstd_decompress_block.c50
-rw-r--r--module/zstd/zfs_zstd.c8
-rw-r--r--rpm/generic/zfs-dkms.spec.in99
-rw-r--r--rpm/generic/zfs-kmod.spec.in35
-rw-r--r--rpm/generic/zfs.spec.in57
-rw-r--r--rpm/redhat/zfs-kmod.spec.in26
-rw-r--r--scripts/Makefile.am23
-rw-r--r--scripts/common.sh.in20
-rwxr-xr-xscripts/cstyle.pl15
-rwxr-xr-xscripts/enum-extract.pl2
-rwxr-xr-xscripts/kmodtool100
-rwxr-xr-xscripts/mancheck.sh2
-rwxr-xr-xscripts/update_authors.pl322
-rwxr-xr-xscripts/zfs-tests.sh27
-rwxr-xr-xscripts/zfs_prepare_disk17
-rwxr-xr-xscripts/zimport.sh46
-rwxr-xr-xscripts/zloop.sh65
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/runfiles/bclone.run46
-rw-r--r--tests/runfiles/common.run146
-rw-r--r--tests/runfiles/freebsd.run5
-rw-r--r--tests/runfiles/linux.run48
-rw-r--r--tests/runfiles/sanity.run24
-rwxr-xr-xtests/test-runner/bin/test-runner.py.in97
-rwxr-xr-xtests/test-runner/bin/zts-report.py.in113
-rw-r--r--tests/test-runner/include/logapi.shlib2
-rw-r--r--tests/zfs-tests/Makefile.am6
-rwxr-xr-xtests/zfs-tests/callbacks/zfs_dbgmsg.ksh3
-rwxr-xr-xtests/zfs-tests/callbacks/zfs_dmesg.ksh3
-rwxr-xr-xtests/zfs-tests/callbacks/zfs_mmp.ksh1
-rw-r--r--tests/zfs-tests/cmd/.gitignore6
-rw-r--r--tests/zfs-tests/cmd/Makefile.am11
-rw-r--r--tests/zfs-tests/cmd/badsend.c6
-rw-r--r--tests/zfs-tests/cmd/btree_test.c70
-rw-r--r--tests/zfs-tests/cmd/checksum/blake3_test.c20
-rw-r--r--tests/zfs-tests/cmd/checksum/edonr_test.c89
-rw-r--r--tests/zfs-tests/cmd/checksum/sha2_test.c54
-rw-r--r--tests/zfs-tests/cmd/checksum/skein_test.c16
-rw-r--r--tests/zfs-tests/cmd/chg_usr_exec.c2
-rw-r--r--tests/zfs-tests/cmd/clone_mmap_cached.c146
-rw-r--r--tests/zfs-tests/cmd/clone_mmap_write.c123
-rw-r--r--tests/zfs-tests/cmd/clonefile.c373
-rw-r--r--tests/zfs-tests/cmd/ctime.c17
-rw-r--r--tests/zfs-tests/cmd/devname2devid.c2
-rw-r--r--tests/zfs-tests/cmd/dir_rd_update.c7
-rw-r--r--tests/zfs-tests/cmd/dosmode_readonly_write.c2
-rw-r--r--tests/zfs-tests/cmd/draid.c43
-rw-r--r--tests/zfs-tests/cmd/ereports.c4
-rw-r--r--tests/zfs-tests/cmd/file/file_append.c2
-rw-r--r--tests/zfs-tests/cmd/file/file_check.c2
-rw-r--r--tests/zfs-tests/cmd/file/file_common.h2
-rw-r--r--tests/zfs-tests/cmd/file/file_fadvise.c101
-rw-r--r--tests/zfs-tests/cmd/file/file_trunc.c6
-rw-r--r--tests/zfs-tests/cmd/file/file_write.c2
-rw-r--r--tests/zfs-tests/cmd/file/largest_file.c4
-rw-r--r--tests/zfs-tests/cmd/file/randfree_file.c2
-rw-r--r--tests/zfs-tests/cmd/file/randwritecomp.c5
-rw-r--r--tests/zfs-tests/cmd/get_diff.c2
-rw-r--r--tests/zfs-tests/cmd/idmap_util.c808
-rw-r--r--tests/zfs-tests/cmd/libzfs_input_check.c24
-rw-r--r--tests/zfs-tests/cmd/mkbusy.c8
-rw-r--r--tests/zfs-tests/cmd/mkfile.c6
-rw-r--r--tests/zfs-tests/cmd/mktree.c2
-rw-r--r--tests/zfs-tests/cmd/mmap_exec.c2
-rw-r--r--tests/zfs-tests/cmd/mmap_libaio.c4
-rw-r--r--tests/zfs-tests/cmd/mmap_seek.c2
-rw-r--r--tests/zfs-tests/cmd/mmap_sync.c10
-rw-r--r--tests/zfs-tests/cmd/mmapwrite.c34
-rw-r--r--tests/zfs-tests/cmd/nvlist_to_lua.c7
-rw-r--r--tests/zfs-tests/cmd/readmmap.c7
-rw-r--r--tests/zfs-tests/cmd/rename_dir.c2
-rw-r--r--tests/zfs-tests/cmd/renameat2.c128
-rw-r--r--tests/zfs-tests/cmd/rm_lnkcnt_zero_file.c2
-rw-r--r--tests/zfs-tests/cmd/send_doall.c2
-rw-r--r--tests/zfs-tests/cmd/stride_dd.c4
-rw-r--r--tests/zfs-tests/cmd/suid_write_to_file.c2
-rw-r--r--tests/zfs-tests/cmd/threadsappend.c2
-rw-r--r--tests/zfs-tests/cmd/user_ns_exec.c3
-rw-r--r--tests/zfs-tests/cmd/xattrtest.c2
-rw-r--r--tests/zfs-tests/cmd/zed_fd_spill-zedlet.c15
-rw-r--r--tests/zfs-tests/cmd/zfs_diff-socket.c3
-rw-r--r--tests/zfs-tests/include/blkdev.shlib2
-rw-r--r--tests/zfs-tests/include/commands.cfg20
-rw-r--r--tests/zfs-tests/include/default.cfg.in6
-rw-r--r--tests/zfs-tests/include/libtest.shlib102
-rw-r--r--tests/zfs-tests/include/math.shlib20
-rw-r--r--tests/zfs-tests/include/properties.shlib3
-rw-r--r--tests/zfs-tests/include/tunables.cfg7
-rw-r--r--tests/zfs-tests/tests/Makefile.am146
-rw-r--r--tests/zfs-tests/tests/functional/acl/acl.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/acl/acl_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/off/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/off/dosmode.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/off/posixmode.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/off/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh5
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/append/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/append/file_append.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/append/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/append/threadsappend_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/atime/atime.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_001_pos.ksh8
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_003_pos.ksh3
-rw-r--r--tests/zfs-tests/tests/functional/atime/atime_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_atime_off.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_atime_on.ksh9
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_relatime_on.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/bclone/TODO4
-rw-r--r--tests/zfs-tests/tests/functional/bclone/bclone.cfg32
-rw-r--r--tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib291
-rw-r--r--tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib325
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh46
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/cleanup.ksh (renamed from tests/zfs-tests/tests/functional/raidz/raidz_003_pos.ksh)29
-rwxr-xr-xtests/zfs-tests/tests/functional/bclone/setup.ksh50
-rw-r--r--tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib58
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_cached.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_write.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh169
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlone.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlonerange.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh132
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh134
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/cleanup.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/block_cloning/setup.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cache/cache.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cache/cache.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_012_pos.ksh27
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cachefile/cachefile.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.zcp27
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/checksum/default.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/filetest_002_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/clean_mirror/default.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_backup.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg3
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh15
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_recursive.ksh146
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_compressed_corrective.ksh193
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_corrective.ksh209
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_large_block_corrective.ksh194
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_skip_missing.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh14
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh12
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_nomount.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_after_mount.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib361
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_checksum.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_002.ksh31
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_003.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_004.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh22
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh0
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh13
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_007_pos.ksh12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_009_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear_retained.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_duplicates.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh62
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg9
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_log_missing.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg7
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib1
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_016_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_017_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile_unclean_export.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_unclean_export.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh165
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh130
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh137
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_status.ksh132
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh141
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_concurrent.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_004_pos.ksh54
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_001_pos.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_002_neg.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh6
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib178
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_dryrun_output.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_003_pos.ksh7
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_004_pos.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_005_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_006_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_007_pos.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_008_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_features_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zilstat_001_pos.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/compression/compress.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_zstd_bswap.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cp_files/.gitignore1
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh161
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cp_stress.ksh73
-rw-r--r--tests/zfs-tests/tests/functional/cp_files/seekflood.c180
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/crtime/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/crtime/crtime_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/crtime/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/deadman/deadman.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/deadman/deadman_ratelimit.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/deadman/deadman_sync.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/deadman/deadman_zio.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/delegate/delegate.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib6
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/devices/devices.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_003_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/devices/devices_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/dos_attributes/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/cleanup.ksh6
-rw-r--r--tests/zfs-tests/tests/functional/events/events.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/events_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/events_002_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/events/events_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_cksum_config.ksh158
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_cksum_reported.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_fd_spill.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_io_config.ksh150
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_rc_filter.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_slow_io.ksh205
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_slow_io_many_vdevs.ksh177
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/exec_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/exec_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fadvise/cleanup.ksh28
-rwxr-xr-xtests/zfs-tests/tests/functional/fadvise/fadvise_sequential.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/fadvise/setup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_online_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh192
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/cleanup.ksh3
-rw-r--r--tests/zfs-tests/tests/functional/fault/fault.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/setup.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/grow/grow.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/history/history.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_010_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/history/history_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/history/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh25
-rw-r--r--tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg25
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh121
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh106
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh138
-rw-r--r--tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib23
-rwxr-xr-xtests/zfs-tests/tests/functional/idmap_mount/setup.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/README.config2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/README.state2
-rwxr-xr-xtests/zfs-tests/tests/functional/inheritance/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config001.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config002.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config003.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config004.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config005.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config006.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config007.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config008.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config009.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config010.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config011.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config012.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config013.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config014.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config015.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config016.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config017.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config018.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config019.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config020.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config021.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config022.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config023.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config024.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/inherit.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh14
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state001.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state002.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state003.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state004.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state005.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state006.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state007.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state008.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state009.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state010.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state011.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state012.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state013.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state014.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state015.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state016.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state017.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state018.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state019.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state020.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state021.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state022.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state023.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state024.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/inuse/inuse.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/io_uring.ksh11
-rwxr-xr-xtests/zfs-tests/tests/functional/io/libaio.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/mmap.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/posixaio.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/psync.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/io/sync.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/l2arc/l2arc_mfuonly_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh19
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/libzfs/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/libzfs/many_fds.c2
-rwxr-xr-xtests/zfs-tests/tests/functional/libzfs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/link_count_001.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/migration/migration.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/migration/migration.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_012_pos.ksh6
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/mmap/mmap.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_mixed.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_seek_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/mmp/mmp.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_write_slow_disk.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/umount_001.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/mv_files/mv_files.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/no_space/enospc.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_ganging.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_rm.ksh12
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib8
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/online_offline/online_offline.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/cleanup.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_basic.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_change_unmounted.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_nounmount.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_recursive.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_short_password.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/pam/utilities.kshlib.in2
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/pool_state.ksh8
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/projectquota/projectquota.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in16
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/quota/quota.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/quota/quota.kshlib9
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_001_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_002_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_003_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_004_pos.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_005_pos.ksh11
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_006_neg.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_001_pos.ksh215
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_002_pos.ksh115
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_003_neg.ksh102
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_003_pos.ksh141
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_004_pos.ksh121
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh177
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_006_neg.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_expand_007_neg.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/redacted_send/redacted.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh12
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/redundancy/redundancy.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib24
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid1.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid2.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid3.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_raidz.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_raidz3.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/refreserv/refreserv.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_indirect.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_mirror.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/renameat2/cleanup.ksh (renamed from tests/zfs-tests/tests/functional/raidz/raidz_004_pos.ksh)19
-rwxr-xr-xtests/zfs-tests/tests/functional/renameat2/renameat2_exchange.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/renameat2/renameat2_noreplace.ksh51
-rwxr-xr-xtests/zfs-tests/tests/functional/renameat2/renameat2_whiteout.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/renameat2/setup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_resilver.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/detach.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/replace_resilver.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/replacement/replacement.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/reservation/reservation.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/reservation/reservation.shlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/rsend/rsend.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/rsend/rsend.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_025_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_026_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_027_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_028_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_029_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_030_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_031_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_volume.ksh9
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_zstream_recompress.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_freeobjects.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh8
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_raw_ashift.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/scrub_mirror/default.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/simd/simd_supported.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/slog/slog.cfg2
-rw-r--r--tests/zfs-tests/tests/functional/slog/slog.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_008_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_011_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_012_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_014_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_016_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh25
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/snapshot/snapshot.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh127
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/snapused/snapused.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/sparse/sparse.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/stat/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/stat/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/stat/stat_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/tmpfile/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/tmpfile/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c7
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c32
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_config.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/trim/trim.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_config.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_integrity.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_l2arc.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/truncate/truncate.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/user_namespace_002.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/user_namespace_003.ksh4
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/user_namespace_004.ksh6
-rw-r--r--tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib2
-rw-r--r--tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2bin0 -> 135829 bytes
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/userquota/userquota.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_encrypted_13709.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/vdev_disk/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/vdev_disk/page_alignment.c413
-rw-r--r--tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib13
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh1
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/xattr/xattr.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_compat.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zap_shrink/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/zap_shrink/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/zap_shrink/zap_shrink_001_pos.ksh81
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_common.shlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh11
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_trim.ksh17
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_stress/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_stress/setup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_stress/zvol_stress.ksh3
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh2
-rw-r--r--tests/zfs-tests/tests/perf/perf.shlib1
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_readwrite.ksh2
-rw-r--r--udev/zvol_id.c11
2631 files changed, 108358 insertions, 38045 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 000000000000..18b292289e20
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,21 @@
+env:
+ CIRRUS_CLONE_DEPTH: 1
+ ARCH: amd64
+
+build_task:
+ matrix:
+ freebsd_instance:
+ image_family: freebsd-12-4
+ freebsd_instance:
+ image_family: freebsd-13-2
+ freebsd_instance:
+ image_family: freebsd-14-0-snap
+ prepare_script:
+ - pkg install -y autoconf automake libtool gettext-runtime gmake ksh93 py39-packaging py39-cffi py39-sysctl
+ configure_script:
+ - env MAKE=gmake ./autogen.sh
+ - env MAKE=gmake ./configure --with-config="user" --with-python=3.9
+ build_script:
+ - gmake -j `sysctl -n kern.smp.cpus`
+ install_script:
+ - gmake install
diff --git a/.github/codeql-cpp.yml b/.github/codeql-cpp.yml
new file mode 100644
index 000000000000..88b8c6086025
--- /dev/null
+++ b/.github/codeql-cpp.yml
@@ -0,0 +1,4 @@
+name: "Custom CodeQL Analysis"
+
+queries:
+ - uses: ./.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql
diff --git a/.github/codeql-python.yml b/.github/codeql-python.yml
new file mode 100644
index 000000000000..93cb4a435ed9
--- /dev/null
+++ b/.github/codeql-python.yml
@@ -0,0 +1,4 @@
+name: "Custom CodeQL Analysis"
+
+paths-ignore:
+ - tests
diff --git a/.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql b/.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql
new file mode 100644
index 000000000000..eb4b7bd6299b
--- /dev/null
+++ b/.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql
@@ -0,0 +1,59 @@
+/**
+ * @name Deprecated function usage detection
+ * @description Detects functions whose usage is banned from the OpenZFS
+ * codebase due to QA concerns.
+ * @kind problem
+ * @severity error
+ * @id cpp/deprecated-function-usage
+*/
+
+import cpp
+
+predicate isDeprecatedFunction(Function f) {
+ f.getName() = "strtok" or
+ f.getName() = "__xpg_basename" or
+ f.getName() = "basename" or
+ f.getName() = "dirname" or
+ f.getName() = "bcopy" or
+ f.getName() = "bcmp" or
+ f.getName() = "bzero" or
+ f.getName() = "asctime" or
+ f.getName() = "asctime_r" or
+ f.getName() = "gmtime" or
+ f.getName() = "localtime" or
+ f.getName() = "strncpy"
+
+}
+
+string getReplacementMessage(Function f) {
+ if f.getName() = "strtok" then
+ result = "Use strtok_r(3) instead!"
+ else if f.getName() = "__xpg_basename" then
+ result = "basename(3) is underspecified. Use zfs_basename() instead!"
+ else if f.getName() = "basename" then
+ result = "basename(3) is underspecified. Use zfs_basename() instead!"
+ else if f.getName() = "dirname" then
+ result = "dirname(3) is underspecified. Use zfs_dirnamelen() instead!"
+ else if f.getName() = "bcopy" then
+ result = "bcopy(3) is deprecated. Use memcpy(3)/memmove(3) instead!"
+ else if f.getName() = "bcmp" then
+ result = "bcmp(3) is deprecated. Use memcmp(3) instead!"
+ else if f.getName() = "bzero" then
+ result = "bzero(3) is deprecated. Use memset(3) instead!"
+ else if f.getName() = "asctime" then
+ result = "Use strftime(3) instead!"
+ else if f.getName() = "asctime_r" then
+ result = "Use strftime(3) instead!"
+ else if f.getName() = "gmtime" then
+ result = "gmtime(3) isn't thread-safe. Use gmtime_r(3) instead!"
+ else if f.getName() = "localtime" then
+ result = "localtime(3) isn't thread-safe. Use localtime_r(3) instead!"
+ else
+ result = "strncpy(3) is deprecated. Use strlcpy(3) instead!"
+}
+
+from FunctionCall fc, Function f
+where
+ fc.getTarget() = f and
+ isDeprecatedFunction(f)
+select fc, getReplacementMessage(f)
diff --git a/.github/codeql/custom-queries/cpp/qlpack.yml b/.github/codeql/custom-queries/cpp/qlpack.yml
new file mode 100644
index 000000000000..cbe0f1cbe3c4
--- /dev/null
+++ b/.github/codeql/custom-queries/cpp/qlpack.yml
@@ -0,0 +1,4 @@
+name: openzfs-cpp-queries
+version: 0.0.0
+libraryPathDependencies: codeql-cpp
+suites: openzfs-cpp-suite
diff --git a/.github/workflows/README.md b/.github/workflows/README.md
new file mode 100644
index 000000000000..eef47dae3dc7
--- /dev/null
+++ b/.github/workflows/README.md
@@ -0,0 +1,61 @@
+
+## The testings are done this way
+
+```mermaid
+flowchart TB
+subgraph CleanUp and Summary
+ CleanUp+Summary
+end
+
+subgraph Functional Testings
+ sanity-checks-20.04
+ zloop-checks-20.04
+ functional-testing-20.04-->Part1-20.04
+ functional-testing-20.04-->Part2-20.04
+ functional-testing-20.04-->Part3-20.04
+ functional-testing-20.04-->Part4-20.04
+ functional-testing-22.04-->Part1-22.04
+ functional-testing-22.04-->Part2-22.04
+ functional-testing-22.04-->Part3-22.04
+ functional-testing-22.04-->Part4-22.04
+ sanity-checks-22.04
+ zloop-checks-22.04
+end
+
+subgraph Code Checking + Building
+ Build-Ubuntu-20.04
+ codeql.yml
+ checkstyle.yml
+ Build-Ubuntu-22.04
+end
+
+ Build-Ubuntu-20.04-->sanity-checks-20.04
+ Build-Ubuntu-20.04-->zloop-checks-20.04
+ Build-Ubuntu-20.04-->functional-testing-20.04
+ Build-Ubuntu-22.04-->sanity-checks-22.04
+ Build-Ubuntu-22.04-->zloop-checks-22.04
+ Build-Ubuntu-22.04-->functional-testing-22.04
+
+ sanity-checks-20.04-->CleanUp+Summary
+ Part1-20.04-->CleanUp+Summary
+ Part2-20.04-->CleanUp+Summary
+ Part3-20.04-->CleanUp+Summary
+ Part4-20.04-->CleanUp+Summary
+ Part1-22.04-->CleanUp+Summary
+ Part2-22.04-->CleanUp+Summary
+ Part3-22.04-->CleanUp+Summary
+ Part4-22.04-->CleanUp+Summary
+ sanity-checks-22.04-->CleanUp+Summary
+```
+
+
+1) build zfs modules for Ubuntu 20.04 and 22.04 (~15m)
+2) 2x zloop test (~10m) + 2x sanity test (~25m)
+3) 4x functional testings in parts 1..4 (each ~1h)
+4) cleanup and create summary
+ - content of summary depends on the results of the steps
+
+When everything runs fine, the full run should be done in
+about 2 hours.
+
+The codeql.yml and checkstyle.yml are not part in this circle.
diff --git a/.github/workflows/build-dependencies.txt b/.github/workflows/build-dependencies.txt
index e591399001f5..73921865c42a 100644
--- a/.github/workflows/build-dependencies.txt
+++ b/.github/workflows/build-dependencies.txt
@@ -6,6 +6,9 @@ bc
build-essential
curl
dbench
+debhelper-compat
+dh-python
+dkms
fakeroot
fio
gdb
@@ -23,21 +26,26 @@ libelf-dev
libffi-dev
libmount-dev
libpam0g-dev
-libselinux-dev
+libselinux1-dev
libssl-dev
libtool
libudev-dev
+linux-headers-generic
lsscsi
mdadm
nfs-kernel-server
pamtester
parted
+po-debconf
python3
+python3-all-dev
python3-cffi
python3-dev
python3-packaging
+python3-pip
python3-setuptools
-rng-tools
+python3-sphinx
+rng-tools-debian
rsync
samba
sysstat
diff --git a/.github/workflows/checkstyle-dependencies.txt b/.github/workflows/checkstyle-dependencies.txt
new file mode 100644
index 000000000000..879d3dbc5553
--- /dev/null
+++ b/.github/workflows/checkstyle-dependencies.txt
@@ -0,0 +1,5 @@
+cppcheck
+devscripts
+mandoc
+pax-utils
+shellcheck
diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml
index 8dafdcf07fed..abcb358fc04f 100644
--- a/.github/workflows/checkstyle.yaml
+++ b/.github/workflows/checkstyle.yaml
@@ -6,16 +6,19 @@ on:
jobs:
checkstyle:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies
run: |
- sudo apt-get update
+ # https://github.com/orgs/community/discussions/47863
+ sudo apt-mark hold grub-efi-amd64-signed
+ sudo apt-get update --fix-missing
+ sudo apt-get upgrade
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq
- sudo apt-get install -qq mandoc cppcheck pax-utils devscripts
+ sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/checkstyle-dependencies.txt apt-get install -qq
sudo python3 -m pip install --quiet flake8
sudo apt-get clean
@@ -49,7 +52,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@v4
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/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000000..e015b2cb71d9
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,41 @@
+name: "CodeQL"
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'cpp', 'python' ]
+
+ steps:
+ - name: Set make jobs
+ run: |
+ echo "MAKEFLAGS=-j$(nproc)" >> $GITHUB_ENV
+
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ config-file: .github/codeql-${{ matrix.language }}.yml
+ languages: ${{ matrix.language }}
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/scripts/generate-summary.sh b/.github/workflows/scripts/generate-summary.sh
new file mode 100755
index 000000000000..b5d89208a5d8
--- /dev/null
+++ b/.github/workflows/scripts/generate-summary.sh
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+
+# for runtime reasons we split functional testings into N parts
+# - use a define to check for missing tarfiles
+FUNCTIONAL_PARTS="4"
+
+ZTS_REPORT="tests/test-runner/bin/zts-report.py"
+chmod +x $ZTS_REPORT
+
+function output() {
+ echo -e $* >> Summary.md
+}
+
+function error() {
+ output ":bangbang: $* :bangbang:\n"
+}
+
+# this function generates the real summary
+# - expects a logfile "log" in current directory
+function generate() {
+ # we issued some error already
+ test ! -s log && return
+
+ # for overview and zts-report
+ cat log | grep '^Test' > list
+
+ # error details
+ awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }
+ /\[SKIP\]|\[PASS\]/{ show=0; } show' log > err
+
+ # summary of errors
+ if [ -s err ]; then
+ output "<pre>"
+ $ZTS_REPORT --no-maybes ./list >> Summary.md
+ output "</pre>"
+
+ # generate seperate error logfile
+ ERRLOGS=$((ERRLOGS+1))
+ errfile="err-$ERRLOGS.md"
+ echo -e "\n## $headline (debugging)\n" >> $errfile
+ echo "<details><summary>Error Listing - with dmesg and dbgmsg</summary><pre>" >> $errfile
+ dd if=err bs=999k count=1 >> $errfile
+ echo "</pre></details>" >> $errfile
+ else
+ output "All tests passed :thumbsup:"
+ fi
+
+ output "<details><summary>Full Listing</summary><pre>"
+ cat list >> Summary.md
+ output "</pre></details>"
+
+ # remove tmp files
+ rm -f err list log
+}
+
+# check tarfiles and untar
+function check_tarfile() {
+ if [ -f "$1" ]; then
+ tar xf "$1" || error "Tarfile $1 returns some error"
+ else
+ error "Tarfile $1 not found"
+ fi
+}
+
+# check logfile and concatenate test results
+function check_logfile() {
+ if [ -f "$1" ]; then
+ cat "$1" >> log
+ else
+ error "Logfile $1 not found"
+ fi
+}
+
+# sanity
+function summarize_s() {
+ headline="$1"
+ output "\n## $headline\n"
+ rm -rf testfiles
+ check_tarfile "$2/sanity.tar"
+ check_logfile "testfiles/log"
+ generate
+}
+
+# functional
+function summarize_f() {
+ headline="$1"
+ output "\n## $headline\n"
+ rm -rf testfiles
+ for i in $(seq 1 $FUNCTIONAL_PARTS); do
+ tarfile="$2-part$i/part$i.tar"
+ check_tarfile "$tarfile"
+ check_logfile "testfiles/log"
+ done
+ generate
+}
+
+# https://docs.github.com/en/enterprise-server@3.6/actions/using-workflows/workflow-commands-for-github-actions#step-isolation-and-limits
+# Job summaries are isolated between steps and each step is restricted to a maximum size of 1MiB.
+# [ ] can not show all error findings here
+# [x] split files into smaller ones and create additional steps
+
+ERRLOGS=0
+if [ ! -f Summary/Summary.md ]; then
+ # first call, we do the default summary (~500k)
+ echo -n > Summary.md
+ summarize_s "Sanity Tests Ubuntu 20.04" Logs-20.04-sanity
+ summarize_s "Sanity Tests Ubuntu 22.04" Logs-22.04-sanity
+ summarize_f "Functional Tests Ubuntu 20.04" Logs-20.04-functional
+ summarize_f "Functional Tests Ubuntu 22.04" Logs-22.04-functional
+
+ cat Summary.md >> $GITHUB_STEP_SUMMARY
+ mkdir -p Summary
+ mv *.md Summary
+else
+ # here we get, when errors where returned in first call
+ test -f Summary/err-$1.md && cat Summary/err-$1.md >> $GITHUB_STEP_SUMMARY
+fi
+
+exit 0
diff --git a/.github/workflows/scripts/reclaim_disk_space.sh b/.github/workflows/scripts/reclaim_disk_space.sh
deleted file mode 100755
index cc16a9079317..000000000000
--- a/.github/workflows/scripts/reclaim_disk_space.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-set -eu
-
-# remove 4GiB of images
-sudo systemd-run docker system prune --force --all --volumes
-
-# remove unused software
-sudo systemd-run rm -rf \
- "$AGENT_TOOLSDIRECTORY" \
- /opt/* \
- /usr/local/* \
- /usr/share/az* \
- /usr/share/dotnet \
- /usr/share/gradle* \
- /usr/share/miniconda \
- /usr/share/swift \
- /var/lib/gems \
- /var/lib/mysql \
- /var/lib/snapd
diff --git a/.github/workflows/scripts/setup-dependencies.sh b/.github/workflows/scripts/setup-dependencies.sh
new file mode 100755
index 000000000000..b40f9290f914
--- /dev/null
+++ b/.github/workflows/scripts/setup-dependencies.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+set -eu
+
+function prerun() {
+ echo "::group::Install build dependencies"
+ # remove snap things, update+upgrade will be faster then
+ for x in lxd core20 snapd; do sudo snap remove $x; done
+ sudo apt-get purge snapd google-chrome-stable firefox
+ # https://github.com/orgs/community/discussions/47863
+ sudo apt-get remove grub-efi-amd64-bin grub-efi-amd64-signed shim-signed --allow-remove-essential
+ sudo apt-get update
+ sudo apt upgrade
+ sudo xargs --arg-file=.github/workflows/build-dependencies.txt apt-get install -qq
+ sudo apt-get clean
+ sudo dmesg -c > /var/tmp/dmesg-prerun
+ echo "::endgroup::"
+}
+
+function mod_build() {
+ echo "::group::Generate debian packages"
+ ./autogen.sh
+ ./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan
+ make --no-print-directory --silent native-deb-utils native-deb-kmod
+ mv ../*.deb .
+ rm ./openzfs-zfs-dracut*.deb ./openzfs-zfs-dkms*.deb
+ echo "$ImageOS-$ImageVersion" > tests/ImageOS.txt
+ echo "::endgroup::"
+}
+
+function mod_install() {
+ # install the pre-built module only on the same runner image
+ MOD=`cat tests/ImageOS.txt`
+ if [ "$MOD" != "$ImageOS-$ImageVersion" ]; then
+ rm -f *.deb
+ mod_build
+ fi
+
+ echo "::group::Install and load modules"
+ # don't use kernel-shipped zfs modules
+ sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
+ sudo apt-get install --fix-missing ./*.deb
+
+ # Native Debian packages enable and start the services
+ # Stop zfs-zed daemon, as it may interfere with some ZTS test cases
+ sudo systemctl stop zfs-zed
+ sudo depmod -a
+ sudo modprobe zfs
+ sudo dmesg
+ sudo dmesg -c > /var/tmp/dmesg-module-load
+ echo "::endgroup::"
+
+ echo "::group::Report CPU information"
+ lscpu
+ cat /proc/spl/kstat/zfs/chksum_bench
+ echo "::endgroup::"
+
+ echo "::group::Optimize storage for ZFS testings"
+ # remove swap and umount fast storage
+ # 89GiB -> rootfs + bootfs with ~80MB/s -> don't care
+ # 64GiB -> /mnt with 420MB/s -> new testing ssd
+ sudo swapoff -a
+
+ # this one is fast and mounted @ /mnt
+ # -> we reformat with ext4 + move it to /var/tmp
+ DEV="/dev/disk/azure/resource-part1"
+ sudo umount /mnt
+ sudo mkfs.ext4 -O ^has_journal -F $DEV
+ sudo mount -o noatime,barrier=0 $DEV /var/tmp
+ sudo chmod 1777 /var/tmp
+
+ # disk usage afterwards
+ sudo df -h /
+ sudo df -h /var/tmp
+ sudo fstrim -a
+ echo "::endgroup::"
+}
+
+case "$1" in
+ build)
+ prerun
+ mod_build
+ ;;
+ tests)
+ prerun
+ mod_install
+ ;;
+esac
diff --git a/.github/workflows/scripts/setup-functional.sh b/.github/workflows/scripts/setup-functional.sh
new file mode 100755
index 000000000000..08c4d872abdf
--- /dev/null
+++ b/.github/workflows/scripts/setup-functional.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+set -eu
+
+TDIR="/usr/share/zfs/zfs-tests/tests/functional"
+echo -n "TODO="
+case "$1" in
+ part1)
+ # ~1h 20m
+ echo "cli_root"
+ ;;
+ part2)
+ # ~1h
+ ls $TDIR|grep '^[a-m]'|grep -v "cli_root"|xargs|tr -s ' ' ','
+ ;;
+ part3)
+ # ~1h
+ ls $TDIR|grep '^[n-qs-z]'|xargs|tr -s ' ' ','
+ ;;
+ part4)
+ # ~1h
+ ls $TDIR|grep '^r'|xargs|tr -s ' ' ','
+ ;;
+esac
diff --git a/.github/workflows/zfs-linux-tests.yml b/.github/workflows/zfs-linux-tests.yml
new file mode 100644
index 000000000000..753f3cd0214e
--- /dev/null
+++ b/.github/workflows/zfs-linux-tests.yml
@@ -0,0 +1,124 @@
+name: zfs-linux-tests
+
+on:
+ workflow_call:
+ inputs:
+ os:
+ description: 'The ubuntu version: 20.02 or 22.04'
+ required: true
+ type: string
+
+jobs:
+
+ zloop:
+ runs-on: ubuntu-${{ inputs.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ - uses: actions/download-artifact@v4
+ with:
+ name: modules-${{ inputs.os }}
+ - name: Install modules
+ run: |
+ tar xzf modules-${{ inputs.os }}.tgz
+ .github/workflows/scripts/setup-dependencies.sh tests
+ - name: Tests
+ timeout-minutes: 30
+ run: |
+ sudo mkdir -p /var/tmp/zloop
+ # run for 10 minutes or at most 2 iterations for a maximum runner
+ # time of 20 minutes.
+ sudo /usr/share/zfs/zloop.sh -t 600 -I 2 -l -m1 -- -T 120 -P 60
+ - name: Prepare artifacts
+ if: failure()
+ run: |
+ sudo chmod +r -R /var/tmp/zloop/
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: Zpool-logs-${{ inputs.os }}
+ path: |
+ /var/tmp/zloop/*/
+ !/var/tmp/zloop/*/vdev/
+ retention-days: 14
+ if-no-files-found: ignore
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: Zpool-files-${{ inputs.os }}
+ path: |
+ /var/tmp/zloop/*/vdev/
+ retention-days: 14
+ if-no-files-found: ignore
+
+ sanity:
+ runs-on: ubuntu-${{ inputs.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ - uses: actions/download-artifact@v4
+ with:
+ name: modules-${{ inputs.os }}
+ - name: Install modules
+ run: |
+ tar xzf modules-${{ inputs.os }}.tgz
+ .github/workflows/scripts/setup-dependencies.sh tests
+ - name: Tests
+ timeout-minutes: 60
+ shell: bash
+ run: |
+ set -o pipefail
+ /usr/share/zfs/zfs-tests.sh -vKR -s 3G -r sanity | scripts/zfs-tests-color.sh
+ - name: Prepare artifacts
+ if: success() || failure()
+ run: |
+ RESPATH="/var/tmp/test_results"
+ mv -f $RESPATH/current $RESPATH/testfiles
+ tar cf $RESPATH/sanity.tar -h -C $RESPATH testfiles
+ - uses: actions/upload-artifact@v4
+ if: success() || failure()
+ with:
+ name: Logs-${{ inputs.os }}-sanity
+ path: /var/tmp/test_results/sanity.tar
+ if-no-files-found: ignore
+
+ functional:
+ runs-on: ubuntu-${{ inputs.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ tests: [ part1, part2, part3, part4 ]
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ - uses: actions/download-artifact@v4
+ with:
+ name: modules-${{ inputs.os }}
+ - name: Install modules
+ run: |
+ tar xzf modules-${{ inputs.os }}.tgz
+ .github/workflows/scripts/setup-dependencies.sh tests
+ - name: Setup tests
+ run: |
+ .github/workflows/scripts/setup-functional.sh ${{ matrix.tests }} >> $GITHUB_ENV
+ - name: Tests
+ timeout-minutes: 120
+ shell: bash
+ run: |
+ set -o pipefail
+ /usr/share/zfs/zfs-tests.sh -vKR -s 3G -T ${{ env.TODO }} | scripts/zfs-tests-color.sh
+ - name: Prepare artifacts
+ if: success() || failure()
+ run: |
+ RESPATH="/var/tmp/test_results"
+ mv -f $RESPATH/current $RESPATH/testfiles
+ tar cf $RESPATH/${{ matrix.tests }}.tar -h -C $RESPATH testfiles
+ - uses: actions/upload-artifact@v4
+ if: success() || failure()
+ with:
+ name: Logs-${{ inputs.os }}-functional-${{ matrix.tests }}
+ path: /var/tmp/test_results/${{ matrix.tests }}.tar
+ if-no-files-found: ignore
diff --git a/.github/workflows/zfs-linux.yml b/.github/workflows/zfs-linux.yml
new file mode 100644
index 000000000000..e6b705c86055
--- /dev/null
+++ b/.github/workflows/zfs-linux.yml
@@ -0,0 +1,64 @@
+name: zfs-linux
+
+on:
+ push:
+ pull_request:
+
+jobs:
+
+ build:
+ name: Build
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [20.04, 22.04]
+ runs-on: ubuntu-${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ - name: Build modules
+ run: .github/workflows/scripts/setup-dependencies.sh build
+ - name: Prepare modules upload
+ run: tar czf modules-${{ matrix.os }}.tgz *.deb .github tests/test-runner tests/ImageOS.txt
+ - uses: actions/upload-artifact@v4
+ with:
+ name: modules-${{ matrix.os }}
+ path: modules-${{ matrix.os }}.tgz
+ retention-days: 14
+
+ testings:
+ name: Testing
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [20.04, 22.04]
+ needs: build
+ uses: ./.github/workflows/zfs-linux-tests.yml
+ with:
+ os: ${{ matrix.os }}
+
+ cleanup:
+ if: always()
+ name: Cleanup
+ runs-on: ubuntu-22.04
+ needs: testings
+ steps:
+ - uses: actions/download-artifact@v4
+ - name: Generating summary
+ run: |
+ tar xzf modules-22.04/modules-22.04.tgz .github tests
+ .github/workflows/scripts/generate-summary.sh
+ # up to 4 steps, each can have 1 MiB output (for debugging log files)
+ - name: Summary for errors #1
+ run: .github/workflows/scripts/generate-summary.sh 1
+ - name: Summary for errors #2
+ run: .github/workflows/scripts/generate-summary.sh 2
+ - name: Summary for errors #3
+ run: .github/workflows/scripts/generate-summary.sh 3
+ - name: Summary for errors #4
+ run: .github/workflows/scripts/generate-summary.sh 4
+ - uses: actions/upload-artifact@v4
+ with:
+ name: Summary Files
+ path: Summary/
diff --git a/.github/workflows/zfs-tests-functional.yml b/.github/workflows/zfs-tests-functional.yml
deleted file mode 100644
index 328cb97f10e4..000000000000
--- a/.github/workflows/zfs-tests-functional.yml
+++ /dev/null
@@ -1,82 +0,0 @@
-name: zfs-tests-functional
-
-on:
- push:
- pull_request:
-
-jobs:
- tests-functional-ubuntu:
- strategy:
- fail-fast: false
- matrix:
- os: [18.04, 20.04]
- runs-on: ubuntu-${{ matrix.os }}
- steps:
- - uses: actions/checkout@v2
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- - name: Reclaim disk space
- run: |
- ${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
- - name: Install dependencies
- run: |
- sudo apt-get update
- xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt sudo apt-get install -qq
- sudo apt-get clean
- - name: Autogen.sh
- run: |
- ./autogen.sh
- - name: Configure
- run: |
- ./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan --with-config=dist
- - name: Make
- run: |
- make -j$(nproc) --no-print-directory --silent pkg-utils pkg-kmod
- - name: Install
- run: |
- sudo dpkg -i *.deb
- # Update order of directories to search for modules, otherwise
- # Ubuntu will load kernel-shipped ones.
- sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
- sudo depmod
- sudo modprobe zfs
- # Workaround for cloud-init bug
- # see https://github.com/openzfs/zfs/issues/12644
- FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules
- if [ -r "${FILE}" ]; then
- HASH=$(md5sum "${FILE}" | awk '{ print $1 }')
- if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then
- # Just shove a zd* exclusion right above the hotplug hook...
- sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
- sudo udevadm control --reload-rules
- fi
- fi
- - name: Clear the kernel ring buffer
- run: |
- sudo dmesg -c >/var/tmp/dmesg-prerun
- - name: Report disk space
- run: |
- df -h /
- - name: Tests
- run: |
- set -o pipefail
- /usr/share/zfs/zfs-tests.sh -vKR -s 3G | scripts/zfs-tests-color.sh
- shell: bash
- timeout-minutes: 330
- - name: Prepare artifacts
- if: failure()
- run: |
- RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
- sudo dmesg > $RESULTS_PATH/dmesg
- sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/
- 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
- if: failure()
- with:
- name: Test logs Ubuntu-${{ matrix.os }}
- path: |
- /var/tmp/test_results/*
- !/var/tmp/test_results/current
- if-no-files-found: ignore
diff --git a/.github/workflows/zfs-tests-sanity.yml b/.github/workflows/zfs-tests-sanity.yml
deleted file mode 100644
index 4c15cecf58d8..000000000000
--- a/.github/workflows/zfs-tests-sanity.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: zfs-tests-sanity
-
-on:
- push:
- pull_request:
-
-jobs:
- tests:
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v2
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- - name: Reclaim disk space
- run: |
- ${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
- - name: Install dependencies
- run: |
- sudo apt-get update
- xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt sudo apt-get install -qq
- sudo apt-get clean
- - name: Autogen.sh
- run: |
- ./autogen.sh
- - name: Configure
- run: |
- ./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan --with-config=dist
- - name: Make
- run: |
- make -j$(nproc) --no-print-directory --silent pkg-utils pkg-kmod
- - name: Install
- run: |
- sudo dpkg -i *.deb
- # Update order of directories to search for modules, otherwise
- # Ubuntu will load kernel-shipped ones.
- sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
- sudo depmod
- sudo modprobe zfs
- # Workaround for cloud-init bug
- # see https://github.com/openzfs/zfs/issues/12644
- FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules
- if [ -r "${FILE}" ]; then
- HASH=$(md5sum "${FILE}" | awk '{ print $1 }')
- if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then
- # Just shove a zd* exclusion right above the hotplug hook...
- sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
- sudo udevadm control --reload-rules
- fi
- fi
- - name: Clear the kernel ring buffer
- run: |
- sudo dmesg -c >/var/tmp/dmesg-prerun
- - name: Report disk space
- run: |
- df -h /
- - name: Tests
- run: |
- set -o pipefail
- /usr/share/zfs/zfs-tests.sh -vKR -s 3G -r sanity | scripts/zfs-tests-color.sh
- shell: bash
- timeout-minutes: 330
- - name: Prepare artifacts
- if: failure()
- run: |
- RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
- sudo dmesg > $RESULTS_PATH/dmesg
- sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/
- 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
- if: failure()
- with:
- name: Test logs Ubuntu-${{ matrix.os }}
- path: |
- /var/tmp/test_results/*
- !/var/tmp/test_results/current
- if-no-files-found: ignore
diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml
deleted file mode 100644
index 64fe96a3ab6b..000000000000
--- a/.github/workflows/zloop.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-name: zloop
-
-on:
- push:
- pull_request:
-
-jobs:
- tests:
- runs-on: ubuntu-20.04
- env:
- TEST_DIR: /var/tmp/zloop
- steps:
- - uses: actions/checkout@v2
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- - name: Install dependencies
- run: |
- sudo apt-get update
- xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt sudo apt-get install -qq
- sudo apt-get clean
- - name: Autogen.sh
- run: |
- ./autogen.sh
- - name: Configure
- run: |
- ./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan --with-config=dist
- - name: Make
- run: |
- make -j$(nproc) --no-print-directory --silent pkg-utils pkg-kmod
- - name: Install
- run: |
- sudo dpkg -i *.deb
- # Update order of directories to search for modules, otherwise
- # Ubuntu will load kernel-shipped ones.
- sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
- sudo depmod
- sudo modprobe zfs
- - name: Tests
- run: |
- sudo mkdir -p $TEST_DIR
- # run for 10 minutes or at most 2 iterations for a maximum runner
- # time of 20 minutes.
- sudo /usr/share/zfs/zloop.sh -t 600 -I 2 -l -m1 -- -T 120 -P 60
- - name: Prepare artifacts
- if: failure()
- run: |
- sudo chmod +r -R $TEST_DIR/
- - uses: actions/upload-artifact@v2
- if: failure()
- with:
- name: Logs
- path: |
- /var/tmp/zloop/*/
- !/var/tmp/zloop/*/vdev/
- if-no-files-found: ignore
- - uses: actions/upload-artifact@v2
- if: failure()
- with:
- name: Pool files
- path: |
- /var/tmp/zloop/*/vdev/
- if-no-files-found: ignore
diff --git a/.gitignore b/.gitignore
index 8d91dd9466c5..a2cb92dd5406 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,8 +42,10 @@
!udev/**
!.editorconfig
+!.cirrus.yml
!.gitignore
!.gitmodules
+!.mailmap
!AUTHORS
!autogen.sh
!CODE_OF_CONDUCT.md
@@ -60,7 +62,6 @@
!TEST
!zfs.release.in
-
#
# Normal rules
#
@@ -82,6 +83,7 @@
modules.order
Makefile
Makefile.in
+changelog
*.patch
*.orig
*.tmp
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 000000000000..32bdb5209613
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,207 @@
+# This file maps the name+email seen in a commit back to a canonical
+# name+email. Git will replace the commit name/email with the canonical version
+# wherever it sees it.
+#
+# If there is a commit in the history with a "wrong" name or email, list it
+# here. If you regularly commit with an alternate name or email address and
+# would like to ensure that you are always listed consistently in the repo, add
+# mapping here.
+#
+# On the other hand, if you use multiple names or email addresses legitimately
+# (eg you use a company email address for your paid OpenZFS work, and a
+# personal address for your evening side projects), then don't map one to the
+# other here.
+#
+# The most common formats are:
+#
+# Canonical Name <canonical-email>
+# Canonical Name <canonical-email> <commit-email>
+# Canonical Name <canonical-email> Commit Name <commit-email>
+#
+# See https://git-scm.com/docs/gitmailmap for more info.
+
+# These maps are making names consistent where they have varied but the email
+# address has never changed. In most cases, the full name is in the
+# Signed-off-by of a commit with a matching author.
+Ahelenia Ziemiańska <nabijaczleweli@gmail.com>
+Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
+Alex John <alex@stty.io>
+Andreas Dilger <adilger@dilger.ca>
+Andrew Walker <awalker@ixsystems.com>
+Benedikt Neuffer <github@itfriend.de>
+Chengfei Zhu <chengfeix.zhu@intel.com>
+ChenHao Lu <18302010006@fudan.edu.cn>
+Chris Lindee <chris.lindee+github@gmail.com>
+Colm Buckley <colm@tuatha.org>
+Crag Wang <crag0715@gmail.com>
+Damian Szuberski <szuberskidamian@gmail.com>
+Daniel Kolesa <daniel@octaforge.org>
+Debabrata Banerjee <dbavatar@gmail.com>
+Finix Yan <yanchongwen@hotmail.com>
+Gaurav Kumar <gauravk.18@gmail.com>
+Gionatan Danti <g.danti@assyoma.it>
+Glenn Washburn <development@efficientek.com>
+Gordan Bobic <gordan.bobic@gmail.com>
+Gregory Bartholomew <gregory.lee.bartholomew@gmail.com>
+hedong zhang <h_d_zhang@163.com>
+Ilkka Sovanto <github@ilkka.kapsi.fi>
+InsanePrawn <Insane.Prawny@gmail.com>
+Jason Cohen <jwittlincohen@gmail.com>
+Jason Harmening <jason.harmening@gmail.com>
+Jeremy Faulkner <gldisater@gmail.com>
+Jinshan Xiong <jinshan.xiong@gmail.com>
+John Poduska <jpoduska@datto.com>
+Justin Scholz <git@justinscholz.de>
+Ka Ho Ng <khng300@gmail.com>
+Kash Pande <github@tripleback.net>
+Kay Pedersen <christianpe96@gmail.com>
+KernelOfTruth <kerneloftruth@gmail.com>
+Liu Hua <liu.hua130@zte.com.cn>
+Liu Qing <winglq@gmail.com>
+loli10K <ezomori.nozomu@gmail.com>
+Mart Frauenlob <allkind@fastest.cc>
+Matthias Blankertz <matthias@blankertz.org>
+Michael Gmelin <grembo@FreeBSD.org>
+Olivier Mazouffre <olivier.mazouffre@ims-bordeaux.fr>
+Piotr Kubaj <pkubaj@anongoth.pl>
+Quentin Zdanis <zdanisq@gmail.com>
+Roberto Ricci <ricci@disroot.org>
+Rob Norris <robn@despairlabs.com>
+Rob Norris <rob.norris@klarasystems.com>
+Sam Lunt <samuel.j.lunt@gmail.com>
+Sanjeev Bagewadi <sanjeev.bagewadi@gmail.com>
+Stoiko Ivanov <github@nomore.at>
+Tamas TEVESZ <ice@extreme.hu>
+WHR <msl0000023508@gmail.com>
+Yanping Gao <yanping.gao@xtaotech.com>
+Youzhong Yang <youzhong@gmail.com>
+
+# Signed-off-by: overriding Author:
+Yuxin Wang <yuxinwang9999@gmail.com> <Bi11gates9999@gmail.com>
+
+# Commits from strange places, long ago
+Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
+Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@fedora-17-amd64.(none)>
+Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@myhost.(none)>
+Brian Behlendorf <behlendorf1@llnl.gov> <ubuntu@ip-172-31-16-145.us-west-1.compute.internal>
+Brian Behlendorf <behlendorf1@llnl.gov> <ubuntu@ip-172-31-20-6.us-west-1.compute.internal>
+Herb Wartens <wartens2@llnl.gov> <wartens2@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
+Ned Bass <bass6@llnl.gov> <bass6@zeno1.(none)>
+Tulsi Jain <tulsi.jain@delphix.com> <tulsi.jain@Tulsi-Jains-MacBook-Pro.local>
+
+# Mappings from Github no-reply addresses
+ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com>
+Alek Pinchuk <apinchuk@axcient.com> <alek-p@users.noreply.github.com>
+Alexander Lobakin <alobakin@pm.me> <solbjorn@users.noreply.github.com>
+Alexey Smirnoff <fling@member.fsf.org> <fling-@users.noreply.github.com>
+Allen Holl <allen.m.holl@gmail.com> <65494904+allen-4@users.noreply.github.com>
+Ameer Hamza <ahamza@ixsystems.com> <106930537+ixhamza@users.noreply.github.com>
+Andrew J. Hesford <ajh@sideband.org> <48421688+ahesford@users.noreply.github.com>>
+Andrew Sun <me@andrewsun.com> <as-com@users.noreply.github.com>
+Aron Xu <happyaron.xu@gmail.com> <happyaron@users.noreply.github.com>
+Arun KV <arun.kv@datacore.com> <65647132+arun-kv@users.noreply.github.com>
+Ben Wolsieffer <benwolsieffer@gmail.com> <lopsided98@users.noreply.github.com>
+bernie1995 <bernie.pikes@gmail.com> <42413912+bernie1995@users.noreply.github.com>
+Boris Protopopov <boris.protopopov@actifio.com> <bprotopopov@users.noreply.github.com>
+Brad Forschinger <github@bnjf.id.au> <bnjf@users.noreply.github.com>
+Brandon Thetford <brandon@dodecatec.com> <dodexahedron@users.noreply.github.com>
+buzzingwires <buzzingwires@outlook.com> <131118055+buzzingwires@users.noreply.github.com>
+Cedric Maunoury <cedric.maunoury@gmail.com> <38213715+cedricmaunoury@users.noreply.github.com>
+Charles Suh <charles.suh@gmail.com> <charlessuh@users.noreply.github.com>
+Chris Peredun <chris.peredun@ixsystems.com> <126915832+chrisperedun@users.noreply.github.com>
+Dacian Reece-Stremtan <dacianstremtan@gmail.com> <35844628+dacianstremtan@users.noreply.github.com>
+Damian Szuberski <szuberskidamian@gmail.com> <30863496+szubersk@users.noreply.github.com>
+Daniel Hiepler <d-git@coderdu.de> <32984777+heeplr@users.noreply.github.com>
+Daniel Kobras <d.kobras@science-computing.de> <sckobras@users.noreply.github.com>
+Daniel Reichelt <hacking@nachtgeist.net> <nachtgeist@users.noreply.github.com>
+David Quigley <david.quigley@intel.com> <dpquigl@users.noreply.github.com>
+Dennis R. Friedrichsen <dennis.r.friedrichsen@gmail.com> <31087738+dennisfriedrichsen@users.noreply.github.com>
+Dex Wood <slash2314@gmail.com> <slash2314@users.noreply.github.com>
+DHE <git@dehacked.net> <DeHackEd@users.noreply.github.com>
+Dmitri John Ledkov <dimitri.ledkov@canonical.com> <19779+xnox@users.noreply.github.com>
+Dries Michiels <driesm.michiels@gmail.com> <32487486+driesmp@users.noreply.github.com>
+Edmund Nadolski <edmund.nadolski@ixsystems.com> <137826107+ednadolski-ix@users.noreply.github.com>
+Érico Nogueira <erico.erc@gmail.com> <34201958+ericonr@users.noreply.github.com>
+Fedor Uporov <fuporov.vstack@gmail.com> <60701163+fuporovvStack@users.noreply.github.com>
+Felix Dörre <felix@dogcraft.de> <felixdoerre@users.noreply.github.com>
+Felix Neumärker <xdch47@posteo.de> <34678034+xdch47@users.noreply.github.com>
+Finix Yan <yancw@info2soft.com> <Finix1979@users.noreply.github.com>
+Gaurav Kumar <gauravk.18@gmail.com> <gaurkuma@users.noreply.github.com>
+George Gaydarov <git@gg7.io> <gg7@users.noreply.github.com>
+Georgy Yakovlev <gyakovlev@gentoo.org> <168902+gyakovlev@users.noreply.github.com>
+Gerardwx <gerardw@alum.mit.edu> <Gerardwx@users.noreply.github.com>
+Gian-Carlo DeFazio <defazio1@llnl.gov> <defaziogiancarlo@users.noreply.github.com>
+Giuseppe Di Natale <dinatale2@llnl.gov> <dinatale2@users.noreply.github.com>
+Hajo Möller <dasjoe@gmail.com> <dasjoe@users.noreply.github.com>
+Harry Mallon <hjmallon@gmail.com> <1816667+hjmallon@users.noreply.github.com>
+Hiếu Lê <leorize+oss@disroot.org> <alaviss@users.noreply.github.com>
+Jake Howard <git@theorangeone.net> <RealOrangeOne@users.noreply.github.com>
+James Cowgill <james.cowgill@mips.com> <jcowgill@users.noreply.github.com>
+Jaron Kent-Dobias <jaron@kent-dobias.com> <kentdobias@users.noreply.github.com>
+Jason King <jason.king@joyent.com> <jasonbking@users.noreply.github.com>
+Jeff Dike <jdike@akamai.com> <52420226+jdike@users.noreply.github.com>
+Jitendra Patidar <jitendra.patidar@nutanix.com> <53164267+jsai20@users.noreply.github.com>
+João Carlos Mendes Luís <jonny@jonny.eng.br> <dioni21@users.noreply.github.com>
+John Eismeier <john.eismeier@gmail.com> <32205350+jeis2497052@users.noreply.github.com>
+John L. Hammond <john.hammond@intel.com> <35266395+jhammond-intel@users.noreply.github.com>
+John-Mark Gurney <jmg@funkthat.com> <jmgurney@users.noreply.github.com>
+John Ramsden <johnramsden@riseup.net> <johnramsden@users.noreply.github.com>
+Jonathon Fernyhough <jonathon@m2x.dev> <559369+jonathonf@users.noreply.github.com>
+Jose Luis Duran <jlduran@gmail.com> <jlduran@users.noreply.github.com>
+Justin Hibbits <chmeeedalf@gmail.com> <chmeeedalf@users.noreply.github.com>
+Kevin Greene <kevin.greene@delphix.com> <104801862+kxgreene@users.noreply.github.com>
+Kevin Jin <lostking2008@hotmail.com> <33590050+jxdking@users.noreply.github.com>
+Kevin P. Fleming <kevin@km6g.us> <kpfleming@users.noreply.github.com>
+Krzysztof Piecuch <piecuch@kpiecuch.pl> <3964215+pikrzysztof@users.noreply.github.com>
+Kyle Evans <kevans@FreeBSD.org> <kevans91@users.noreply.github.com>
+Laurențiu Nicola <lnicola@dend.ro> <lnicola@users.noreply.github.com>
+loli10K <ezomori.nozomu@gmail.com> <loli10K@users.noreply.github.com>
+Lorenz Hüdepohl <dev@stellardeath.org> <lhuedepohl@users.noreply.github.com>
+Luís Henriques <henrix@camandro.org> <73643340+lumigch@users.noreply.github.com>
+Marcin Skarbek <git@skarbek.name> <mskarbek@users.noreply.github.com>
+Matt Fiddaman <github@m.fiddaman.uk> <81489167+matt-fidd@users.noreply.github.com>
+Maxim Filimonov <che@bein.link> <part1zano@users.noreply.github.com>
+Max Zettlmeißl <max@zettlmeissl.de> <6818198+maxz@users.noreply.github.com>
+Michael Niewöhner <foss@mniewoehner.de> <c0d3z3r0@users.noreply.github.com>
+Michael Zhivich <mzhivich@akamai.com> <33133421+mzhivich@users.noreply.github.com>
+MigeljanImeri <ImeriMigel@gmail.com> <78048439+MigeljanImeri@users.noreply.github.com>
+Mo Zhou <cdluminate@gmail.com> <5723047+cdluminate@users.noreply.github.com>
+Nick Mattis <nickm970@gmail.com> <nmattis@users.noreply.github.com>
+omni <omni+vagant@hack.org> <79493359+omnivagant@users.noreply.github.com>
+Pablo Correa Gómez <ablocorrea@hotmail.com> <32678034+pablofsf@users.noreply.github.com>
+Paul Zuchowski <pzuchowski@datto.com> <31706010+PaulZ-98@users.noreply.github.com>
+Peter Ashford <ashford@accs.com> <pashford@users.noreply.github.com>
+Peter Dave Hello <hsu@peterdavehello.org> <PeterDaveHello@users.noreply.github.com>
+Peter Wirdemo <peter.wirdemo@gmail.com> <4224155+pewo@users.noreply.github.com>
+Petros Koutoupis <petros@petroskoutoupis.com> <pkoutoupis@users.noreply.github.com>
+Ping Huang <huangping@smartx.com> <101400146+hpingfs@users.noreply.github.com>
+Piotr P. Stefaniak <pstef@freebsd.org> <pstef@users.noreply.github.com>
+Richard Allen <belperite@gmail.com> <33836503+belperite@users.noreply.github.com>
+Rich Ercolani <rincebrain@gmail.com> <214141+rincebrain@users.noreply.github.com>
+Rick Macklem <rmacklem@uoguelph.ca> <64620010+rmacklem@users.noreply.github.com>
+Rob Wing <rob.wing@klarasystems.com> <98866084+rob-wing@users.noreply.github.com>
+Roman Strashkin <roman.strashkin@nexenta.com> <Ramzec@users.noreply.github.com>
+Ryan Hirasaki <ryanhirasaki@gmail.com> <4690732+RyanHir@users.noreply.github.com>
+Samuel Wycliffe J <samwyc@hpe.com> <115969550+samwyc@users.noreply.github.com>
+Samuel Wycliffe <samuelwycliffe@gmail.com> <50765275+npc203@users.noreply.github.com>
+Savyasachee Jha <hi@savyasacheejha.com> <savyajha@users.noreply.github.com>
+Scott Colby <scott@scolby.com> <scolby33@users.noreply.github.com>
+Sean Eric Fagan <kithrup@mac.com> <kithrup@users.noreply.github.com>
+Spencer Kinny <spencerkinny1995@gmail.com> <30333052+Spencer-Kinny@users.noreply.github.com>
+Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com> <75025422+nssrikanth@users.noreply.github.com>
+Stefan Lendl <s.lendl@proxmox.com> <1321542+stfl@users.noreply.github.com>
+Thomas Bertschinger <bertschinger@lanl.gov> <101425190+bertschinger@users.noreply.github.com>
+Thomas Geppert <geppi@digitx.de> <geppi@users.noreply.github.com>
+Tim Crawford <tcrawford@datto.com> <crawfxrd@users.noreply.github.com>
+Tom Matthews <tom@axiom-partners.com> <tomtastic@users.noreply.github.com>
+Tony Perkins <tperkins@datto.com> <62951051+tony-zfs@users.noreply.github.com>
+Torsten Wörtwein <twoertwein@gmail.com> <twoertwein@users.noreply.github.com>
+Tulsi Jain <tulsi.jain@delphix.com> <TulsiJain@users.noreply.github.com>
+Václav Skála <skala@vshosting.cz> <33496485+vaclavskala@users.noreply.github.com>
+Vaibhav Bhanawat <vaibhav.bhanawat@delphix.com> <88050553+vaibhav-delphix@users.noreply.github.com>
+Violet Purcell <vimproved@inventati.org> <66446404+vimproved@users.noreply.github.com>
+Vipin Kumar Verma <vipin.verma@hpe.com> <75025470+vermavipinkumar@users.noreply.github.com>
+Wolfgang Bumiller <w.bumiller@proxmox.com> <Blub@users.noreply.github.com>
+xtouqh <xtouqh@hotmail.com> <72357159+xtouqh@users.noreply.github.com>
+Yuri Pankov <yuripv@FreeBSD.org> <113725409+yuripv@users.noreply.github.com>
+Yuri Pankov <yuripv@FreeBSD.org> <82001006+yuripv@users.noreply.github.com>
diff --git a/AUTHORS b/AUTHORS
index 86083ba87715..d7d55f42d2e7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -10,300 +10,650 @@ PAST MAINTAINERS:
CONTRIBUTORS:
Aaron Fineman <abyxcos@gmail.com>
+ Adam D. Moss <c@yotes.com>
Adam Leventhal <ahl@delphix.com>
Adam Stevko <adam.stevko@gmail.com>
+ adisbladis <adis@blad.is>
+ Adrian Chadd <adrian@freebsd.org>
+ Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Ahmed G <ahmedg@delphix.com>
+ Aidan Harris <me@aidanharr.is>
+ AJ Jordan <alex@strugee.net>
+ ajs124 <git@ajs124.de>
Akash Ayare <aayare@delphix.com>
+ Akash B <akash-b@hpe.com>
Alan Somers <asomers@gmail.com>
Alar Aun <spamtoaun@gmail.com>
Albert Lee <trisk@nexenta.com>
Alec Salazar <alec.j.salazar@gmail.com>
+ Alejandro Colomar <Colomar.6.4.3@GMail.com>
Alejandro R. Sedeño <asedeno@mit.edu>
Alek Pinchuk <alek@nexenta.com>
- Alex Braunegg <alex.braunegg@gmail.com>
- Alex McWhirter <alexmcwhirter@triadic.us>
- Alex Reece <alex@delphix.com>
- Alex Wilson <alex.wilson@joyent.com>
- Alex Zhuravlev <alexey.zhuravlev@intel.com>
+ Aleksa Sarai <cyphar@cyphar.com>
Alexander Eremin <a.eremin@nexenta.com>
+ Alexander Lobakin <alobakin@pm.me>
Alexander Motin <mav@freebsd.org>
Alexander Pyhalov <apyhalov@gmail.com>
+ Alexander Richardson <Alexander.Richardson@cl.cam.ac.uk>
Alexander Stetsenko <ams@nexenta.com>
+ Alex Braunegg <alex.braunegg@gmail.com>
Alexey Shvetsov <alexxy@gentoo.org>
Alexey Smirnoff <fling@member.fsf.org>
+ Alex John <alex@stty.io>
+ Alex McWhirter <alexmcwhirter@triadic.us>
+ Alex Reece <alex@delphix.com>
+ Alex Wilson <alex.wilson@joyent.com>
+ Alex Zhuravlev <alexey.zhuravlev@intel.com>
Allan Jude <allanjude@freebsd.org>
+ Allen Holl <allen.m.holl@gmail.com>
+ alteriks <alteriks@gmail.com>
+ Alyssa Ross <hi@alyssa.is>
+ Ameer Hamza <ahamza@ixsystems.com>
+ Anatoly Borodin <anatoly.borodin@gmail.com>
AndCycle <andcycle@andcycle.idv.tw>
+ Andrea Gelmini <andrea.gelmini@gelma.net>
+ Andrea Righi <andrea.righi@canonical.com>
Andreas Buschmann <andreas.buschmann@tech.net.de>
Andreas Dilger <adilger@intel.com>
+ Andreas Vögele <andreas@andreasvoegele.com>
Andrew Barnes <barnes333@gmail.com>
Andrew Hamilton <ahamilto@tjhsst.edu>
+ Andrew Innes <andrew.c12@gmail.com>
+ Andrew J. Hesford <ajh@sideband.org>
Andrew Reid <ColdCanuck@nailedtotheperch.com>
Andrew Stormont <andrew.stormont@nexenta.com>
+ Andrew Sun <me@andrewsun.com>
Andrew Tselischev <andrewtselischev@gmail.com>
+ Andrew Turner <andrew@fubar.geek.nz>
+ Andrew Walker <awalker@ixsystems.com>
+ Andrey Prokopenko <job@terem.fr>
Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
Andriy Gapon <avg@freebsd.org>
Andy Bakun <github@thwartedefforts.org>
+ Andy Fiddaman <omnios@citrus-it.co.uk>
Aniruddha Shankar <k@191a.net>
+ Anton Gubarkov <anton.gubarkov@gmail.com>
Antonio Russo <antonio.e.russo@gmail.com>
Arkadiusz Bubała <arkadiusz.bubala@open-e.com>
+ Armin Wehrfritz <dkxls23@gmail.com>
Arne Jansen <arne@die-jansens.de>
Aron Xu <happyaron.xu@gmail.com>
+ Arshad Hussain <arshad.hussain@aeoncomputing.com>
+ Arun KV <arun.kv@datacore.com>
+ Arvind Sankar <nivedita@alum.mit.edu>
+ Attila Fülöp <attila@fueloep.org>
+ Avatat <kontakt@avatat.pl>
Bart Coddens <bart.coddens@gmail.com>
Basil Crow <basil.crow@delphix.com>
- Huang Liu <liu.huang@zte.com.cn>
+ Bassu <bassu@phi9.com>
Ben Allen <bsallen@alcf.anl.gov>
- Ben Rubson <ben.rubson@gmail.com>
+ Ben Cordero <bencord0@condi.me>
+ Benda Xu <orv@debian.org>
+ Benedikt Neuffer <github@itfriend.de>
Benjamin Albrecht <git@albrecht.io>
+ Benjamin Gentil <benjgentil.pro@gmail.com>
+ Benjamin Sherman <benjamin@holyarmy.org>
+ Ben McGough <bmcgough@fredhutch.org>
+ Ben Rubson <ben.rubson@gmail.com>
+ Ben Wolsieffer <benwolsieffer@gmail.com>
+ bernie1995 <bernie.pikes@gmail.com>
Bill McGonigle <bill-github.com-public1@bfccomputing.com>
Bill Pijewski <wdp@joyent.com>
Boris Protopopov <boris.protopopov@nexenta.com>
+ Brad Forschinger <github@bnjf.id.au>
Brad Lewis <brad.lewis@delphix.com>
+ Brandon Thetford <brandon@dodecatec.com>
+ Brian Atkinson <bwa@g.clemson.edu>
Brian Behlendorf <behlendorf1@llnl.gov>
Brian J. Murrell <brian@sun.com>
+ Brooks Davis <brooks@one-eyed-alien.net>
+ BtbN <btbn@btbn.de>
+ bunder2015 <omfgbunder@gmail.com>
+ buzzingwires <buzzingwires@outlook.com>
+ bzzz77 <bzzz.tomas@gmail.com>
+ cable2999 <cable2999@users.noreply.github.com>
Caleb James DeLisle <calebdelisle@lavabit.com>
+ Cameron Harr <harr1@llnl.gov>
Cao Xuewen <cao.xuewen@zte.com.cn>
Carlo Landmeter <clandmeter@gmail.com>
Carlos Alberto Lopez Perez <clopez@igalia.com>
+ Cedric Maunoury <cedric.maunoury@gmail.com>
Chaoyu Zhang <zhang.chaoyu@zte.com.cn>
+ Charles Suh <charles.suh@gmail.com>
Chen Can <chen.can2@zte.com.cn>
+ Chengfei Zhu <chengfeix.zhu@intel.com>
Chen Haiquan <oc@yunify.com>
+ ChenHao Lu <18302010006@fudan.edu.cn>
Chip Parker <aparker@enthought.com>
Chris Burroughs <chris.burroughs@gmail.com>
+ Chris Davidson <christopher.davidson@gmail.com>
Chris Dunlap <cdunlap@llnl.gov>
Chris Dunlop <chris@onthe.net.au>
+ Chris Lindee <chris.lindee+github@gmail.com>
+ Chris McDonough <chrism@plope.com>
+ Chris Peredun <chris.peredun@ixsystems.com>
Chris Siden <chris.siden@delphix.com>
- Chris Wedgwood <cw@f00f.org>
- Chris Williamson <chris.williamson@delphix.com>
- Chris Zubrzycki <github@mid-earth.net>
- Christ Schlacta <aarcane@aarcane.info>
+ Chris Siebenmann <cks.github@cs.toronto.edu>
Christer Ekholm <che@chrekh.se>
Christian Kohlschütter <christian@kohlschutter.com>
Christian Neukirchen <chneukirchen@gmail.com>
Christian Schwarz <me@cschwarz.com>
Christopher Voltz <cjunk@voltz.ws>
+ Christ Schlacta <aarcane@aarcane.info>
+ Chris Wedgwood <cw@f00f.org>
+ Chris Williamson <chris.williamson@delphix.com>
+ Chris Zubrzycki <github@mid-earth.net>
+ Chuck Tuffli <ctuffli@gmail.com>
Chunwei Chen <david.chen@nutanix.com>
Clemens Fruhwirth <clemens@endorphin.org>
+ Clemens Lang <cl@clang.name>
+ Clint Armstrong <clint@clintarmstrong.net>
Coleman Kane <ckane@colemankane.org>
Colin Ian King <colin.king@canonical.com>
+ Colin Percival <cperciva@tarsnap.com>
+ Colm Buckley <colm@tuatha.org>
+ Crag Wang <crag0715@gmail.com>
Craig Loomis <cloomis@astro.princeton.edu>
Craig Sanders <github@taz.net.au>
Cyril Plisko <cyril.plisko@infinidat.com>
- DHE <git@dehacked.net>
+ Cy Schubert <cy@FreeBSD.org>
+ Cédric Berger <cedric@precidata.com>
+ Dacian Reece-Stremtan <dacianstremtan@gmail.com>
+ Dag-Erling Smørgrav <des@FreeBSD.org>
+ Damiano Albani <damiano.albani@gmail.com>
+ Damian Szuberski <szuberskidamian@gmail.com>
Damian Wojsław <damian@wojslaw.pl>
+ Daniel Berlin <dberlin@dberlin.org>
+ Daniel Hiepler <d-git@coderdu.de>
+ Daniel Hoffman <dj.hoffman@delphix.com>
+ Daniel Kobras <d.kobras@science-computing.de>
+ Daniel Kolesa <daniel@octaforge.org>
+ Daniel Reichelt <hacking@nachtgeist.net>
+ Daniel Stevenson <bot@dstev.net>
+ Daniel Verite <daniel@verite.pro>
+ Daniil Lunev <d.lunev.mail@gmail.com>
Dan Kimmel <dan.kimmel@delphix.com>
Dan McDonald <danmcd@nexenta.com>
Dan Swartzendruber <dswartz@druber.com>
Dan Vatca <dan.vatca@gmail.com>
- Daniel Hoffman <dj.hoffman@delphix.com>
- Daniel Verite <daniel@verite.pro>
- Daniil Lunev <d.lunev.mail@gmail.com>
Darik Horn <dajhorn@vanadac.com>
Dave Eddy <dave@daveeddy.com>
+ David Hedberg <david@qzx.se>
David Lamparter <equinox@diac24.net>
David Qian <david.qian@intel.com>
David Quigley <david.quigley@intel.com>
Debabrata Banerjee <dbanerje@akamai.com>
+ D. Ebdrup <debdrup@freebsd.org>
+ Dennis R. Friedrichsen <dennis.r.friedrichsen@gmail.com>
Denys Rtveliashvili <denys@rtveliashvili.name>
Derek Dai <daiderek@gmail.com>
+ Dex Wood <slash2314@gmail.com>
+ DHE <git@dehacked.net>
+ Didier Roche <didrocks@ubuntu.com>
Dimitri John Ledkov <xnox@ubuntu.com>
+ Dimitry Andric <dimitry@andric.com>
+ Dirkjan Bussink <d.bussink@gmail.com>
Dmitry Khasanov <pik4ez@gmail.com>
+ Dominic Pearson <dsp@technoanimal.net>
Dominik Hassler <hadfl@omniosce.org>
Dominik Honnef <dominikh@fork-bomb.org>
Don Brady <don.brady@delphix.com>
+ Doug Rabson <dfr@rabson.org>
Dr. András Korn <korn-github.com@elan.rulez.org>
+ Dries Michiels <driesm.michiels@gmail.com>
+ Edmund Nadolski <edmund.nadolski@ixsystems.com>
+ Eitan Adler <lists@eitanadler.com>
Eli Rosenthal <eli.rosenthal@delphix.com>
+ Eli Schwartz <eschwartz93@gmail.com>
Eric Desrochers <eric.desrochers@canonical.com>
Eric Dillmann <eric@jave.fr>
Eric Schrock <Eric.Schrock@delphix.com>
+ Ethan Coe-Renner <coerenner1@llnl.gov>
Etienne Dechamps <etienne@edechamps.fr>
+ Evan Allrich <eallrich@gmail.com>
+ Evan Harris <eharris@puremagic.com>
Evan Susarret <evansus@gmail.com>
Fabian Grünbichler <f.gruenbichler@proxmox.com>
+ Fabio Buso <dev.siroibaf@gmail.com>
+ Fabio Scaccabarozzi <fsvm88@gmail.com>
Fajar A. Nugraha <github@fajar.net>
Fan Yong <fan.yong@intel.com>
+ fbynite <fbynite@users.noreply.github.com>
+ Fedor Uporov <fuporov.vstack@gmail.com>
+ Felix Dörre <felix@dogcraft.de>
+ Felix Neumärker <xdch47@posteo.de>
Feng Sun <loyou85@gmail.com>
+ Finix Yan <yancw@info2soft.com>
+ Francesco Mazzoli <f@mazzo.li>
Frederik Wessels <wessels147@gmail.com>
Frédéric Vanniere <f.vanniere@planet-work.com>
+ Gabriel A. Devenyi <gdevenyi@gmail.com>
Garrett D'Amore <garrett@nexenta.com>
+ Garrett Fields <ghfields@gmail.com>
Garrison Jensen <garrison.jensen@gmail.com>
Gary Mills <gary_mills@fastmail.fm>
Gaurav Kumar <gauravk.18@gmail.com>
GeLiXin <ge.lixin@zte.com.cn>
George Amanakis <g_amanakis@yahoo.com>
+ George Diamantopoulos <georgediam@gmail.com>
+ George Gaydarov <git@gg7.io>
George Melikov <mail@gmelikov.ru>
George Wilson <gwilson@delphix.com>
Georgy Yakovlev <ya@sysdump.net>
+ Gerardwx <gerardw@alum.mit.edu>
+ Gian-Carlo DeFazio <defazio1@llnl.gov>
+ Gionatan Danti <g.danti@assyoma.it>
Giuseppe Di Natale <guss80@gmail.com>
+ Glenn Washburn <development@efficientek.com>
+ gofaster <felix.gofaster@gmail.com>
Gordan Bobic <gordan@redsleeve.org>
+ Gordon Bergling <gbergling@googlemail.com>
Gordon Ross <gwr@nexenta.com>
+ Gordon Tetlow <gordon@freebsd.org>
+ Graham Christensen <graham@grahamc.com>
+ Graham Perrin <grahamperrin@gmail.com>
Gregor Kopka <gregor@kopka.net>
+ Gregory Bartholomew <gregory.lee.bartholomew@gmail.com>
+ grembo <freebsd@grem.de>
Grischa Zengel <github.zfsonlinux@zengel.info>
+ grodik <pat@litke.dev>
Gunnar Beutner <gunnar@beutner.name>
Gvozden Neskovic <neskovic@gmail.com>
Hajo Möller <dasjoe@gmail.com>
+ Han Gao <rabenda.cn@gmail.com>
Hans Rosenfeld <hans.rosenfeld@nexenta.com>
+ Harald van Dijk <harald@gigawatt.nl>
+ Harry Mallon <hjmallon@gmail.com>
+ Harry Sintonen <github-piru@kyber.fi>
+ HC <mmttdebbcc@yahoo.com>
+ hedong zhang <h_d_zhang@163.com>
+ Heitor Alves de Siqueira <halves@canonical.com>
+ Henrik Riomar <henrik.riomar@gmail.com>
+ Herb Wartens <wartens2@llnl.gov>
+ Hiếu Lê <leorize+oss@disroot.org>
+ Huang Liu <liu.huang@zte.com.cn>
Håkan Johansson <f96hajo@chalmers.se>
+ Igor K <igor@dilos.org>
Igor Kozhukhov <ikozhukhov@gmail.com>
Igor Lvovsky <ilvovsky@gmail.com>
+ ilbsmart <wgqimut@gmail.com>
+ Ilkka Sovanto <github@ilkka.kapsi.fi>
+ illiliti <illiliti@protonmail.com>
+ ilovezfs <ilovezfs@icloud.com>
+ InsanePrawn <Insane.Prawny@gmail.com>
Isaac Huang <he.huang@intel.com>
- JK Dingwall <james@dingwall.me.uk>
Jacek Fefliński <feflik@gmail.com>
+ Jacob Adams <tookmund@gmail.com>
+ Jake Howard <git@theorangeone.net>
James Cowgill <james.cowgill@mips.com>
+ James H <james@kagisoft.co.uk>
James Lee <jlee@thestaticvoid.com>
James Pan <jiaming.pan@yahoo.com>
+ James Wah <james@laird-wah.net>
Jan Engelhardt <jengelh@inai.de>
Jan Kryl <jan.kryl@nexenta.com>
Jan Sanislo <oystr@cs.washington.edu>
+ Jaron Kent-Dobias <jaron@kent-dobias.com>
+ Jason Cohen <jwittlincohen@gmail.com>
+ Jason Harmening <jason.harmening@gmail.com>
Jason King <jason.brian.king@gmail.com>
+ Jason Lee <jasonlee@lanl.gov>
Jason Zaman <jasonzaman@gmail.com>
Javen Wu <wu.javen@gmail.com>
+ Jean-Baptiste Lallement <jean-baptiste@ubuntu.com>
+ Jeff Dike <jdike@akamai.com>
+ Jeremy Faulkner <gldisater@gmail.com>
Jeremy Gill <jgill@parallax-innovations.com>
Jeremy Jones <jeremy@delphix.com>
+ Jeremy Visser <jeremy.visser@gmail.com>
Jerry Jelinek <jerry.jelinek@joyent.com>
+ Jessica Clarke <jrtc27@jrtc27.com>
Jinshan Xiong <jinshan.xiong@intel.com>
+ Jitendra Patidar <jitendra.patidar@nutanix.com>
+ JK Dingwall <james@dingwall.me.uk>
Joe Stein <joe.stein@delphix.com>
+ John-Mark Gurney <jmg@funkthat.com>
John Albietz <inthecloud247@gmail.com>
John Eismeier <john.eismeier@gmail.com>
- John L. Hammond <john.hammond@intel.com>
+ John Gallagher <john.gallagher@delphix.com>
John Layman <jlayman@sagecloud.com>
+ John L. Hammond <john.hammond@intel.com>
+ John M. Layman <jml@frijid.net>
+ Johnny Stenback <github@jstenback.com>
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+ John Poduska <jpoduska@datto.com>
+ John Ramsden <johnramsden@riseup.net>
John Wren Kennedy <john.kennedy@delphix.com>
- Johnny Stenback <github@jstenback.com>
+ jokersus <lolivampireslave@gmail.com>
+ Jonathon Fernyhough <jonathon@m2x.dev>
Jorgen Lundman <lundman@lundman.net>
Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
+ Jose Luis Duran <jlduran@gmail.com>
+ Josh Soref <jsoref@users.noreply.github.com>
Joshua M. Clulow <josh@sysmgr.org>
+ José Luis Salvador Rufo <salvador.joseluis@gmail.com>
+ João Carlos Mendes Luís <jonny@jonny.eng.br>
+ Julian Brunner <julian.brunner@gmail.com>
+ Julian Heuking <JulianH@beckhoff.com>
+ jumbi77 <jumbi77@users.noreply.github.com>
Justin Bedő <cu@cua0.org>
+ Justin Gottula <justin@jgottula.com>
+ Justin Hibbits <chmeeedalf@gmail.com>
+ Justin Keogh <github.com@v6y.net>
Justin Lecher <jlec@gentoo.org>
+ Justin Scholz <git@justinscholz.de>
Justin T. Gibbs <gibbs@FreeBSD.org>
+ jyxent <jordanp@gmail.com>
Jörg Thalheim <joerg@higgsboson.tk>
- KORN Andras <korn@elan.rulez.org>
+ ka7 <ka7@la-evento.com>
+ Ka Ho Ng <khng@FreeBSD.org>
Kamil Domański <kamil@domanski.co>
Karsten Kretschmer <kkretschmer@gmail.com>
Kash Pande <kash@tripleback.net>
+ Kay Pedersen <christianpe96@gmail.com>
Keith M Wesolowski <wesolows@foobazco.org>
+ Kent Ross <k@mad.cash>
+ KernelOfTruth <kerneloftruth@gmail.com>
+ Kevin Bowling <kevin.bowling@kev009.com>
+ Kevin Greene <kevin.greene@delphix.com>
+ Kevin Jin <lostking2008@hotmail.com>
+ Kevin P. Fleming <kevin@km6g.us>
Kevin Tanguy <kevin.tanguy@ovh.net>
KireinaHoro <i@jsteward.moe>
Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
+ Kleber Tarcísio <klebertarcisio@yahoo.com.br>
+ Kody A Kantor <kody.kantor@gmail.com>
Kohsuke Kawaguchi <kk@kohsuke.org>
+ Konstantin Khorenko <khorenko@virtuozzo.com>
+ KORN Andras <korn@elan.rulez.org>
+ Kristof Provost <github@sigsegv.be>
+ Krzysztof Piecuch <piecuch@kpiecuch.pl>
Kyle Blatter <kyleblatter@llnl.gov>
+ Kyle Evans <kevans@FreeBSD.org>
Kyle Fuller <inbox@kylefuller.co.uk>
- Loli <ezomori.nozomu@gmail.com>
+ Laevos <Laevos@users.noreply.github.com>
+ Lalufu <Lalufu@users.noreply.github.com>
Lars Johannsen <laj@it.dk>
+ Laura Hild <lsh@jlab.org>
+ Laurențiu Nicola <lnicola@dend.ro>
+ Lauri Tirkkonen <lauri@hacktheplanet.fi>
+ liaoyuxiangqin <guo.yong33@zte.com.cn>
Li Dongyang <dongyang.li@anu.edu.au>
+ Liu Hua <liu.hua130@zte.com.cn>
+ Liu Qing <winglq@gmail.com>
Li Wei <W.Li@Sun.COM>
+ Loli <ezomori.nozomu@gmail.com>
+ lorddoskias <lorddoskias@gmail.com>
+ Lorenz Brun <lorenz@dolansoft.org>
+ Lorenz Hüdepohl <dev@stellardeath.org>
+ louwrentius <louwrentius@gmail.com>
Lukas Wunner <lukas@wunner.de>
+ luozhengzheng <luo.zhengzheng@zte.com.cn>
+ Luís Henriques <henrix@camandro.org>
Madhav Suresh <madhav.suresh@delphix.com>
+ manfromafar <jonsonb10@gmail.com>
Manoj Joseph <manoj.joseph@delphix.com>
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
Marcel Huber <marcelhuberfoo@gmail.com>
+ Marcel Menzel <mail@mcl.gg>
+ Marcel Schilling <marcel.schilling@uni-luebeck.de>
Marcel Telka <marcel.telka@nexenta.com>
Marcel Wysocki <maci.stgn@gmail.com>
+ Marcin Skarbek <git@skarbek.name>
+ Mariusz Zaborski <mariusz.zaborski@klarasystems.com>
+ Mark Johnston <markj@FreeBSD.org>
+ Mark Maybee <mark.maybee@delphix.com>
+ Mark Roper <markroper@gmail.com>
Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
+ marku89 <mar42@kola.li>
Mark Wright <markwright@internode.on.net>
+ Mart Frauenlob <allkind@fastest.cc>
Martin Matuska <mm@FreeBSD.org>
+ Martin Rüegg <martin.rueegg@metaworx.ch>
Massimo Maggi <me@massimo-maggi.eu>
- Matt Johnston <matt@fugro-fsi.com.au>
- Matt Kemp <matt@mattikus.com>
+ Mateusz Guzik <mjguzik@gmail.com>
+ Mateusz Piotrowski <0mp@FreeBSD.org>
+ Mathieu Velten <matmaul@gmail.com>
+ Matt Fiddaman <github@m.fiddaman.uk>
Matthew Ahrens <matt@delphix.com>
Matthew Thode <mthode@mthode.org>
+ Matthias Blankertz <matthias@blankertz.org>
+ Matt Johnston <matt@fugro-fsi.com.au>
+ Matt Kemp <matt@mattikus.com>
+ Matt Macy <mmacy@freebsd.org>
Matus Kral <matuskral@me.com>
+ Mauricio Faria de Oliveira <mfo@canonical.com>
Max Grossman <max.grossman@delphix.com>
+ Maxim Filimonov <che@bein.link>
Maximilian Mehnert <maximilian.mehnert@gmx.de>
+ Max Zettlmeißl <max@zettlmeissl.de>
+ Md Islam <mdnahian@outlook.com>
+ megari <megari@iki.fi>
+ Michael D Labriola <michael.d.labriola@gmail.com>
+ Michael Franzl <michael@franzl.name>
Michael Gebetsroither <michael@mgeb.org>
Michael Kjorling <michael@kjorling.se>
Michael Martin <mgmartin.mgm@gmail.com>
Michael Niewöhner <foss@mniewoehner.de>
+ Michael Zhivich <mzhivich@akamai.com>
+ Michal Vasilek <michal@vasilek.cz>
+ MigeljanImeri <ImeriMigel@gmail.com>
Mike Gerdts <mike.gerdts@joyent.com>
Mike Harsch <mike@harschsystems.com>
Mike Leddy <mike.leddy@gmail.com>
Mike Swanson <mikeonthecomputer@gmail.com>
Milan Jurik <milan.jurik@xylab.cz>
+ Minsoo Choo <minsoochoo0122@proton.me>
+ Mohamed Tawfik <m_tawfik@aucegypt.edu>
Morgan Jones <mjones@rice.edu>
Moritz Maxeiner <moritz@ucworks.org>
+ Mo Zhou <cdluminate@gmail.com>
+ naivekun <naivekun@outlook.com>
+ nathancheek <myself@nathancheek.com>
Nathaniel Clark <Nathaniel.Clark@misrule.us>
Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
+ Nathan Lewis <linux.robotdude@gmail.com>
Nav Ravindranath <nav@delphix.com>
Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
Ned Bass <bass6@llnl.gov>
Neependra Khare <neependra@kqinfotech.com>
Neil Stockbridge <neil@dist.ro>
+ Nick Black <dank@qemfd.net>
Nick Garvey <garvey.nick@gmail.com>
+ Nick Mattis <nickm970@gmail.com>
+ Nick Terrell <terrelln@fb.com>
+ Niklas Haas <github-c6e1c8@haasn.xyz>
Nikolay Borisov <n.borisov.lkml@gmail.com>
+ nordaux <nordaux@gmail.com>
+ ofthesun9 <olivier@ofthesun.net>
Olaf Faaland <faaland1@llnl.gov>
Oleg Drokin <green@linuxhacker.ru>
Oleg Stepura <oleg@stepura.com>
+ Olivier Certner <olce.freebsd@certner.fr>
+ Olivier Mazouffre <olivier.mazouffre@ims-bordeaux.fr>
+ omni <omni+vagant@hack.org>
+ Orivej Desh <orivej@gmx.fr>
+ Pablo Correa Gómez <ablocorrea@hotmail.com>
+ Palash Gandhi <pbg4930@rit.edu>
+ Patrick Mooney <pmooney@pfmooney.com>
Patrik Greco <sikevux@sikevux.se>
Paul B. Henson <henson@acm.org>
Paul Dagnelie <pcd@delphix.com>
Paul Zuchowski <pzuchowski@datto.com>
Pavel Boldin <boldin.pavel@gmail.com>
+ Pavel Snajdr <snajpa@snajpa.net>
Pavel Zakharov <pavel.zakharov@delphix.com>
Pawel Jakub Dawidek <pjd@FreeBSD.org>
Pedro Giffuni <pfg@freebsd.org>
Peng <peng.hse@xtaotech.com>
Peter Ashford <ashford@accs.com>
+ Peter Dave Hello <hsu@peterdavehello.org>
+ Peter Levine <plevine457@gmail.com>
+ Peter Wirdemo <peter.wirdemo@gmail.com>
+ Petros Koutoupis <petros@petroskoutoupis.com>
+ Philip Pokorny <ppokorny@penguincomputing.com>
+ Philipp Riederer <pt@philipptoelke.de>
+ Phil Kauffman <philip@kauffman.me>
+ Ping Huang <huangping@smartx.com>
+ Piotr Kubaj <pkubaj@anongoth.pl>
+ Piotr P. Stefaniak <pstef@freebsd.org>
Prakash Surya <prakash.surya@delphix.com>
Prasad Joshi <prasadjoshi124@gmail.com>
+ privb0x23 <privb0x23@users.noreply.github.com>
+ P.SCH <p88@yahoo.com>
+ Quartz <yyhran@163.com>
+ Quentin Zdanis <zdanisq@gmail.com>
+ Rafael Kitover <rkitover@gmail.com>
+ RageLtMan <sempervictus@users.noreply.github.com>
Ralf Ertzinger <ralf@skytale.net>
Randall Mason <ClashTheBunny@gmail.com>
Remy Blank <remy.blank@pobox.com>
+ renelson <bnelson@nelsonbe.com>
+ Reno Reckling <e-github@wthack.de>
Ricardo M. Correia <ricardo.correia@oracle.com>
- Rich Ercolani <rincebrain@gmail.com>
+ Riccardo Schirone <rschirone91@gmail.com>
+ Richard Allen <belperite@gmail.com>
Richard Elling <Richard.Elling@RichardElling.com>
+ Richard Kojedzinszky <richard@kojedz.in>
Richard Laager <rlaager@wiktel.com>
Richard Lowe <richlowe@richlowe.net>
Richard Sharpe <rsharpe@samba.org>
Richard Yao <ryao@gentoo.org>
+ Rich Ercolani <rincebrain@gmail.com>
+ Rick Macklem <rmacklem@uoguelph.ca>
+ rilysh <nightquick@proton.me>
+ Robert Evans <evansr@google.com>
+ Robert Novak <sailnfool@gmail.com>
+ Roberto Ricci <ricci@disroot.org>
+ Rob Norris <robn@despairlabs.com>
+ Rob Wing <rew@FreeBSD.org>
Rohan Puri <rohan.puri15@gmail.com>
Romain Dolbeau <romain.dolbeau@atos.net>
Roman Strashkin <roman.strashkin@nexenta.com>
+ Ross Williams <ross@ross-williams.net>
Ruben Kerkhof <ruben@rubenkerkhof.com>
+ Ryan Hirasaki <ryanhirasaki@gmail.com>
+ Ryan Lahfa <masterancpp@gmail.com>
+ Ryan Libby <rlibby@FreeBSD.org>
+ Ryan Moeller <freqlabs@FreeBSD.org>
+ Sam Atkinson <samatk@amazon.com>
+ Sam Hathaway <github.com@munkynet.org>
+ Sam James <sam@gentoo.org>
+ Sam Lunt <samuel.j.lunt@gmail.com>
+ Samuel VERSCHELDE <stormi-github@ylix.fr>
+ Samuel Wycliffe <samuelwycliffe@gmail.com>
+ Samuel Wycliffe J <samwyc@hpe.com>
+ Sanjeev Bagewadi <sanjeev.bagewadi@gmail.com>
+ Sara Hartse <sara.hartse@delphix.com>
Saso Kiselkov <saso.kiselkov@nexenta.com>
+ Satadru Pramanik <satadru@gmail.com>
+ Savyasachee Jha <genghizkhan91@hawkradius.com>
+ Scott Colby <scott@scolby.com>
Scot W. Stevenson <scot.stevenson@gmail.com>
Sean Eric Fagan <sef@ixsystems.com>
Sebastian Gottschall <s.gottschall@dd-wrt.com>
+ Sebastien Roy <seb@delphix.com>
Sen Haerens <sen@senhaerens.be>
Serapheim Dimitropoulos <serapheim@delphix.com>
Seth Forshee <seth.forshee@canonical.com>
+ Shaan Nobee <sniper111@gmail.com>
Shampavman <sham.pavman@nexenta.com>
+ Shaun Tancheff <shaun@aeonazure.com>
+ Shawn Bayern <sbayern@law.fsu.edu>
+ Shengqi Chen <harry-chen@outlook.com>
Shen Yan <shenyanxxxy@qq.com>
Simon Guest <simon.guest@tesujimath.org>
Simon Klinkert <simon.klinkert@gmail.com>
Sowrabha Gopal <sowrabha.gopal@delphix.com>
+ Spencer Kinny <spencerkinny1995@gmail.com>
+ Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com>
Stanislav Seletskiy <s.seletskiy@gmail.com>
+ Stefan Lendl <s.lendl@proxmox.com>
Steffen Müthing <steffen.muething@iwr.uni-heidelberg.de>
Stephen Blinick <stephen.blinick@delphix.com>
+ sterlingjensen <sterlingjensen@users.noreply.github.com>
Steve Dougherty <sdougherty@barracuda.com>
+ Steve Mokris <smokris@softpixel.com>
Steven Burgess <sburgess@dattobackup.com>
Steven Hartland <smh@freebsd.org>
Steven Johnson <sjohnson@sakuraindustries.com>
+ Steven Noonan <steven@uplinklabs.net>
+ stf <s@ctrlc.hu>
Stian Ellingsen <stian@plaimi.net>
+ Stoiko Ivanov <github@nomore.at>
+ Stéphane Lesimple <speed47_github@speed47.net>
Suman Chakravartula <schakrava@gmail.com>
Sydney Vanda <sydney.m.vanda@intel.com>
Sören Tempel <soeren+git@soeren-tempel.net>
+ Tamas TEVESZ <ice@extreme.hu>
+ Teodor Spæren <teodor_spaeren@riseup.net>
+ TerraTech <TerraTech@users.noreply.github.com>
Thijs Cramer <thijs.cramer@gmail.com>
+ Thomas Bertschinger <bertschinger@lanl.gov>
+ Thomas Geppert <geppi@digitx.de>
+ Thomas Lamprecht <guggentom@hotmail.de>
+ Till Maas <opensource@till.name>
Tim Chase <tim@chase2k.com>
Tim Connors <tconnors@rather.puzzling.org>
Tim Crawford <tcrawford@datto.com>
Tim Haley <Tim.Haley@Sun.COM>
+ timor <timor.dd@googlemail.com>
+ Timothy Day <tday141@gmail.com>
+ Tim Schumacher <timschumi@gmx.de>
Tino Reichardt <milky-zfs@mcmilk.de>
Tobin Harding <me@tobin.cc>
Tom Caputi <tcaputi@datto.com>
Tom Matthews <tom@axiom-partners.com>
- Tom Prince <tom.prince@ualberta.net>
Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
+ Tom Prince <tom.prince@ualberta.net>
Tony Hutter <hutter2@llnl.gov>
+ Tony Nguyen <tony.nguyen@delphix.com>
+ Tony Perkins <tperkins@datto.com>
Toomas Soome <tsoome@me.com>
+ Torsten Wörtwein <twoertwein@gmail.com>
+ Toyam Cox <aviator45003@gmail.com>
+ Trevor Bautista <trevrb@trevrb.net>
Trey Dockendorf <treydock@gmail.com>
+ Troels Nørgaard <tnn@tradeshift.com>
+ Tulsi Jain <tulsi.jain@delphix.com>
Turbo Fredriksson <turbo@bayour.com>
Tyler J. Stachecki <stachecki.tyler@gmail.com>
+ Umer Saleem <usaleem@ixsystems.com>
+ Vaibhav Bhanawat <vaibhav.bhanawat@delphix.com>
+ Valmiky Arquissandas <kayvlim@gmail.com>
+ Val Packett <val@packett.cool>
+ Vince van Oosten <techhazard@codeforyouand.me>
+ Violet Purcell <vimproved@inventati.org>
+ Vipin Kumar Verma <vipin.verma@hpe.com>
Vitaut Bajaryn <vitaut.bayaryn@gmail.com>
+ Volker Mauel <volkermauel@gmail.com>
+ Václav Skála <skala@vshosting.cz>
+ Walter Huf <hufman@gmail.com>
+ Warner Losh <imp@bsdimp.com>
Weigang Li <weigang.li@intel.com>
+ WHR <msl0000023508@gmail.com>
Will Andrews <will@freebsd.org>
Will Rouesnel <w.rouesnel@gmail.com>
+ Windel Bouwman <windel@windel.nl>
+ Wojciech Małota-Wójcik <outofforest@users.noreply.github.com>
Wolfgang Bumiller <w.bumiller@proxmox.com>
Xin Li <delphij@FreeBSD.org>
+ Xinliang Liu <xinliang.liu@linaro.org>
+ xtouqh <xtouqh@hotmail.com>
+ Yann Collet <cyan@fb.com>
+ Yanping Gao <yanping.gao@xtaotech.com>
Ying Zhu <casualfisher@gmail.com>
+ Youzhong Yang <youzhong@gmail.com>
+ yparitcher <y@paritcher.com>
+ yuina822 <ayuichi@club.kyutech.ac.jp>
YunQiang Su <syq@debian.org>
Yuri Pankov <yuri.pankov@gmail.com>
+ Yuxin Wang <yuxinwang9999@gmail.com>
Yuxuan Shui <yshuiv7@gmail.com>
Zachary Bedell <zac@thebedells.org>
+ Zach Dykstra <dykstra.zachary@gmail.com>
+ zgock <zgock@nuc.base.zgock-lab.net>
+ Zhu Chuang <chuang@melty.land>
+ Érico Nogueira <erico.erc@gmail.com>
+ Đoàn Trần Công Danh <congdanhqx@gmail.com>
+ 韩朴宇 <w12101111@gmail.com>
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 2dcc251e553d..51c9ef195430 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,2 +1,2 @@
-The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
+The [OpenZFS Code of Conduct](https://openzfs.org/wiki/Code_of_Conduct)
applies to spaces associated with the OpenZFS project, including GitHub.
diff --git a/META b/META
index f16f7972575f..19a796050f5b 100644
--- a/META
+++ b/META
@@ -1,10 +1,10 @@
Meta: 1
Name: zfs
Branch: 1.0
-Version: 2.1.99
+Version: 2.2.99
Release: 1
Release-Tags: relext
License: CDDL
Author: OpenZFS
-Linux-Maximum: 5.18
+Linux-Maximum: 6.8
Linux-Minimum: 3.10
diff --git a/Makefile.am b/Makefile.am
index 54d300e7d40b..11e45dae8255 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,6 +9,7 @@ include $(top_srcdir)/config/Rules.am
include $(top_srcdir)/config/CppCheck.am
include $(top_srcdir)/config/Shellcheck.am
include $(top_srcdir)/config/Substfiles.am
+include $(top_srcdir)/scripts/Makefile.am
ACLOCAL_AMFLAGS = -I config
@@ -23,7 +24,6 @@ include $(srcdir)/%D%/contrib/Makefile.am
include $(srcdir)/%D%/etc/Makefile.am
include $(srcdir)/%D%/lib/Makefile.am
include $(srcdir)/%D%/man/Makefile.am
-include $(srcdir)/%D%/scripts/Makefile.am
include $(srcdir)/%D%/tests/Makefile.am
if BUILD_LINUX
include $(srcdir)/%D%/udev/Makefile.am
diff --git a/README.md b/README.md
index 331889560950..af244c1fff14 100644
--- a/README.md
+++ b/README.md
@@ -32,4 +32,4 @@ For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197`
# Supported Kernels
* The `META` file contains the officially recognized supported Linux kernel versions.
- * Supported FreeBSD versions are any supported branches and releases starting from 12.2-RELEASE.
+ * Supported FreeBSD versions are any supported branches and releases starting from 12.4-RELEASE.
diff --git a/autogen.sh b/autogen.sh
index c817090183f1..39eb82203d69 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -16,7 +16,7 @@ automake --version | awk '{print $NF; exit}' | (
dir="${dir%/Makefile.am}"
grep -q '%[CD]%' "$dir/Makefile.am" || continue
- reldir="${dir#$root}"
+ reldir="${dir#"$root"}"
reldir="${reldir#/}"
canon_reldir="$(printf '%s' "$reldir" | tr -C 'a-zA-Z0-9@_' '_')"
diff --git a/cmd/Makefile.am b/cmd/Makefile.am
index 65de980da308..2bd9d039f20e 100644
--- a/cmd/Makefile.am
+++ b/cmd/Makefile.am
@@ -39,8 +39,6 @@ zhack_LDADD = \
ztest_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
-# Get rid of compiler warning for unchecked truncating snprintfs on gcc 7.1.1
-ztest_CFLAGS += $(NO_FORMAT_TRUNCATION)
ztest_CPPFLAGS = $(AM_CPPFLAGS) $(FORCEDEBUG_CPPFLAGS)
sbin_PROGRAMS += ztest
@@ -100,12 +98,13 @@ endif
if USING_PYTHON
-bin_SCRIPTS += arc_summary arcstat dbufstat
-CLEANFILES += arc_summary arcstat dbufstat
-dist_noinst_DATA += %D%/arc_summary %D%/arcstat.in %D%/dbufstat.in
+bin_SCRIPTS += arc_summary arcstat dbufstat zilstat
+CLEANFILES += arc_summary arcstat dbufstat zilstat
+dist_noinst_DATA += %D%/arc_summary %D%/arcstat.in %D%/dbufstat.in %D%/zilstat.in
$(call SUBST,arcstat,%D%/)
$(call SUBST,dbufstat,%D%/)
+$(call SUBST,zilstat,%D%/)
arc_summary: %D%/arc_summary
$(AM_V_at)cp $< $@
endif
diff --git a/cmd/arc_summary b/cmd/arc_summary
index 4f275813d973..100fb1987a8b 100755
--- a/cmd/arc_summary
+++ b/cmd/arc_summary
@@ -64,7 +64,6 @@ SECTION_HELP = 'print info from one section ('+' '.join(SECTIONS)+')'
SECTION_PATHS = {'arc': 'arcstats',
'dmu': 'dmu_tx',
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
- 'vdev': 'vdev_cache_stats',
'zfetch': 'zfetchstats',
'zil': 'zil'}
@@ -90,8 +89,6 @@ if sys.platform.startswith('freebsd'):
# Requires py36-sysctl on FreeBSD
import sysctl
- VDEV_CACHE_SIZE = 'vdev.cache_size'
-
def is_value(ctl):
return ctl.type != sysctl.CTLTYPE_NODE
@@ -135,8 +132,6 @@ elif sys.platform.startswith('linux'):
SPL_PATH = '/sys/module/spl/parameters'
TUNABLES_PATH = '/sys/module/zfs/parameters'
- VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'
-
def load_kstats(section):
path = os.path.join(KSTAT_PATH, section)
with open(path) as f:
@@ -270,16 +265,14 @@ def draw_graph(kstats_dict):
arc_perc = f_perc(arc_stats['size'], arc_stats['c_max'])
mfu_size = f_bytes(arc_stats['mfu_size'])
mru_size = f_bytes(arc_stats['mru_size'])
- meta_limit = f_bytes(arc_stats['arc_meta_limit'])
meta_size = f_bytes(arc_stats['arc_meta_used'])
dnode_limit = f_bytes(arc_stats['arc_dnode_limit'])
dnode_size = f_bytes(arc_stats['dnode_size'])
- info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} ({5}) '
- 'DNODE {6} ({7})')
+ info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} '
+ 'DNODE {5} ({6})')
info_line = info_form.format(arc_size, arc_perc, mfu_size, mru_size,
- meta_size, meta_limit, dnode_size,
- dnode_limit)
+ meta_size, dnode_size, dnode_limit)
info_spc = ' '*int((GRAPH_WIDTH-len(info_line))/2)
info_line = GRAPH_INDENT+info_spc+info_line
@@ -558,12 +551,28 @@ def section_arc(kstats_dict):
arc_target_size = arc_stats['c']
arc_max = arc_stats['c_max']
arc_min = arc_stats['c_min']
- mfu_size = arc_stats['mfu_size']
- mru_size = arc_stats['mru_size']
- meta_limit = arc_stats['arc_meta_limit']
- meta_size = arc_stats['arc_meta_used']
+ meta = arc_stats['meta']
+ pd = arc_stats['pd']
+ pm = arc_stats['pm']
+ anon_data = arc_stats['anon_data']
+ anon_metadata = arc_stats['anon_metadata']
+ mfu_data = arc_stats['mfu_data']
+ mfu_metadata = arc_stats['mfu_metadata']
+ mru_data = arc_stats['mru_data']
+ mru_metadata = arc_stats['mru_metadata']
+ mfug_data = arc_stats['mfu_ghost_data']
+ mfug_metadata = arc_stats['mfu_ghost_metadata']
+ mrug_data = arc_stats['mru_ghost_data']
+ mrug_metadata = arc_stats['mru_ghost_metadata']
+ unc_data = arc_stats['uncached_data']
+ unc_metadata = arc_stats['uncached_metadata']
+ bonus_size = arc_stats['bonus_size']
dnode_limit = arc_stats['arc_dnode_limit']
dnode_size = arc_stats['dnode_size']
+ dbuf_size = arc_stats['dbuf_size']
+ hdr_size = arc_stats['hdr_size']
+ l2_hdr_size = arc_stats['l2_hdr_size']
+ abd_chunk_waste_size = arc_stats['abd_chunk_waste_size']
target_size_ratio = '{0}:1'.format(int(arc_max) // int(arc_min))
prt_2('ARC size (current):',
@@ -574,19 +583,56 @@ def section_arc(kstats_dict):
f_perc(arc_min, arc_max), f_bytes(arc_min))
prt_i2('Max size (high water):',
target_size_ratio, f_bytes(arc_max))
- caches_size = int(mfu_size)+int(mru_size)
- prt_i2('Most Frequently Used (MFU) cache size:',
- f_perc(mfu_size, caches_size), f_bytes(mfu_size))
- prt_i2('Most Recently Used (MRU) cache size:',
- f_perc(mru_size, caches_size), f_bytes(mru_size))
- prt_i2('Metadata cache size (hard limit):',
- f_perc(meta_limit, arc_max), f_bytes(meta_limit))
- prt_i2('Metadata cache size (current):',
- f_perc(meta_size, meta_limit), f_bytes(meta_size))
- prt_i2('Dnode cache size (hard limit):',
- f_perc(dnode_limit, meta_limit), f_bytes(dnode_limit))
- prt_i2('Dnode cache size (current):',
+ caches_size = int(anon_data)+int(anon_metadata)+\
+ int(mfu_data)+int(mfu_metadata)+int(mru_data)+int(mru_metadata)+\
+ int(unc_data)+int(unc_metadata)
+ prt_i2('Anonymous data size:',
+ f_perc(anon_data, caches_size), f_bytes(anon_data))
+ prt_i2('Anonymous metadata size:',
+ f_perc(anon_metadata, caches_size), f_bytes(anon_metadata))
+ s = 4294967296
+ v = (s-int(pd))*(s-int(meta))/s
+ prt_i2('MFU data target:', f_perc(v, s),
+ f_bytes(v / 65536 * caches_size / 65536))
+ prt_i2('MFU data size:',
+ f_perc(mfu_data, caches_size), f_bytes(mfu_data))
+ prt_i1('MFU ghost data size:', f_bytes(mfug_data))
+ v = (s-int(pm))*int(meta)/s
+ prt_i2('MFU metadata target:', f_perc(v, s),
+ f_bytes(v / 65536 * caches_size / 65536))
+ prt_i2('MFU metadata size:',
+ f_perc(mfu_metadata, caches_size), f_bytes(mfu_metadata))
+ prt_i1('MFU ghost metadata size:', f_bytes(mfug_metadata))
+ v = int(pd)*(s-int(meta))/s
+ prt_i2('MRU data target:', f_perc(v, s),
+ f_bytes(v / 65536 * caches_size / 65536))
+ prt_i2('MRU data size:',
+ f_perc(mru_data, caches_size), f_bytes(mru_data))
+ prt_i1('MRU ghost data size:', f_bytes(mrug_data))
+ v = int(pm)*int(meta)/s
+ prt_i2('MRU metadata target:', f_perc(v, s),
+ f_bytes(v / 65536 * caches_size / 65536))
+ prt_i2('MRU metadata size:',
+ f_perc(mru_metadata, caches_size), f_bytes(mru_metadata))
+ prt_i1('MRU ghost metadata size:', f_bytes(mrug_metadata))
+ prt_i2('Uncached data size:',
+ f_perc(unc_data, caches_size), f_bytes(unc_data))
+ prt_i2('Uncached metadata size:',
+ f_perc(unc_metadata, caches_size), f_bytes(unc_metadata))
+ prt_i2('Bonus size:',
+ f_perc(bonus_size, arc_size), f_bytes(bonus_size))
+ prt_i2('Dnode cache target:',
+ f_perc(dnode_limit, arc_max), f_bytes(dnode_limit))
+ prt_i2('Dnode cache size:',
f_perc(dnode_size, dnode_limit), f_bytes(dnode_size))
+ prt_i2('Dbuf size:',
+ f_perc(dbuf_size, arc_size), f_bytes(dbuf_size))
+ prt_i2('Header size:',
+ f_perc(hdr_size, arc_size), f_bytes(hdr_size))
+ prt_i2('L2 header size:',
+ f_perc(l2_hdr_size, arc_size), f_bytes(l2_hdr_size))
+ prt_i2('ABD chunk waste size:',
+ f_perc(abd_chunk_waste_size, arc_size), f_bytes(abd_chunk_waste_size))
print()
print('ARC hash breakdown:')
@@ -626,78 +672,119 @@ def section_archits(kstats_dict):
"""
arc_stats = isolate_section('arcstats', kstats_dict)
- all_accesses = int(arc_stats['hits'])+int(arc_stats['misses'])
- actual_hits = int(arc_stats['mfu_hits'])+int(arc_stats['mru_hits'])
-
- prt_1('ARC total accesses (hits + misses):', f_hits(all_accesses))
- ta_todo = (('Cache hit ratio:', arc_stats['hits']),
- ('Cache miss ratio:', arc_stats['misses']),
- ('Actual hit ratio (MFU + MRU hits):', actual_hits))
+ all_accesses = int(arc_stats['hits'])+int(arc_stats['iohits'])+\
+ int(arc_stats['misses'])
+ prt_1('ARC total accesses:', f_hits(all_accesses))
+ ta_todo = (('Total hits:', arc_stats['hits']),
+ ('Total I/O hits:', arc_stats['iohits']),
+ ('Total misses:', arc_stats['misses']))
for title, value in ta_todo:
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
+ print()
dd_total = int(arc_stats['demand_data_hits']) +\
+ int(arc_stats['demand_data_iohits']) +\
int(arc_stats['demand_data_misses'])
- prt_i2('Data demand efficiency:',
- f_perc(arc_stats['demand_data_hits'], dd_total),
- f_hits(dd_total))
+ prt_2('ARC demand data accesses:', f_perc(dd_total, all_accesses),
+ f_hits(dd_total))
+ dd_todo = (('Demand data hits:', arc_stats['demand_data_hits']),
+ ('Demand data I/O hits:', arc_stats['demand_data_iohits']),
+ ('Demand data misses:', arc_stats['demand_data_misses']))
+ for title, value in dd_todo:
+ prt_i2(title, f_perc(value, dd_total), f_hits(value))
+ print()
- dp_total = int(arc_stats['prefetch_data_hits']) +\
+ dm_total = int(arc_stats['demand_metadata_hits']) +\
+ int(arc_stats['demand_metadata_iohits']) +\
+ int(arc_stats['demand_metadata_misses'])
+ prt_2('ARC demand metadata accesses:', f_perc(dm_total, all_accesses),
+ f_hits(dm_total))
+ dm_todo = (('Demand metadata hits:', arc_stats['demand_metadata_hits']),
+ ('Demand metadata I/O hits:',
+ arc_stats['demand_metadata_iohits']),
+ ('Demand metadata misses:', arc_stats['demand_metadata_misses']))
+ for title, value in dm_todo:
+ prt_i2(title, f_perc(value, dm_total), f_hits(value))
+ print()
+
+ pd_total = int(arc_stats['prefetch_data_hits']) +\
+ int(arc_stats['prefetch_data_iohits']) +\
int(arc_stats['prefetch_data_misses'])
- prt_i2('Data prefetch efficiency:',
- f_perc(arc_stats['prefetch_data_hits'], dp_total),
- f_hits(dp_total))
+ prt_2('ARC prefetch data accesses:', f_perc(pd_total, all_accesses),
+ f_hits(pd_total))
+ pd_todo = (('Prefetch data hits:', arc_stats['prefetch_data_hits']),
+ ('Prefetch data I/O hits:', arc_stats['prefetch_data_iohits']),
+ ('Prefetch data misses:', arc_stats['prefetch_data_misses']))
+ for title, value in pd_todo:
+ prt_i2(title, f_perc(value, pd_total), f_hits(value))
+ print()
- known_hits = int(arc_stats['mfu_hits']) +\
- int(arc_stats['mru_hits']) +\
- int(arc_stats['mfu_ghost_hits']) +\
- int(arc_stats['mru_ghost_hits'])
+ pm_total = int(arc_stats['prefetch_metadata_hits']) +\
+ int(arc_stats['prefetch_metadata_iohits']) +\
+ int(arc_stats['prefetch_metadata_misses'])
+ prt_2('ARC prefetch metadata accesses:', f_perc(pm_total, all_accesses),
+ f_hits(pm_total))
+ pm_todo = (('Prefetch metadata hits:',
+ arc_stats['prefetch_metadata_hits']),
+ ('Prefetch metadata I/O hits:',
+ arc_stats['prefetch_metadata_iohits']),
+ ('Prefetch metadata misses:',
+ arc_stats['prefetch_metadata_misses']))
+ for title, value in pm_todo:
+ prt_i2(title, f_perc(value, pm_total), f_hits(value))
+ print()
- anon_hits = int(arc_stats['hits'])-known_hits
+ all_prefetches = int(arc_stats['predictive_prefetch'])+\
+ int(arc_stats['prescient_prefetch'])
+ prt_2('ARC predictive prefetches:',
+ f_perc(arc_stats['predictive_prefetch'], all_prefetches),
+ f_hits(arc_stats['predictive_prefetch']))
+ prt_i2('Demand hits after predictive:',
+ f_perc(arc_stats['demand_hit_predictive_prefetch'],
+ arc_stats['predictive_prefetch']),
+ f_hits(arc_stats['demand_hit_predictive_prefetch']))
+ prt_i2('Demand I/O hits after predictive:',
+ f_perc(arc_stats['demand_iohit_predictive_prefetch'],
+ arc_stats['predictive_prefetch']),
+ f_hits(arc_stats['demand_iohit_predictive_prefetch']))
+ never = int(arc_stats['predictive_prefetch']) -\
+ int(arc_stats['demand_hit_predictive_prefetch']) -\
+ int(arc_stats['demand_iohit_predictive_prefetch'])
+ prt_i2('Never demanded after predictive:',
+ f_perc(never, arc_stats['predictive_prefetch']),
+ f_hits(never))
+ print()
+ prt_2('ARC prescient prefetches:',
+ f_perc(arc_stats['prescient_prefetch'], all_prefetches),
+ f_hits(arc_stats['prescient_prefetch']))
+ prt_i2('Demand hits after prescient:',
+ f_perc(arc_stats['demand_hit_prescient_prefetch'],
+ arc_stats['prescient_prefetch']),
+ f_hits(arc_stats['demand_hit_prescient_prefetch']))
+ prt_i2('Demand I/O hits after prescient:',
+ f_perc(arc_stats['demand_iohit_prescient_prefetch'],
+ arc_stats['prescient_prefetch']),
+ f_hits(arc_stats['demand_iohit_prescient_prefetch']))
+ never = int(arc_stats['prescient_prefetch'])-\
+ int(arc_stats['demand_hit_prescient_prefetch'])-\
+ int(arc_stats['demand_iohit_prescient_prefetch'])
+ prt_i2('Never demanded after prescient:',
+ f_perc(never, arc_stats['prescient_prefetch']),
+ f_hits(never))
print()
- print('Cache hits by cache type:')
+
+ print('ARC states hits of all accesses:')
cl_todo = (('Most frequently used (MFU):', arc_stats['mfu_hits']),
('Most recently used (MRU):', arc_stats['mru_hits']),
('Most frequently used (MFU) ghost:',
arc_stats['mfu_ghost_hits']),
('Most recently used (MRU) ghost:',
- arc_stats['mru_ghost_hits']))
-
+ arc_stats['mru_ghost_hits']),
+ ('Uncached:', arc_stats['uncached_hits']))
for title, value in cl_todo:
- prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
-
- # For some reason, anon_hits can turn negative, which is weird. Until we
- # have figured out why this happens, we just hide the problem, following
- # the behavior of the original arc_summary.
- if anon_hits >= 0:
- prt_i2('Anonymously used:',
- f_perc(anon_hits, arc_stats['hits']), f_hits(anon_hits))
-
- print()
- print('Cache hits by data type:')
- dt_todo = (('Demand data:', arc_stats['demand_data_hits']),
- ('Demand prefetch data:', arc_stats['prefetch_data_hits']),
- ('Demand metadata:', arc_stats['demand_metadata_hits']),
- ('Demand prefetch metadata:',
- arc_stats['prefetch_metadata_hits']))
-
- for title, value in dt_todo:
- prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
-
- print()
- print('Cache misses by data type:')
- dm_todo = (('Demand data:', arc_stats['demand_data_misses']),
- ('Demand prefetch data:',
- arc_stats['prefetch_data_misses']),
- ('Demand metadata:', arc_stats['demand_metadata_misses']),
- ('Demand prefetch metadata:',
- arc_stats['prefetch_metadata_misses']))
-
- for title, value in dm_todo:
- prt_i2(title, f_perc(value, arc_stats['misses']), f_hits(value))
-
+ prt_i2(title, f_perc(value, all_accesses), f_hits(value))
print()
@@ -706,13 +793,28 @@ def section_dmu(kstats_dict):
zfetch_stats = isolate_section('zfetchstats', kstats_dict)
- zfetch_access_total = int(zfetch_stats['hits'])+int(zfetch_stats['misses'])
+ zfetch_access_total = int(zfetch_stats['hits']) +\
+ int(zfetch_stats['future']) + int(zfetch_stats['stride']) +\
+ int(zfetch_stats['past']) + int(zfetch_stats['misses'])
- prt_1('DMU prefetch efficiency:', f_hits(zfetch_access_total))
- prt_i2('Hit ratio:', f_perc(zfetch_stats['hits'], zfetch_access_total),
+ prt_1('DMU predictive prefetcher calls:', f_hits(zfetch_access_total))
+ prt_i2('Stream hits:',
+ f_perc(zfetch_stats['hits'], zfetch_access_total),
f_hits(zfetch_stats['hits']))
- prt_i2('Miss ratio:', f_perc(zfetch_stats['misses'], zfetch_access_total),
+ future = int(zfetch_stats['future']) + int(zfetch_stats['stride'])
+ prt_i2('Hits ahead of stream:', f_perc(future, zfetch_access_total),
+ f_hits(future))
+ prt_i2('Hits behind stream:',
+ f_perc(zfetch_stats['past'], zfetch_access_total),
+ f_hits(zfetch_stats['past']))
+ prt_i2('Stream misses:',
+ f_perc(zfetch_stats['misses'], zfetch_access_total),
f_hits(zfetch_stats['misses']))
+ prt_i2('Streams limit reached:',
+ f_perc(zfetch_stats['max_streams'], zfetch_stats['misses']),
+ f_hits(zfetch_stats['max_streams']))
+ prt_i1('Stream strides:', f_hits(zfetch_stats['stride']))
+ prt_i1('Prefetches issued', f_hits(zfetch_stats['io_issued']))
print()
@@ -744,7 +846,8 @@ def section_l2arc(kstats_dict):
('Free on write:', 'l2_free_on_write'),
('R/W clashes:', 'l2_rw_clash'),
('Bad checksums:', 'l2_cksum_bad'),
- ('I/O errors:', 'l2_io_error'))
+ ('Read errors:', 'l2_io_error'),
+ ('Write errors:', 'l2_writes_error'))
for title, value in l2_todo:
prt_i1(title, f_hits(arc_stats[value]))
@@ -780,28 +883,20 @@ def section_l2arc(kstats_dict):
prt_i2('Miss ratio:',
f_perc(arc_stats['l2_misses'], l2_access_total),
f_hits(arc_stats['l2_misses']))
- prt_i1('Feeds:', f_hits(arc_stats['l2_feeds']))
print()
- print('L2ARC writes:')
-
- if arc_stats['l2_writes_done'] != arc_stats['l2_writes_sent']:
- prt_i2('Writes sent:', 'FAULTED', f_hits(arc_stats['l2_writes_sent']))
- prt_i2('Done ratio:',
- f_perc(arc_stats['l2_writes_done'],
- arc_stats['l2_writes_sent']),
- f_hits(arc_stats['l2_writes_done']))
- prt_i2('Error ratio:',
- f_perc(arc_stats['l2_writes_error'],
- arc_stats['l2_writes_sent']),
- f_hits(arc_stats['l2_writes_error']))
- else:
- prt_i2('Writes sent:', '100 %', f_hits(arc_stats['l2_writes_sent']))
+ print('L2ARC I/O:')
+ prt_i2('Reads:',
+ f_bytes(arc_stats['l2_read_bytes']),
+ f_hits(arc_stats['l2_hits']))
+ prt_i2('Writes:',
+ f_bytes(arc_stats['l2_write_bytes']),
+ f_hits(arc_stats['l2_writes_sent']))
print()
print('L2ARC evicts:')
- prt_i1('Lock retries:', f_hits(arc_stats['l2_evict_lock_retry']))
- prt_i1('Upon reading:', f_hits(arc_stats['l2_evict_reading']))
+ prt_i1('L1 cached:', f_hits(arc_stats['l2_evict_l1cached']))
+ prt_i1('While reading:', f_hits(arc_stats['l2_evict_reading']))
print()
@@ -861,35 +956,6 @@ def section_tunables(*_):
print()
-def section_vdev(kstats_dict):
- """Collect information on VDEV caches"""
-
- # Currently [Nov 2017] the VDEV cache is disabled, because it is actually
- # harmful. When this is the case, we just skip the whole entry. See
- # https://github.com/openzfs/zfs/blob/master/module/zfs/vdev_cache.c
- # for details
- tunables = get_vdev_params()
-
- if tunables[VDEV_CACHE_SIZE] == '0':
- print('VDEV cache disabled, skipping section\n')
- return
-
- vdev_stats = isolate_section('vdev_cache_stats', kstats_dict)
-
- vdev_cache_total = int(vdev_stats['hits']) +\
- int(vdev_stats['misses']) +\
- int(vdev_stats['delegations'])
-
- prt_1('VDEV cache summary:', f_hits(vdev_cache_total))
- prt_i2('Hit ratio:', f_perc(vdev_stats['hits'], vdev_cache_total),
- f_hits(vdev_stats['hits']))
- prt_i2('Miss ratio:', f_perc(vdev_stats['misses'], vdev_cache_total),
- f_hits(vdev_stats['misses']))
- prt_i2('Delegations:', f_perc(vdev_stats['delegations'], vdev_cache_total),
- f_hits(vdev_stats['delegations']))
- print()
-
-
def section_zil(kstats_dict):
"""Collect information on the ZFS Intent Log. Some of the information
taken from https://github.com/openzfs/zfs/blob/master/include/sys/zil.h
@@ -917,7 +983,6 @@ section_calls = {'arc': section_arc,
'l2arc': section_l2arc,
'spl': section_spl,
'tunables': section_tunables,
- 'vdev': section_vdev,
'zil': section_zil}
diff --git a/cmd/arcstat.in b/cmd/arcstat.in
index 9327f644f544..c4f10a1d6d3b 100755
--- a/cmd/arcstat.in
+++ b/cmd/arcstat.in
@@ -29,7 +29,7 @@
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -62,31 +62,64 @@ from signal import signal, SIGINT, SIGWINCH, SIG_DFL
cols = {
# HDR: [Size, Scale, Description]
"time": [8, -1, "Time"],
- "hits": [4, 1000, "ARC reads per second"],
+ "hits": [4, 1000, "ARC hits per second"],
+ "iohs": [4, 1000, "ARC I/O hits per second"],
"miss": [4, 1000, "ARC misses per second"],
"read": [4, 1000, "Total ARC accesses per second"],
"hit%": [4, 100, "ARC hit percentage"],
+ "ioh%": [4, 100, "ARC I/O hit percentage"],
"miss%": [5, 100, "ARC miss percentage"],
"dhit": [4, 1000, "Demand hits per second"],
+ "dioh": [4, 1000, "Demand I/O hits per second"],
"dmis": [4, 1000, "Demand misses per second"],
"dh%": [3, 100, "Demand hit percentage"],
+ "di%": [3, 100, "Demand I/O hit percentage"],
"dm%": [3, 100, "Demand miss percentage"],
+ "ddhit": [5, 1000, "Demand data hits per second"],
+ "ddioh": [5, 1000, "Demand data I/O hits per second"],
+ "ddmis": [5, 1000, "Demand data misses per second"],
+ "ddh%": [4, 100, "Demand data hit percentage"],
+ "ddi%": [4, 100, "Demand data I/O hit percentage"],
+ "ddm%": [4, 100, "Demand data miss percentage"],
+ "dmhit": [5, 1000, "Demand metadata hits per second"],
+ "dmioh": [5, 1000, "Demand metadata I/O hits per second"],
+ "dmmis": [5, 1000, "Demand metadata misses per second"],
+ "dmh%": [4, 100, "Demand metadata hit percentage"],
+ "dmi%": [4, 100, "Demand metadata I/O hit percentage"],
+ "dmm%": [4, 100, "Demand metadata miss percentage"],
"phit": [4, 1000, "Prefetch hits per second"],
+ "pioh": [4, 1000, "Prefetch I/O hits per second"],
"pmis": [4, 1000, "Prefetch misses per second"],
"ph%": [3, 100, "Prefetch hits percentage"],
+ "pi%": [3, 100, "Prefetch I/O hits percentage"],
"pm%": [3, 100, "Prefetch miss percentage"],
+ "pdhit": [5, 1000, "Prefetch data hits per second"],
+ "pdioh": [5, 1000, "Prefetch data I/O hits per second"],
+ "pdmis": [5, 1000, "Prefetch data misses per second"],
+ "pdh%": [4, 100, "Prefetch data hits percentage"],
+ "pdi%": [4, 100, "Prefetch data I/O hits percentage"],
+ "pdm%": [4, 100, "Prefetch data miss percentage"],
+ "pmhit": [5, 1000, "Prefetch metadata hits per second"],
+ "pmioh": [5, 1000, "Prefetch metadata I/O hits per second"],
+ "pmmis": [5, 1000, "Prefetch metadata misses per second"],
+ "pmh%": [4, 100, "Prefetch metadata hits percentage"],
+ "pmi%": [4, 100, "Prefetch metadata I/O hits percentage"],
+ "pmm%": [4, 100, "Prefetch metadata miss percentage"],
"mhit": [4, 1000, "Metadata hits per second"],
+ "mioh": [4, 1000, "Metadata I/O hits per second"],
"mmis": [4, 1000, "Metadata misses per second"],
"mread": [5, 1000, "Metadata accesses per second"],
"mh%": [3, 100, "Metadata hit percentage"],
+ "mi%": [3, 100, "Metadata I/O hit percentage"],
"mm%": [3, 100, "Metadata miss percentage"],
"arcsz": [5, 1024, "ARC size"],
- "size": [4, 1024, "ARC size"],
- "c": [4, 1024, "ARC target size"],
+ "size": [5, 1024, "ARC size"],
+ "c": [5, 1024, "ARC target size"],
"mfu": [4, 1000, "MFU list hits per second"],
"mru": [4, 1000, "MRU list hits per second"],
"mfug": [4, 1000, "MFU ghost list hits per second"],
"mrug": [4, 1000, "MRU ghost list hits per second"],
+ "unc": [4, 1000, "Uncached list hits per second"],
"eskip": [5, 1000, "evict_skip per second"],
"el2skip": [7, 1000, "evict skip, due to l2 writes, per second"],
"el2cach": [7, 1024, "Size of L2 cached evictions per second"],
@@ -96,7 +129,11 @@ cols = {
"el2inel": [7, 1024, "Size of L2 ineligible evictions per second"],
"mtxmis": [6, 1000, "mutex_miss per second"],
"dread": [5, 1000, "Demand accesses per second"],
+ "ddread": [6, 1000, "Demand data accesses per second"],
+ "dmread": [6, 1000, "Demand metadata accesses per second"],
"pread": [5, 1000, "Prefetch accesses per second"],
+ "pdread": [6, 1000, "Prefetch data accesses per second"],
+ "pmread": [6, 1000, "Prefetch metadata accesses per second"],
"l2hits": [6, 1000, "L2ARC hits per second"],
"l2miss": [6, 1000, "L2ARC misses per second"],
"l2read": [6, 1000, "Total L2ARC accesses per second"],
@@ -116,23 +153,34 @@ cols = {
"l2size": [6, 1024, "Size of the L2ARC"],
"l2bytes": [7, 1024, "Bytes read per second from the L2ARC"],
"grow": [4, 1000, "ARC grow disabled"],
- "need": [4, 1024, "ARC reclaim need"],
- "free": [4, 1024, "ARC free memory"],
+ "need": [5, 1024, "ARC reclaim need"],
+ "free": [5, 1024, "ARC free memory"],
"avail": [5, 1024, "ARC available memory"],
"waste": [5, 1024, "Wasted memory due to round up to pagesize"],
+ "ztotal": [6, 1000, "zfetch total prefetcher calls per second"],
+ "zhits": [5, 1000, "zfetch stream hits per second"],
+ "zahead": [6, 1000, "zfetch hits ahead of streams per second"],
+ "zpast": [5, 1000, "zfetch hits behind streams per second"],
+ "zmisses": [7, 1000, "zfetch stream misses per second"],
+ "zmax": [4, 1000, "zfetch limit reached per second"],
+ "zfuture": [7, 1000, "zfetch stream future per second"],
+ "zstride": [7, 1000, "zfetch stream strides per second"],
+ "zissued": [7, 1000, "zfetch prefetches issued per second"],
+ "zactive": [7, 1000, "zfetch prefetches active per second"],
}
v = {}
-hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis",
- "mm%", "size", "c", "avail"]
-xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread",
- "pread", "read"]
+hdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%",
+ "size", "c", "avail"]
+xhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis",
+ "dread", "pread", "read"]
+zhdr = ["time", "ztotal", "zhits", "zahead", "zpast", "zmisses", "zmax",
+ "zfuture", "zstride", "zissued", "zactive"]
sint = 1 # Default interval is 1 second
count = 1 # Default count is 1
hdr_intr = 20 # Print header every 20 lines of output
opfile = None
sep = " " # Default separator is 2 spaces
-version = "0.4"
l2exist = False
cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
"[count]]\n")
@@ -152,6 +200,8 @@ if sys.platform.startswith('freebsd'):
k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
if ctl.type != sysctl.CTLTYPE_NODE]
+ k += [ctl for ctl in sysctl.filter('kstat.zfs.misc.zfetchstats')
+ if ctl.type != sysctl.CTLTYPE_NODE]
if not k:
sys.exit(1)
@@ -163,19 +213,28 @@ if sys.platform.startswith('freebsd'):
continue
name, value = s.name, s.value
- # Trims 'kstat.zfs.misc.arcstats' from the name
- kstat[name[24:]] = int(value)
+
+ if "arcstats" in name:
+ # Trims 'kstat.zfs.misc.arcstats' from the name
+ kstat[name[24:]] = int(value)
+ else:
+ kstat["zfetch_" + name[27:]] = int(value)
elif sys.platform.startswith('linux'):
def kstat_update():
global kstat
- k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
+ k1 = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
- if not k:
+ k2 = ["zfetch_" + line.strip() for line in
+ open('/proc/spl/kstat/zfs/zfetchstats')]
+
+ if k1 is None or k2 is None:
sys.exit(1)
- del k[0:2]
+ del k1[0:2]
+ del k2[0:2]
+ k = k1 + k2
kstat = {}
for s in k:
@@ -203,6 +262,7 @@ def usage():
sys.stderr.write("\t -v : List all possible field headers and definitions"
"\n")
sys.stderr.write("\t -x : Print extended stats\n")
+ sys.stderr.write("\t -z : Print zfetch stats\n")
sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n")
sys.stderr.write("\t -o : Redirect output to the specified file\n")
sys.stderr.write("\t -s : Override default field separator with custom "
@@ -271,7 +331,7 @@ def print_values():
if pretty_print:
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
else:
- fmt = lambda col: v[col]
+ fmt = lambda col: str(v[col])
sys.stdout.write(sep.join(fmt(col) for col in hdr))
sys.stdout.write("\n")
@@ -321,6 +381,7 @@ def init():
global count
global hdr
global xhdr
+ global zhdr
global opfile
global sep
global out
@@ -332,15 +393,17 @@ def init():
xflag = False
hflag = False
vflag = False
+ zflag = False
i = 1
try:
opts, args = getopt.getopt(
sys.argv[1:],
- "axo:hvs:f:p",
+ "axzo:hvs:f:p",
[
"all",
"extended",
+ "zfetch",
"outfile",
"help",
"verbose",
@@ -374,13 +437,15 @@ def init():
i += 1
if opt in ('-p', '--parsable'):
pretty_print = False
+ if opt in ('-z', '--zfetch'):
+ zflag = True
i += 1
argv = sys.argv[i:]
sint = int(argv[0]) if argv else sint
count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1)
- if hflag or (xflag and desired_cols):
+ if hflag or (xflag and zflag) or ((zflag or xflag) and desired_cols):
usage()
if vflag:
@@ -389,6 +454,9 @@ def init():
if xflag:
hdr = xhdr
+ if zflag:
+ hdr = zhdr
+
update_hdr_intr()
# check if L2ARC exists
@@ -442,34 +510,80 @@ def calculate():
v = dict()
v["time"] = time.strftime("%H:%M:%S", time.localtime())
v["hits"] = d["hits"] // sint
+ v["iohs"] = d["iohits"] // sint
v["miss"] = d["misses"] // sint
- v["read"] = v["hits"] + v["miss"]
+ v["read"] = v["hits"] + v["iohs"] + v["miss"]
v["hit%"] = 100 * v["hits"] // v["read"] if v["read"] > 0 else 0
- v["miss%"] = 100 - v["hit%"] if v["read"] > 0 else 0
+ v["ioh%"] = 100 * v["iohs"] // v["read"] if v["read"] > 0 else 0
+ v["miss%"] = 100 - v["hit%"] - v["ioh%"] if v["read"] > 0 else 0
v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) // sint
+ v["dioh"] = (d["demand_data_iohits"] + d["demand_metadata_iohits"]) // sint
v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) // sint
- v["dread"] = v["dhit"] + v["dmis"]
+ v["dread"] = v["dhit"] + v["dioh"] + v["dmis"]
v["dh%"] = 100 * v["dhit"] // v["dread"] if v["dread"] > 0 else 0
- v["dm%"] = 100 - v["dh%"] if v["dread"] > 0 else 0
+ v["di%"] = 100 * v["dioh"] // v["dread"] if v["dread"] > 0 else 0
+ v["dm%"] = 100 - v["dh%"] - v["di%"] if v["dread"] > 0 else 0
+
+ v["ddhit"] = d["demand_data_hits"] // sint
+ v["ddioh"] = d["demand_data_iohits"] // sint
+ v["ddmis"] = d["demand_data_misses"] // sint
+
+ v["ddread"] = v["ddhit"] + v["ddioh"] + v["ddmis"]
+ v["ddh%"] = 100 * v["ddhit"] // v["ddread"] if v["ddread"] > 0 else 0
+ v["ddi%"] = 100 * v["ddioh"] // v["ddread"] if v["ddread"] > 0 else 0
+ v["ddm%"] = 100 - v["ddh%"] - v["ddi%"] if v["ddread"] > 0 else 0
+
+ v["dmhit"] = d["demand_metadata_hits"] // sint
+ v["dmioh"] = d["demand_metadata_iohits"] // sint
+ v["dmmis"] = d["demand_metadata_misses"] // sint
+
+ v["dmread"] = v["dmhit"] + v["dmioh"] + v["dmmis"]
+ v["dmh%"] = 100 * v["dmhit"] // v["dmread"] if v["dmread"] > 0 else 0
+ v["dmi%"] = 100 * v["dmioh"] // v["dmread"] if v["dmread"] > 0 else 0
+ v["dmm%"] = 100 - v["dmh%"] - v["dmi%"] if v["dmread"] > 0 else 0
v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) // sint
+ v["pioh"] = (d["prefetch_data_iohits"] +
+ d["prefetch_metadata_iohits"]) // sint
v["pmis"] = (d["prefetch_data_misses"] +
d["prefetch_metadata_misses"]) // sint
- v["pread"] = v["phit"] + v["pmis"]
+ v["pread"] = v["phit"] + v["pioh"] + v["pmis"]
v["ph%"] = 100 * v["phit"] // v["pread"] if v["pread"] > 0 else 0
- v["pm%"] = 100 - v["ph%"] if v["pread"] > 0 else 0
+ v["pi%"] = 100 * v["pioh"] // v["pread"] if v["pread"] > 0 else 0
+ v["pm%"] = 100 - v["ph%"] - v["pi%"] if v["pread"] > 0 else 0
+
+ v["pdhit"] = d["prefetch_data_hits"] // sint
+ v["pdioh"] = d["prefetch_data_iohits"] // sint
+ v["pdmis"] = d["prefetch_data_misses"] // sint
+
+ v["pdread"] = v["pdhit"] + v["pdioh"] + v["pdmis"]
+ v["pdh%"] = 100 * v["pdhit"] // v["pdread"] if v["pdread"] > 0 else 0
+ v["pdi%"] = 100 * v["pdioh"] // v["pdread"] if v["pdread"] > 0 else 0
+ v["pdm%"] = 100 - v["pdh%"] - v["pdi%"] if v["pdread"] > 0 else 0
+
+ v["pmhit"] = d["prefetch_metadata_hits"] // sint
+ v["pmioh"] = d["prefetch_metadata_iohits"] // sint
+ v["pmmis"] = d["prefetch_metadata_misses"] // sint
+
+ v["pmread"] = v["pmhit"] + v["pmioh"] + v["pmmis"]
+ v["pmh%"] = 100 * v["pmhit"] // v["pmread"] if v["pmread"] > 0 else 0
+ v["pmi%"] = 100 * v["pmioh"] // v["pmread"] if v["pmread"] > 0 else 0
+ v["pmm%"] = 100 - v["pmh%"] - v["pmi%"] if v["pmread"] > 0 else 0
v["mhit"] = (d["prefetch_metadata_hits"] +
d["demand_metadata_hits"]) // sint
+ v["mioh"] = (d["prefetch_metadata_iohits"] +
+ d["demand_metadata_iohits"]) // sint
v["mmis"] = (d["prefetch_metadata_misses"] +
d["demand_metadata_misses"]) // sint
- v["mread"] = v["mhit"] + v["mmis"]
+ v["mread"] = v["mhit"] + v["mioh"] + v["mmis"]
v["mh%"] = 100 * v["mhit"] // v["mread"] if v["mread"] > 0 else 0
- v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
+ v["mi%"] = 100 * v["mioh"] // v["mread"] if v["mread"] > 0 else 0
+ v["mm%"] = 100 - v["mh%"] - v["mi%"] if v["mread"] > 0 else 0
v["arcsz"] = cur["size"]
v["size"] = cur["size"]
@@ -478,6 +592,7 @@ def calculate():
v["mru"] = d["mru_hits"] // sint
v["mrug"] = d["mru_ghost_hits"] // sint
v["mfug"] = d["mfu_ghost_hits"] // sint
+ v["unc"] = d["uncached_hits"] // sint
v["eskip"] = d["evict_skip"] // sint
v["el2skip"] = d["evict_l2_skip"] // sint
v["el2cach"] = d["evict_l2_cached"] // sint
@@ -486,6 +601,17 @@ def calculate():
v["el2mru"] = d["evict_l2_eligible_mru"] // sint
v["el2inel"] = d["evict_l2_ineligible"] // sint
v["mtxmis"] = d["mutex_miss"] // sint
+ v["ztotal"] = (d["zfetch_hits"] + d["zfetch_future"] + d["zfetch_stride"] +
+ d["zfetch_past"] + d["zfetch_misses"]) // sint
+ v["zhits"] = d["zfetch_hits"] // sint
+ v["zahead"] = (d["zfetch_future"] + d["zfetch_stride"]) // sint
+ v["zpast"] = d["zfetch_past"] // sint
+ v["zmisses"] = d["zfetch_misses"] // sint
+ v["zmax"] = d["zfetch_max_streams"] // sint
+ v["zfuture"] = d["zfetch_future"] // sint
+ v["zstride"] = d["zfetch_stride"] // sint
+ v["zissued"] = d["zfetch_io_issued"] // sint
+ v["zactive"] = d["zfetch_io_active"] // sint
if l2exist:
v["l2hits"] = d["l2_hits"] // sint
diff --git a/cmd/dbufstat.in b/cmd/dbufstat.in
index b716a0c9749b..1252496577bc 100755
--- a/cmd/dbufstat.in
+++ b/cmd/dbufstat.in
@@ -12,7 +12,7 @@
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -37,7 +37,7 @@ import re
bhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"]
bxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize",
- "meta", "state", "dbholds", "dbc", "list", "atype", "flags",
+ "usize", "meta", "state", "dbholds", "dbc", "list", "atype", "flags",
"count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2",
"l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype",
"data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"]
@@ -47,17 +47,17 @@ dhdr = ["pool", "objset", "object", "dtype", "cached"]
dxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs",
"bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct",
"indirect", "bonus", "spill"]
-dincompat = ["level", "blkid", "offset", "dbsize", "meta", "state", "dbholds",
- "dbc", "list", "atype", "flags", "count", "asize", "access",
- "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
- "l2_comp", "aholds"]
+dincompat = ["level", "blkid", "offset", "dbsize", "usize", "meta", "state",
+ "dbholds", "dbc", "list", "atype", "flags", "count", "asize",
+ "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
+ "l2_asize", "l2_comp", "aholds"]
thdr = ["pool", "objset", "dtype", "cached"]
txhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect",
"bonus", "spill"]
-tincompat = ["object", "level", "blkid", "offset", "dbsize", "meta", "state",
- "dbc", "dbholds", "list", "atype", "flags", "count", "asize",
- "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
+tincompat = ["object", "level", "blkid", "offset", "dbsize", "usize", "meta",
+ "state", "dbc", "dbholds", "list", "atype", "flags", "count",
+ "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
"l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs",
"bsize", "lvls", "dholds", "blocks", "dsize"]
@@ -70,6 +70,7 @@ cols = {
"blkid": [8, -1, "block number of buffer"],
"offset": [12, 1024, "offset in object of buffer"],
"dbsize": [7, 1024, "size of buffer"],
+ "usize": [7, 1024, "size of attached user data"],
"meta": [4, -1, "is this buffer metadata?"],
"state": [5, -1, "state of buffer (read, cached, etc)"],
"dbholds": [7, 1000, "number of holds on buffer"],
@@ -399,6 +400,7 @@ def update_dict(d, k, line, labels):
key = line[labels[k]]
dbsize = int(line[labels['dbsize']])
+ usize = int(line[labels['usize']])
blkid = int(line[labels['blkid']])
level = int(line[labels['level']])
@@ -416,7 +418,7 @@ def update_dict(d, k, line, labels):
d[pool][objset][key]['indirect'] = 0
d[pool][objset][key]['spill'] = 0
- d[pool][objset][key]['cached'] += dbsize
+ d[pool][objset][key]['cached'] += dbsize + usize
if blkid == -1:
d[pool][objset][key]['bonus'] += dbsize
diff --git a/cmd/mount_zfs.c b/cmd/mount_zfs.c
index 1f26a3f60353..fc9220950647 100644
--- a/cmd/mount_zfs.c
+++ b/cmd/mount_zfs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -74,7 +74,7 @@ parse_dataset(const char *target, char **dataset)
nvlist_t *cfg = NULL;
if (zpool_read_label(fd, &cfg, NULL) == 0) {
- char *nm = NULL;
+ const char *nm = NULL;
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
strlcpy(*dataset, nm, PATH_MAX);
nvlist_free(cfg);
diff --git a/cmd/raidz_test/raidz_bench.c b/cmd/raidz_test/raidz_bench.c
index 76f8e353c7f2..730e6e1a040b 100644
--- a/cmd/raidz_test/raidz_bench.c
+++ b/cmd/raidz_test/raidz_bench.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -84,10 +84,10 @@ run_gen_bench_impl(const char *impl)
if (rto_opts.rto_expand) {
rm_bench = vdev_raidz_map_alloc_expanded(
- zio_bench.io_abd,
- zio_bench.io_size, zio_bench.io_offset,
+ &zio_bench,
rto_opts.rto_ashift, ncols+1, ncols,
- fn+1, rto_opts.rto_expand_offset);
+ fn+1, rto_opts.rto_expand_offset,
+ 0, B_FALSE);
} else {
rm_bench = vdev_raidz_map_alloc(&zio_bench,
BENCH_ASHIFT, ncols, fn+1);
@@ -172,10 +172,10 @@ run_rec_bench_impl(const char *impl)
if (rto_opts.rto_expand) {
rm_bench = vdev_raidz_map_alloc_expanded(
- zio_bench.io_abd,
- zio_bench.io_size, zio_bench.io_offset,
+ &zio_bench,
BENCH_ASHIFT, ncols+1, ncols,
- PARITY_PQR, rto_opts.rto_expand_offset);
+ PARITY_PQR,
+ rto_opts.rto_expand_offset, 0, B_FALSE);
} else {
rm_bench = vdev_raidz_map_alloc(&zio_bench,
BENCH_ASHIFT, ncols, PARITY_PQR);
diff --git a/cmd/raidz_test/raidz_test.c b/cmd/raidz_test/raidz_test.c
index 8b21bc098e01..6a018ecf0737 100644
--- a/cmd/raidz_test/raidz_test.c
+++ b/cmd/raidz_test/raidz_test.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -146,8 +146,6 @@ static void process_options(int argc, char **argv)
memcpy(o, &rto_opts_defaults, sizeof (*o));
while ((opt = getopt(argc, argv, "TDBSvha:er:o:d:s:t:")) != -1) {
- value = 0;
-
switch (opt) {
case 'a':
value = strtoull(optarg, NULL, 0);
@@ -329,14 +327,12 @@ init_raidz_golden_map(raidz_test_opts_t *opts, const int parity)
if (opts->rto_expand) {
opts->rm_golden =
- vdev_raidz_map_alloc_expanded(opts->zio_golden->io_abd,
- opts->zio_golden->io_size, opts->zio_golden->io_offset,
+ vdev_raidz_map_alloc_expanded(opts->zio_golden,
opts->rto_ashift, total_ncols+1, total_ncols,
- parity, opts->rto_expand_offset);
- rm_test = vdev_raidz_map_alloc_expanded(zio_test->io_abd,
- zio_test->io_size, zio_test->io_offset,
+ parity, opts->rto_expand_offset, 0, B_FALSE);
+ rm_test = vdev_raidz_map_alloc_expanded(zio_test,
opts->rto_ashift, total_ncols+1, total_ncols,
- parity, opts->rto_expand_offset);
+ parity, opts->rto_expand_offset, 0, B_FALSE);
} else {
opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden,
opts->rto_ashift, total_ncols, parity);
@@ -363,187 +359,6 @@ init_raidz_golden_map(raidz_test_opts_t *opts, const int parity)
return (err);
}
-/*
- * If reflow is not in progress, reflow_offset should be UINT64_MAX.
- * For each row, if the row is entirely before reflow_offset, it will
- * come from the new location. Otherwise this row will come from the
- * old location. Therefore, rows that straddle the reflow_offset will
- * come from the old location.
- *
- * NOTE: Until raidz expansion is implemented this function is only
- * needed by raidz_test.c to the multi-row raid_map_t functionality.
- */
-raidz_map_t *
-vdev_raidz_map_alloc_expanded(abd_t *abd, uint64_t size, uint64_t offset,
- uint64_t ashift, uint64_t physical_cols, uint64_t logical_cols,
- uint64_t nparity, uint64_t reflow_offset)
-{
- /* The zio's size in units of the vdev's minimum sector size. */
- uint64_t s = size >> ashift;
- uint64_t q, r, bc, devidx, asize = 0, tot;
-
- /*
- * "Quotient": The number of data sectors for this stripe on all but
- * the "big column" child vdevs that also contain "remainder" data.
- * AKA "full rows"
- */
- q = s / (logical_cols - nparity);
-
- /*
- * "Remainder": The number of partial stripe data sectors in this I/O.
- * This will add a sector to some, but not all, child vdevs.
- */
- r = s - q * (logical_cols - nparity);
-
- /* The number of "big columns" - those which contain remainder data. */
- bc = (r == 0 ? 0 : r + nparity);
-
- /*
- * The total number of data and parity sectors associated with
- * this I/O.
- */
- tot = s + nparity * (q + (r == 0 ? 0 : 1));
-
- /* How many rows contain data (not skip) */
- uint64_t rows = howmany(tot, logical_cols);
- int cols = MIN(tot, logical_cols);
-
- raidz_map_t *rm = kmem_zalloc(offsetof(raidz_map_t, rm_row[rows]),
- KM_SLEEP);
- rm->rm_nrows = rows;
-
- for (uint64_t row = 0; row < rows; row++) {
- raidz_row_t *rr = kmem_alloc(offsetof(raidz_row_t,
- rr_col[cols]), KM_SLEEP);
- rm->rm_row[row] = rr;
-
- /* The starting RAIDZ (parent) vdev sector of the row. */
- uint64_t b = (offset >> ashift) + row * logical_cols;
-
- /*
- * If we are in the middle of a reflow, and any part of this
- * row has not been copied, then use the old location of
- * this row.
- */
- int row_phys_cols = physical_cols;
- if (b + (logical_cols - nparity) > reflow_offset >> ashift)
- row_phys_cols--;
-
- /* starting child of this row */
- uint64_t child_id = b % row_phys_cols;
- /* The starting byte offset on each child vdev. */
- uint64_t child_offset = (b / row_phys_cols) << ashift;
-
- /*
- * We set cols to the entire width of the block, even
- * if this row is shorter. This is needed because parity
- * generation (for Q and R) needs to know the entire width,
- * because it treats the short row as though it was
- * full-width (and the "phantom" sectors were zero-filled).
- *
- * Another approach to this would be to set cols shorter
- * (to just the number of columns that we might do i/o to)
- * and have another mechanism to tell the parity generation
- * about the "entire width". Reconstruction (at least
- * vdev_raidz_reconstruct_general()) would also need to
- * know about the "entire width".
- */
- rr->rr_cols = cols;
- rr->rr_bigcols = bc;
- rr->rr_missingdata = 0;
- rr->rr_missingparity = 0;
- rr->rr_firstdatacol = nparity;
- rr->rr_abd_empty = NULL;
- rr->rr_nempty = 0;
-
- for (int c = 0; c < rr->rr_cols; c++, child_id++) {
- if (child_id >= row_phys_cols) {
- child_id -= row_phys_cols;
- child_offset += 1ULL << ashift;
- }
- rr->rr_col[c].rc_devidx = child_id;
- rr->rr_col[c].rc_offset = child_offset;
- rr->rr_col[c].rc_orig_data = NULL;
- rr->rr_col[c].rc_error = 0;
- rr->rr_col[c].rc_tried = 0;
- rr->rr_col[c].rc_skipped = 0;
- rr->rr_col[c].rc_need_orig_restore = B_FALSE;
-
- uint64_t dc = c - rr->rr_firstdatacol;
- if (c < rr->rr_firstdatacol) {
- rr->rr_col[c].rc_size = 1ULL << ashift;
- rr->rr_col[c].rc_abd =
- abd_alloc_linear(rr->rr_col[c].rc_size,
- B_TRUE);
- } else if (row == rows - 1 && bc != 0 && c >= bc) {
- /*
- * Past the end, this for parity generation.
- */
- rr->rr_col[c].rc_size = 0;
- rr->rr_col[c].rc_abd = NULL;
- } else {
- /*
- * "data column" (col excluding parity)
- * Add an ASCII art diagram here
- */
- uint64_t off;
-
- if (c < bc || r == 0) {
- off = dc * rows + row;
- } else {
- off = r * rows +
- (dc - r) * (rows - 1) + row;
- }
- rr->rr_col[c].rc_size = 1ULL << ashift;
- rr->rr_col[c].rc_abd = abd_get_offset_struct(
- &rr->rr_col[c].rc_abdstruct,
- abd, off << ashift, 1 << ashift);
- }
-
- asize += rr->rr_col[c].rc_size;
- }
- /*
- * If all data stored spans all columns, there's a danger that
- * parity will always be on the same device and, since parity
- * isn't read during normal operation, that that device's I/O
- * bandwidth won't be used effectively. We therefore switch
- * the parity every 1MB.
- *
- * ...at least that was, ostensibly, the theory. As a practical
- * matter unless we juggle the parity between all devices
- * evenly, we won't see any benefit. Further, occasional writes
- * that aren't a multiple of the LCM of the number of children
- * and the minimum stripe width are sufficient to avoid pessimal
- * behavior. Unfortunately, this decision created an implicit
- * on-disk format requirement that we need to support for all
- * eternity, but only for single-parity RAID-Z.
- *
- * If we intend to skip a sector in the zeroth column for
- * padding we must make sure to note this swap. We will never
- * intend to skip the first column since at least one data and
- * one parity column must appear in each row.
- */
- if (rr->rr_firstdatacol == 1 && rr->rr_cols > 1 &&
- (offset & (1ULL << 20))) {
- ASSERT(rr->rr_cols >= 2);
- ASSERT(rr->rr_col[0].rc_size == rr->rr_col[1].rc_size);
- devidx = rr->rr_col[0].rc_devidx;
- uint64_t o = rr->rr_col[0].rc_offset;
- rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx;
- rr->rr_col[0].rc_offset = rr->rr_col[1].rc_offset;
- rr->rr_col[1].rc_devidx = devidx;
- rr->rr_col[1].rc_offset = o;
- }
-
- }
- ASSERT3U(asize, ==, tot << ashift);
-
- /* init RAIDZ parity ops */
- rm->rm_ops = vdev_raidz_math_get_ops();
-
- return (rm);
-}
-
static raidz_map_t *
init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
{
@@ -563,10 +378,9 @@ init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
init_zio_abd(*zio);
if (opts->rto_expand) {
- rm = vdev_raidz_map_alloc_expanded((*zio)->io_abd,
- (*zio)->io_size, (*zio)->io_offset,
+ rm = vdev_raidz_map_alloc_expanded(*zio,
opts->rto_ashift, total_ncols+1, total_ncols,
- parity, opts->rto_expand_offset);
+ parity, opts->rto_expand_offset, 0, B_FALSE);
} else {
rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift,
total_ncols, parity);
@@ -939,7 +753,7 @@ run_sweep(void)
opts = umem_zalloc(sizeof (raidz_test_opts_t), UMEM_NOFAIL);
opts->rto_ashift = ashift_v[a];
opts->rto_dcols = dcols_v[d];
- opts->rto_offset = (1 << ashift_v[a]) * rand();
+ opts->rto_offset = (1ULL << ashift_v[a]) * rand();
opts->rto_dsize = size_v[s];
opts->rto_expand = rto_opts.rto_expand;
opts->rto_expand_offset = rto_opts.rto_expand_offset;
diff --git a/cmd/raidz_test/raidz_test.h b/cmd/raidz_test/raidz_test.h
index 7059d985b329..f912e281f6f3 100644
--- a/cmd/raidz_test/raidz_test.h
+++ b/cmd/raidz_test/raidz_test.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -119,7 +119,4 @@ void init_zio_abd(zio_t *zio);
void run_raidz_benchmark(void);
-struct raidz_map *vdev_raidz_map_alloc_expanded(abd_t *, uint64_t, uint64_t,
- uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
-
#endif /* RAIDZ_TEST_H */
diff --git a/cmd/zdb/Makefile.am b/cmd/zdb/Makefile.am
index b80f38b3fd57..ebdc19128e1a 100644
--- a/cmd/zdb/Makefile.am
+++ b/cmd/zdb/Makefile.am
@@ -1,4 +1,5 @@
zdb_CPPFLAGS = $(AM_CPPFLAGS) $(FORCEDEBUG_CPPFLAGS)
+zdb_CFLAGS = $(AM_CFLAGS) $(LIBCRYPTO_CFLAGS)
sbin_PROGRAMS += zdb
CPPCHECKTARGETS += zdb
@@ -9,6 +10,9 @@ zdb_SOURCES = \
%D%/zdb_il.c
zdb_LDADD = \
+ libzdb.la \
libzpool.la \
libzfs_core.la \
libnvpair.la
+
+zdb_LDADD += $(LIBCRYPTO_LIBS)
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 13994c3bbf8a..449b6bf2ccb3 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,6 +33,8 @@
* under sponsorship from the FreeBSD Foundation.
* Copyright (c) 2021 Allan Jude
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
+ * Copyright (c) 2023, Klara Inc.
+ * Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
*/
#include <stdio.h>
@@ -40,6 +42,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <getopt.h>
+#include <openssl/evp.h>
#include <sys/zfs_context.h>
#include <sys/spa.h>
#include <sys/spa_impl.h>
@@ -71,96 +74,50 @@
#include <sys/arc.h>
#include <sys/arc_impl.h>
#include <sys/ddt.h>
+#include <sys/ddt_impl.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <sys/dsl_crypt.h>
#include <sys/dsl_scan.h>
#include <sys/btree.h>
+#include <sys/brt.h>
+#include <sys/brt_impl.h>
#include <zfs_comutil.h>
#include <sys/zstd/zstd.h>
#include <libnvpair.h>
#include <libzutil.h>
-#include "zdb.h"
+#include <libzdb.h>
-#define ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
- zio_compress_table[(idx)].ci_name : "UNKNOWN")
-#define ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
- zio_checksum_table[(idx)].ci_name : "UNKNOWN")
-#define ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : \
- (idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA ? \
- DMU_OT_ZAP_OTHER : \
- (idx) == DMU_OTN_UINT64_DATA || (idx) == DMU_OTN_UINT64_METADATA ? \
- DMU_OT_UINT64_OTHER : DMU_OT_NUMTYPES)
-
-/* Some platforms require part of inode IDs to be remapped */
-#ifdef __APPLE__
-#define ZDB_MAP_OBJECT_ID(obj) INO_XNUTOZFS(obj, 2)
-#else
-#define ZDB_MAP_OBJECT_ID(obj) (obj)
-#endif
+#include "zdb.h"
-static const char *
-zdb_ot_name(dmu_object_type_t type)
-{
- if (type < DMU_OT_NUMTYPES)
- return (dmu_ot[type].ot_name);
- else if ((type & DMU_OT_NEWTYPE) &&
- ((type & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS))
- return (dmu_ot_byteswap[type & DMU_OT_BYTESWAP_MASK].ob_name);
- else
- return ("UNKNOWN");
-}
extern int reference_tracking_enable;
extern int zfs_recover;
-extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
-extern int zfs_vdev_async_read_max_active;
+extern uint_t zfs_vdev_async_read_max_active;
extern boolean_t spa_load_verify_dryrun;
extern boolean_t spa_mode_readable_spacemaps;
-extern int zfs_reconstruct_indirect_combinations_max;
-extern int zfs_btree_verify_intensity;
+extern uint_t zfs_reconstruct_indirect_combinations_max;
+extern uint_t zfs_btree_verify_intensity;
static const char cmdname[] = "zdb";
uint8_t dump_opt[256];
typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
-uint64_t *zopt_metaslab = NULL;
+static uint64_t *zopt_metaslab = NULL;
static unsigned zopt_metaslab_args = 0;
-typedef struct zopt_object_range {
- uint64_t zor_obj_start;
- uint64_t zor_obj_end;
- uint64_t zor_flags;
-} zopt_object_range_t;
-zopt_object_range_t *zopt_object_ranges = NULL;
+
+static zopt_object_range_t *zopt_object_ranges = NULL;
static unsigned zopt_object_args = 0;
static int flagbits[256];
-#define ZOR_FLAG_PLAIN_FILE 0x0001
-#define ZOR_FLAG_DIRECTORY 0x0002
-#define ZOR_FLAG_SPACE_MAP 0x0004
-#define ZOR_FLAG_ZAP 0x0008
-#define ZOR_FLAG_ALL_TYPES -1
-#define ZOR_SUPPORTED_FLAGS (ZOR_FLAG_PLAIN_FILE | \
- ZOR_FLAG_DIRECTORY | \
- ZOR_FLAG_SPACE_MAP | \
- ZOR_FLAG_ZAP)
-#define ZDB_FLAG_CHECKSUM 0x0001
-#define ZDB_FLAG_DECOMPRESS 0x0002
-#define ZDB_FLAG_BSWAP 0x0004
-#define ZDB_FLAG_GBH 0x0008
-#define ZDB_FLAG_INDIRECT 0x0010
-#define ZDB_FLAG_RAW 0x0020
-#define ZDB_FLAG_PRINT_BLKPTR 0x0040
-#define ZDB_FLAG_VERBOSE 0x0080
-
-uint64_t max_inflight_bytes = 256 * 1024 * 1024; /* 256MB */
+static uint64_t max_inflight_bytes = 256 * 1024 * 1024; /* 256MB */
static int leaked_objects = 0;
static range_tree_t *mos_refd_objs;
@@ -171,62 +128,7 @@ static void mos_obj_refd_multiple(uint64_t);
static int dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t free,
dmu_tx_t *tx);
-typedef struct sublivelist_verify {
- /* FREE's that haven't yet matched to an ALLOC, in one sub-livelist */
- zfs_btree_t sv_pair;
-
- /* ALLOC's without a matching FREE, accumulates across sub-livelists */
- zfs_btree_t sv_leftover;
-} sublivelist_verify_t;
-
-static int
-livelist_compare(const void *larg, const void *rarg)
-{
- const blkptr_t *l = larg;
- const blkptr_t *r = rarg;
-
- /* Sort them according to dva[0] */
- uint64_t l_dva0_vdev, r_dva0_vdev;
- l_dva0_vdev = DVA_GET_VDEV(&l->blk_dva[0]);
- r_dva0_vdev = DVA_GET_VDEV(&r->blk_dva[0]);
- if (l_dva0_vdev < r_dva0_vdev)
- return (-1);
- else if (l_dva0_vdev > r_dva0_vdev)
- return (+1);
-
- /* if vdevs are equal, sort by offsets. */
- uint64_t l_dva0_offset;
- uint64_t r_dva0_offset;
- l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
- r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
- if (l_dva0_offset < r_dva0_offset) {
- return (-1);
- } else if (l_dva0_offset > r_dva0_offset) {
- return (+1);
- }
- /*
- * Since we're storing blkptrs without cancelling FREE/ALLOC pairs,
- * it's possible the offsets are equal. In that case, sort by txg
- */
- if (l->blk_birth < r->blk_birth) {
- return (-1);
- } else if (l->blk_birth > r->blk_birth) {
- return (+1);
- }
- return (0);
-}
-
-typedef struct sublivelist_verify_block {
- dva_t svb_dva;
-
- /*
- * We need this to check if the block marked as allocated
- * in the livelist was freed (and potentially reallocated)
- * in the metaslab spacemaps at a later TXG.
- */
- uint64_t svb_allocated_txg;
-} sublivelist_verify_block_t;
static void zdb_print_blkptr(const blkptr_t *bp, int flags);
@@ -297,7 +199,8 @@ sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
break;
sublivelist_verify_block_t svb = {
.svb_dva = bp->blk_dva[i],
- .svb_allocated_txg = bp->blk_birth
+ .svb_allocated_txg =
+ BP_GET_LOGICAL_BIRTH(bp)
};
if (zfs_btree_find(&sv->sv_leftover, &svb,
@@ -325,7 +228,7 @@ sublivelist_verify_func(void *args, dsl_deadlist_entry_t *dle)
int err;
struct sublivelist_verify *sv = args;
- zfs_btree_create(&sv->sv_pair, sublivelist_block_refcnt_compare,
+ zfs_btree_create(&sv->sv_pair, sublivelist_block_refcnt_compare, NULL,
sizeof (sublivelist_verify_block_refcnt_t));
err = bpobj_iterate_nofree(&dle->dle_bpobj, sublivelist_verify_blkptr,
@@ -389,7 +292,7 @@ sublivelist_verify_lightweight(void *args, dsl_deadlist_entry_t *dle)
{
(void) args;
sublivelist_verify_t sv;
- zfs_btree_create(&sv.sv_leftover, livelist_block_compare,
+ zfs_btree_create(&sv.sv_leftover, livelist_block_compare, NULL,
sizeof (sublivelist_verify_block_t));
int err = sublivelist_verify_func(&sv, dle);
zfs_btree_clear(&sv.sv_leftover);
@@ -467,7 +370,7 @@ static void
verify_livelist_allocs(metaslab_verify_t *mv, uint64_t txg,
uint64_t offset, uint64_t size)
{
- sublivelist_verify_block_t svb;
+ sublivelist_verify_block_t svb = {{{0}}};
DVA_SET_VDEV(&svb.svb_dva, mv->mv_vdid);
DVA_SET_OFFSET(&svb.svb_dva, offset);
DVA_SET_ASIZE(&svb.svb_dva, size);
@@ -681,7 +584,7 @@ livelist_metaslab_validate(spa_t *spa)
(void) printf("Verifying deleted livelist entries\n");
sublivelist_verify_t sv;
- zfs_btree_create(&sv.sv_leftover, livelist_block_compare,
+ zfs_btree_create(&sv.sv_leftover, livelist_block_compare, NULL,
sizeof (sublivelist_verify_block_t));
iterate_deleted_livelists(spa, livelist_verify, &sv);
@@ -715,7 +618,7 @@ livelist_metaslab_validate(spa_t *spa)
mv.mv_start = m->ms_start;
mv.mv_end = m->ms_start + m->ms_size;
zfs_btree_create(&mv.mv_livelist_allocs,
- livelist_block_compare,
+ livelist_block_compare, NULL,
sizeof (sublivelist_verify_block_t));
mv_populate_livelist_allocs(&mv, &sv);
@@ -784,23 +687,27 @@ usage(void)
"Usage:\t%s [-AbcdDFGhikLMPsvXy] [-e [-V] [-p <path> ...]] "
"[-I <inflight I/Os>]\n"
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
+ "\t\t[-K <key>]\n"
"\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]]\n"
- "\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
+ "\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] [-K <key>]\n"
"\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]\n"
+ "\t%s -B [-e [-V] [-p <path> ...]] [-I <inflight I/Os>]\n"
+ "\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
+ "\t\t[-K <key>] <poolname>/<objset id> [<backupflags>]\n"
"\t%s [-v] <bookmark>\n"
- "\t%s -C [-A] [-U <cache>]\n"
+ "\t%s -C [-A] [-U <cache>] [<poolname>]\n"
"\t%s -l [-Aqu] <device>\n"
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
- "\t%s -O <dataset> <path>\n"
- "\t%s -r <dataset> <path> <destination>\n"
+ "\t%s -O [-K <key>] <dataset> <path>\n"
+ "\t%s -r [-K <key>] <dataset> <path> <destination>\n"
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
"\t%s -E [-A] word0:word1:...:word15\n"
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
"<poolname>\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
- cmdname, cmdname, cmdname, cmdname);
+ cmdname, cmdname, cmdname, cmdname, cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
"separator character '/' or '@'\n");
@@ -823,6 +730,8 @@ usage(void)
(void) fprintf(stderr, " Options to control amount of output:\n");
(void) fprintf(stderr, " -b --block-stats "
"block statistics\n");
+ (void) fprintf(stderr, " -B --backup "
+ "backup stream\n");
(void) fprintf(stderr, " -c --checksum "
"checksum all metadata (twice for all data) blocks\n");
(void) fprintf(stderr, " -C --config "
@@ -878,6 +787,8 @@ usage(void)
(void) fprintf(stderr, " -I --inflight=INTEGER "
"specify the maximum number of checksumming I/Os "
"[default is 200]\n");
+ (void) fprintf(stderr, " -K --key=KEY "
+ "decryption key for encrypted dataset\n");
(void) fprintf(stderr, " -o --option=\"OPTION=INTEGER\" "
"set global variable to an unsigned 32-bit integer\n");
(void) fprintf(stderr, " -p --path==PATH "
@@ -888,6 +799,8 @@ usage(void)
"don't print label contents\n");
(void) fprintf(stderr, " -t --txg=INTEGER "
"highest txg to use when searching for uberblocks\n");
+ (void) fprintf(stderr, " -T --brt-stats "
+ "BRT statistics\n");
(void) fprintf(stderr, " -u --uberblock "
"uberblock\n");
(void) fprintf(stderr, " -U --cachefile=PATH "
@@ -985,7 +898,16 @@ zdb_nicenum(uint64_t num, char *buf, size_t buflen)
if (dump_opt['P'])
(void) snprintf(buf, buflen, "%llu", (longlong_t)num);
else
- nicenum(num, buf, sizeof (buf));
+ nicenum(num, buf, buflen);
+}
+
+static void
+zdb_nicebytes(uint64_t bytes, char *buf, size_t buflen)
+{
+ if (dump_opt['P'])
+ (void) snprintf(buf, buflen, "%llu", (longlong_t)bytes);
+ else
+ zfs_nicebytes(bytes, buf, buflen);
}
static const char histo_stars[] = "****************************************";
@@ -1000,11 +922,13 @@ dump_histogram(const uint64_t *histo, int size, int offset)
uint64_t max = 0;
for (i = 0; i < size; i++) {
+ if (histo[i] == 0)
+ continue;
if (histo[i] > max)
max = histo[i];
- if (histo[i] > 0 && i > maxidx)
+ if (i > maxidx)
maxidx = i;
- if (histo[i] > 0 && i < minidx)
+ if (i < minidx)
minidx = i;
}
@@ -1137,6 +1061,8 @@ dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
}
if (size == 0) {
+ if (data == NULL)
+ kmem_free(arr, oursize);
(void) printf("\t\t[]\n");
return;
}
@@ -1980,7 +1906,7 @@ dump_dedup_ratio(const ddt_stat_t *dds)
}
static void
-dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
+dump_ddt(ddt_t *ddt, ddt_type_t type, ddt_class_t class)
{
char name[DDT_NAMELEN];
ddt_entry_t dde;
@@ -2040,8 +1966,10 @@ dump_all_ddts(spa_t *spa)
for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
ddt_t *ddt = spa->spa_ddt[c];
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES;
+ if (!ddt)
+ continue;
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES;
class++) {
dump_ddt(ddt, type, class);
}
@@ -2067,6 +1995,76 @@ dump_all_ddts(spa_t *spa)
}
static void
+dump_brt(spa_t *spa)
+{
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_BLOCK_CLONING)) {
+ printf("BRT: unsupported on this pool\n");
+ return;
+ }
+
+ if (!spa_feature_is_active(spa, SPA_FEATURE_BLOCK_CLONING)) {
+ printf("BRT: empty\n");
+ return;
+ }
+
+ brt_t *brt = spa->spa_brt;
+ VERIFY(brt);
+
+ char count[32], used[32], saved[32];
+ zdb_nicebytes(brt_get_used(spa), used, sizeof (used));
+ zdb_nicebytes(brt_get_saved(spa), saved, sizeof (saved));
+ uint64_t ratio = brt_get_ratio(spa);
+ printf("BRT: used %s; saved %s; ratio %llu.%02llux\n", used, saved,
+ (u_longlong_t)(ratio / 100), (u_longlong_t)(ratio % 100));
+
+ if (dump_opt['T'] < 2)
+ return;
+
+ for (uint64_t vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brt_vdev_t *brtvd = &brt->brt_vdevs[vdevid];
+ if (brtvd == NULL)
+ continue;
+
+ if (!brtvd->bv_initiated) {
+ printf("BRT: vdev %" PRIu64 ": empty\n", vdevid);
+ continue;
+ }
+
+ zdb_nicenum(brtvd->bv_totalcount, count, sizeof (count));
+ zdb_nicebytes(brtvd->bv_usedspace, used, sizeof (used));
+ zdb_nicebytes(brtvd->bv_savedspace, saved, sizeof (saved));
+ printf("BRT: vdev %" PRIu64 ": refcnt %s; used %s; saved %s\n",
+ vdevid, count, used, saved);
+ }
+
+ if (dump_opt['T'] < 3)
+ return;
+
+ char dva[64];
+ printf("\n%-16s %-10s\n", "DVA", "REFCNT");
+
+ for (uint64_t vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brt_vdev_t *brtvd = &brt->brt_vdevs[vdevid];
+ if (brtvd == NULL || !brtvd->bv_initiated)
+ continue;
+
+ zap_cursor_t zc;
+ zap_attribute_t za;
+ for (zap_cursor_init(&zc, brt->brt_mos, brtvd->bv_mos_entries);
+ zap_cursor_retrieve(&zc, &za) == 0;
+ zap_cursor_advance(&zc)) {
+ uint64_t offset = *(uint64_t *)za.za_name;
+ uint64_t refcnt = za.za_first_integer;
+
+ snprintf(dva, sizeof (dva), "%" PRIu64 ":%llx", vdevid,
+ (u_longlong_t)offset);
+ printf("%-16s %-10llu\n", dva, (u_longlong_t)refcnt);
+ }
+ zap_cursor_fini(&zc);
+ }
+}
+
+static void
dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
{
char *prefix = arg;
@@ -2262,7 +2260,7 @@ static void
snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
const blkptr_t *bp)
{
- abd_t *pabd;
+ static abd_t *pabd = NULL;
void *buf;
zio_t *zio;
zfs_zstdhdr_t zstd_hdr;
@@ -2293,7 +2291,8 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
return;
}
- pabd = abd_alloc_for_io(SPA_MAXBLOCKSIZE, B_FALSE);
+ if (!pabd)
+ pabd = abd_alloc_for_io(SPA_MAXBLOCKSIZE, B_FALSE);
zio = zio_root(spa, NULL, NULL, 0);
/* Decrypt but don't decompress so we can read the compression header */
@@ -2342,7 +2341,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
(int)BPE_GET_ETYPE(bp),
(u_longlong_t)BPE_GET_LSIZE(bp),
(u_longlong_t)BPE_GET_PSIZE(bp),
- (u_longlong_t)bp->blk_birth);
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp));
return;
}
@@ -2360,7 +2359,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
buflen - strlen(blkbuf),
"%llxL B=%llu",
(u_longlong_t)BP_GET_LSIZE(bp),
- (u_longlong_t)bp->blk_birth);
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp));
} else {
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf),
@@ -2368,13 +2367,14 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
(u_longlong_t)BP_GET_LSIZE(bp),
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)BP_GET_FILL(bp),
- (u_longlong_t)bp->blk_birth,
- (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp),
+ (u_longlong_t)BP_GET_BIRTH(bp));
if (bp_freed)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), " %s", "FREE");
(void) snprintf(blkbuf + strlen(blkbuf),
- buflen - strlen(blkbuf), " cksum=%llx:%llx:%llx:%llx",
+ buflen - strlen(blkbuf),
+ " cksum=%016llx:%016llx:%016llx:%016llx",
(u_longlong_t)bp->blk_cksum.zc_word[0],
(u_longlong_t)bp->blk_cksum.zc_word[1],
(u_longlong_t)bp->blk_cksum.zc_word[2],
@@ -2418,7 +2418,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
{
int err = 0;
- if (bp->blk_birth == 0)
+ if (BP_GET_LOGICAL_BIRTH(bp) == 0)
return (0);
print_indirect(spa, bp, zb, dnp);
@@ -2606,7 +2606,7 @@ dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- if (bp->blk_birth != 0) {
+ if (BP_GET_LOGICAL_BIRTH(bp) != 0) {
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
}
@@ -2647,7 +2647,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- ASSERT(bp->blk_birth != 0);
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) != 0);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp, bp_freed);
(void) printf("\t%s\n", blkbuf);
return (0);
@@ -2855,9 +2855,11 @@ dump_bookmarks(objset_t *os, int verbosity)
zap_cursor_advance(&zc)) {
char osname[ZFS_MAX_DATASET_NAME_LEN];
char buf[ZFS_MAX_DATASET_NAME_LEN];
+ int len;
dmu_objset_name(os, osname);
- VERIFY3S(0, <=, snprintf(buf, sizeof (buf), "%s#%s", osname,
- attr.za_name));
+ len = snprintf(buf, sizeof (buf), "%s#%s", osname,
+ attr.za_name);
+ VERIFY3S(len, <, ZFS_MAX_DATASET_NAME_LEN);
(void) dump_bookmark(dp, buf, verbosity >= 5, verbosity >= 6);
}
zap_cursor_fini(&zc);
@@ -3017,6 +3019,118 @@ verify_dd_livelist(objset_t *os)
return (0);
}
+static char *key_material = NULL;
+
+static boolean_t
+zdb_derive_key(dsl_dir_t *dd, uint8_t *key_out)
+{
+ uint64_t keyformat, salt, iters;
+ int i;
+ unsigned char c;
+
+ VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj,
+ zfs_prop_to_name(ZFS_PROP_KEYFORMAT), sizeof (uint64_t),
+ 1, &keyformat));
+
+ switch (keyformat) {
+ case ZFS_KEYFORMAT_HEX:
+ for (i = 0; i < WRAPPING_KEY_LEN * 2; i += 2) {
+ if (!isxdigit(key_material[i]) ||
+ !isxdigit(key_material[i+1]))
+ return (B_FALSE);
+ if (sscanf(&key_material[i], "%02hhx", &c) != 1)
+ return (B_FALSE);
+ key_out[i / 2] = c;
+ }
+ break;
+
+ case ZFS_KEYFORMAT_PASSPHRASE:
+ VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset,
+ dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT),
+ sizeof (uint64_t), 1, &salt));
+ VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset,
+ dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS),
+ sizeof (uint64_t), 1, &iters));
+
+ if (PKCS5_PBKDF2_HMAC_SHA1(key_material, strlen(key_material),
+ ((uint8_t *)&salt), sizeof (uint64_t), iters,
+ WRAPPING_KEY_LEN, key_out) != 1)
+ return (B_FALSE);
+
+ break;
+
+ default:
+ fatal("no support for key format %u\n",
+ (unsigned int) keyformat);
+ }
+
+ return (B_TRUE);
+}
+
+static char encroot[ZFS_MAX_DATASET_NAME_LEN];
+static boolean_t key_loaded = B_FALSE;
+
+static void
+zdb_load_key(objset_t *os)
+{
+ dsl_pool_t *dp;
+ dsl_dir_t *dd, *rdd;
+ uint8_t key[WRAPPING_KEY_LEN];
+ uint64_t rddobj;
+ int err;
+
+ dp = spa_get_dsl(os->os_spa);
+ dd = os->os_dsl_dataset->ds_dir;
+
+ dsl_pool_config_enter(dp, FTAG);
+ VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj,
+ DSL_CRYPTO_KEY_ROOT_DDOBJ, sizeof (uint64_t), 1, &rddobj));
+ VERIFY0(dsl_dir_hold_obj(dd->dd_pool, rddobj, NULL, FTAG, &rdd));
+ dsl_dir_name(rdd, encroot);
+ dsl_dir_rele(rdd, FTAG);
+
+ if (!zdb_derive_key(dd, key))
+ fatal("couldn't derive encryption key");
+
+ dsl_pool_config_exit(dp, FTAG);
+
+ ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_UNAVAILABLE);
+
+ dsl_crypto_params_t *dcp;
+ nvlist_t *crypto_args;
+
+ crypto_args = fnvlist_alloc();
+ fnvlist_add_uint8_array(crypto_args, "wkeydata",
+ (uint8_t *)key, WRAPPING_KEY_LEN);
+ VERIFY0(dsl_crypto_params_create_nvlist(DCP_CMD_NONE,
+ NULL, crypto_args, &dcp));
+ err = spa_keystore_load_wkey(encroot, dcp, B_FALSE);
+
+ dsl_crypto_params_free(dcp, (err != 0));
+ fnvlist_free(crypto_args);
+
+ if (err != 0)
+ fatal(
+ "couldn't load encryption key for %s: %s",
+ encroot, err == ZFS_ERR_CRYPTO_NOTSUP ?
+ "crypto params not supported" : strerror(err));
+
+ ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_AVAILABLE);
+
+ printf("Unlocked encryption root: %s\n", encroot);
+ key_loaded = B_TRUE;
+}
+
+static void
+zdb_unload_key(void)
+{
+ if (!key_loaded)
+ return;
+
+ VERIFY0(spa_keystore_unload_wkey(encroot));
+ key_loaded = B_FALSE;
+}
+
static avl_tree_t idx_tree;
static avl_tree_t domain_tree;
static boolean_t fuid_table_loaded;
@@ -3031,12 +3145,36 @@ open_objset(const char *path, const void *tag, objset_t **osp)
uint64_t version = 0;
VERIFY3P(sa_os, ==, NULL);
+
/*
* We can't own an objset if it's redacted. Therefore, we do this
* dance: hold the objset, then acquire a long hold on its dataset, then
* release the pool (which is held as part of holding the objset).
*/
- err = dmu_objset_hold(path, tag, osp);
+
+ if (dump_opt['K']) {
+ /* decryption requested, try to load keys */
+ err = dmu_objset_hold(path, tag, osp);
+ if (err != 0) {
+ (void) fprintf(stderr, "failed to hold dataset "
+ "'%s': %s\n",
+ path, strerror(err));
+ return (err);
+ }
+ dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
+ dsl_pool_rele(dmu_objset_pool(*osp), tag);
+
+ /* succeeds or dies */
+ zdb_load_key(*osp);
+
+ /* release it all */
+ dsl_dataset_long_rele(dmu_objset_ds(*osp), tag);
+ dsl_dataset_rele(dmu_objset_ds(*osp), tag);
+ }
+
+ int ds_hold_flags = key_loaded ? DS_HOLD_FLAG_DECRYPT : 0;
+
+ err = dmu_objset_hold_flags(path, ds_hold_flags, tag, osp);
if (err != 0) {
(void) fprintf(stderr, "failed to hold dataset '%s': %s\n",
path, strerror(err));
@@ -3045,7 +3183,8 @@ open_objset(const char *path, const void *tag, objset_t **osp)
dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
dsl_pool_rele(dmu_objset_pool(*osp), tag);
- if (dmu_objset_type(*osp) == DMU_OST_ZFS && !(*osp)->os_encrypted) {
+ if (dmu_objset_type(*osp) == DMU_OST_ZFS &&
+ (key_loaded || !(*osp)->os_encrypted)) {
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
8, 1, &version);
if (version >= ZPL_VERSION_SA) {
@@ -3058,13 +3197,14 @@ open_objset(const char *path, const void *tag, objset_t **osp)
(void) fprintf(stderr, "sa_setup failed: %s\n",
strerror(err));
dsl_dataset_long_rele(dmu_objset_ds(*osp), tag);
- dsl_dataset_rele(dmu_objset_ds(*osp), tag);
+ dsl_dataset_rele_flags(dmu_objset_ds(*osp),
+ ds_hold_flags, tag);
*osp = NULL;
}
}
sa_os = *osp;
- return (0);
+ return (err);
}
static void
@@ -3074,9 +3214,12 @@ close_objset(objset_t *os, const void *tag)
if (os->os_sa != NULL)
sa_tear_down(os);
dsl_dataset_long_rele(dmu_objset_ds(os), tag);
- dsl_dataset_rele(dmu_objset_ds(os), tag);
+ dsl_dataset_rele_flags(dmu_objset_ds(os),
+ key_loaded ? DS_HOLD_FLAG_DECRYPT : 0, tag);
sa_attr_table = NULL;
sa_os = NULL;
+
+ zdb_unload_key();
}
static void
@@ -3170,13 +3313,22 @@ dump_znode_sa_xattr(sa_handle_t *hdl)
(void) printf("\tSA xattrs: %d bytes, %d entries\n\n",
sa_xattr_size, sa_xattr_entries);
while ((elem = nvlist_next_nvpair(sa_xattr, elem)) != NULL) {
+ boolean_t can_print = !dump_opt['P'];
uchar_t *value;
uint_t cnt, idx;
(void) printf("\t\t%s = ", nvpair_name(elem));
nvpair_value_byte_array(elem, &value, &cnt);
+
+ for (idx = 0; idx < cnt; ++idx) {
+ if (!isprint(value[idx])) {
+ can_print = B_FALSE;
+ break;
+ }
+ }
+
for (idx = 0; idx < cnt; ++idx) {
- if (isprint(value[idx]))
+ if (can_print)
(void) putchar(value[idx]);
else
(void) printf("\\%3.3o", value[idx]);
@@ -3458,7 +3610,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity,
if (error)
fatal("dmu_object_info() failed, errno %u", error);
- if (os->os_encrypted &&
+ if (!key_loaded && os->os_encrypted &&
DMU_OT_IS_ENCRYPTED(doi.doi_bonus_type)) {
error = dnode_hold(os, object, FTAG, &dn);
if (error)
@@ -3491,9 +3643,9 @@ dump_object(objset_t *os, uint64_t object, int verbosity,
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
zdb_nicenum(doi.doi_dnodesize, dnsize, sizeof (dnsize));
- (void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
- doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
- doi.doi_max_offset);
+ (void) snprintf(fill, sizeof (fill), "%6.2f", 100.0 *
+ doi.doi_fill_count * doi.doi_data_block_size / (object == 0 ?
+ DNODES_PER_BLOCK : 1) / doi.doi_max_offset);
aux[0] = '\0';
@@ -3555,7 +3707,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity,
(void) printf("\t\t(bonus encrypted)\n");
}
- if (!os->os_encrypted || !DMU_OT_IS_ENCRYPTED(doi.doi_type)) {
+ if (key_loaded ||
+ (!os->os_encrypted || !DMU_OT_IS_ENCRYPTED(doi.doi_type))) {
object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object,
NULL, 0);
} else {
@@ -3565,8 +3718,15 @@ dump_object(objset_t *os, uint64_t object, int verbosity,
*print_header = B_TRUE;
}
- if (verbosity >= 5)
+ if (verbosity >= 5) {
+ if (dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
+ char blkbuf[BP_SPRINTF_LEN];
+ snprintf_blkptr_compact(blkbuf, sizeof (blkbuf),
+ DN_SPILL_BLKPTR(dn->dn_phys), B_FALSE);
+ (void) printf("\nSpill block: %s\n", blkbuf);
+ }
dump_indirect(dn);
+ }
if (verbosity >= 5) {
/*
@@ -3958,6 +4118,11 @@ dump_uberblock(uberblock_t *ub, const char *header, const char *footer)
}
(void) printf("\tcheckpoint_txg = %llu\n",
(u_longlong_t)ub->ub_checkpoint_txg);
+
+ (void) printf("\traidz_reflow state=%u off=%llu\n",
+ (int)RRSS_GET_STATE(ub),
+ (u_longlong_t)RRSS_GET_OFFSET(ub));
+
(void) printf("%s", footer ? footer : "");
}
@@ -4049,7 +4214,7 @@ collect_nvlist_stats(nvlist_t *nvl, zdb_nvl_stats_t *stats)
{
nvlist_t *list, **array;
nvpair_t *nvp = NULL;
- char *name;
+ const char *name;
uint_t i, items;
stats->zns_list_count++;
@@ -4329,26 +4494,26 @@ dump_l2arc_log_entries(uint64_t log_entries,
}
static void
-dump_l2arc_log_blkptr(l2arc_log_blkptr_t lbps)
+dump_l2arc_log_blkptr(const l2arc_log_blkptr_t *lbps)
{
- (void) printf("|\t\tdaddr: %llu\n", (u_longlong_t)lbps.lbp_daddr);
+ (void) printf("|\t\tdaddr: %llu\n", (u_longlong_t)lbps->lbp_daddr);
(void) printf("|\t\tpayload_asize: %llu\n",
- (u_longlong_t)lbps.lbp_payload_asize);
+ (u_longlong_t)lbps->lbp_payload_asize);
(void) printf("|\t\tpayload_start: %llu\n",
- (u_longlong_t)lbps.lbp_payload_start);
+ (u_longlong_t)lbps->lbp_payload_start);
(void) printf("|\t\tlsize: %llu\n",
- (u_longlong_t)L2BLK_GET_LSIZE((&lbps)->lbp_prop));
+ (u_longlong_t)L2BLK_GET_LSIZE(lbps->lbp_prop));
(void) printf("|\t\tasize: %llu\n",
- (u_longlong_t)L2BLK_GET_PSIZE((&lbps)->lbp_prop));
+ (u_longlong_t)L2BLK_GET_PSIZE(lbps->lbp_prop));
(void) printf("|\t\tcompralgo: %llu\n",
- (u_longlong_t)L2BLK_GET_COMPRESS((&lbps)->lbp_prop));
+ (u_longlong_t)L2BLK_GET_COMPRESS(lbps->lbp_prop));
(void) printf("|\t\tcksumalgo: %llu\n",
- (u_longlong_t)L2BLK_GET_CHECKSUM((&lbps)->lbp_prop));
+ (u_longlong_t)L2BLK_GET_CHECKSUM(lbps->lbp_prop));
(void) printf("|\n\n");
}
static void
-dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
+dump_l2arc_log_blocks(int fd, const l2arc_dev_hdr_phys_t *l2dhdr,
l2arc_dev_hdr_phys_t *rebuild)
{
l2arc_log_blk_phys_t this_lb;
@@ -4361,13 +4526,13 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
if (!dump_opt['q'])
print_l2arc_log_blocks();
- memcpy(lbps, l2dhdr.dh_start_lbps, sizeof (lbps));
+ memcpy(lbps, l2dhdr->dh_start_lbps, sizeof (lbps));
- dev.l2ad_evict = l2dhdr.dh_evict;
- dev.l2ad_start = l2dhdr.dh_start;
- dev.l2ad_end = l2dhdr.dh_end;
+ dev.l2ad_evict = l2dhdr->dh_evict;
+ dev.l2ad_start = l2dhdr->dh_start;
+ dev.l2ad_end = l2dhdr->dh_end;
- if (l2dhdr.dh_start_lbps[0].lbp_daddr == 0) {
+ if (l2dhdr->dh_start_lbps[0].lbp_daddr == 0) {
/* no log blocks to read */
if (!dump_opt['q']) {
(void) printf("No log blocks to read\n");
@@ -4379,7 +4544,7 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
L2BLK_GET_PSIZE((&lbps[0])->lbp_prop);
}
- dev.l2ad_first = !!(l2dhdr.dh_flags & L2ARC_DEV_HDR_EVICT_FIRST);
+ dev.l2ad_first = !!(l2dhdr->dh_flags & L2ARC_DEV_HDR_EVICT_FIRST);
for (;;) {
if (!l2arc_log_blkptr_valid(&dev, &lbps[0]))
@@ -4400,7 +4565,7 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
failed++;
if (!dump_opt['q']) {
(void) printf("Invalid cksum\n");
- dump_l2arc_log_blkptr(lbps[0]);
+ dump_l2arc_log_blkptr(&lbps[0]);
}
break;
}
@@ -4411,9 +4576,14 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
default:
abd = abd_alloc_for_io(asize, B_TRUE);
abd_copy_from_buf_off(abd, &this_lb, 0, asize);
- zio_decompress_data(L2BLK_GET_COMPRESS(
+ if (zio_decompress_data(L2BLK_GET_COMPRESS(
(&lbps[0])->lbp_prop), abd, &this_lb,
- asize, sizeof (this_lb), NULL);
+ asize, sizeof (this_lb), NULL) != 0) {
+ (void) printf("L2ARC block decompression "
+ "failed\n");
+ abd_free(abd);
+ goto out;
+ }
abd_free(abd);
break;
}
@@ -4432,11 +4602,11 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
(void) printf("lb[%4llu]\tmagic: %llu\n",
(u_longlong_t)rebuild->dh_lb_count,
(u_longlong_t)this_lb.lb_magic);
- dump_l2arc_log_blkptr(lbps[0]);
+ dump_l2arc_log_blkptr(&lbps[0]);
}
if (dump_opt['l'] > 2 && !dump_opt['q'])
- dump_l2arc_log_entries(l2dhdr.dh_log_entries,
+ dump_l2arc_log_entries(l2dhdr->dh_log_entries,
this_lb.lb_entries,
rebuild->dh_lb_count);
@@ -4448,7 +4618,7 @@ dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr,
lbps[0] = lbps[1];
lbps[1] = this_lb.lb_prev_lbp;
}
-
+out:
if (!dump_opt['q']) {
(void) printf("log_blk_count:\t %llu with valid cksum\n",
(u_longlong_t)rebuild->dh_lb_count);
@@ -4514,7 +4684,7 @@ dump_l2arc_header(int fd)
(u_longlong_t)l2dhdr.dh_trim_state);
}
- dump_l2arc_log_blocks(fd, l2dhdr, &rebuild);
+ dump_l2arc_log_blocks(fd, &l2dhdr, &rebuild);
/*
* The total aligned size of log blocks and the number of log blocks
* reported in the header of the device may be less than what zdb
@@ -4702,6 +4872,81 @@ dump_path(char *ds, char *path, uint64_t *retobj)
}
static int
+dump_backup_bytes(objset_t *os, void *buf, int len, void *arg)
+{
+ const char *p = (const char *)buf;
+ ssize_t nwritten;
+
+ (void) os;
+ (void) arg;
+
+ /* Write the data out, handling short writes and signals. */
+ while ((nwritten = write(STDOUT_FILENO, p, len)) < len) {
+ if (nwritten < 0) {
+ if (errno == EINTR)
+ continue;
+ return (errno);
+ }
+ p += nwritten;
+ len -= nwritten;
+ }
+
+ return (0);
+}
+
+static void
+dump_backup(const char *pool, uint64_t objset_id, const char *flagstr)
+{
+ boolean_t embed = B_FALSE;
+ boolean_t large_block = B_FALSE;
+ boolean_t compress = B_FALSE;
+ boolean_t raw = B_FALSE;
+
+ const char *c;
+ for (c = flagstr; c != NULL && *c != '\0'; c++) {
+ switch (*c) {
+ case 'e':
+ embed = B_TRUE;
+ break;
+ case 'L':
+ large_block = B_TRUE;
+ break;
+ case 'c':
+ compress = B_TRUE;
+ break;
+ case 'w':
+ raw = B_TRUE;
+ break;
+ default:
+ fprintf(stderr, "dump_backup: invalid flag "
+ "'%c'\n", *c);
+ return;
+ }
+ }
+
+ if (isatty(STDOUT_FILENO)) {
+ fprintf(stderr, "dump_backup: stream cannot be written "
+ "to a terminal\n");
+ return;
+ }
+
+ offset_t off = 0;
+ dmu_send_outparams_t out = {
+ .dso_outfunc = dump_backup_bytes,
+ .dso_dryrun = B_FALSE,
+ };
+
+ int err = dmu_send_obj(pool, objset_id, /* fromsnap */0, embed,
+ large_block, compress, raw, /* saved */ B_FALSE, STDOUT_FILENO,
+ &off, &out);
+ if (err != 0) {
+ fprintf(stderr, "dump_backup: dmu_send_obj: %s\n",
+ strerror(err));
+ return;
+ }
+}
+
+static int
zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
{
int err = 0;
@@ -4730,6 +4975,8 @@ zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
}
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1)
+ return (errno);
/*
* We cap the size at 1 mebibyte here to prevent
* allocation failures and nigh-infinite printing if the
@@ -4739,6 +4986,7 @@ zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
offset = 0;
char *buf = kmem_alloc(oursize, KM_NOSLEEP);
if (buf == NULL) {
+ (void) close(fd);
return (ENOMEM);
}
@@ -4748,6 +4996,7 @@ zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
if (err != 0) {
(void) printf("got error %u from dmu_read\n", err);
kmem_free(buf, oursize);
+ (void) close(fd);
return (err);
}
if (dump_opt['v'] > 3) {
@@ -4919,7 +5168,7 @@ dump_label(const char *dev)
if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0)
size = buflen;
- /* If the device is a cache device clear the header. */
+ /* If the device is a cache device read the header. */
if (!read_l2arc_header) {
if (nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 &&
@@ -5033,8 +5282,18 @@ dump_one_objset(const char *dsname, void *arg)
avl_first(&dmu_objset_ds(os)->ds_bookmarks); dbn != NULL;
dbn = AVL_NEXT(&dmu_objset_ds(os)->ds_bookmarks, dbn)) {
mos_obj_refd(dbn->dbn_phys.zbm_redaction_obj);
- if (dbn->dbn_phys.zbm_redaction_obj != 0)
- global_feature_count[SPA_FEATURE_REDACTION_BOOKMARKS]++;
+ if (dbn->dbn_phys.zbm_redaction_obj != 0) {
+ global_feature_count[
+ SPA_FEATURE_REDACTION_BOOKMARKS]++;
+ objset_t *mos = os->os_spa->spa_meta_objset;
+ dnode_t *rl;
+ VERIFY0(dnode_hold(mos,
+ dbn->dbn_phys.zbm_redaction_obj, FTAG, &rl));
+ if (rl->dn_have_spill) {
+ global_feature_count[
+ SPA_FEATURE_REDACTION_LIST_SPILL]++;
+ }
+ }
if (dbn->dbn_phys.zbm_flags & ZBM_FLAG_HAS_FBN)
global_feature_count[SPA_FEATURE_BOOKMARK_WRITTEN]++;
}
@@ -5083,12 +5342,20 @@ static const char *zdb_ot_extname[] = {
#define ZB_TOTAL DN_MAX_LEVELS
#define SPA_MAX_FOR_16M (SPA_MAXBLOCKSHIFT+1)
+typedef struct zdb_brt_entry {
+ dva_t zbre_dva;
+ uint64_t zbre_refcount;
+ avl_node_t zbre_node;
+} zdb_brt_entry_t;
+
typedef struct zdb_cb {
zdb_blkstats_t zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1];
uint64_t zcb_removing_size;
uint64_t zcb_checkpoint_size;
uint64_t zcb_dedup_asize;
uint64_t zcb_dedup_blocks;
+ uint64_t zcb_clone_asize;
+ uint64_t zcb_clone_blocks;
uint64_t zcb_psize_count[SPA_MAX_FOR_16M];
uint64_t zcb_lsize_count[SPA_MAX_FOR_16M];
uint64_t zcb_asize_count[SPA_MAX_FOR_16M];
@@ -5109,6 +5376,8 @@ typedef struct zdb_cb {
int zcb_haderrors;
spa_t *zcb_spa;
uint32_t **zcb_vd_obsolete_counts;
+ avl_tree_t zcb_brt;
+ boolean_t zcb_brt_is_active;
} zdb_cb_t;
/* test if two DVA offsets from same vdev are within the same metaslab */
@@ -5403,6 +5672,45 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
zcb->zcb_asize_len[bin] += BP_GET_ASIZE(bp);
zcb->zcb_asize_total += BP_GET_ASIZE(bp);
+ if (zcb->zcb_brt_is_active && brt_maybe_exists(zcb->zcb_spa, bp)) {
+ /*
+ * Cloned blocks are special. We need to count them, so we can
+ * later uncount them when reporting leaked space, and we must
+ * only claim them them once.
+ *
+ * To do this, we keep our own in-memory BRT. For each block
+ * we haven't seen before, we look it up in the real BRT and
+ * if its there, we note it and its refcount then proceed as
+ * normal. If we see the block again, we count it as a clone
+ * and then give it no further consideration.
+ */
+ zdb_brt_entry_t zbre_search, *zbre;
+ avl_index_t where;
+
+ zbre_search.zbre_dva = bp->blk_dva[0];
+ zbre = avl_find(&zcb->zcb_brt, &zbre_search, &where);
+ if (zbre != NULL) {
+ zcb->zcb_clone_asize += BP_GET_ASIZE(bp);
+ zcb->zcb_clone_blocks++;
+
+ zbre->zbre_refcount--;
+ if (zbre->zbre_refcount == 0) {
+ avl_remove(&zcb->zcb_brt, zbre);
+ umem_free(zbre, sizeof (zdb_brt_entry_t));
+ }
+ return;
+ }
+
+ uint64_t crefcnt = brt_entry_get_refcount(zcb->zcb_spa, bp);
+ if (crefcnt > 0) {
+ zbre = umem_zalloc(sizeof (zdb_brt_entry_t),
+ UMEM_NOFAIL);
+ zbre->zbre_dva = bp->blk_dva[0];
+ zbre->zbre_refcount = crefcnt;
+ avl_insert(&zcb->zcb_brt, zbre, where);
+ }
+ }
+
if (dump_opt['L'])
return;
@@ -5481,7 +5789,7 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
if (zb->zb_level == ZB_DNODE_LEVEL)
return (0);
- if (dump_opt['b'] >= 5 && bp->blk_birth > 0) {
+ if (dump_opt['b'] >= 5 && BP_GET_LOGICAL_BIRTH(bp) > 0) {
char blkbuf[BP_SPRINTF_LEN];
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("objset %llu object %llu "
@@ -5757,6 +6065,8 @@ zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb)
return;
ASSERT(ddt_phys_total_refcnt(&dde) > 1);
+ ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum];
+ VERIFY(ddt);
for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
if (ddp->ddp_phys_birth == 0)
@@ -5771,7 +6081,7 @@ zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb)
zcb->zcb_dedup_blocks++;
}
}
- ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum];
+
ddt_enter(ddt);
VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL);
ddt_exit(ddt);
@@ -6192,10 +6502,10 @@ zdb_check_for_obsolete_leaks(vdev_t *vd, zdb_cb_t *zcb)
*/
for (uint64_t inner_offset = 0;
inner_offset < DVA_GET_ASIZE(&vimep->vimep_dst);
- inner_offset += 1 << vd->vdev_ashift) {
+ inner_offset += 1ULL << vd->vdev_ashift) {
if (range_tree_contains(msp->ms_allocatable,
- offset + inner_offset, 1 << vd->vdev_ashift)) {
- obsolete_bytes += 1 << vd->vdev_ashift;
+ offset + inner_offset, 1ULL << vd->vdev_ashift)) {
+ obsolete_bytes += 1ULL << vd->vdev_ashift;
}
}
@@ -6406,9 +6716,23 @@ deleted_livelists_dump_mos(spa_t *spa)
}
static int
+zdb_brt_entry_compare(const void *zcn1, const void *zcn2)
+{
+ const dva_t *dva1 = &((const zdb_brt_entry_t *)zcn1)->zbre_dva;
+ const dva_t *dva2 = &((const zdb_brt_entry_t *)zcn2)->zbre_dva;
+ int cmp;
+
+ cmp = TREE_CMP(DVA_GET_VDEV(dva1), DVA_GET_VDEV(dva2));
+ if (cmp == 0)
+ cmp = TREE_CMP(DVA_GET_OFFSET(dva1), DVA_GET_OFFSET(dva2));
+
+ return (cmp);
+}
+
+static int
dump_block_stats(spa_t *spa)
{
- zdb_cb_t zcb = {{{{0}}}};
+ zdb_cb_t *zcb;
zdb_blkstats_t *zb, *tzb;
uint64_t norm_alloc, norm_space, total_alloc, total_found;
int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
@@ -6417,6 +6741,15 @@ dump_block_stats(spa_t *spa)
int e, c, err;
bp_embedded_type_t i;
+ zcb = umem_zalloc(sizeof (zdb_cb_t), UMEM_NOFAIL);
+
+ if (spa_feature_is_active(spa, SPA_FEATURE_BLOCK_CLONING)) {
+ avl_create(&zcb->zcb_brt, zdb_brt_entry_compare,
+ sizeof (zdb_brt_entry_t),
+ offsetof(zdb_brt_entry_t, zbre_node));
+ zcb->zcb_brt_is_active = B_TRUE;
+ }
+
(void) printf("\nTraversing all blocks %s%s%s%s%s...\n\n",
(dump_opt['c'] || !dump_opt['L']) ? "to verify " : "",
(dump_opt['c'] == 1) ? "metadata " : "",
@@ -6436,39 +6769,39 @@ dump_block_stats(spa_t *spa)
* pool claiming each block we discover, but we skip opening any space
* maps.
*/
- zdb_leak_init(spa, &zcb);
+ zdb_leak_init(spa, zcb);
/*
* If there's a deferred-free bplist, process that first.
*/
(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
- bpobj_count_block_cb, &zcb, NULL);
+ bpobj_count_block_cb, zcb, NULL);
if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
- bpobj_count_block_cb, &zcb, NULL);
+ bpobj_count_block_cb, zcb, NULL);
}
- zdb_claim_removing(spa, &zcb);
+ zdb_claim_removing(spa, zcb);
if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {
VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
- &zcb, NULL));
+ zcb, NULL));
}
- deleted_livelists_count_blocks(spa, &zcb);
+ deleted_livelists_count_blocks(spa, zcb);
if (dump_opt['c'] > 1)
flags |= TRAVERSE_PREFETCH_DATA;
- zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
- zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa));
- zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
- zcb.zcb_totalasize +=
+ zcb->zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
+ zcb->zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa));
+ zcb->zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
+ zcb->zcb_totalasize +=
metaslab_class_get_alloc(spa_embedded_log_class(spa));
- zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
- err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
+ zcb->zcb_start = zcb->zcb_lastprint = gethrtime();
+ err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, zcb);
/*
* If we've traversed the data blocks then we need to wait for those
@@ -6489,15 +6822,15 @@ dump_block_stats(spa_t *spa)
* Done after zio_wait() since zcb_haderrors is modified in
* zdb_blkptr_done()
*/
- zcb.zcb_haderrors |= err;
+ zcb->zcb_haderrors |= err;
- if (zcb.zcb_haderrors) {
+ if (zcb->zcb_haderrors) {
(void) printf("\nError counts:\n\n");
(void) printf("\t%5s %s\n", "errno", "count");
for (e = 0; e < 256; e++) {
- if (zcb.zcb_errors[e] != 0) {
+ if (zcb->zcb_errors[e] != 0) {
(void) printf("\t%5d %llu\n",
- e, (u_longlong_t)zcb.zcb_errors[e]);
+ e, (u_longlong_t)zcb->zcb_errors[e]);
}
}
}
@@ -6505,9 +6838,9 @@ dump_block_stats(spa_t *spa)
/*
* Report any leaked segments.
*/
- leaks |= zdb_leak_fini(spa, &zcb);
+ leaks |= zdb_leak_fini(spa, zcb);
- tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL];
+ tzb = &zcb->zcb_type[ZB_TOTAL][ZDB_OT_TOTAL];
norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
norm_space = metaslab_class_get_space(spa_normal_class(spa));
@@ -6518,8 +6851,9 @@ dump_block_stats(spa_t *spa)
metaslab_class_get_alloc(spa_special_class(spa)) +
metaslab_class_get_alloc(spa_dedup_class(spa)) +
get_unflushed_alloc_space(spa);
- total_found = tzb->zb_asize - zcb.zcb_dedup_asize +
- zcb.zcb_removing_size + zcb.zcb_checkpoint_size;
+ total_found =
+ tzb->zb_asize - zcb->zcb_dedup_asize - zcb->zcb_clone_asize +
+ zcb->zcb_removing_size + zcb->zcb_checkpoint_size;
if (total_found == total_alloc && !dump_opt['L']) {
(void) printf("\n\tNo leaks (block sum matches space"
@@ -6534,8 +6868,10 @@ dump_block_stats(spa_t *spa)
leaks = B_TRUE;
}
- if (tzb->zb_count == 0)
+ if (tzb->zb_count == 0) {
+ umem_free(zcb, sizeof (zdb_cb_t));
return (2);
+ }
(void) printf("\n");
(void) printf("\t%-16s %14llu\n", "bp count:",
@@ -6554,9 +6890,12 @@ dump_block_stats(spa_t *spa)
(u_longlong_t)(tzb->zb_asize / tzb->zb_count),
(double)tzb->zb_lsize / tzb->zb_asize);
(void) printf("\t%-16s %14llu ref>1: %6llu deduplication: %6.2f\n",
- "bp deduped:", (u_longlong_t)zcb.zcb_dedup_asize,
- (u_longlong_t)zcb.zcb_dedup_blocks,
- (double)zcb.zcb_dedup_asize / tzb->zb_asize + 1.0);
+ "bp deduped:", (u_longlong_t)zcb->zcb_dedup_asize,
+ (u_longlong_t)zcb->zcb_dedup_blocks,
+ (double)zcb->zcb_dedup_asize / tzb->zb_asize + 1.0);
+ (void) printf("\t%-16s %14llu count: %6llu\n",
+ "bp cloned:", (u_longlong_t)zcb->zcb_clone_asize,
+ (u_longlong_t)zcb->zcb_clone_blocks);
(void) printf("\t%-16s %14llu used: %5.2f%%\n", "Normal class:",
(u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
@@ -6594,19 +6933,19 @@ dump_block_stats(spa_t *spa)
}
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
- if (zcb.zcb_embedded_blocks[i] == 0)
+ if (zcb->zcb_embedded_blocks[i] == 0)
continue;
(void) printf("\n");
(void) printf("\tadditional, non-pointer bps of type %u: "
"%10llu\n",
- i, (u_longlong_t)zcb.zcb_embedded_blocks[i]);
+ i, (u_longlong_t)zcb->zcb_embedded_blocks[i]);
if (dump_opt['b'] >= 3) {
(void) printf("\t number of (compressed) bytes: "
"number of bps\n");
- dump_histogram(zcb.zcb_embedded_histogram[i],
- sizeof (zcb.zcb_embedded_histogram[i]) /
- sizeof (zcb.zcb_embedded_histogram[i][0]), 0);
+ dump_histogram(zcb->zcb_embedded_histogram[i],
+ sizeof (zcb->zcb_embedded_histogram[i]) /
+ sizeof (zcb->zcb_embedded_histogram[i][0]), 0);
}
}
@@ -6639,12 +6978,15 @@ dump_block_stats(spa_t *spa)
if (dump_opt['b'] >= 2) {
int l, t, level;
+ char csize[32], lsize[32], psize[32], asize[32];
+ char avg[32], gang[32];
(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
"\t avg\t comp\t%%Total\tType\n");
+ zfs_blkstat_t *mdstats = umem_zalloc(sizeof (zfs_blkstat_t),
+ UMEM_NOFAIL);
+
for (t = 0; t <= ZDB_OT_TOTAL; t++) {
- char csize[32], lsize[32], psize[32], asize[32];
- char avg[32], gang[32];
const char *typename;
/* make sure nicenum has enough space */
@@ -6666,7 +7008,7 @@ dump_block_stats(spa_t *spa)
else
typename = zdb_ot_extname[t - DMU_OT_NUMTYPES];
- if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) {
+ if (zcb->zcb_type[ZB_TOTAL][t].zb_asize == 0) {
(void) printf("%6s\t%5s\t%5s\t%5s"
"\t%5s\t%5s\t%6s\t%s\n",
"-",
@@ -6682,16 +7024,25 @@ dump_block_stats(spa_t *spa)
for (l = ZB_TOTAL - 1; l >= -1; l--) {
level = (l == -1 ? ZB_TOTAL : l);
- zb = &zcb.zcb_type[level][t];
+ zb = &zcb->zcb_type[level][t];
if (zb->zb_asize == 0)
continue;
+ if (level != ZB_TOTAL && t < DMU_OT_NUMTYPES &&
+ (level > 0 || DMU_OT_IS_METADATA(t))) {
+ mdstats->zb_count += zb->zb_count;
+ mdstats->zb_lsize += zb->zb_lsize;
+ mdstats->zb_psize += zb->zb_psize;
+ mdstats->zb_asize += zb->zb_asize;
+ mdstats->zb_gangs += zb->zb_gangs;
+ }
+
if (dump_opt['b'] < 3 && level != ZB_TOTAL)
continue;
if (level == 0 && zb->zb_asize ==
- zcb.zcb_type[ZB_TOTAL][t].zb_asize)
+ zcb->zcb_type[ZB_TOTAL][t].zb_asize)
continue;
zdb_nicenum(zb->zb_count, csize,
@@ -6732,25 +7083,51 @@ dump_block_stats(spa_t *spa)
}
}
}
+ zdb_nicenum(mdstats->zb_count, csize,
+ sizeof (csize));
+ zdb_nicenum(mdstats->zb_lsize, lsize,
+ sizeof (lsize));
+ zdb_nicenum(mdstats->zb_psize, psize,
+ sizeof (psize));
+ zdb_nicenum(mdstats->zb_asize, asize,
+ sizeof (asize));
+ zdb_nicenum(mdstats->zb_asize / mdstats->zb_count, avg,
+ sizeof (avg));
+ zdb_nicenum(mdstats->zb_gangs, gang, sizeof (gang));
+
+ (void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
+ "\t%5.2f\t%6.2f\t",
+ csize, lsize, psize, asize, avg,
+ (double)mdstats->zb_lsize / mdstats->zb_psize,
+ 100.0 * mdstats->zb_asize / tzb->zb_asize);
+ (void) printf("%s\n", "Metadata Total");
/* Output a table summarizing block sizes in the pool */
if (dump_opt['b'] >= 2) {
- dump_size_histograms(&zcb);
+ dump_size_histograms(zcb);
}
+
+ umem_free(mdstats, sizeof (zfs_blkstat_t));
}
(void) printf("\n");
- if (leaks)
+ if (leaks) {
+ umem_free(zcb, sizeof (zdb_cb_t));
return (2);
+ }
- if (zcb.zcb_haderrors)
+ if (zcb->zcb_haderrors) {
+ umem_free(zcb, sizeof (zdb_cb_t));
return (3);
+ }
+ umem_free(zcb, sizeof (zdb_cb_t));
return (0);
}
typedef struct zdb_ddt_entry {
+ /* key must be first for ddt_key_compare */
ddt_key_t zdde_key;
uint64_t zdde_ref_blocks;
uint64_t zdde_ref_lsize;
@@ -6811,7 +7188,7 @@ dump_simulated_ddt(spa_t *spa)
ddt_histogram_t ddh_total = {{{0}}};
ddt_stat_t dds_total = {0};
- avl_create(&t, ddt_entry_compare,
+ avl_create(&t, ddt_key_compare,
sizeof (zdb_ddt_entry_t), offsetof(zdb_ddt_entry_t, zdde_node));
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
@@ -7037,8 +7414,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
freecfg = B_TRUE;
}
- if (asprintf(&bogus_name, "%s%s", poolname, BOGUS_SUFFIX) == -1)
+ if (asprintf(&bogus_name, "%s%s", poolname, BOGUS_SUFFIX) == -1) {
+ if (target != poolname)
+ free(poolname);
return (NULL);
+ }
fnvlist_add_string(cfg, ZPOOL_CONFIG_POOL_NAME, bogus_name);
error = spa_import(bogus_name, cfg, NULL,
@@ -7053,6 +7433,7 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
if (new_path != NULL && path_start != NULL) {
if (asprintf(new_path, "%s%s", bogus_name, path_start) == -1) {
+ free(bogus_name);
if (path_start != NULL)
free(poolname);
return (NULL);
@@ -7448,6 +7829,9 @@ mos_leak_vdev(vdev_t *vd)
mos_obj_refd(space_map_object(ms->ms_sm));
}
+ if (vd->vdev_root_zap != 0)
+ mos_obj_refd(vd->vdev_root_zap);
+
if (vd->vdev_top_zap != 0) {
mos_obj_refd(vd->vdev_top_zap);
mos_leak_vdev_top_zap(vd);
@@ -7475,6 +7859,19 @@ mos_leak_log_spacemaps(spa_t *spa)
mos_obj_refd(sls->sls_sm_obj);
}
+static void
+errorlog_count_refd(objset_t *mos, uint64_t errlog)
+{
+ zap_cursor_t zc;
+ zap_attribute_t za;
+ for (zap_cursor_init(&zc, mos, errlog);
+ zap_cursor_retrieve(&zc, &za) == 0;
+ zap_cursor_advance(&zc)) {
+ mos_obj_refd(za.za_first_integer);
+ }
+ zap_cursor_fini(&zc);
+}
+
static int
dump_mos_leaks(spa_t *spa)
{
@@ -7495,6 +7892,12 @@ dump_mos_leaks(spa_t *spa)
mos_obj_refd(spa->spa_history);
mos_obj_refd(spa->spa_errlog_last);
mos_obj_refd(spa->spa_errlog_scrub);
+
+ if (spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
+ errorlog_count_refd(mos, spa->spa_errlog_last);
+ errorlog_count_refd(mos, spa->spa_errlog_scrub);
+ }
+
mos_obj_refd(spa->spa_all_vdev_zaps);
mos_obj_refd(spa->spa_dsl_pool->dp_bptree_obj);
mos_obj_refd(spa->spa_dsl_pool->dp_tmp_userrefs_obj);
@@ -7551,11 +7954,24 @@ dump_mos_leaks(spa_t *spa)
for (uint64_t cksum = 0;
cksum < ZIO_CHECKSUM_FUNCTIONS; cksum++) {
ddt_t *ddt = spa->spa_ddt[cksum];
+ if (!ddt)
+ continue;
mos_obj_refd(ddt->ddt_object[type][class]);
}
}
}
+ if (spa->spa_brt != NULL) {
+ brt_t *brt = spa->spa_brt;
+ for (uint64_t vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brt_vdev_t *brtvd = &brt->brt_vdevs[vdevid];
+ if (brtvd != NULL && brtvd->bv_initiated) {
+ mos_obj_refd(brtvd->bv_mos_brtvdev);
+ mos_obj_refd(brtvd->bv_mos_entries);
+ }
+ }
+ }
+
/*
* Visit all allocated objects and make sure they are referenced.
*/
@@ -7566,7 +7982,7 @@ dump_mos_leaks(spa_t *spa)
} else {
dmu_object_info_t doi;
const char *name;
- dmu_object_info(mos, object, &doi);
+ VERIFY0(dmu_object_info(mos, object, &doi));
if (doi.doi_type & DMU_OT_NEWTYPE) {
dmu_object_byteswap_t bswap =
DMU_OT_BYTESWAP(doi.doi_type);
@@ -7692,6 +8108,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['D'])
dump_all_ddts(spa);
+ if (dump_opt['T'])
+ dump_brt(spa);
+
if (dump_opt['d'] > 2 || dump_opt['m'])
dump_metaslabs(spa);
if (dump_opt['M'])
@@ -7734,6 +8153,7 @@ dump_zpool(spa_t *spa)
for (spa_feature_t f = 0; f < SPA_FEATURES; f++)
global_feature_count[f] = UINT64_MAX;
global_feature_count[SPA_FEATURE_REDACTION_BOOKMARKS] = 0;
+ global_feature_count[SPA_FEATURE_REDACTION_LIST_SPILL] = 0;
global_feature_count[SPA_FEATURE_BOOKMARK_WRITTEN] = 0;
global_feature_count[SPA_FEATURE_LIVELIST] = 0;
@@ -7984,11 +8404,45 @@ zdb_parse_block_sizes(char *sizes, uint64_t *lsize, uint64_t *psize)
#define ZIO_COMPRESS_MASK(alg) (1ULL << (ZIO_COMPRESS_##alg))
static boolean_t
+try_decompress_block(abd_t *pabd, uint64_t lsize, uint64_t psize,
+ int flags, int cfunc, void *lbuf, void *lbuf2)
+{
+ if (flags & ZDB_FLAG_VERBOSE) {
+ (void) fprintf(stderr,
+ "Trying %05llx -> %05llx (%s)\n",
+ (u_longlong_t)psize,
+ (u_longlong_t)lsize,
+ zio_compress_table[cfunc].ci_name);
+ }
+
+ /*
+ * We set lbuf to all zeros and lbuf2 to all
+ * ones, then decompress to both buffers and
+ * compare their contents. This way we can
+ * know if decompression filled exactly to
+ * lsize or if it left some bytes unwritten.
+ */
+
+ memset(lbuf, 0x00, lsize);
+ memset(lbuf2, 0xff, lsize);
+
+ if (zio_decompress_data(cfunc, pabd,
+ lbuf, psize, lsize, NULL) == 0 &&
+ zio_decompress_data(cfunc, pabd,
+ lbuf2, psize, lsize, NULL) == 0 &&
+ memcmp(lbuf, lbuf2, lsize) == 0)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
+static uint64_t
zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
uint64_t psize, int flags)
{
(void) buf;
- boolean_t exceeded = B_FALSE;
+ uint64_t orig_lsize = lsize;
+ boolean_t tryzle = ((getenv("ZDB_NO_ZLE") == NULL));
+ boolean_t found = B_FALSE;
/*
* We don't know how the data was compressed, so just try
* every decompress function at every inflated blocksize.
@@ -7999,10 +8453,18 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
uint64_t maxlsize = SPA_MAXBLOCKSIZE;
uint64_t mask = ZIO_COMPRESS_MASK(ON) | ZIO_COMPRESS_MASK(OFF) |
ZIO_COMPRESS_MASK(INHERIT) | ZIO_COMPRESS_MASK(EMPTY) |
- (getenv("ZDB_NO_ZLE") ? ZIO_COMPRESS_MASK(ZLE) : 0);
+ ZIO_COMPRESS_MASK(ZLE);
*cfuncp++ = ZIO_COMPRESS_LZ4;
*cfuncp++ = ZIO_COMPRESS_LZJB;
mask |= ZIO_COMPRESS_MASK(LZ4) | ZIO_COMPRESS_MASK(LZJB);
+ /*
+ * Every gzip level has the same decompressor, no need to
+ * run it 9 times per bruteforce attempt.
+ */
+ mask |= ZIO_COMPRESS_MASK(GZIP_2) | ZIO_COMPRESS_MASK(GZIP_3);
+ mask |= ZIO_COMPRESS_MASK(GZIP_4) | ZIO_COMPRESS_MASK(GZIP_5);
+ mask |= ZIO_COMPRESS_MASK(GZIP_6) | ZIO_COMPRESS_MASK(GZIP_7);
+ mask |= ZIO_COMPRESS_MASK(GZIP_8) | ZIO_COMPRESS_MASK(GZIP_9);
for (int c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++)
if (((1ULL << c) & mask) == 0)
*cfuncp++ = c;
@@ -8018,46 +8480,38 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
lsize += SPA_MINBLOCKSIZE;
else
maxlsize = lsize;
+
for (; lsize <= maxlsize; lsize += SPA_MINBLOCKSIZE) {
for (cfuncp = cfuncs; *cfuncp; cfuncp++) {
- if (flags & ZDB_FLAG_VERBOSE) {
- (void) fprintf(stderr,
- "Trying %05llx -> %05llx (%s)\n",
- (u_longlong_t)psize,
- (u_longlong_t)lsize,
- zio_compress_table[*cfuncp].\
- ci_name);
- }
-
- /*
- * We randomize lbuf2, and decompress to both
- * lbuf and lbuf2. This way, we will know if
- * decompression fill exactly to lsize.
- */
- VERIFY0(random_get_pseudo_bytes(lbuf2, lsize));
-
- if (zio_decompress_data(*cfuncp, pabd,
- lbuf, psize, lsize, NULL) == 0 &&
- zio_decompress_data(*cfuncp, pabd,
- lbuf2, psize, lsize, NULL) == 0 &&
- memcmp(lbuf, lbuf2, lsize) == 0)
+ if (try_decompress_block(pabd, lsize, psize, flags,
+ *cfuncp, lbuf, lbuf2)) {
+ found = B_TRUE;
break;
+ }
}
if (*cfuncp != 0)
break;
}
+ if (!found && tryzle) {
+ for (lsize = orig_lsize; lsize <= maxlsize;
+ lsize += SPA_MINBLOCKSIZE) {
+ if (try_decompress_block(pabd, lsize, psize, flags,
+ ZIO_COMPRESS_ZLE, lbuf, lbuf2)) {
+ *cfuncp = ZIO_COMPRESS_ZLE;
+ found = B_TRUE;
+ break;
+ }
+ }
+ }
umem_free(lbuf2, SPA_MAXBLOCKSIZE);
- if (lsize > maxlsize) {
- exceeded = B_TRUE;
- }
if (*cfuncp == ZIO_COMPRESS_ZLE) {
printf("\nZLE decompression was selected. If you "
"suspect the results are wrong,\ntry avoiding ZLE "
"by setting and exporting ZDB_NO_ZLE=\"true\"\n");
}
- return (exceeded);
+ return (lsize > maxlsize ? -1 : lsize);
}
/*
@@ -8173,8 +8627,7 @@ zdb_read_block(char *thing, spa_t *spa)
vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev);
if (vd == NULL) {
(void) printf("***Invalid vdev: %s\n", vdev);
- free(dup);
- return;
+ goto done;
} else {
if (vd->vdev_path)
(void) fprintf(stderr, "Found vdev: %s\n",
@@ -8221,9 +8674,9 @@ zdb_read_block(char *thing, spa_t *spa)
*/
zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pabd,
psize, ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_PROPAGATE |
- ZIO_FLAG_DONT_RETRY | ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
- ZIO_FLAG_OPTIONAL, NULL, NULL));
+ ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW | ZIO_FLAG_OPTIONAL,
+ NULL, NULL));
}
error = zio_wait(zio);
@@ -8237,9 +8690,9 @@ zdb_read_block(char *thing, spa_t *spa)
uint64_t orig_lsize = lsize;
buf = lbuf;
if (flags & ZDB_FLAG_DECOMPRESS) {
- boolean_t failed = zdb_decompress_block(pabd, buf, lbuf,
+ lsize = zdb_decompress_block(pabd, buf, lbuf,
lsize, psize, flags);
- if (failed) {
+ if (lsize == -1) {
(void) printf("Decompress of %s failed\n", thing);
goto out;
}
@@ -8255,17 +8708,17 @@ zdb_read_block(char *thing, spa_t *spa)
!(flags & ZDB_FLAG_DECOMPRESS)) {
const blkptr_t *b = (const blkptr_t *)(void *)
((uintptr_t)buf + (uintptr_t)blkptr_offset);
- if (zfs_blkptr_verify(spa, b, B_FALSE, BLK_VERIFY_ONLY) ==
- B_FALSE) {
+ if (zfs_blkptr_verify(spa, b,
+ BLK_CONFIG_NEEDED, BLK_VERIFY_ONLY) == B_FALSE) {
abd_return_buf_copy(pabd, buf, lsize);
borrowed = B_FALSE;
buf = lbuf;
- boolean_t failed = zdb_decompress_block(pabd, buf,
+ lsize = zdb_decompress_block(pabd, buf,
lbuf, lsize, psize, flags);
b = (const blkptr_t *)(void *)
((uintptr_t)buf + (uintptr_t)blkptr_offset);
- if (failed || zfs_blkptr_verify(spa, b, B_FALSE,
- BLK_VERIFY_LOG) == B_FALSE) {
+ if (lsize == -1 || zfs_blkptr_verify(spa, b,
+ BLK_CONFIG_NEEDED, BLK_VERIFY_LOG) == B_FALSE) {
printf("invalid block pointer at this DVA\n");
goto out;
}
@@ -8305,8 +8758,6 @@ zdb_read_block(char *thing, spa_t *spa)
BP_SET_CHECKSUM(bp, ck);
spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
czio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
- czio->io_bp = bp;
-
if (vd == vd->vdev_top) {
zio_nowait(zio_read(czio, spa, bp, pabd, psize,
NULL, NULL,
@@ -8317,7 +8768,6 @@ zdb_read_block(char *thing, spa_t *spa)
zio_nowait(zio_vdev_child_io(czio, bp, vd,
offset, pabd, psize, ZIO_TYPE_READ,
ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE |
ZIO_FLAG_DONT_PROPAGATE |
ZIO_FLAG_DONT_RETRY |
ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
@@ -8326,12 +8776,15 @@ zdb_read_block(char *thing, spa_t *spa)
}
error = zio_wait(czio);
if (error == 0 || error == ECKSUM) {
- zio_t *ck_zio = zio_root(spa, NULL, NULL, 0);
+ zio_t *ck_zio = zio_null(NULL, spa, NULL,
+ NULL, NULL, 0);
ck_zio->io_offset =
DVA_GET_OFFSET(&bp->blk_dva[0]);
ck_zio->io_bp = bp;
zio_checksum_compute(ck_zio, ck, pabd, lsize);
- printf("%12s\tcksum=%llx:%llx:%llx:%llx\n",
+ printf(
+ "%12s\t"
+ "cksum=%016llx:%016llx:%016llx:%016llx\n",
zio_checksum_table[ck].ci_name,
(u_longlong_t)bp->blk_cksum.zc_word[0],
(u_longlong_t)bp->blk_cksum.zc_word[1],
@@ -8449,6 +8902,7 @@ main(int argc, char **argv)
struct option long_options[] = {
{"ignore-assertions", no_argument, NULL, 'A'},
{"block-stats", no_argument, NULL, 'b'},
+ {"backup", no_argument, NULL, 'B'},
{"checksum", no_argument, NULL, 'c'},
{"config", no_argument, NULL, 'C'},
{"datasets", no_argument, NULL, 'd'},
@@ -8461,6 +8915,7 @@ main(int argc, char **argv)
{"intent-logs", no_argument, NULL, 'i'},
{"inflight", required_argument, NULL, 'I'},
{"checkpointed-state", no_argument, NULL, 'k'},
+ {"key", required_argument, NULL, 'K'},
{"label", no_argument, NULL, 'l'},
{"disable-leak-tracking", no_argument, NULL, 'L'},
{"metaslabs", no_argument, NULL, 'm'},
@@ -8476,6 +8931,7 @@ main(int argc, char **argv)
{"io-stats", no_argument, NULL, 's'},
{"simulate-dedup", no_argument, NULL, 'S'},
{"txg", required_argument, NULL, 't'},
+ {"brt-stats", no_argument, NULL, 'T'},
{"uberblock", no_argument, NULL, 'u'},
{"cachefile", required_argument, NULL, 'U'},
{"verbose", no_argument, NULL, 'v'},
@@ -8489,10 +8945,11 @@ main(int argc, char **argv)
};
while ((c = getopt_long(argc, argv,
- "AbcCdDeEFGhiI:klLmMNo:Op:PqrRsSt:uU:vVx:XYyZ",
+ "AbBcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:TuU:vVx:XYyZ",
long_options, NULL)) != -1) {
switch (c) {
case 'b':
+ case 'B':
case 'c':
case 'C':
case 'd':
@@ -8510,6 +8967,7 @@ main(int argc, char **argv)
case 'R':
case 's':
case 'S':
+ case 'T':
case 'u':
case 'y':
case 'Z':
@@ -8540,6 +8998,12 @@ main(int argc, char **argv)
usage();
}
break;
+ case 'K':
+ dump_opt[c]++;
+ key_material = strdup(optarg);
+ /* redact key material in process table */
+ while (*optarg != '\0') { *optarg++ = '*'; }
+ break;
case 'o':
error = set_global_var(optarg);
if (error != 0)
@@ -8601,8 +9065,8 @@ main(int argc, char **argv)
* ZDB does not typically re-read blocks; therefore limit the ARC
* to 256 MB, which can be used entirely for metadata.
*/
- zfs_arc_min = zfs_arc_meta_min = 2ULL << SPA_MAXBLOCKSHIFT;
- zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
+ zfs_arc_min = 2ULL << SPA_MAXBLOCKSHIFT;
+ zfs_arc_max = 256 * 1024 * 1024;
#endif
/*
@@ -8634,7 +9098,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
- if (dump_all && strchr("AeEFklLNOPrRSXy", c) == NULL)
+ if (dump_all && strchr("ABeEFkKlLNOPrRSXy", c) == NULL)
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
@@ -8666,20 +9130,6 @@ main(int argc, char **argv)
if (dump_opt['l'])
return (dump_label(argv[0]));
- if (dump_opt['O']) {
- if (argc != 2)
- usage();
- dump_opt['v'] = verbose + 3;
- return (dump_path(argv[0], argv[1], NULL));
- }
- if (dump_opt['r']) {
- target_is_spa = B_FALSE;
- if (argc != 3)
- usage();
- dump_opt['v'] = verbose;
- error = dump_path(argv[0], argv[1], &object);
- }
-
if (dump_opt['X'] || dump_opt['F'])
rewind = ZPOOL_DO_REWIND |
(dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
@@ -8746,8 +9196,12 @@ main(int argc, char **argv)
args.path = searchdirs;
args.can_be_active = B_TRUE;
- error = zpool_find_config(NULL, target_pool, &cfg, &args,
- &libzpool_config_ops);
+ libpc_handle_t lpch = {
+ .lpc_lib_handle = NULL,
+ .lpc_ops = &libzpool_config_ops,
+ .lpc_printerr = B_TRUE
+ };
+ error = zpool_find_config(&lpch, target_pool, &cfg, &args);
if (error == 0) {
@@ -8777,6 +9231,29 @@ main(int argc, char **argv)
}
/*
+ * We need to make sure to process -O option or call
+ * dump_path after the -e option has been processed,
+ * which imports the pool to the namespace if it's
+ * not in the cachefile.
+ */
+ if (dump_opt['O']) {
+ if (argc != 2)
+ usage();
+ dump_opt['v'] = verbose + 3;
+ return (dump_path(argv[0], argv[1], NULL));
+ }
+
+ if (dump_opt['r']) {
+ target_is_spa = B_FALSE;
+ if (argc != 3)
+ usage();
+ dump_opt['v'] = verbose;
+ error = dump_path(argv[0], argv[1], &object);
+ if (error != 0)
+ fatal("internal error: %s", strerror(error));
+ }
+
+ /*
* import_checkpointed_state makes the assumption that the
* target pool that we pass it is already part of the spa
* namespace. Because of that we need to make sure to call
@@ -8814,7 +9291,8 @@ main(int argc, char **argv)
checkpoint_pool, error);
}
- } else if (target_is_spa || dump_opt['R'] || objset_id == 0) {
+ } else if (target_is_spa || dump_opt['R'] || dump_opt['B'] ||
+ objset_id == 0) {
zdb_set_skip_mmp(target);
error = spa_open_rewind(target, &spa, FTAG, policy,
NULL);
@@ -8950,7 +9428,10 @@ retry_lookup:
strerror(errno));
}
}
- if (os != NULL) {
+ if (dump_opt['B']) {
+ dump_backup(target, objset_id,
+ argc > 0 ? argv[0] : NULL);
+ } else if (os != NULL) {
dump_objset(os);
} else if (zopt_object_args > 0 && !dump_opt['m']) {
dump_objset(spa->spa_meta_objset);
diff --git a/cmd/zdb/zdb.h b/cmd/zdb/zdb.h
index 49579811efbb..a7d453c8c0d7 100644
--- a/cmd/zdb/zdb.h
+++ b/cmd/zdb/zdb.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zdb/zdb_il.c b/cmd/zdb/zdb_il.c
index 76b1d64d76dc..e3caaeb70e14 100644
--- a/cmd/zdb/zdb_il.c
+++ b/cmd/zdb/zdb_il.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -128,6 +128,14 @@ zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg)
(void) printf("%ssdoid %llu, tdoid %llu\n", tab_prefix,
(u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid);
(void) printf("%ssrc %s tgt %s\n", tab_prefix, snm, tnm);
+ switch (txtype) {
+ case TX_RENAME_EXCHANGE:
+ (void) printf("%sflags RENAME_EXCHANGE\n", tab_prefix);
+ break;
+ case TX_RENAME_WHITEOUT:
+ (void) printf("%sflags RENAME_WHITEOUT\n", tab_prefix);
+ break;
+ }
}
static int
@@ -160,28 +168,31 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
(u_longlong_t)lr->lr_length);
- if (txtype == TX_WRITE2 || verbose < 5)
+ if (txtype == TX_WRITE2 || verbose < 4)
return;
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", tab_prefix,
- !BP_IS_HOLE(bp) &&
- bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa) ?
+ !BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
+ spa_min_claim_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, tab_prefix);
+ if (verbose < 5)
+ return;
if (BP_IS_HOLE(bp)) {
(void) printf("\t\t\tLSIZE 0x%llx\n",
(u_longlong_t)BP_GET_LSIZE(bp));
(void) printf("%s<hole>\n", tab_prefix);
return;
}
- if (bp->blk_birth < zilog->zl_header->zh_claim_txg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
(void) printf("%s<block already committed>\n",
tab_prefix);
return;
}
+ ASSERT3U(BP_GET_LSIZE(bp), !=, 0);
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os),
lr->lr_foid, ZB_ZIL_LEVEL,
lr->lr_offset / BP_GET_LSIZE(bp));
@@ -193,6 +204,9 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
if (error)
goto out;
} else {
+ if (verbose < 5)
+ return;
+
/* data is stored after the end of the lr_write record */
data = abd_alloc(lr->lr_length, B_FALSE);
abd_copy_from_buf(data, lr + 1, lr->lr_length);
@@ -209,6 +223,28 @@ out:
}
static void
+zil_prt_rec_write_enc(zilog_t *zilog, int txtype, const void *arg)
+{
+ (void) txtype;
+ const lr_write_t *lr = arg;
+ const blkptr_t *bp = &lr->lr_blkptr;
+ int verbose = MAX(dump_opt['d'], dump_opt['i']);
+
+ (void) printf("%s(encrypted)\n", tab_prefix);
+
+ if (verbose < 4)
+ return;
+
+ if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
+ (void) printf("%shas blkptr, %s\n", tab_prefix,
+ !BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
+ spa_min_claim_txg(zilog->zl_spa) ?
+ "will claim" : "won't claim");
+ print_log_bp(bp, tab_prefix);
+ }
+}
+
+static void
zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
{
(void) zilog, (void) txtype;
@@ -298,9 +334,50 @@ zil_prt_rec_acl(zilog_t *zilog, int txtype, const void *arg)
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt);
}
+static void
+zil_prt_rec_clone_range(zilog_t *zilog, int txtype, const void *arg)
+{
+ (void) zilog, (void) txtype;
+ const lr_clone_range_t *lr = arg;
+ int verbose = MAX(dump_opt['d'], dump_opt['i']);
+
+ (void) printf("%sfoid %llu, offset %llx, length %llx, blksize %llx\n",
+ tab_prefix, (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
+ (u_longlong_t)lr->lr_length, (u_longlong_t)lr->lr_blksz);
+
+ if (verbose < 4)
+ return;
+
+ for (unsigned int i = 0; i < lr->lr_nbps; i++) {
+ (void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
+ (u_longlong_t)lr->lr_nbps);
+ print_log_bp(&lr->lr_bps[i], "");
+ }
+}
+
+static void
+zil_prt_rec_clone_range_enc(zilog_t *zilog, int txtype, const void *arg)
+{
+ (void) zilog, (void) txtype;
+ const lr_clone_range_t *lr = arg;
+ int verbose = MAX(dump_opt['d'], dump_opt['i']);
+
+ (void) printf("%s(encrypted)\n", tab_prefix);
+
+ if (verbose < 4)
+ return;
+
+ for (unsigned int i = 0; i < lr->lr_nbps; i++) {
+ (void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
+ (u_longlong_t)lr->lr_nbps);
+ print_log_bp(&lr->lr_bps[i], "");
+ }
+}
+
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, const void *);
typedef struct zil_rec_info {
zil_prt_rec_func_t zri_print;
+ zil_prt_rec_func_t zri_print_enc;
const char *zri_name;
uint64_t zri_count;
} zil_rec_info_t;
@@ -315,7 +392,9 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
- {.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE "},
+ {.zri_print = zil_prt_rec_write,
+ .zri_print_enc = zil_prt_rec_write_enc,
+ .zri_name = "TX_WRITE "},
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
@@ -329,6 +408,11 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE2 "},
{.zri_print = zil_prt_rec_setsaxattr,
.zri_name = "TX_SETSAXATTR "},
+ {.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_EXCHANGE "},
+ {.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_WHITEOUT "},
+ {.zri_print = zil_prt_rec_clone_range,
+ .zri_print_enc = zil_prt_rec_clone_range_enc,
+ .zri_name = "TX_CLONE_RANGE "},
};
static int
@@ -354,6 +438,8 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
if (txtype && verbose >= 3) {
if (!zilog->zl_os->os_encrypted) {
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
+ } else if (zil_rec_info[txtype].zri_print_enc) {
+ zil_rec_info[txtype].zri_print_enc(zilog, txtype, lr);
} else {
(void) printf("%s(encrypted)\n", tab_prefix);
}
@@ -387,7 +473,7 @@ print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
if (claim_txg != 0)
claim = "already claimed";
- else if (bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa))
+ else if (BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
claim = "will claim";
else
claim = "won't claim";
diff --git a/cmd/zed/agents/fmd_api.c b/cmd/zed/agents/fmd_api.c
index af78eb74cb74..fe43e2ab971e 100644
--- a/cmd/zed/agents/fmd_api.c
+++ b/cmd/zed/agents/fmd_api.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Copyright (c) 2016, Intel Corporation.
+ * Copyright (c) 2023, Klara Inc.
*/
/*
@@ -231,28 +232,6 @@ fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name)
if (strcmp(name, "spare_on_remove") == 0)
return (1);
- if (strcmp(name, "io_N") == 0 || strcmp(name, "checksum_N") == 0)
- return (10); /* N = 10 events */
-
- return (0);
-}
-
-int64_t
-fmd_prop_get_int64(fmd_hdl_t *hdl, const char *name)
-{
- (void) hdl;
-
- /*
- * These can be looked up in mp->modinfo->fmdi_props
- * For now we just hard code for phase 2. In the
- * future, there can be a ZED based override.
- */
- if (strcmp(name, "remove_timeout") == 0)
- return (15ULL * 1000ULL * 1000ULL * 1000ULL); /* 15 sec */
-
- if (strcmp(name, "io_T") == 0 || strcmp(name, "checksum_T") == 0)
- return (1000ULL * 1000ULL * 1000ULL * 600ULL); /* 10 min */
-
return (0);
}
@@ -359,7 +338,7 @@ static void
zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
{
nvlist_t *rsrc;
- char *strval;
+ const char *strval;
uint64_t guid;
uint8_t byte;
@@ -372,7 +351,7 @@ zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
if (code != NULL)
zed_log_msg(LOG_INFO, "\t%s: %s", FM_SUSPECT_DIAG_CODE, code);
if (nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &byte) == 0)
- zed_log_msg(LOG_INFO, "\t%s: %llu", FM_FAULT_CERTAINTY, byte);
+ zed_log_msg(LOG_INFO, "\t%s: %hhu", FM_FAULT_CERTAINTY, byte);
if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &strval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %s", FM_FMRI_SCHEME,
@@ -389,7 +368,7 @@ zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
static const char *
fmd_fault_mkcode(nvlist_t *fault)
{
- char *class;
+ const char *class;
const char *code = "-";
/*
@@ -535,20 +514,31 @@ fmd_serd_exists(fmd_hdl_t *hdl, const char *name)
return (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL);
}
-void
-fmd_serd_reset(fmd_hdl_t *hdl, const char *name)
+int
+fmd_serd_active(fmd_hdl_t *hdl, const char *name)
{
fmd_module_t *mp = (fmd_module_t *)hdl;
fmd_serd_eng_t *sgp;
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name);
- return;
+ return (0);
}
+ return (fmd_serd_eng_fired(sgp) || !fmd_serd_eng_empty(sgp));
+}
- fmd_serd_eng_reset(sgp);
+void
+fmd_serd_reset(fmd_hdl_t *hdl, const char *name)
+{
+ fmd_module_t *mp = (fmd_module_t *)hdl;
+ fmd_serd_eng_t *sgp;
- fmd_hdl_debug(hdl, "serd_reset %s", name);
+ if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
+ zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name);
+ } else {
+ fmd_serd_eng_reset(sgp);
+ fmd_hdl_debug(hdl, "serd_reset %s", name);
+ }
}
int
@@ -556,16 +546,21 @@ fmd_serd_record(fmd_hdl_t *hdl, const char *name, fmd_event_t *ep)
{
fmd_module_t *mp = (fmd_module_t *)hdl;
fmd_serd_eng_t *sgp;
- int err;
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
zed_log_msg(LOG_ERR, "failed to add record to SERD engine '%s'",
name);
return (0);
}
- err = fmd_serd_eng_record(sgp, ep->ev_hrt);
+ return (fmd_serd_eng_record(sgp, ep->ev_hrt));
+}
+
+void
+fmd_serd_gc(fmd_hdl_t *hdl)
+{
+ fmd_module_t *mp = (fmd_module_t *)hdl;
- return (err);
+ fmd_serd_hash_apply(&mp->mod_serds, fmd_serd_eng_gc, NULL);
}
/* FMD Timers */
@@ -579,7 +574,7 @@ _timer_notify(union sigval sv)
const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops;
struct itimerspec its;
- fmd_hdl_debug(hdl, "timer fired (%p)", ftp->ft_tid);
+ fmd_hdl_debug(hdl, "%s timer fired (%p)", mp->mod_name, ftp->ft_tid);
/* disarm the timer */
memset(&its, 0, sizeof (struct itimerspec));
@@ -616,6 +611,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);
@@ -707,7 +703,7 @@ int
fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern)
{
(void) hdl;
- char *class;
+ const char *class;
return (nvl != NULL &&
nvlist_lookup_string(nvl, FM_CLASS, &class) == 0 &&
diff --git a/cmd/zed/agents/fmd_api.h b/cmd/zed/agents/fmd_api.h
index 2c55365c3db9..8471feecf33f 100644
--- a/cmd/zed/agents/fmd_api.h
+++ b/cmd/zed/agents/fmd_api.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -151,7 +151,6 @@ extern void fmd_hdl_vdebug(fmd_hdl_t *, const char *, va_list);
extern void fmd_hdl_debug(fmd_hdl_t *, const char *, ...);
extern int32_t fmd_prop_get_int32(fmd_hdl_t *, const char *);
-extern int64_t fmd_prop_get_int64(fmd_hdl_t *, const char *);
#define FMD_STAT_NOALLOC 0x0 /* fmd should use caller's memory */
#define FMD_STAT_ALLOC 0x1 /* fmd should allocate stats memory */
@@ -195,10 +194,12 @@ extern size_t fmd_buf_size(fmd_hdl_t *, fmd_case_t *, const char *);
extern void fmd_serd_create(fmd_hdl_t *, const char *, uint_t, hrtime_t);
extern void fmd_serd_destroy(fmd_hdl_t *, const char *);
extern int fmd_serd_exists(fmd_hdl_t *, const char *);
+extern int fmd_serd_active(fmd_hdl_t *, const char *);
extern void fmd_serd_reset(fmd_hdl_t *, const char *);
extern int fmd_serd_record(fmd_hdl_t *, const char *, fmd_event_t *);
extern int fmd_serd_fired(fmd_hdl_t *, const char *);
extern int fmd_serd_empty(fmd_hdl_t *, const char *);
+extern void fmd_serd_gc(fmd_hdl_t *);
extern id_t fmd_timer_install(fmd_hdl_t *, void *, fmd_event_t *, hrtime_t);
extern void fmd_timer_remove(fmd_hdl_t *, id_t);
diff --git a/cmd/zed/agents/fmd_serd.c b/cmd/zed/agents/fmd_serd.c
index 98c752ae7879..f942e62b3f48 100644
--- a/cmd/zed/agents/fmd_serd.c
+++ b/cmd/zed/agents/fmd_serd.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -74,9 +74,18 @@ fmd_serd_eng_alloc(const char *name, uint64_t n, hrtime_t t)
fmd_serd_eng_t *sgp;
sgp = malloc(sizeof (fmd_serd_eng_t));
+ if (sgp == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
memset(sgp, 0, sizeof (fmd_serd_eng_t));
sgp->sg_name = strdup(name);
+ if (sgp->sg_name == NULL) {
+ perror("strdup");
+ exit(EXIT_FAILURE);
+ }
+
sgp->sg_flags = FMD_SERD_DIRTY;
sgp->sg_n = n;
sgp->sg_t = t;
@@ -123,6 +132,12 @@ fmd_serd_hash_create(fmd_serd_hash_t *shp)
shp->sh_hashlen = FMD_STR_BUCKETS;
shp->sh_hash = calloc(shp->sh_hashlen, sizeof (void *));
shp->sh_count = 0;
+
+ if (shp->sh_hash == NULL) {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
}
void
@@ -241,6 +256,10 @@ fmd_serd_eng_record(fmd_serd_eng_t *sgp, hrtime_t hrt)
fmd_serd_eng_discard(sgp, list_tail(&sgp->sg_list));
sep = malloc(sizeof (fmd_serd_elem_t));
+ if (sep == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
sep->se_hrt = hrt;
list_insert_head(&sgp->sg_list, sep);
@@ -291,8 +310,9 @@ fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
}
void
-fmd_serd_eng_gc(fmd_serd_eng_t *sgp)
+fmd_serd_eng_gc(fmd_serd_eng_t *sgp, void *arg)
{
+ (void) arg;
fmd_serd_elem_t *sep, *nep;
hrtime_t hrt;
diff --git a/cmd/zed/agents/fmd_serd.h b/cmd/zed/agents/fmd_serd.h
index c35c9acc7785..80ff9a3b25b8 100644
--- a/cmd/zed/agents/fmd_serd.h
+++ b/cmd/zed/agents/fmd_serd.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -77,7 +77,7 @@ extern int fmd_serd_eng_fired(fmd_serd_eng_t *);
extern int fmd_serd_eng_empty(fmd_serd_eng_t *);
extern void fmd_serd_eng_reset(fmd_serd_eng_t *);
-extern void fmd_serd_eng_gc(fmd_serd_eng_t *);
+extern void fmd_serd_eng_gc(fmd_serd_eng_t *, void *);
#ifdef __cplusplus
}
diff --git a/cmd/zed/agents/zfs_agents.c b/cmd/zed/agents/zfs_agents.c
index 2bc84a4f57d1..8fabb8d081a5 100644
--- a/cmd/zed/agents/zfs_agents.c
+++ b/cmd/zed/agents/zfs_agents.c
@@ -64,7 +64,7 @@ typedef enum device_type {
typedef struct guid_search {
uint64_t gs_pool_guid;
uint64_t gs_vdev_guid;
- char *gs_devid;
+ const char *gs_devid;
device_type_t gs_vdev_type;
uint64_t gs_vdev_expandtime; /* vdev expansion time */
} guid_search_t;
@@ -77,9 +77,10 @@ static boolean_t
zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
{
guid_search_t *gsp = arg;
- char *path = NULL;
+ const char *path = NULL;
uint_t c, children;
nvlist_t **child;
+ uint64_t vdev_guid;
/*
* First iterate over any children.
@@ -100,7 +101,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&child, &children) == 0) {
for (c = 0; c < children; c++) {
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
- gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
+ gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
return (B_TRUE);
}
}
@@ -109,7 +110,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&child, &children) == 0) {
for (c = 0; c < children; c++) {
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
- gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
+ gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
return (B_TRUE);
}
}
@@ -126,6 +127,21 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&gsp->gs_vdev_expandtime);
return (B_TRUE);
}
+ /*
+ * Otherwise, on a vdev guid match, grab the devid and expansion
+ * time. The devid might be missing on removal since its not part
+ * of blkid cache and L2ARC VDEV does not contain pool guid in its
+ * blkid, so this is a special case for L2ARC VDEV.
+ */
+ else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
+ nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
+ gsp->gs_vdev_guid == vdev_guid) {
+ (void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
+ &gsp->gs_devid);
+ (void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
+ &gsp->gs_vdev_expandtime);
+ return (B_TRUE);
+ }
return (B_FALSE);
}
@@ -148,13 +164,13 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
/*
* if a match was found then grab the pool guid
*/
- if (gsp->gs_vdev_guid) {
+ if (gsp->gs_vdev_guid && gsp->gs_devid) {
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
&gsp->gs_pool_guid);
}
zpool_close(zhp);
- return (gsp->gs_vdev_guid != 0);
+ return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
}
void
@@ -195,11 +211,13 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
uint64_t pool_guid = 0, vdev_guid = 0;
guid_search_t search = { 0 };
device_type_t devtype = DEVICE_TYPE_PRIMARY;
+ const char *devid = NULL;
class = "resource.fs.zfs.removed";
subclass = "";
(void) nvlist_add_string(payload, FM_CLASS, class);
+ (void) nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
@@ -209,20 +227,24 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
/*
+ * If devid is missing but vdev_guid is available, find devid
+ * and pool_guid from vdev_guid.
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
* ZFS_EV_POOL_GUID may be missing so find them.
*/
- if (pool_guid == 0 || vdev_guid == 0) {
- if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER,
- &search.gs_devid) == 0) &&
- (zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search)
- == 1)) {
- if (pool_guid == 0)
- pool_guid = search.gs_pool_guid;
- if (vdev_guid == 0)
- vdev_guid = search.gs_vdev_guid;
- devtype = search.gs_vdev_type;
- }
+ if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
+ if (devid == NULL)
+ search.gs_vdev_guid = vdev_guid;
+ else
+ search.gs_devid = devid;
+ zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
+ if (devid == NULL)
+ devid = search.gs_devid;
+ if (pool_guid == 0)
+ pool_guid = search.gs_pool_guid;
+ if (vdev_guid == 0)
+ vdev_guid = search.gs_vdev_guid;
+ devtype = search.gs_vdev_type;
}
/*
@@ -235,7 +257,9 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
"for recently expanded device '%s'", EC_DEV_REMOVE,
- search.gs_devid);
+ devid);
+ fnvlist_free(payload);
+ free(event);
goto out;
}
@@ -345,9 +369,7 @@ zfs_agent_consumer_thread(void *arg)
return (NULL);
}
- if ((event = (list_head(&agent_events))) != NULL) {
- list_remove(&agent_events, event);
-
+ if ((event = list_remove_head(&agent_events)) != NULL) {
(void) pthread_mutex_unlock(&agent_lock);
/* dispatch to all event subscribers */
@@ -410,8 +432,7 @@ zfs_agent_fini(void)
(void) pthread_join(g_agents_tid, NULL);
/* drain any pending events */
- while ((event = (list_head(&agent_events))) != NULL) {
- list_remove(&agent_events, event);
+ while ((event = list_remove_head(&agent_events)) != NULL) {
nvlist_free(event->ae_nvl);
free(event);
}
diff --git a/cmd/zed/agents/zfs_diagnosis.c b/cmd/zed/agents/zfs_diagnosis.c
index 813916d2e82c..e0ad00800add 100644
--- a/cmd/zed/agents/zfs_diagnosis.c
+++ b/cmd/zed/agents/zfs_diagnosis.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,6 +23,7 @@
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016, Intel Corporation.
+ * Copyright (c) 2023, Klara Inc.
*/
#include <stddef.h>
@@ -40,9 +41,23 @@
#include "fmd_api.h"
/*
- * Our serd engines are named 'zfs_<pool_guid>_<vdev_guid>_{checksum,io}'. This
- * #define reserves enough space for two 64-bit hex values plus the length of
- * the longest string.
+ * Default values for the serd engine when processing checksum or io errors. The
+ * semantics are N <events> in T <seconds>.
+ */
+#define DEFAULT_CHECKSUM_N 10 /* events */
+#define DEFAULT_CHECKSUM_T 600 /* seconds */
+#define DEFAULT_IO_N 10 /* events */
+#define DEFAULT_IO_T 600 /* seconds */
+#define DEFAULT_SLOW_IO_N 10 /* events */
+#define DEFAULT_SLOW_IO_T 30 /* seconds */
+
+#define CASE_GC_TIMEOUT_SECS 43200 /* 12 hours */
+
+/*
+ * Our serd engines are named in the following format:
+ * 'zfs_<pool_guid>_<vdev_guid>_{checksum,io,slow_io}'
+ * This #define reserves enough space for two 64-bit hex values plus the
+ * length of the longest string.
*/
#define MAX_SERDLEN (16 * 2 + sizeof ("zfs___checksum"))
@@ -59,6 +74,7 @@ typedef struct zfs_case_data {
int zc_pool_state;
char zc_serd_checksum[MAX_SERDLEN];
char zc_serd_io[MAX_SERDLEN];
+ char zc_serd_slow_io[MAX_SERDLEN];
int zc_has_remove_timer;
} zfs_case_data_t;
@@ -105,7 +121,8 @@ zfs_de_stats_t zfs_stats = {
{ "resource_drops", FMD_TYPE_UINT64, "resource related ereports" }
};
-static hrtime_t zfs_remove_timeout;
+/* wait 15 seconds after a removal */
+static hrtime_t zfs_remove_timeout = SEC2NSEC(15);
uu_list_pool_t *zfs_case_pool;
uu_list_t *zfs_cases;
@@ -115,6 +132,8 @@ uu_list_t *zfs_cases;
#define ZFS_MAKE_EREPORT(type) \
FM_EREPORT_CLASS "." ZFS_ERROR_CLASS "." type
+static void zfs_purge_cases(fmd_hdl_t *hdl);
+
/*
* Write out the persistent representation of an active case.
*/
@@ -162,6 +181,42 @@ zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
}
/*
+ * count other unique slow-io cases in a pool
+ */
+static uint_t
+zfs_other_slow_cases(fmd_hdl_t *hdl, const zfs_case_data_t *zfs_case)
+{
+ zfs_case_t *zcp;
+ uint_t cases = 0;
+ static hrtime_t next_check = 0;
+
+ /*
+ * Note that plumbing in some external GC would require adding locking,
+ * since most of this module code is not thread safe and assumes there
+ * is only one thread running against the module. So we perform GC here
+ * inline periodically so that future delay induced faults will be
+ * possible once the issue causing multiple vdev delays is resolved.
+ */
+ if (gethrestime_sec() > next_check) {
+ /* Periodically purge old SERD entries and stale cases */
+ fmd_serd_gc(hdl);
+ zfs_purge_cases(hdl);
+ next_check = gethrestime_sec() + CASE_GC_TIMEOUT_SECS;
+ }
+
+ for (zcp = uu_list_first(zfs_cases); zcp != NULL;
+ zcp = uu_list_next(zfs_cases, zcp)) {
+ if (zcp->zc_data.zc_pool_guid == zfs_case->zc_pool_guid &&
+ zcp->zc_data.zc_vdev_guid != zfs_case->zc_vdev_guid &&
+ zcp->zc_data.zc_serd_slow_io[0] != '\0' &&
+ fmd_serd_active(hdl, zcp->zc_data.zc_serd_slow_io)) {
+ cases++;
+ }
+ }
+ return (cases);
+}
+
+/*
* Iterate over any active cases. If any cases are associated with a pool or
* vdev which is no longer present on the system, close the associated case.
*/
@@ -367,6 +422,14 @@ zfs_serd_name(char *buf, uint64_t pool_guid, uint64_t vdev_guid,
(long long unsigned int)vdev_guid, type);
}
+static void
+zfs_case_retire(fmd_hdl_t *hdl, zfs_case_t *zcp)
+{
+ fmd_hdl_debug(hdl, "retiring case");
+
+ fmd_case_close(hdl, zcp->zc_case);
+}
+
/*
* Solve a given ZFS case. This first checks to make sure the diagnosis is
* still valid, as well as cleaning up any pending timer associated with the
@@ -448,12 +511,14 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
zfs_case_t *zcp, *dcp;
int32_t pool_state;
uint64_t ena, pool_guid, vdev_guid;
+ uint64_t checksum_n, checksum_t;
+ uint64_t io_n, io_t;
er_timeval_t pool_load;
er_timeval_t er_when;
nvlist_t *detector;
boolean_t pool_found = B_FALSE;
boolean_t isresource;
- char *type;
+ const char *type;
/*
* We subscribe to notifications for vdev or pool removal. In these
@@ -621,9 +686,7 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
if (strcmp(class,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DATA)) == 0 ||
strcmp(class,
- ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE)) == 0 ||
- strcmp(class,
- ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY)) == 0) {
+ ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE)) == 0) {
zfs_stats.resource_drops.fmds_value.ui64++;
return;
}
@@ -691,6 +754,9 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
if (zcp->zc_data.zc_serd_checksum[0] != '\0')
fmd_serd_reset(hdl,
zcp->zc_data.zc_serd_checksum);
+ if (zcp->zc_data.zc_serd_slow_io[0] != '\0')
+ fmd_serd_reset(hdl,
+ zcp->zc_data.zc_serd_slow_io);
} else if (fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_RSRC(FM_RESOURCE_STATECHANGE))) {
uint64_t state = 0;
@@ -719,7 +785,11 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
if (fmd_case_solved(hdl, zcp->zc_case))
return;
- fmd_hdl_debug(hdl, "error event '%s'", class);
+ if (vdev_guid)
+ fmd_hdl_debug(hdl, "error event '%s', vdev %llu", class,
+ vdev_guid);
+ else
+ fmd_hdl_debug(hdl, "error event '%s'", class);
/*
* Determine if we should solve the case and generate a fault. We solve
@@ -768,8 +838,10 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO_FAILURE)) ||
fmd_nvl_class_match(hdl, nvl,
+ ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY)) ||
+ fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
- char *failmode = NULL;
+ const char *failmode = NULL;
boolean_t checkremove = B_FALSE;
uint32_t pri = 0;
int32_t flags = 0;
@@ -784,16 +856,71 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
if (fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO))) {
if (zcp->zc_data.zc_serd_io[0] == '\0') {
+ if (nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N,
+ &io_n) != 0) {
+ io_n = DEFAULT_IO_N;
+ }
+ if (nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T,
+ &io_t) != 0) {
+ io_t = DEFAULT_IO_T;
+ }
zfs_serd_name(zcp->zc_data.zc_serd_io,
pool_guid, vdev_guid, "io");
fmd_serd_create(hdl, zcp->zc_data.zc_serd_io,
- fmd_prop_get_int32(hdl, "io_N"),
- fmd_prop_get_int64(hdl, "io_T"));
+ io_n,
+ SEC2NSEC(io_t));
zfs_case_serialize(zcp);
}
if (fmd_serd_record(hdl, zcp->zc_data.zc_serd_io, ep))
checkremove = B_TRUE;
} else if (fmd_nvl_class_match(hdl, nvl,
+ ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY))) {
+ uint64_t slow_io_n, slow_io_t;
+
+ /*
+ * Create a slow io SERD engine when the VDEV has the
+ * 'vdev_slow_io_n' and 'vdev_slow_io_n' properties.
+ */
+ if (zcp->zc_data.zc_serd_slow_io[0] == '\0' &&
+ nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_N,
+ &slow_io_n) == 0 &&
+ nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_T,
+ &slow_io_t) == 0) {
+ zfs_serd_name(zcp->zc_data.zc_serd_slow_io,
+ pool_guid, vdev_guid, "slow_io");
+ fmd_serd_create(hdl,
+ zcp->zc_data.zc_serd_slow_io,
+ slow_io_n,
+ SEC2NSEC(slow_io_t));
+ zfs_case_serialize(zcp);
+ }
+ /* Pass event to SERD engine and see if this triggers */
+ if (zcp->zc_data.zc_serd_slow_io[0] != '\0' &&
+ fmd_serd_record(hdl, zcp->zc_data.zc_serd_slow_io,
+ ep)) {
+ /*
+ * Ignore a slow io diagnosis when other
+ * VDEVs in the pool show signs of being slow.
+ */
+ if (zfs_other_slow_cases(hdl, &zcp->zc_data)) {
+ zfs_case_retire(hdl, zcp);
+ fmd_hdl_debug(hdl, "pool %llu has "
+ "multiple slow io cases -- skip "
+ "degrading vdev %llu",
+ (u_longlong_t)
+ zcp->zc_data.zc_pool_guid,
+ (u_longlong_t)
+ zcp->zc_data.zc_vdev_guid);
+ } else {
+ zfs_case_solve(hdl, zcp,
+ "fault.fs.zfs.vdev.slow_io");
+ }
+ }
+ } else if (fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) {
/*
* We ignore ereports for checksum errors generated by
@@ -813,12 +940,23 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
}
if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
+ if (nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N,
+ &checksum_n) != 0) {
+ checksum_n = DEFAULT_CHECKSUM_N;
+ }
+ if (nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T,
+ &checksum_t) != 0) {
+ checksum_t = DEFAULT_CHECKSUM_T;
+ }
+
zfs_serd_name(zcp->zc_data.zc_serd_checksum,
pool_guid, vdev_guid, "checksum");
fmd_serd_create(hdl,
zcp->zc_data.zc_serd_checksum,
- fmd_prop_get_int32(hdl, "checksum_N"),
- fmd_prop_get_int64(hdl, "checksum_T"));
+ checksum_n,
+ SEC2NSEC(checksum_t));
zfs_case_serialize(zcp);
}
if (fmd_serd_record(hdl,
@@ -892,6 +1030,8 @@ zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
if (zcp->zc_data.zc_serd_io[0] != '\0')
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
+ if (zcp->zc_data.zc_serd_slow_io[0] != '\0')
+ fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_slow_io);
if (zcp->zc_data.zc_has_remove_timer)
fmd_timer_remove(hdl, zcp->zc_remove_timer);
@@ -900,30 +1040,15 @@ zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
}
-/*
- * We use the fmd gc entry point to look for old cases that no longer apply.
- * This allows us to keep our set of case data small in a long running system.
- */
-static void
-zfs_fm_gc(fmd_hdl_t *hdl)
-{
- zfs_purge_cases(hdl);
-}
-
static const fmd_hdl_ops_t fmd_ops = {
zfs_fm_recv, /* fmdo_recv */
zfs_fm_timeout, /* fmdo_timeout */
zfs_fm_close, /* fmdo_close */
NULL, /* fmdo_stats */
- zfs_fm_gc, /* fmdo_gc */
+ NULL, /* fmdo_gc */
};
static const fmd_prop_t fmd_props[] = {
- { "checksum_N", FMD_TYPE_UINT32, "10" },
- { "checksum_T", FMD_TYPE_TIME, "10min" },
- { "io_N", FMD_TYPE_UINT32, "10" },
- { "io_T", FMD_TYPE_TIME, "10min" },
- { "remove_timeout", FMD_TYPE_TIME, "15sec" },
{ NULL, 0, NULL }
};
@@ -964,8 +1089,6 @@ _zfs_diagnosis_init(fmd_hdl_t *hdl)
(void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (zfs_stats) /
sizeof (fmd_stat_t), (fmd_stat_t *)&zfs_stats);
-
- zfs_remove_timeout = fmd_prop_get_int64(hdl, "remove_timeout");
}
void
diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c
index 17e47873ebb7..69163b80bd5a 100644
--- a/cmd/zed/agents/zfs_mod.c
+++ b/cmd/zed/agents/zfs_mod.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,6 +24,7 @@
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016, 2017, Intel Corporation.
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+ * Copyright (c) 2023, Klara Inc.
*/
/*
@@ -133,6 +134,11 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
if (zfs_toplevel_state(zhp) < VDEV_STATE_DEGRADED) {
unavailpool_t *uap;
uap = malloc(sizeof (unavailpool_t));
+ if (uap == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
uap->uap_zhp = zhp;
list_insert_tail((list_t *)data, uap);
} else {
@@ -142,6 +148,17 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
}
/*
+ * Write an array of strings to the zed log
+ */
+static void lines_to_zed_log_msg(char **lines, int lines_cnt)
+{
+ int i;
+ for (i = 0; i < lines_cnt; i++) {
+ zed_log_msg(LOG_INFO, "%s", lines[i]);
+ }
+}
+
+/*
* Two stage replace on Linux
* since we get disk notifications
* we can wait for partitioned disk slice to show up!
@@ -178,22 +195,31 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
static void
zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
{
- char *path;
+ const char *path;
vdev_state_t newstate;
nvlist_t *nvroot, *newvd;
pendingdev_t *device;
uint64_t wholedisk = 0ULL;
uint64_t offline = 0ULL, faulted = 0ULL;
uint64_t guid = 0ULL;
- char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
+ uint64_t is_spare = 0;
+ const char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
char rawpath[PATH_MAX], fullpath[PATH_MAX];
- char devpath[PATH_MAX];
+ char pathbuf[PATH_MAX];
int ret;
+ int online_flag = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE;
boolean_t is_sd = B_FALSE;
boolean_t is_mpath_wholedisk = B_FALSE;
uint_t c;
vdev_stat_t *vs;
+ char **lines = NULL;
+ int lines_cnt = 0;
+ /*
+ * Get the persistent path, typically under the '/dev/disk/by-id' or
+ * '/dev/disk/by-vdev' directories. Note that this path can change
+ * when a vdev is replaced with a new disk.
+ */
if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
return;
@@ -207,13 +233,18 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
}
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &physpath);
+
+ update_vdev_config_dev_sysfs_path(vdev, path,
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
&enc_sysfs_path);
+
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
+ (void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_IS_SPARE, &is_spare);
/*
* Special case:
@@ -304,11 +335,13 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
}
}
+ if (is_spare)
+ online_flag |= ZFS_ONLINE_SPARE;
+
/*
* Attempt to online the device.
*/
- if (zpool_vdev_online(zhp, fullpath,
- ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
+ if (zpool_vdev_online(zhp, fullpath, online_flag, &newstate) == 0 &&
(newstate == VDEV_STATE_HEALTHY ||
newstate == VDEV_STATE_DEGRADED)) {
zed_log_msg(LOG_INFO,
@@ -347,24 +380,27 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
(void) snprintf(rawpath, sizeof (rawpath), "%s%s",
is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath);
- if (realpath(rawpath, devpath) == NULL && !is_mpath_wholedisk) {
+ if (realpath(rawpath, pathbuf) == NULL && !is_mpath_wholedisk) {
zed_log_msg(LOG_INFO, " realpath: %s failed (%s)",
rawpath, strerror(errno));
- (void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT,
- &newstate);
+ int err = zpool_vdev_online(zhp, fullpath,
+ ZFS_ONLINE_FORCEFAULT, &newstate);
- zed_log_msg(LOG_INFO, " zpool_vdev_online: %s FORCEFAULT (%s)",
- fullpath, libzfs_error_description(g_zfshdl));
+ zed_log_msg(LOG_INFO, " zpool_vdev_online: %s FORCEFAULT (%s) "
+ "err %d, new state %d",
+ fullpath, libzfs_error_description(g_zfshdl), err,
+ err ? (int)newstate : 0);
return;
}
/* Only autoreplace bad disks */
if ((vs->vs_state != VDEV_STATE_DEGRADED) &&
(vs->vs_state != VDEV_STATE_FAULTED) &&
+ (vs->vs_state != VDEV_STATE_REMOVED) &&
(vs->vs_state != VDEV_STATE_CANT_OPEN)) {
zed_log_msg(LOG_INFO, " not autoreplacing since disk isn't in "
- "a bad state (currently %d)", vs->vs_state);
+ "a bad state (currently %llu)", vs->vs_state);
return;
}
@@ -372,6 +408,22 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
if (is_mpath_wholedisk) {
/* Don't label device mapper or multipath disks. */
+ zed_log_msg(LOG_INFO,
+ " it's a multipath wholedisk, don't label");
+ if (zpool_prepare_disk(zhp, vdev, "autoreplace", &lines,
+ &lines_cnt) != 0) {
+ zed_log_msg(LOG_INFO,
+ " zpool_prepare_disk: could not "
+ "prepare '%s' (%s)", fullpath,
+ libzfs_error_description(g_zfshdl));
+ if (lines_cnt > 0) {
+ zed_log_msg(LOG_INFO,
+ " zfs_prepare_disk output:");
+ lines_to_zed_log_msg(lines, lines_cnt);
+ }
+ libzfs_free_str_array(lines, lines_cnt);
+ return;
+ }
} else if (!labeled) {
/*
* we're auto-replacing a raw disk, so label it first
@@ -388,16 +440,24 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* to trigger a ZFS fault for the device (and any hot spare
* replacement).
*/
- leafname = strrchr(devpath, '/') + 1;
+ leafname = strrchr(pathbuf, '/') + 1;
/*
* If this is a request to label a whole disk, then attempt to
* write out the label.
*/
- if (zpool_label_disk(g_zfshdl, zhp, leafname) != 0) {
- zed_log_msg(LOG_INFO, " zpool_label_disk: could not "
+ if (zpool_prepare_and_label_disk(g_zfshdl, zhp, leafname,
+ vdev, "autoreplace", &lines, &lines_cnt) != 0) {
+ zed_log_msg(LOG_WARNING,
+ " zpool_prepare_and_label_disk: could not "
"label '%s' (%s)", leafname,
libzfs_error_description(g_zfshdl));
+ if (lines_cnt > 0) {
+ zed_log_msg(LOG_INFO,
+ " zfs_prepare_disk output:");
+ lines_to_zed_log_msg(lines, lines_cnt);
+ }
+ libzfs_free_str_array(lines, lines_cnt);
(void) zpool_vdev_online(zhp, fullpath,
ZFS_ONLINE_FORCEFAULT, &newstate);
@@ -411,11 +471,16 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* completed.
*/
device = malloc(sizeof (pendingdev_t));
+ if (device == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
(void) strlcpy(device->pd_physpath, physpath,
sizeof (device->pd_physpath));
list_insert_tail(&g_device_list, device);
- zed_log_msg(LOG_INFO, " zpool_label_disk: async '%s' (%llu)",
+ zed_log_msg(LOG_NOTICE, " zpool_label_disk: async '%s' (%llu)",
leafname, (u_longlong_t)guid);
return; /* resumes at EC_DEV_ADD.ESC_DISK for partition */
@@ -438,8 +503,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
}
if (!found) {
/* unexpected partition slice encountered */
- zed_log_msg(LOG_INFO, "labeled disk %s unexpected here",
- fullpath);
+ zed_log_msg(LOG_WARNING, "labeled disk %s was "
+ "unexpected here", fullpath);
(void) zpool_vdev_online(zhp, fullpath,
ZFS_ONLINE_FORCEFAULT, &newstate);
return;
@@ -448,10 +513,21 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
zed_log_msg(LOG_INFO, " zpool_label_disk: resume '%s' (%llu)",
physpath, (u_longlong_t)guid);
- (void) snprintf(devpath, sizeof (devpath), "%s%s",
- DEV_BYID_PATH, new_devid);
+ /*
+ * Paths that begin with '/dev/disk/by-id/' will change and so
+ * they must be updated before calling zpool_vdev_attach().
+ */
+ if (strncmp(path, DEV_BYID_PATH, strlen(DEV_BYID_PATH)) == 0) {
+ (void) snprintf(pathbuf, sizeof (pathbuf), "%s%s",
+ DEV_BYID_PATH, new_devid);
+ zed_log_msg(LOG_INFO, " zpool_label_disk: path '%s' "
+ "replaced by '%s'", path, pathbuf);
+ path = pathbuf;
+ }
}
+ libzfs_free_str_array(lines, lines_cnt);
+
/*
* Construct the root vdev to pass to zpool_vdev_attach(). While adding
* the entire vdev structure is harmless, we construct a reduced set of
@@ -490,9 +566,11 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* Wait for udev to verify the links exist, then auto-replace
* the leaf disk at same physical location.
*/
- if (zpool_label_disk_wait(path, 3000) != 0) {
- zed_log_msg(LOG_WARNING, "zfs_mod: expected replacement "
- "disk %s is missing", path);
+ if (zpool_label_disk_wait(path, DISK_LABEL_WAIT) != 0) {
+ zed_log_msg(LOG_WARNING, "zfs_mod: pool '%s', after labeling "
+ "replacement disk, the expected disk partition link '%s' "
+ "is missing after waiting %u ms",
+ zpool_get_name(zhp), path, DISK_LABEL_WAIT);
nvlist_free(nvroot);
return;
}
@@ -507,7 +585,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
B_TRUE, B_FALSE);
}
- zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
+ zed_log_msg(LOG_WARNING, " zpool_vdev_replace: %s with %s (%s)",
fullpath, path, (ret == 0) ? "no errors" :
libzfs_error_description(g_zfshdl));
@@ -525,16 +603,20 @@ typedef struct dev_data {
boolean_t dd_islabeled;
uint64_t dd_pool_guid;
uint64_t dd_vdev_guid;
+ uint64_t dd_new_vdev_guid;
const char *dd_new_devid;
+ uint64_t dd_num_spares;
} dev_data_t;
static void
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
{
dev_data_t *dp = data;
- char *path = NULL;
+ const char *path = NULL;
uint_t c, children;
nvlist_t **child;
+ uint64_t guid = 0;
+ uint64_t isspare = 0;
/*
* First iterate over any children.
@@ -560,19 +642,16 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
}
/* once a vdev was matched and processed there is nothing left to do */
- if (dp->dd_found)
+ if (dp->dd_found && dp->dd_num_spares == 0)
return;
+ (void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
/*
* Match by GUID if available otherwise fallback to devid or physical
*/
if (dp->dd_vdev_guid != 0) {
- uint64_t guid;
-
- if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
- &guid) != 0 || guid != dp->dd_vdev_guid) {
+ if (guid != dp->dd_vdev_guid)
return;
- }
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
dp->dd_found = B_TRUE;
@@ -582,11 +661,21 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
* illumos, substring matching is not required to accommodate
* the partition suffix. An exact match will be present in
* the dp->dd_compare value.
+ * If the attached disk already contains a vdev GUID, it means
+ * the disk is not clean. In such a scenario, the physical path
+ * would be a match that makes the disk faulted when trying to
+ * online it. So, we would only want to proceed if either GUID
+ * matches with the last attached disk or the disk is in clean
+ * state.
*/
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
strcmp(dp->dd_compare, path) != 0) {
- zed_log_msg(LOG_INFO, " %s: no match (%s != vdev %s)",
- __func__, dp->dd_compare, path);
+ return;
+ }
+ if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
+ zed_log_msg(LOG_INFO, " %s: no match (GUID:%llu"
+ " != vdev GUID:%llu)", __func__,
+ dp->dd_new_vdev_guid, guid);
return;
}
@@ -594,13 +683,17 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
dp->dd_prop, path);
dp->dd_found = B_TRUE;
- /* pass the new devid for use by replacing code */
+ /* pass the new devid for use by auto-replacing code */
if (dp->dd_new_devid != NULL) {
(void) nvlist_add_string(nvl, "new_devid",
dp->dd_new_devid);
}
}
+ if (dp->dd_found == B_TRUE && nvlist_lookup_uint64(nvl,
+ ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare)
+ dp->dd_num_spares++;
+
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
}
@@ -661,7 +754,9 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
}
zpool_close(zhp);
- return (dp->dd_found); /* cease iteration after a match */
+
+ /* cease iteration after a match */
+ return (dp->dd_found && dp->dd_num_spares == 0);
}
/*
@@ -670,7 +765,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
*/
static boolean_t
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
- boolean_t is_slice)
+ boolean_t is_slice, uint64_t new_vdev_guid)
{
dev_data_t data = { 0 };
@@ -680,6 +775,7 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
data.dd_found = B_FALSE;
data.dd_islabeled = is_slice;
data.dd_new_devid = devid; /* used by auto replace code */
+ data.dd_new_vdev_guid = new_vdev_guid;
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
@@ -816,7 +912,7 @@ guid_iter(uint64_t pool_guid, uint64_t vdev_guid, const char *devid,
static int
zfs_deliver_add(nvlist_t *nvl)
{
- char *devpath = NULL, *devid = NULL;
+ const char *devpath = NULL, *devid = NULL;
uint64_t pool_guid = 0, vdev_guid = 0;
boolean_t is_slice;
@@ -848,7 +944,7 @@ zfs_deliver_add(nvlist_t *nvl)
if (devid_iter(devid, zfs_process_add, is_slice))
return (0);
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
- is_slice))
+ is_slice, vdev_guid))
return (0);
if (vdev_guid != 0)
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
@@ -894,21 +990,98 @@ zfs_deliver_check(nvlist_t *nvl)
return (0);
}
+/*
+ * Given a path to a vdev, lookup the vdev's physical size from its
+ * config nvlist.
+ *
+ * Returns the vdev's physical size in bytes on success, 0 on error.
+ */
+static uint64_t
+vdev_size_from_config(zpool_handle_t *zhp, const char *vdev_path)
+{
+ nvlist_t *nvl = NULL;
+ boolean_t avail_spare, l2cache, log;
+ vdev_stat_t *vs = NULL;
+ uint_t c;
+
+ nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
+ if (!nvl)
+ return (0);
+
+ verify(nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
+ (uint64_t **)&vs, &c) == 0);
+ if (!vs) {
+ zed_log_msg(LOG_INFO, "%s: no nvlist for '%s'", __func__,
+ vdev_path);
+ return (0);
+ }
+
+ return (vs->vs_pspace);
+}
+
+/*
+ * Given a path to a vdev, lookup if the vdev is a "whole disk" in the
+ * config nvlist. "whole disk" means that ZFS was passed a whole disk
+ * at pool creation time, which it partitioned up and has full control over.
+ * Thus a partition with wholedisk=1 set tells us that zfs created the
+ * partition at creation time. A partition without whole disk set would have
+ * been created by externally (like with fdisk) and passed to ZFS.
+ *
+ * Returns the whole disk value (either 0 or 1).
+ */
+static uint64_t
+vdev_whole_disk_from_config(zpool_handle_t *zhp, const char *vdev_path)
+{
+ nvlist_t *nvl = NULL;
+ boolean_t avail_spare, l2cache, log;
+ uint64_t wholedisk = 0;
+
+ nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
+ if (!nvl)
+ return (0);
+
+ (void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
+
+ return (wholedisk);
+}
+
+/*
+ * If the device size grew more than 1% then return true.
+ */
+#define DEVICE_GREW(oldsize, newsize) \
+ ((newsize > oldsize) && \
+ ((newsize / (newsize - oldsize)) <= 100))
+
static int
zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
{
- char *devname = data;
boolean_t avail_spare, l2cache;
+ nvlist_t *udev_nvl = data;
nvlist_t *tgt;
int error;
+ const char *tmp_devname;
+ char devname[MAXPATHLEN] = "";
+ uint64_t guid;
+
+ if (nvlist_lookup_uint64(udev_nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
+ sprintf(devname, "%llu", (u_longlong_t)guid);
+ } else if (nvlist_lookup_string(udev_nvl, DEV_PHYS_PATH,
+ &tmp_devname) == 0) {
+ strlcpy(devname, tmp_devname, MAXPATHLEN);
+ zfs_append_partition(devname, MAXPATHLEN);
+ } else {
+ zed_log_msg(LOG_INFO, "%s: no guid or physpath", __func__);
+ }
+
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'",
devname, zpool_get_name(zhp));
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
&avail_spare, &l2cache, NULL)) != NULL) {
- char *path, fullpath[MAXPATHLEN];
- uint64_t wholedisk;
+ const char *path;
+ char fullpath[MAXPATHLEN];
+ uint64_t wholedisk = 0;
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
if (error) {
@@ -916,16 +1089,15 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
return (0);
}
- error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
+ (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
&wholedisk);
- if (error)
- wholedisk = 0;
if (wholedisk) {
+ char *tmp;
path = strrchr(path, '/');
if (path != NULL) {
- path = zfs_strip_partition(path + 1);
- if (path == NULL) {
+ tmp = zfs_strip_partition(path + 1);
+ if (tmp == NULL) {
zpool_close(zhp);
return (0);
}
@@ -934,8 +1106,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
return (0);
}
- (void) strlcpy(fullpath, path, sizeof (fullpath));
- free(path);
+ (void) strlcpy(fullpath, tmp, sizeof (fullpath));
+ free(tmp);
/*
* We need to reopen the pool associated with this
@@ -953,12 +1125,75 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
vdev_state_t newstate;
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
- error = zpool_vdev_online(zhp, fullpath, 0,
- &newstate);
- zed_log_msg(LOG_INFO, "zfsdle_vdev_online: "
- "setting device '%s' to ONLINE state "
- "in pool '%s': %d", fullpath,
- zpool_get_name(zhp), error);
+ /*
+ * If this disk size has not changed, then
+ * there's no need to do an autoexpand. To
+ * check we look at the disk's size in its
+ * config, and compare it to the disk size
+ * that udev is reporting.
+ */
+ uint64_t udev_size = 0, conf_size = 0,
+ wholedisk = 0, udev_parent_size = 0;
+
+ /*
+ * Get the size of our disk that udev is
+ * reporting.
+ */
+ if (nvlist_lookup_uint64(udev_nvl, DEV_SIZE,
+ &udev_size) != 0) {
+ udev_size = 0;
+ }
+
+ /*
+ * Get the size of our disk's parent device
+ * from udev (where sda1's parent is sda).
+ */
+ if (nvlist_lookup_uint64(udev_nvl,
+ DEV_PARENT_SIZE, &udev_parent_size) != 0) {
+ udev_parent_size = 0;
+ }
+
+ conf_size = vdev_size_from_config(zhp,
+ fullpath);
+
+ wholedisk = vdev_whole_disk_from_config(zhp,
+ fullpath);
+
+ /*
+ * Only attempt an autoexpand if the vdev size
+ * changed. There are two different cases
+ * to consider.
+ *
+ * 1. wholedisk=1
+ * If you do a 'zpool create' on a whole disk
+ * (like /dev/sda), then zfs will create
+ * partitions on the disk (like /dev/sda1). In
+ * that case, wholedisk=1 will be set in the
+ * partition's nvlist config. So zed will need
+ * to see if your parent device (/dev/sda)
+ * expanded in size, and if so, then attempt
+ * the autoexpand.
+ *
+ * 2. wholedisk=0
+ * If you do a 'zpool create' on an existing
+ * partition, or a device that doesn't allow
+ * partitions, then wholedisk=0, and you will
+ * simply need to check if the device itself
+ * expanded in size.
+ */
+ if (DEVICE_GREW(conf_size, udev_size) ||
+ (wholedisk && DEVICE_GREW(conf_size,
+ udev_parent_size))) {
+ error = zpool_vdev_online(zhp, fullpath,
+ 0, &newstate);
+
+ zed_log_msg(LOG_INFO,
+ "%s: autoexpanding '%s' from %llu"
+ " to %llu bytes in pool '%s': %d",
+ __func__, fullpath, conf_size,
+ MAX(udev_size, udev_parent_size),
+ zpool_get_name(zhp), error);
+ }
}
}
zpool_close(zhp);
@@ -977,7 +1212,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
static int
zfs_deliver_dle(nvlist_t *nvl)
{
- char *devname, name[MAXPATHLEN];
+ const char *devname;
+ char name[MAXPATHLEN];
uint64_t guid;
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
@@ -986,10 +1222,11 @@ 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");
}
- if (zpool_iter(g_zfshdl, zfsdle_vdev_online, name) != 1) {
+ if (zpool_iter(g_zfshdl, zfsdle_vdev_online, nvl) != 1) {
zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not "
"found", name);
return (1);
@@ -1112,17 +1349,14 @@ zfs_slm_fini(void)
tpool_destroy(g_tpool);
}
- while ((pool = (list_head(&g_pool_list))) != NULL) {
- list_remove(&g_pool_list, pool);
+ while ((pool = list_remove_head(&g_pool_list)) != NULL) {
zpool_close(pool->uap_zhp);
free(pool);
}
list_destroy(&g_pool_list);
- while ((device = (list_head(&g_device_list))) != NULL) {
- list_remove(&g_device_list, device);
+ while ((device = list_remove_head(&g_device_list)) != NULL)
free(device);
- }
list_destroy(&g_device_list);
libzfs_fini(g_zfshdl);
diff --git a/cmd/zed/agents/zfs_retire.c b/cmd/zed/agents/zfs_retire.c
index 8f12bb82e1e4..1ef5c631a438 100644
--- a/cmd/zed/agents/zfs_retire.c
+++ b/cmd/zed/agents/zfs_retire.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -76,6 +76,8 @@ typedef struct find_cbdata {
uint64_t cb_guid;
zpool_handle_t *cb_zhp;
nvlist_t *cb_vdev;
+ uint64_t cb_vdev_guid;
+ uint64_t cb_num_spares;
} find_cbdata_t;
static int
@@ -141,6 +143,64 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
return (NULL);
}
+static int
+remove_spares(zpool_handle_t *zhp, void *data)
+{
+ nvlist_t *config, *nvroot;
+ nvlist_t **spares;
+ uint_t nspares;
+ char *devname;
+ find_cbdata_t *cbp = data;
+ uint64_t spareguid = 0;
+ vdev_stat_t *vs;
+ unsigned int c;
+
+ config = zpool_get_config(zhp, NULL);
+ if (nvlist_lookup_nvlist(config,
+ ZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0) {
+ zpool_close(zhp);
+ return (0);
+ }
+
+ if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
+ &spares, &nspares) != 0) {
+ zpool_close(zhp);
+ return (0);
+ }
+
+ for (int i = 0; i < nspares; i++) {
+ if (nvlist_lookup_uint64(spares[i], ZPOOL_CONFIG_GUID,
+ &spareguid) == 0 && spareguid == cbp->cb_vdev_guid) {
+ devname = zpool_vdev_name(NULL, zhp, spares[i],
+ B_FALSE);
+ nvlist_lookup_uint64_array(spares[i],
+ ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c);
+ if (vs->vs_state != VDEV_STATE_REMOVED &&
+ zpool_vdev_remove_wanted(zhp, devname) == 0)
+ cbp->cb_num_spares++;
+ break;
+ }
+ }
+
+ zpool_close(zhp);
+ return (0);
+}
+
+/*
+ * Given a vdev guid, find and remove all spares associated with it.
+ */
+static int
+find_and_remove_spares(libzfs_handle_t *zhdl, uint64_t vdev_guid)
+{
+ find_cbdata_t cb;
+
+ cb.cb_num_spares = 0;
+ cb.cb_vdev_guid = vdev_guid;
+ zpool_iter(zhdl, remove_spares, &cb);
+
+ return (cb.cb_num_spares);
+}
+
/*
* Given a (pool, vdev) GUID pair, find the matching pool and vdev.
*/
@@ -222,7 +282,7 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
*/
for (s = 0; s < nspares; s++) {
boolean_t rebuild = B_FALSE;
- char *spare_name, *type;
+ const char *spare_name, *type;
if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
&spare_name) != 0)
@@ -315,18 +375,23 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
libzfs_handle_t *zhdl = zdp->zrd_hdl;
boolean_t fault_device, degrade_device;
boolean_t is_repair;
- char *scheme;
+ boolean_t l2arc = B_FALSE;
+ boolean_t spare = B_FALSE;
+ const char *scheme;
nvlist_t *vdev = NULL;
- char *uuid;
+ const char *uuid;
int repair_done = 0;
boolean_t retire;
boolean_t is_disk;
vdev_aux_t aux;
uint64_t state = 0;
+ vdev_stat_t *vs;
+ unsigned int c;
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
- nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE, &state);
+ (void) nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE,
+ &state);
/*
* If this is a resource notifying us of device removal then simply
@@ -336,13 +401,34 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
if (strcmp(class, "resource.fs.zfs.removed") == 0 ||
(strcmp(class, "resource.fs.zfs.statechange") == 0 &&
(state == VDEV_STATE_REMOVED || state == VDEV_STATE_FAULTED))) {
- char *devtype;
+ const char *devtype;
char *devname;
+ if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
+ &devtype) == 0) {
+ if (strcmp(devtype, VDEV_TYPE_SPARE) == 0)
+ spare = B_TRUE;
+ else if (strcmp(devtype, VDEV_TYPE_L2CACHE) == 0)
+ l2arc = B_TRUE;
+ }
+
+ if (nvlist_lookup_uint64(nvl,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
+ return;
+
+ if (vdev_guid == 0) {
+ fmd_hdl_debug(hdl, "Got a zero GUID");
+ return;
+ }
+
+ if (spare) {
+ int nspares = find_and_remove_spares(zhdl, vdev_guid);
+ fmd_hdl_debug(hdl, "%d spares removed", nspares);
+ return;
+ }
+
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
- &pool_guid) != 0 ||
- nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
- &vdev_guid) != 0)
+ &pool_guid) != 0)
return;
if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid,
@@ -351,13 +437,30 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
- /* Can't replace l2arc with a spare: offline the device */
- if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
- &devtype) == 0 && strcmp(devtype, VDEV_TYPE_L2CACHE) == 0) {
- fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
- zpool_vdev_offline(zhp, devname, B_TRUE);
- } else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
- replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
+ nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
+ (uint64_t **)&vs, &c);
+
+ /*
+ * If state removed is requested for already removed vdev,
+ * its a loopback event from spa_async_remove(). Just
+ * ignore it.
+ */
+ if (vs->vs_state == VDEV_STATE_REMOVED &&
+ state == VDEV_STATE_REMOVED)
+ return;
+
+ /* Remove the vdev since device is unplugged */
+ int remove_status = 0;
+ if (l2arc || (strcmp(class, "resource.fs.zfs.removed") == 0)) {
+ remove_status = zpool_vdev_remove_wanted(zhp, devname);
+ fmd_hdl_debug(hdl, "zpool_vdev_remove_wanted '%s'"
+ ", err:%d", devname, libzfs_errno(zhdl));
+ }
+
+ /* Replace the vdev with a spare if its not a l2arc */
+ if (!l2arc && !remove_status &&
+ (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
+ replace_with_spare(hdl, zhp, vdev) == B_FALSE)) {
/* Could not handle with spare */
fmd_hdl_debug(hdl, "no spare for '%s'", devname);
}
@@ -421,6 +524,9 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
"fault.fs.zfs.vdev.checksum")) {
degrade_device = B_TRUE;
} else if (fmd_nvl_class_match(hdl, fault,
+ "fault.fs.zfs.vdev.slow_io")) {
+ degrade_device = B_TRUE;
+ } else if (fmd_nvl_class_match(hdl, fault,
"fault.fs.zfs.device")) {
fault_device = B_FALSE;
} else if (fmd_nvl_class_match(hdl, fault, "fault.io.*")) {
diff --git a/cmd/zed/zed.d/Makefile.am b/cmd/zed/zed.d/Makefile.am
index c65b43fb027e..812558cf6d0f 100644
--- a/cmd/zed/zed.d/Makefile.am
+++ b/cmd/zed/zed.d/Makefile.am
@@ -16,6 +16,7 @@ dist_zedexec_SCRIPTS = \
%D%/scrub_finish-notify.sh \
%D%/statechange-led.sh \
%D%/statechange-notify.sh \
+ %D%/statechange-slot_off.sh \
%D%/trim_finish-notify.sh \
%D%/vdev_attach-led.sh \
%D%/vdev_clear-led.sh
@@ -35,6 +36,7 @@ zedconfdefaults = \
scrub_finish-notify.sh \
statechange-led.sh \
statechange-notify.sh \
+ statechange-slot_off.sh \
vdev_attach-led.sh \
vdev_clear-led.sh
diff --git a/cmd/zed/zed.d/statechange-led.sh b/cmd/zed/zed.d/statechange-led.sh
index 46bfc1b866f1..40cb61f17307 100755
--- a/cmd/zed/zed.d/statechange-led.sh
+++ b/cmd/zed/zed.d/statechange-led.sh
@@ -121,7 +121,7 @@ state_to_val()
{
state="$1"
case "$state" in
- FAULTED|DEGRADED|UNAVAIL)
+ FAULTED|DEGRADED|UNAVAIL|REMOVED)
echo 1
;;
ONLINE)
diff --git a/cmd/zed/zed.d/statechange-notify.sh b/cmd/zed/zed.d/statechange-notify.sh
index c475fdb36660..ae610df20e45 100755
--- a/cmd/zed/zed.d/statechange-notify.sh
+++ b/cmd/zed/zed.d/statechange-notify.sh
@@ -38,7 +38,7 @@ if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \
fi
umask 077
-note_subject="ZFS device fault for pool ${ZEVENT_POOL_GUID} on $(hostname)"
+note_subject="ZFS device fault for pool ${ZEVENT_POOL} on $(hostname)"
note_pathname="$(mktemp)"
{
if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then
@@ -66,7 +66,7 @@ note_pathname="$(mktemp)"
[ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}"
[ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}"
- echo " pool: ${ZEVENT_POOL_GUID}"
+ echo " pool: ${ZEVENT_POOL} (${ZEVENT_POOL_GUID})"
} > "${note_pathname}"
diff --git a/cmd/zed/zed.d/statechange-slot_off.sh b/cmd/zed/zed.d/statechange-slot_off.sh
new file mode 100755
index 000000000000..06acce93b8aa
--- /dev/null
+++ b/cmd/zed/zed.d/statechange-slot_off.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# shellcheck disable=SC3014,SC2154,SC2086,SC2034
+#
+# Turn off disk's enclosure slot if it becomes FAULTED.
+#
+# Bad SCSI disks can often "disappear and reappear" causing all sorts of chaos
+# as they flip between FAULTED and ONLINE. If
+# ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
+# FAULTED, then power down the slot via sysfs:
+#
+# /sys/class/enclosure/<enclosure>/<slot>/power_status
+#
+# We assume the user will be responsible for turning the slot back on again.
+#
+# Note that this script requires that your enclosure be supported by the
+# Linux SCSI Enclosure services (SES) driver. The script will do nothing
+# if you have no enclosure, or if your enclosure isn't supported.
+#
+# Exit codes:
+# 0: slot successfully powered off
+# 1: enclosure not available
+# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT disabled
+# 3: vdev was not FAULTED
+# 4: The enclosure sysfs path passed from ZFS does not exist
+# 5: Enclosure slot didn't actually turn off after we told it to
+
+[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
+. "${ZED_ZEDLET_DIR}/zed-functions.sh"
+
+if [ ! -d /sys/class/enclosure ] ; then
+ # No JBOD enclosure or NVMe slots
+ exit 1
+fi
+
+if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT}" != "1" ] ; then
+ exit 2
+fi
+
+if [ "$ZEVENT_VDEV_STATE_STR" != "FAULTED" ] ; then
+ exit 3
+fi
+
+if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
+ exit 4
+fi
+
+# Turn off the slot and wait for sysfs to report that the slot is off.
+# It can take ~400ms on some enclosures and multiple retries may be needed.
+for i in $(seq 1 20) ; do
+ echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
+
+ for j in $(seq 1 5) ; do
+ if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
+ break 2
+ fi
+ sleep 0.1
+ done
+done
+
+if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
+ exit 5
+fi
+
+zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"
diff --git a/cmd/zed/zed.d/zed-functions.sh b/cmd/zed/zed.d/zed-functions.sh
index 49b6b54029aa..470739d16460 100644
--- a/cmd/zed/zed.d/zed-functions.sh
+++ b/cmd/zed/zed.d/zed-functions.sh
@@ -205,6 +205,14 @@ zed_notify()
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
+ zed_notify_ntfy "${subject}" "${pathname}"; rv=$?
+ [ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
+ [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
+
+ zed_notify_gotify "${subject}" "${pathname}"; rv=$?
+ [ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
+ [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
+
[ "${num_success}" -gt 0 ] && return 0
[ "${num_failure}" -gt 0 ] && return 1
return 2
@@ -527,6 +535,191 @@ zed_notify_pushover()
}
+# zed_notify_ntfy (subject, pathname)
+#
+# Send a notification via Ntfy.sh <https://ntfy.sh/>.
+# The ntfy topic (ZED_NTFY_TOPIC) identifies the topic that the notification
+# will be sent to Ntfy.sh server. The ntfy url (ZED_NTFY_URL) defines the
+# self-hosted or provided hosted ntfy service location. The ntfy access token
+# <https://docs.ntfy.sh/publish/#access-tokens> (ZED_NTFY_ACCESS_TOKEN) reprsents an
+# access token that could be used if a topic is read/write protected. If a
+# topic can be written to publicaly, a ZED_NTFY_ACCESS_TOKEN is not required.
+#
+# Requires curl and sed executables to be installed in the standard PATH.
+#
+# References
+# https://docs.ntfy.sh
+#
+# Arguments
+# subject: notification subject
+# pathname: pathname containing the notification message (OPTIONAL)
+#
+# Globals
+# ZED_NTFY_TOPIC
+# ZED_NTFY_ACCESS_TOKEN (OPTIONAL)
+# ZED_NTFY_URL
+#
+# Return
+# 0: notification sent
+# 1: notification failed
+# 2: not configured
+#
+zed_notify_ntfy()
+{
+ local subject="$1"
+ local pathname="${2:-"/dev/null"}"
+ local msg_body
+ local msg_out
+ local msg_err
+
+ [ -n "${ZED_NTFY_TOPIC}" ] || return 2
+ local url="${ZED_NTFY_URL:-"https://ntfy.sh"}/${ZED_NTFY_TOPIC}"
+
+ if [ ! -r "${pathname}" ]; then
+ zed_log_err "ntfy cannot read \"${pathname}\""
+ return 1
+ fi
+
+ zed_check_cmd "curl" "sed" || return 1
+
+ # Read the message body in.
+ #
+ msg_body="$(cat "${pathname}")"
+
+ if [ -z "${msg_body}" ]
+ then
+ msg_body=$subject
+ subject=""
+ fi
+
+ # Send the POST request and check for errors.
+ #
+ if [ -n "${ZED_NTFY_ACCESS_TOKEN}" ]; then
+ msg_out="$( \
+ curl \
+ -u ":${ZED_NTFY_ACCESS_TOKEN}" \
+ -H "Title: ${subject}" \
+ -d "${msg_body}" \
+ -H "Priority: high" \
+ "${url}" \
+ 2>/dev/null \
+ )"; rv=$?
+ else
+ msg_out="$( \
+ curl \
+ -H "Title: ${subject}" \
+ -d "${msg_body}" \
+ -H "Priority: high" \
+ "${url}" \
+ 2>/dev/null \
+ )"; rv=$?
+ fi
+ if [ "${rv}" -ne 0 ]; then
+ zed_log_err "curl exit=${rv}"
+ return 1
+ fi
+ msg_err="$(echo "${msg_out}" \
+ | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
+ if [ -n "${msg_err}" ]; then
+ zed_log_err "ntfy \"${msg_err}"\"
+ return 1
+ fi
+ return 0
+}
+
+
+# zed_notify_gotify (subject, pathname)
+#
+# Send a notification via Gotify <https://gotify.net/>.
+# The Gotify URL (ZED_GOTIFY_URL) defines a self-hosted Gotify location.
+# The Gotify application token (ZED_GOTIFY_APPTOKEN) defines a
+# Gotify application token which is associated with a message.
+# The optional Gotify priority value (ZED_GOTIFY_PRIORITY) overrides the
+# default or configured priority at the Gotify server for the application.
+#
+# Requires curl and sed executables to be installed in the standard PATH.
+#
+# References
+# https://gotify.net/docs/index
+#
+# Arguments
+# subject: notification subject
+# pathname: pathname containing the notification message (OPTIONAL)
+#
+# Globals
+# ZED_GOTIFY_URL
+# ZED_GOTIFY_APPTOKEN
+# ZED_GOTIFY_PRIORITY
+#
+# Return
+# 0: notification sent
+# 1: notification failed
+# 2: not configured
+#
+zed_notify_gotify()
+{
+ local subject="$1"
+ local pathname="${2:-"/dev/null"}"
+ local msg_body
+ local msg_out
+ local msg_err
+
+ [ -n "${ZED_GOTIFY_URL}" ] && [ -n "${ZED_GOTIFY_APPTOKEN}" ] || return 2
+ local url="${ZED_GOTIFY_URL}/message?token=${ZED_GOTIFY_APPTOKEN}"
+
+ if [ ! -r "${pathname}" ]; then
+ zed_log_err "gotify cannot read \"${pathname}\""
+ return 1
+ fi
+
+ zed_check_cmd "curl" "sed" || return 1
+
+ # Read the message body in.
+ #
+ msg_body="$(cat "${pathname}")"
+
+ if [ -z "${msg_body}" ]
+ then
+ msg_body=$subject
+ subject=""
+ fi
+
+ # Send the POST request and check for errors.
+ #
+ if [ -n "${ZED_GOTIFY_PRIORITY}" ]; then
+ msg_out="$( \
+ curl \
+ --form-string "title=${subject}" \
+ --form-string "message=${msg_body}" \
+ --form-string "priority=${ZED_GOTIFY_PRIORITY}" \
+ "${url}" \
+ 2>/dev/null \
+ )"; rv=$?
+ else
+ msg_out="$( \
+ curl \
+ --form-string "title=${subject}" \
+ --form-string "message=${msg_body}" \
+ "${url}" \
+ 2>/dev/null \
+ )"; rv=$?
+ fi
+
+ if [ "${rv}" -ne 0 ]; then
+ zed_log_err "curl exit=${rv}"
+ return 1
+ fi
+ msg_err="$(echo "${msg_out}" \
+ | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
+ if [ -n "${msg_err}" ]; then
+ zed_log_err "gotify \"${msg_err}"\"
+ return 1
+ fi
+ return 0
+}
+
+
+
# zed_rate_limit (tag, [interval])
#
# Check whether an event of a given type [tag] has already occurred within the
diff --git a/cmd/zed/zed.d/zed.rc b/cmd/zed/zed.d/zed.rc
index c55a70c79f75..ec64ecfaa13c 100644
--- a/cmd/zed/zed.d/zed.rc
+++ b/cmd/zed/zed.d/zed.rc
@@ -142,3 +142,51 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
# Disabled by default, 1 to enable and 0 to disable.
#ZED_SYSLOG_DISPLAY_GUIDS=1
+##
+# Power off the drive's slot in the enclosure if it becomes FAULTED. This can
+# help silence misbehaving drives. This assumes your drive enclosure fully
+# supports slot power control via sysfs.
+#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT=1
+
+##
+# Ntfy topic
+# This defines which topic will receive the ntfy notification.
+# <https://docs.ntfy.sh/publish/>
+# Disabled by default; uncomment to enable.
+#ZED_NTFY_TOPIC=""
+
+##
+# Ntfy access token (optional for public topics)
+# This defines an access token which can be used
+# to allow you to authenticate when sending to topics
+# <https://docs.ntfy.sh/publish/#access-tokens>
+# Disabled by default; uncomment to enable.
+#ZED_NTFY_ACCESS_TOKEN=""
+
+##
+# Ntfy Service URL
+# This defines which service the ntfy call will be directed toward
+# <https://docs.ntfy.sh/install/>
+# https://ntfy.sh by default; uncomment to enable an alternative service url.
+#ZED_NTFY_URL="https://ntfy.sh"
+
+##
+# Gotify server URL
+# This defines a URL that the Gotify call will be directed toward.
+# <https://gotify.net/docs/index>
+# Disabled by default; uncomment to enable.
+#ZED_GOTIFY_URL=""
+
+##
+# Gotify application token
+# This defines a Gotify application token which a message is associated with.
+# This token is generated when an application is created on the Gotify server.
+# Disabled by default; uncomment to enable.
+#ZED_GOTIFY_APPTOKEN=""
+
+##
+# Gotify priority (optional)
+# If defined, this overrides the default priority of the
+# Gotify application associated with ZED_GOTIFY_APPTOKEN.
+# Value is an integer 0 and up.
+#ZED_GOTIFY_PRIORITY=""
diff --git a/cmd/zed/zed_conf.c b/cmd/zed/zed_conf.c
index 59935102f123..29de27c77c34 100644
--- a/cmd/zed/zed_conf.c
+++ b/cmd/zed/zed_conf.c
@@ -48,6 +48,7 @@ zed_conf_init(struct zed_conf *zcp)
zcp->zevent_fd = -1; /* opened in zed_event_init() */
zcp->max_jobs = 16;
+ zcp->max_zevent_buf_len = 1 << 20;
if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
@@ -141,6 +142,8 @@ _zed_conf_display_help(const char *prog, boolean_t got_err)
.v = ZED_STATE_FILE },
{ .o = "-j JOBS", .d = "Start at most JOBS at once.",
.v = "16" },
+ { .o = "-b LEN", .d = "Cap kernel event buffer at LEN entries.",
+ .v = "1048576" },
{},
};
@@ -230,7 +233,7 @@ _zed_conf_parse_path(char **resultp, const char *path)
void
zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
{
- const char * const opts = ":hLVd:p:P:s:vfFMZIj:";
+ const char * const opts = ":hLVd:p:P:s:vfFMZIj:b:";
int opt;
unsigned long raw;
@@ -291,6 +294,17 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
zcp->max_jobs = raw;
}
break;
+ case 'b':
+ errno = 0;
+ raw = strtoul(optarg, NULL, 0);
+ if (errno == ERANGE || raw > INT32_MAX) {
+ zed_log_die("%lu is too large", raw);
+ } if (raw == 0) {
+ zcp->max_zevent_buf_len = INT32_MAX;
+ } else {
+ zcp->max_zevent_buf_len = raw;
+ }
+ break;
case '?':
default:
if (optopt == '?')
@@ -643,7 +657,7 @@ zed_conf_read_state(struct zed_conf *zcp, uint64_t *eidp, int64_t etime[])
} else if (n != len) {
errno = EIO;
zed_log_msg(LOG_WARNING,
- "Failed to read state file \"%s\": Read %d of %d bytes",
+ "Failed to read state file \"%s\": Read %zd of %zd bytes",
zcp->state_file, n, len);
return (-1);
}
@@ -692,7 +706,7 @@ zed_conf_write_state(struct zed_conf *zcp, uint64_t eid, int64_t etime[])
if (n != len) {
errno = EIO;
zed_log_msg(LOG_WARNING,
- "Failed to write state file \"%s\": Wrote %d of %d bytes",
+ "Failed to write state file \"%s\": Wrote %zd of %zd bytes",
zcp->state_file, n, len);
return (-1);
}
diff --git a/cmd/zed/zed_conf.h b/cmd/zed/zed_conf.h
index 0b30a1503c52..84825a05da6b 100644
--- a/cmd/zed/zed_conf.h
+++ b/cmd/zed/zed_conf.h
@@ -33,6 +33,7 @@ struct zed_conf {
int zevent_fd; /* fd for access to zevents */
int16_t max_jobs; /* max zedlets to run at one time */
+ int32_t max_zevent_buf_len; /* max size of kernel event list */
boolean_t do_force:1; /* true if force enabled */
boolean_t do_foreground:1; /* true if run in foreground */
diff --git a/cmd/zed/zed_disk_event.c b/cmd/zed/zed_disk_event.c
index c4ca5452354b..32a8789d3001 100644
--- a/cmd/zed/zed_disk_event.c
+++ b/cmd/zed/zed_disk_event.c
@@ -49,7 +49,7 @@ struct udev_monitor *g_mon;
#define DEV_BYID_PATH "/dev/disk/by-id/"
/* 64MB is minimum usable disk for ZFS */
-#define MINIMUM_SECTORS 131072
+#define MINIMUM_SECTORS 131072ULL
/*
@@ -60,7 +60,7 @@ struct udev_monitor *g_mon;
static void
zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
{
- char *strval;
+ const char *strval;
uint64_t numval;
zed_log_msg(LOG_INFO, "zed_disk_event:");
@@ -78,6 +78,8 @@ zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PHYS_PATH, strval);
if (nvlist_lookup_uint64(nvl, DEV_SIZE, &numval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_SIZE, numval);
+ if (nvlist_lookup_uint64(nvl, DEV_PARENT_SIZE, &numval) == 0)
+ zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_PARENT_SIZE, numval);
if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &numval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %llu", ZFS_EV_POOL_GUID, numval);
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &numval) == 0)
@@ -130,6 +132,20 @@ dev_event_nvlist(struct udev_device *dev)
numval *= strtoull(value, NULL, 10);
(void) nvlist_add_uint64(nvl, DEV_SIZE, numval);
+
+ /*
+ * If the device has a parent, then get the parent block
+ * device's size as well. For example, /dev/sda1's parent
+ * is /dev/sda.
+ */
+ struct udev_device *parent_dev = udev_device_get_parent(dev);
+ if ((value = udev_device_get_sysattr_value(parent_dev, "size"))
+ != NULL) {
+ uint64_t numval = DEV_BSIZE;
+
+ numval *= strtoull(value, NULL, 10);
+ (void) nvlist_add_uint64(nvl, DEV_PARENT_SIZE, numval);
+ }
}
/*
@@ -162,14 +178,15 @@ static void *
zed_udev_monitor(void *arg)
{
struct udev_monitor *mon = arg;
- char *tmp, *tmp2;
+ const char *tmp;
+ char *tmp2;
zed_log_msg(LOG_INFO, "Waiting for new udev disk events...");
while (1) {
struct udev_device *dev;
const char *action, *type, *part, *sectors;
- const char *bus, *uuid;
+ const char *bus, *uuid, *devpath;
const char *class, *subclass;
nvlist_t *nvl;
boolean_t is_zfs = B_FALSE;
@@ -208,6 +225,12 @@ zed_udev_monitor(void *arg)
* if this is a disk and it is partitioned, then the
* zfs label will reside in a DEVTYPE=partition and
* we can skip passing this event
+ *
+ * Special case: Blank disks are sometimes reported with
+ * an erroneous 'atari' partition, and should not be
+ * excluded from being used as an autoreplace disk:
+ *
+ * https://github.com/openzfs/zfs/issues/13497
*/
type = udev_device_get_property_value(dev, "DEVTYPE");
part = udev_device_get_property_value(dev,
@@ -215,14 +238,23 @@ zed_udev_monitor(void *arg)
if (type != NULL && type[0] != '\0' &&
strcmp(type, "disk") == 0 &&
part != NULL && part[0] != '\0') {
- zed_log_msg(LOG_INFO,
- "%s: skip %s since it has a %s partition already",
- __func__,
- udev_device_get_property_value(dev, "DEVNAME"),
- part);
- /* skip and wait for partition event */
- udev_device_unref(dev);
- continue;
+ const char *devname =
+ udev_device_get_property_value(dev, "DEVNAME");
+
+ if (strcmp(part, "atari") == 0) {
+ zed_log_msg(LOG_INFO,
+ "%s: %s is reporting an atari partition, "
+ "but we're going to assume it's a false "
+ "positive and still use it (issue #13497)",
+ __func__, devname);
+ } else {
+ zed_log_msg(LOG_INFO,
+ "%s: skip %s since it has a %s partition "
+ "already", __func__, devname, part);
+ /* skip and wait for partition event */
+ udev_device_unref(dev);
+ continue;
+ }
}
/*
@@ -248,10 +280,19 @@ zed_udev_monitor(void *arg)
* device id string is required in the message schema
* for matching with vdevs. Preflight here for expected
* udev information.
+ *
+ * Special case:
+ * NVMe devices don't have ID_BUS set (at least on RHEL 7-8),
+ * but they are valid for autoreplace. Add a special case for
+ * them by searching for "/nvme/" in the udev DEVPATH:
+ *
+ * DEVPATH=/devices/pci0000:00/0000:00:1e.0/nvme/nvme2/nvme2n1
*/
bus = udev_device_get_property_value(dev, "ID_BUS");
uuid = udev_device_get_property_value(dev, "DM_UUID");
- if (!is_zfs && (bus == NULL && uuid == NULL)) {
+ devpath = udev_device_get_devpath(dev);
+ if (!is_zfs && (bus == NULL && uuid == NULL &&
+ strstr(devpath, "/nvme/") == NULL)) {
zed_log_msg(LOG_INFO, "zed_udev_monitor: %s no devid "
"source", udev_device_get_devnode(dev));
udev_device_unref(dev);
@@ -296,7 +337,7 @@ zed_udev_monitor(void *arg)
if (strcmp(class, EC_DEV_STATUS) == 0 &&
udev_device_get_property_value(dev, "DM_UUID") &&
udev_device_get_property_value(dev, "MPATH_SBIN_PATH")) {
- tmp = (char *)udev_device_get_devnode(dev);
+ tmp = udev_device_get_devnode(dev);
tmp2 = zfs_get_underlying_path(tmp);
if (tmp && tmp2 && (strcmp(tmp, tmp2) != 0)) {
/*
@@ -313,8 +354,7 @@ zed_udev_monitor(void *arg)
class = EC_DEV_ADD;
subclass = ESC_DISK;
} else {
- tmp = (char *)
- udev_device_get_property_value(dev,
+ tmp = udev_device_get_property_value(dev,
"DM_NR_VALID_PATHS");
/* treat as a multipath remove */
if (tmp != NULL && strcmp(tmp, "0") == 0) {
diff --git a/cmd/zed/zed_event.c b/cmd/zed/zed_event.c
index d5cafdaff061..7e5867692234 100644
--- a/cmd/zed/zed_event.c
+++ b/cmd/zed/zed_event.c
@@ -35,9 +35,12 @@
#include "zed_strings.h"
#include "agents/zfs_agents.h"
+#include <libzutil.h>
#define MAXBUF 4096
+static int max_zevent_buf_len = 1 << 20;
+
/*
* Open the libzfs interface.
*/
@@ -70,6 +73,9 @@ zed_event_init(struct zed_conf *zcp)
zed_log_die("Failed to initialize disk events");
}
+ if (zcp->max_zevent_buf_len != 0)
+ max_zevent_buf_len = zcp->max_zevent_buf_len;
+
return (0);
}
@@ -105,7 +111,7 @@ _bump_event_queue_length(void)
{
int zzlm = -1, wr;
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
- long int qlen;
+ long int qlen, orig_qlen;
zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
if (zzlm < 0)
@@ -116,7 +122,7 @@ _bump_event_queue_length(void)
qlen_buf[sizeof (qlen_buf) - 1] = '\0';
errno = 0;
- qlen = strtol(qlen_buf, NULL, 10);
+ orig_qlen = qlen = strtol(qlen_buf, NULL, 10);
if (errno == ERANGE)
goto done;
@@ -125,11 +131,21 @@ _bump_event_queue_length(void)
else
qlen *= 2;
- if (qlen > INT_MAX)
- qlen = INT_MAX;
+ /*
+ * Don't consume all of kernel memory with event logs if something
+ * goes wrong.
+ */
+ if (qlen > max_zevent_buf_len)
+ qlen = max_zevent_buf_len;
+ if (qlen == orig_qlen)
+ goto done;
wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
+ if (wr >= sizeof (qlen_buf)) {
+ wr = sizeof (qlen_buf) - 1;
+ zed_log_msg(LOG_WARNING, "Truncation in %s()", __func__);
+ }
- if (pwrite(zzlm, qlen_buf, wr, 0) < 0)
+ if (pwrite(zzlm, qlen_buf, wr + 1, 0) < 0)
goto done;
zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
@@ -597,7 +613,7 @@ _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
char buf[MAXBUF];
int buflen = sizeof (buf);
const char *name;
- char **strp;
+ const char **strp;
uint_t nelem;
uint_t i;
char *p;
@@ -637,7 +653,7 @@ _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
uint16_t i16;
uint32_t i32;
uint64_t i64;
- char *str;
+ const char *str;
assert(zsp != NULL);
assert(nvp != NULL);
@@ -907,6 +923,25 @@ _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
}
}
+
+static void
+_zed_event_update_enc_sysfs_path(nvlist_t *nvl)
+{
+ const char *vdev_path;
+
+ if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH,
+ &vdev_path) != 0) {
+ return; /* some other kind of event, ignore it */
+ }
+
+ if (vdev_path == NULL) {
+ return;
+ }
+
+ update_vdev_config_dev_sysfs_path(nvl, vdev_path,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH);
+}
+
/*
* Service the next zevent, blocking until one is available.
*/
@@ -920,7 +955,7 @@ zed_event_service(struct zed_conf *zcp)
uint64_t eid;
int64_t *etime;
uint_t nelem;
- char *class;
+ const char *class;
const char *subclass;
int rv;
@@ -954,6 +989,17 @@ zed_event_service(struct zed_conf *zcp)
zed_log_msg(LOG_WARNING,
"Failed to lookup zevent class (eid=%llu)", eid);
} else {
+ /*
+ * Special case: If we can dynamically detect an enclosure sysfs
+ * path, then use that value rather than the one stored in the
+ * vd->vdev_enc_sysfs_path. There have been rare cases where
+ * vd->vdev_enc_sysfs_path becomes outdated. However, there
+ * will be other times when we can not dynamically detect the
+ * sysfs path (like if a disk disappears) and have to rely on
+ * the old value for things like turning on the fault LED.
+ */
+ _zed_event_update_enc_sysfs_path(nvl);
+
/* let internal modules see this event first */
zfs_agent_post_event(class, NULL, nvl);
diff --git a/cmd/zed/zed_exec.c b/cmd/zed/zed_exec.c
index 369c4b6950c5..e45acfb2c69f 100644
--- a/cmd/zed/zed_exec.c
+++ b/cmd/zed/zed_exec.c
@@ -175,6 +175,10 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
node->pid = pid;
node->eid = eid;
node->name = strdup(prog);
+ if (node->name == NULL) {
+ perror("strdup");
+ exit(EXIT_FAILURE);
+ }
avl_add(&_launched_processes, node);
}
@@ -263,7 +267,7 @@ _reap_children(void *arg)
zed_log_msg(LOG_INFO,
"Finished \"%s\" eid=%llu pid=%d "
"time=%llu.%06us status=0x%X",
- node.name, node.eid,
+ node.name, node.eid, pid,
(unsigned long long) usage.ru_utime.tv_sec,
(unsigned int) usage.ru_utime.tv_usec,
(unsigned int) status);
diff --git a/cmd/zed/zed_log.h b/cmd/zed/zed_log.h
index ed88ad41d7e2..18ab0553ea40 100644
--- a/cmd/zed/zed_log.h
+++ b/cmd/zed/zed_log.h
@@ -39,6 +39,7 @@ void zed_log_syslog_close(void);
void zed_log_msg(int priority, const char *fmt, ...);
+__attribute__((format(printf, 1, 2), __noreturn__))
void zed_log_die(const char *fmt, ...);
#endif /* !ZED_LOG_H */
diff --git a/cmd/zfs/zfs_iter.c b/cmd/zfs/zfs_iter.c
index c0426d4f81ea..202cb0e82b5a 100644
--- a/cmd/zfs/zfs_iter.c
+++ b/cmd/zfs/zfs_iter.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -143,19 +143,20 @@ zfs_callback(zfs_handle_t *zhp, void *data)
(cb->cb_types &
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
- (void) zfs_iter_filesystems(zhp, zfs_callback, data);
+ (void) zfs_iter_filesystems_v2(zhp, cb->cb_flags,
+ zfs_callback, data);
}
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
- (void) zfs_iter_snapshots(zhp,
- (cb->cb_flags & ZFS_ITER_SIMPLE) != 0,
+ (void) zfs_iter_snapshots_v2(zhp, cb->cb_flags,
zfs_callback, data, 0, 0);
}
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
- (void) zfs_iter_bookmarks(zhp, zfs_callback, data);
+ (void) zfs_iter_bookmarks_v2(zhp, cb->cb_flags,
+ zfs_callback, data);
}
cb->cb_depth--;
@@ -211,11 +212,58 @@ zfs_free_sort_columns(zfs_sort_column_t *sc)
}
}
-int
-zfs_sort_only_by_name(const zfs_sort_column_t *sc)
+/*
+ * Return true if all of the properties to be sorted are populated by
+ * dsl_dataset_fast_stat(). Note that sc == NULL (no sort) means we
+ * don't need any extra properties, so returns true.
+ */
+boolean_t
+zfs_sort_only_by_fast(const zfs_sort_column_t *sc)
{
- return (sc != NULL && sc->sc_next == NULL &&
- sc->sc_prop == ZFS_PROP_NAME);
+ while (sc != NULL) {
+ switch (sc->sc_prop) {
+ case ZFS_PROP_NAME:
+ case ZFS_PROP_GUID:
+ case ZFS_PROP_CREATETXG:
+ case ZFS_PROP_NUMCLONES:
+ case ZFS_PROP_INCONSISTENT:
+ case ZFS_PROP_REDACTED:
+ case ZFS_PROP_ORIGIN:
+ break;
+ default:
+ return (B_FALSE);
+ }
+ sc = sc->sc_next;
+ }
+
+ return (B_TRUE);
+}
+
+boolean_t
+zfs_list_only_by_fast(const zprop_list_t *p)
+{
+ if (p == NULL) {
+ /* NULL means 'all' so we can't use simple mode */
+ return (B_FALSE);
+ }
+
+ while (p != NULL) {
+ switch (p->pl_prop) {
+ case ZFS_PROP_NAME:
+ case ZFS_PROP_GUID:
+ case ZFS_PROP_CREATETXG:
+ case ZFS_PROP_NUMCLONES:
+ case ZFS_PROP_INCONSISTENT:
+ case ZFS_PROP_REDACTED:
+ case ZFS_PROP_ORIGIN:
+ break;
+ default:
+ return (B_FALSE);
+ }
+ p = p->pl_next;
+ }
+
+ return (B_TRUE);
}
static int
@@ -300,8 +348,8 @@ zfs_sort(const void *larg, const void *rarg, void *data)
for (psc = sc; psc != NULL; psc = psc->sc_next) {
char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
- char *lstr, *rstr;
- uint64_t lnum, rnum;
+ const char *lstr, *rstr;
+ uint64_t lnum = 0, rnum = 0;
boolean_t lvalid, rvalid;
int ret = 0;
@@ -352,11 +400,9 @@ zfs_sort(const void *larg, const void *rarg, void *data)
zfs_get_type(r), B_FALSE);
if (lvalid)
- (void) zfs_prop_get_numeric(l, psc->sc_prop,
- &lnum, NULL, NULL, 0);
+ lnum = zfs_prop_get_int(l, psc->sc_prop);
if (rvalid)
- (void) zfs_prop_get_numeric(r, psc->sc_prop,
- &rnum, NULL, NULL, 0);
+ rnum = zfs_prop_get_int(r, psc->sc_prop);
}
if (!lvalid && !rvalid)
diff --git a/cmd/zfs/zfs_iter.h b/cmd/zfs/zfs_iter.h
index 2697fbdca1df..d742ec7b2ec4 100644
--- a/cmd/zfs/zfs_iter.h
+++ b/cmd/zfs/zfs_iter.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -40,19 +40,12 @@ typedef struct zfs_sort_column {
boolean_t sc_reverse;
} zfs_sort_column_t;
-#define ZFS_ITER_RECURSE (1 << 0)
-#define ZFS_ITER_ARGS_CAN_BE_PATHS (1 << 1)
-#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
-#define ZFS_ITER_DEPTH_LIMIT (1 << 3)
-#define ZFS_ITER_RECVD_PROPS (1 << 4)
-#define ZFS_ITER_LITERAL_PROPS (1 << 5)
-#define ZFS_ITER_SIMPLE (1 << 6)
-
int zfs_for_each(int, char **, int options, zfs_type_t,
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
void zfs_free_sort_columns(zfs_sort_column_t *);
-int zfs_sort_only_by_name(const zfs_sort_column_t *);
+boolean_t zfs_sort_only_by_fast(const zfs_sort_column_t *);
+boolean_t zfs_list_only_by_fast(const zprop_list_t *);
#ifdef __cplusplus
}
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index e71959c3ca59..0bbdd5b18eda 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -132,6 +132,8 @@ static int zfs_do_zone(int argc, char **argv);
static int zfs_do_unzone(int argc, char **argv);
#endif
+static int zfs_do_help(int argc, char **argv);
+
/*
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
*/
@@ -307,7 +309,8 @@ get_usage(zfs_help_t idx)
"[filesystem|volume|snapshot] ...\n"));
case HELP_MOUNT:
return (gettext("\tmount\n"
- "\tmount [-flvO] [-o opts] <-a | filesystem>\n"));
+ "\tmount [-flvO] [-o opts] <-a|-R filesystem|"
+ "filesystem>\n"));
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
@@ -327,17 +330,17 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
- return (gettext("\tsend [-DLPbcehnpsvw] "
+ return (gettext("\tsend [-DLPbcehnpsVvw] "
"[-i|-I snapshot]\n"
"\t [-R [-X dataset[,dataset]...]] <snapshot>\n"
- "\tsend [-DnvPLecw] [-i snapshot|bookmark] "
+ "\tsend [-DnVvPLecw] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"
- "\tsend [-DnPpvLec] [-i bookmark|snapshot] "
+ "\tsend [-DnPpVvLec] [-i bookmark|snapshot] "
"--redact <bookmark> <snapshot>\n"
- "\tsend [-nvPe] -t <receive_resume_token>\n"
- "\tsend [-Pnv] --saved filesystem\n"));
+ "\tsend [-nVvPe] -t <receive_resume_token>\n"
+ "\tsend [-PnVv] --saved filesystem\n"));
case HELP_SET:
- return (gettext("\tset <property=value> ... "
+ return (gettext("\tset [-u] <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
return (gettext("\tshare [-l] <-a [nfs|smb] | filesystem>\n"));
@@ -392,11 +395,11 @@ get_usage(zfs_help_t idx)
case HELP_HOLD:
return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
case HELP_HOLDS:
- return (gettext("\tholds [-rH] <snapshot> ...\n"));
+ return (gettext("\tholds [-rHp] <snapshot> ...\n"));
case HELP_RELEASE:
return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
case HELP_DIFF:
- return (gettext("\tdiff [-FHt] <snapshot> "
+ return (gettext("\tdiff [-FHth] <snapshot> "
"[snapshot|filesystem]\n"));
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot|bookmark> "
@@ -548,7 +551,7 @@ usage(boolean_t requested)
show_properties = B_TRUE;
if (show_properties) {
- (void) fprintf(fp,
+ (void) fprintf(fp, "%s",
gettext("\nThe following properties are supported:\n"));
(void) fprintf(fp, "\n\t%-14s %s %s %s\n\n",
@@ -606,6 +609,9 @@ usage(boolean_t requested)
(void) fprintf(fp,
gettext("\nFor the delegated permission list, run: %s\n"),
"zfs allow|unallow");
+ (void) fprintf(fp,
+ gettext("\nFor further help on a command or topic, "
+ "run: %s\n"), "zfs help [<topic>]");
}
/*
@@ -1049,7 +1055,7 @@ zfs_do_create(int argc, char **argv)
int ret = 1;
nvlist_t *props;
uint64_t intval;
- char *strval;
+ const char *strval;
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
@@ -1173,11 +1179,12 @@ zfs_do_create(int argc, char **argv)
if (volblocksize != ZVOL_DEFAULT_BLOCKSIZE &&
nvlist_lookup_string(props, prop, &strval) != 0) {
- if (asprintf(&strval, "%llu",
+ char *tmp;
+ if (asprintf(&tmp, "%llu",
(u_longlong_t)volblocksize) == -1)
nomem();
- nvlist_add_string(props, prop, strval);
- free(strval);
+ nvlist_add_string(props, prop, tmp);
+ free(tmp);
}
/*
@@ -1252,7 +1259,7 @@ zfs_do_create(int argc, char **argv)
dryrun ? "would create %s\n" : "create %s\n", argv[0]);
while ((nvp = nvlist_next_nvpair(props, nvp)) != NULL) {
uint64_t uval;
- char *sval;
+ const char *sval;
switch (nvpair_type(nvp)) {
case DATA_TYPE_UINT64:
@@ -1453,8 +1460,13 @@ destroy_callback(zfs_handle_t *zhp, void *data)
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
cb->cb_snap_count++;
fnvlist_add_boolean(cb->cb_batchedsnaps, name);
- if (cb->cb_snap_count % 10 == 0 && cb->cb_defer_destroy)
+ if (cb->cb_snap_count % 10 == 0 && cb->cb_defer_destroy) {
error = destroy_batched(cb);
+ if (error != 0) {
+ zfs_close(zhp);
+ return (-1);
+ }
+ }
} else {
error = destroy_batched(cb);
if (error != 0 ||
@@ -1526,7 +1538,8 @@ destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
int err;
assert(cb->cb_firstsnap == NULL);
assert(cb->cb_prevsnap == NULL);
- err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb, 0, 0);
+ err = zfs_iter_snapshots_sorted_v2(fs_zhp, 0, destroy_print_cb, cb, 0,
+ 0);
if (cb->cb_firstsnap != NULL) {
uint64_t used = 0;
if (err == 0) {
@@ -1552,7 +1565,7 @@ snapshot_to_nvl_cb(zfs_handle_t *zhp, void *arg)
if (!cb->cb_doclones && !cb->cb_defer_destroy) {
cb->cb_target = zhp;
cb->cb_first = B_TRUE;
- err = zfs_iter_dependents(zhp, B_TRUE,
+ err = zfs_iter_dependents_v2(zhp, 0, B_TRUE,
destroy_check_dependent, cb);
}
@@ -1570,7 +1583,8 @@ gather_snapshots(zfs_handle_t *zhp, void *arg)
destroy_cbdata_t *cb = arg;
int err = 0;
- err = zfs_iter_snapspec(zhp, cb->cb_snapspec, snapshot_to_nvl_cb, cb);
+ err = zfs_iter_snapspec_v2(zhp, 0, cb->cb_snapspec,
+ snapshot_to_nvl_cb, cb);
if (err == ENOENT)
err = 0;
if (err != 0)
@@ -1583,7 +1597,7 @@ gather_snapshots(zfs_handle_t *zhp, void *arg)
}
if (cb->cb_recurse)
- err = zfs_iter_filesystems(zhp, gather_snapshots, cb);
+ err = zfs_iter_filesystems_v2(zhp, 0, gather_snapshots, cb);
out:
zfs_close(zhp);
@@ -1608,7 +1622,7 @@ destroy_clones(destroy_cbdata_t *cb)
* false while destroying the clones.
*/
cb->cb_defer_destroy = B_FALSE;
- err = zfs_iter_dependents(zhp, B_FALSE,
+ err = zfs_iter_dependents_v2(zhp, 0, B_FALSE,
destroy_callback, cb);
cb->cb_defer_destroy = defer;
zfs_close(zhp);
@@ -1818,9 +1832,8 @@ zfs_do_destroy(int argc, char **argv)
* Check for any dependents and/or clones.
*/
cb.cb_first = B_TRUE;
- if (!cb.cb_doclones &&
- zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
- &cb) != 0) {
+ if (!cb.cb_doclones && zfs_iter_dependents_v2(zhp, 0, B_TRUE,
+ destroy_check_dependent, &cb) != 0) {
rv = 1;
goto out;
}
@@ -1830,7 +1843,7 @@ zfs_do_destroy(int argc, char **argv)
goto out;
}
cb.cb_batchedsnaps = fnvlist_alloc();
- if (zfs_iter_dependents(zhp, B_FALSE, destroy_callback,
+ if (zfs_iter_dependents_v2(zhp, 0, B_FALSE, destroy_callback,
&cb) != 0) {
rv = 1;
goto out;
@@ -2133,15 +2146,25 @@ found2:;
for (char *tok; (tok = strsep(&optarg, ",")); ) {
static const char *const type_opts[] = {
- "filesystem", "volume",
- "snapshot", "snap",
+ "filesystem",
+ "fs",
+ "volume",
+ "vol",
+ "snapshot",
+ "snap",
"bookmark",
- "all" };
+ "all"
+ };
static const int type_types[] = {
- ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
- ZFS_TYPE_SNAPSHOT, ZFS_TYPE_SNAPSHOT,
+ ZFS_TYPE_FILESYSTEM,
+ ZFS_TYPE_FILESYSTEM,
+ ZFS_TYPE_VOLUME,
+ ZFS_TYPE_VOLUME,
+ ZFS_TYPE_SNAPSHOT,
+ ZFS_TYPE_SNAPSHOT,
ZFS_TYPE_BOOKMARK,
- ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK };
+ ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK
+ };
for (i = 0; i < ARRAY_SIZE(type_opts); ++i)
if (strcmp(tok, type_opts[i]) == 0) {
@@ -2459,7 +2482,8 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data)
cb->cb_numupgraded++;
else
cb->cb_numfailed++;
- (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
+ (void) strlcpy(cb->cb_lastfs, zfs_get_name(zhp),
+ sizeof (cb->cb_lastfs));
} else if (version > cb->cb_version) {
/* can't downgrade */
(void) printf(gettext("%s: can not be downgraded; "
@@ -2575,7 +2599,7 @@ zfs_do_upgrade(int argc, char **argv)
cb.cb_foundone = B_FALSE;
cb.cb_newer = B_TRUE;
- ret = zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM,
+ ret |= zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM,
NULL, NULL, 0, upgrade_list_callback, &cb);
if (!cb.cb_foundone && !found) {
@@ -2694,8 +2718,8 @@ us_compare(const void *larg, const void *rarg, void *unused)
boolean_t lvb, rvb;
for (; sortcol != NULL; sortcol = sortcol->sc_next) {
- char *lvstr = (char *)"";
- char *rvstr = (char *)"";
+ const char *lvstr = "";
+ const char *rvstr = "";
uint32_t lv32 = 0;
uint32_t rv32 = 0;
uint64_t lv64 = 0;
@@ -3433,6 +3457,8 @@ print_header(list_cbdata_t *cb)
boolean_t first = B_TRUE;
boolean_t right_justify;
+ color_start(ANSI_BOLD);
+
for (; pl != NULL; pl = pl->pl_next) {
if (!first) {
(void) printf(" ");
@@ -3459,10 +3485,32 @@ print_header(list_cbdata_t *cb)
(void) printf("%-*s", (int)pl->pl_width, header);
}
+ color_end();
+
(void) printf("\n");
}
/*
+ * Decides on the color that the avail value should be printed in.
+ * > 80% used = yellow
+ * > 90% used = red
+ */
+static const char *
+zfs_list_avail_color(zfs_handle_t *zhp)
+{
+ uint64_t used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
+ uint64_t avail = zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE);
+ int percentage = (int)((double)avail / MAX(avail + used, 1) * 100);
+
+ if (percentage > 20)
+ return (NULL);
+ else if (percentage > 10)
+ return (ANSI_YELLOW);
+ else
+ return (ANSI_RED);
+}
+
+/*
* Given a dataset and a list of fields, print out all the properties according
* to the described layout.
*/
@@ -3525,6 +3573,22 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
}
/*
+ * zfs_list_avail_color() needs ZFS_PROP_AVAILABLE + USED
+ * - so we need another for() search for the USED part
+ * - when no colors wanted, we can skip the whole thing
+ */
+ if (use_color() && pl->pl_prop == ZFS_PROP_AVAILABLE) {
+ zprop_list_t *pl2 = cb->cb_proplist;
+ for (; pl2 != NULL; pl2 = pl2->pl_next) {
+ if (pl2->pl_prop == ZFS_PROP_USED) {
+ color_start(zfs_list_avail_color(zhp));
+ /* found it, no need for more loops */
+ break;
+ }
+ }
+ }
+
+ /*
* If this is being called in scripted mode, or if this is the
* last column and it is left-justified, don't include a width
* format specifier.
@@ -3535,6 +3599,9 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
(void) printf("%*s", (int)pl->pl_width, propstr);
else
(void) printf("%-*s", (int)pl->pl_width, propstr);
+
+ if (pl->pl_prop == ZFS_PROP_AVAILABLE)
+ color_end();
}
(void) putchar('\n');
@@ -3616,15 +3683,25 @@ zfs_do_list(int argc, char **argv)
for (char *tok; (tok = strsep(&optarg, ",")); ) {
static const char *const type_subopts[] = {
- "filesystem", "volume",
- "snapshot", "snap",
+ "filesystem",
+ "fs",
+ "volume",
+ "vol",
+ "snapshot",
+ "snap",
"bookmark",
- "all" };
+ "all"
+ };
static const int type_types[] = {
- ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
- ZFS_TYPE_SNAPSHOT, ZFS_TYPE_SNAPSHOT,
+ ZFS_TYPE_FILESYSTEM,
+ ZFS_TYPE_FILESYSTEM,
+ ZFS_TYPE_VOLUME,
+ ZFS_TYPE_VOLUME,
+ ZFS_TYPE_SNAPSHOT,
+ ZFS_TYPE_SNAPSHOT,
ZFS_TYPE_BOOKMARK,
- ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK };
+ ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK
+ };
for (c = 0; c < ARRAY_SIZE(type_subopts); ++c)
if (strcmp(tok, type_subopts[c]) == 0) {
@@ -3654,13 +3731,6 @@ found3:;
argv += optind;
/*
- * If we are only going to list snapshot names and sort by name,
- * then we can use faster version.
- */
- if (strcmp(fields, "name") == 0 && zfs_sort_only_by_name(sortcol))
- flags |= ZFS_ITER_SIMPLE;
-
- /*
* If "-o space" and no types were specified, don't display snapshots.
*/
if (strcmp(fields, "space") == 0 && types_specified == B_FALSE)
@@ -3687,6 +3757,15 @@ found3:;
cb.cb_first = B_TRUE;
+ /*
+ * If we are only going to list and sort by properties that are "fast"
+ * then we can use "simple" mode and avoid populating the properties
+ * nvlist.
+ */
+ if (zfs_list_only_by_fast(cb.cb_proplist) &&
+ zfs_sort_only_by_fast(sortcol))
+ flags |= ZFS_ITER_SIMPLE;
+
ret = zfs_for_each(argc, argv, flags, types, sortcol, &cb.cb_proplist,
limit, list_callback, &cb);
@@ -3873,10 +3952,25 @@ zfs_do_redact(int argc, char **argv)
switch (err) {
case 0:
break;
- case ENOENT:
- (void) fprintf(stderr,
- gettext("provided snapshot %s does not exist\n"), snap);
+ case ENOENT: {
+ zfs_handle_t *zhp = zfs_open(g_zfs, snap, ZFS_TYPE_SNAPSHOT);
+ if (zhp == NULL) {
+ (void) fprintf(stderr, gettext("provided snapshot %s "
+ "does not exist\n"), snap);
+ } else {
+ zfs_close(zhp);
+ }
+ for (int i = 0; i < numrsnaps; i++) {
+ zhp = zfs_open(g_zfs, rsnaps[i], ZFS_TYPE_SNAPSHOT);
+ if (zhp == NULL) {
+ (void) fprintf(stderr, gettext("provided "
+ "snapshot %s does not exist\n"), rsnaps[i]);
+ } else {
+ zfs_close(zhp);
+ }
+ }
break;
+ }
case EEXIST:
(void) fprintf(stderr, gettext("specified redaction bookmark "
"(%s) provided already exists\n"), bookname);
@@ -3910,6 +4004,10 @@ zfs_do_redact(int argc, char **argv)
(void) fprintf(stderr, gettext("potentially invalid redaction "
"snapshot; full dataset names required\n"));
break;
+ case ESRCH:
+ (void) fprintf(stderr, gettext("attempted to resume redaction "
+ " with a mismatched redaction list\n"));
+ break;
default:
(void) fprintf(stderr, gettext("internal error: %s\n"),
strerror(errno));
@@ -3997,7 +4095,7 @@ rollback_check(zfs_handle_t *zhp, void *data)
}
if (cbp->cb_recurse) {
- if (zfs_iter_dependents(zhp, B_TRUE,
+ if (zfs_iter_dependents_v2(zhp, 0, B_TRUE,
rollback_check_dependent, cbp) != 0) {
zfs_close(zhp);
return (-1);
@@ -4096,10 +4194,10 @@ zfs_do_rollback(int argc, char **argv)
if (cb.cb_create > 0)
min_txg = cb.cb_create;
- if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb,
+ if ((ret = zfs_iter_snapshots_v2(zhp, 0, rollback_check, &cb,
min_txg, 0)) != 0)
goto out;
- if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
+ if ((ret = zfs_iter_bookmarks_v2(zhp, 0, rollback_check, &cb)) != 0)
goto out;
if ((ret = cb.cb_error) != 0)
@@ -4129,9 +4227,10 @@ out:
static int
set_callback(zfs_handle_t *zhp, void *data)
{
- nvlist_t *props = data;
+ zprop_set_cbdata_t *cb = data;
+ int ret = zfs_prop_set_list_flags(zhp, cb->cb_proplist, cb->cb_flags);
- if (zfs_prop_set_list(zhp, props) != 0) {
+ if (ret != 0 || libzfs_errno(g_zfs) != EZFS_SUCCESS) {
switch (libzfs_errno(g_zfs)) {
case EZFS_MOUNTFAILED:
(void) fprintf(stderr, gettext("property may be set "
@@ -4142,33 +4241,42 @@ set_callback(zfs_handle_t *zhp, void *data)
"but unable to reshare filesystem\n"));
break;
}
- return (1);
}
- return (0);
+ return (ret);
}
static int
zfs_do_set(int argc, char **argv)
{
- nvlist_t *props = NULL;
+ zprop_set_cbdata_t cb = { 0 };
int ds_start = -1; /* argv idx of first dataset arg */
int ret = 0;
- int i;
+ int i, c;
- /* check for options */
- if (argc > 1 && argv[1][0] == '-') {
- (void) fprintf(stderr, gettext("invalid option '%c'\n"),
- argv[1][1]);
- usage(B_FALSE);
+ /* check options */
+ while ((c = getopt(argc, argv, "u")) != -1) {
+ switch (c) {
+ case 'u':
+ cb.cb_flags |= ZFS_SET_NOMOUNT;
+ break;
+ case '?':
+ default:
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
}
+ argc -= optind;
+ argv += optind;
+
/* check number of arguments */
- if (argc < 2) {
+ if (argc < 1) {
(void) fprintf(stderr, gettext("missing arguments\n"));
usage(B_FALSE);
}
- if (argc < 3) {
- if (strchr(argv[1], '=') == NULL) {
+ if (argc < 2) {
+ if (strchr(argv[0], '=') == NULL) {
(void) fprintf(stderr, gettext("missing property=value "
"argument(s)\n"));
} else {
@@ -4179,7 +4287,7 @@ zfs_do_set(int argc, char **argv)
}
/* validate argument order: prop=val args followed by dataset args */
- for (i = 1; i < argc; i++) {
+ for (i = 0; i < argc; i++) {
if (strchr(argv[i], '=') != NULL) {
if (ds_start > 0) {
/* out-of-order prop=val argument */
@@ -4197,20 +4305,20 @@ zfs_do_set(int argc, char **argv)
}
/* Populate a list of property settings */
- if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
+ if (nvlist_alloc(&cb.cb_proplist, NV_UNIQUE_NAME, 0) != 0)
nomem();
- for (i = 1; i < ds_start; i++) {
- if (!parseprop(props, argv[i])) {
+ for (i = 0; i < ds_start; i++) {
+ if (!parseprop(cb.cb_proplist, argv[i])) {
ret = -1;
goto error;
}
}
ret = zfs_for_each(argc - ds_start, argv + ds_start, 0,
- ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, props);
+ ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
error:
- nvlist_free(props);
+ nvlist_free(cb.cb_proplist);
return (ret);
}
@@ -4241,7 +4349,7 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
free(name);
if (sd->sd_recursive)
- rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
+ rv = zfs_iter_filesystems_v2(zhp, 0, zfs_snapshot_cb, sd);
zfs_close(zhp);
return (rv);
}
@@ -4379,6 +4487,7 @@ zfs_do_send(int argc, char **argv)
{"props", no_argument, NULL, 'p'},
{"parsable", no_argument, NULL, 'P'},
{"dedup", no_argument, NULL, 'D'},
+ {"proctitle", no_argument, NULL, 'V'},
{"verbose", no_argument, NULL, 'v'},
{"dryrun", no_argument, NULL, 'n'},
{"large-block", no_argument, NULL, 'L'},
@@ -4394,7 +4503,7 @@ zfs_do_send(int argc, char **argv)
};
/* check options */
- while ((c = getopt_long(argc, argv, ":i:I:RsDpvnPLeht:cwbd:SX:",
+ while ((c = getopt_long(argc, argv, ":i:I:RsDpVvnPLeht:cwbd:SX:",
long_options, NULL)) != -1) {
switch (c) {
case 'X':
@@ -4443,6 +4552,9 @@ zfs_do_send(int argc, char **argv)
case 'P':
flags.parsable = B_TRUE;
break;
+ case 'V':
+ flags.progressastitle = B_TRUE;
+ break;
case 'v':
flags.verbosity++;
flags.progress = B_TRUE;
@@ -4495,6 +4607,7 @@ zfs_do_send(int argc, char **argv)
gettext("missing argument for '%s' "
"option\n"), argv[optind - 1]);
}
+ free(excludes.list);
usage(B_FALSE);
break;
case '?':
@@ -4513,14 +4626,16 @@ zfs_do_send(int argc, char **argv)
argv[optind - 1]);
}
+ free(excludes.list);
usage(B_FALSE);
}
}
- if (flags.parsable && flags.verbosity == 0)
+ if ((flags.parsable || flags.progressastitle) && flags.verbosity == 0)
flags.verbosity = 1;
if (excludes.count > 0 && !flags.replicate) {
+ free(excludes.list);
(void) fprintf(stderr, gettext("Cannot specify "
"dataset exclusion (-X) on a non-recursive "
"send.\n"));
@@ -4534,21 +4649,25 @@ zfs_do_send(int argc, char **argv)
if (fromname != NULL || flags.replicate || flags.props ||
flags.backup || flags.holds ||
flags.saved || redactbook != NULL) {
+ free(excludes.list);
(void) fprintf(stderr,
gettext("invalid flags combined with -t\n"));
usage(B_FALSE);
}
if (argc > 0) {
+ free(excludes.list);
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
} else {
if (argc < 1) {
+ free(excludes.list);
(void) fprintf(stderr,
gettext("missing snapshot argument\n"));
usage(B_FALSE);
}
if (argc > 1) {
+ free(excludes.list);
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
@@ -4559,11 +4678,15 @@ zfs_do_send(int argc, char **argv)
flags.doall || flags.backup ||
flags.holds || flags.largeblock || flags.embed_data ||
flags.compress || flags.raw || redactbook != NULL) {
+ free(excludes.list);
+
(void) fprintf(stderr, gettext("incompatible flags "
"combined with saved send flag\n"));
usage(B_FALSE);
}
if (strchr(argv[0], '@') != NULL) {
+ free(excludes.list);
+
(void) fprintf(stderr, gettext("saved send must "
"specify the dataset with partially-received "
"state\n"));
@@ -4572,12 +4695,14 @@ zfs_do_send(int argc, char **argv)
}
if (flags.raw && redactbook != NULL) {
+ free(excludes.list);
(void) fprintf(stderr,
gettext("Error: raw sends may not be redacted.\n"));
return (1);
}
if (!flags.dryrun && isatty(STDOUT_FILENO)) {
+ free(excludes.list);
(void) fprintf(stderr,
gettext("Error: Stream can not be written to a terminal.\n"
"You must redirect standard output.\n"));
@@ -4586,19 +4711,24 @@ zfs_do_send(int argc, char **argv)
if (flags.saved) {
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
- if (zhp == NULL)
+ if (zhp == NULL) {
+ free(excludes.list);
return (1);
+ }
err = zfs_send_saved(zhp, &flags, STDOUT_FILENO,
resume_token);
+ free(excludes.list);
zfs_close(zhp);
return (err != 0);
} else if (resume_token != NULL) {
+ free(excludes.list);
return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
resume_token));
}
if (flags.skipmissing && !flags.replicate) {
+ free(excludes.list);
(void) fprintf(stderr,
gettext("skip-missing flag can only be used in "
"conjunction with replicate\n"));
@@ -4641,10 +4771,14 @@ zfs_do_send(int argc, char **argv)
}
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
- if (zhp == NULL)
+ if (zhp == NULL) {
+ free(excludes.list);
return (1);
+ }
err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags,
redactbook);
+
+ free(excludes.list);
zfs_close(zhp);
return (err != 0);
}
@@ -4653,25 +4787,30 @@ zfs_do_send(int argc, char **argv)
(void) fprintf(stderr,
gettext("Error: multiple snapshots cannot be "
"sent from a bookmark.\n"));
+ free(excludes.list);
return (1);
}
if (redactbook != NULL) {
(void) fprintf(stderr, gettext("Error: multiple snapshots "
"cannot be sent redacted.\n"));
+ free(excludes.list);
return (1);
}
if ((cp = strchr(argv[0], '@')) == NULL) {
(void) fprintf(stderr, gettext("Error: "
"Unsupported flag with filesystem or bookmark.\n"));
+ free(excludes.list);
return (1);
}
*cp = '\0';
toname = cp + 1;
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
- if (zhp == NULL)
+ if (zhp == NULL) {
+ free(excludes.list);
return (1);
+ }
/*
* If they specified the full path to the snapshot, chop off
@@ -4691,6 +4830,8 @@ zfs_do_send(int argc, char **argv)
} else {
*cp = '\0';
if (cp != fromname && strcmp(argv[0], fromname)) {
+ zfs_close(zhp);
+ free(excludes.list);
(void) fprintf(stderr,
gettext("incremental source must be "
"in same filesystem\n"));
@@ -4698,6 +4839,8 @@ zfs_do_send(int argc, char **argv)
}
fromname = cp + 1;
if (strchr(fromname, '@') || strchr(fromname, '/')) {
+ zfs_close(zhp);
+ free(excludes.list);
(void) fprintf(stderr,
gettext("invalid incremental source\n"));
usage(B_FALSE);
@@ -4743,7 +4886,7 @@ zfs_do_receive(int argc, char **argv)
nomem();
/* check options */
- while ((c = getopt(argc, argv, ":o:x:dehMnuvFsA")) != -1) {
+ while ((c = getopt(argc, argv, ":o:x:dehMnuvFsAc")) != -1) {
switch (c) {
case 'o':
if (!parseprop(props, optarg)) {
@@ -4799,6 +4942,9 @@ zfs_do_receive(int argc, char **argv)
case 'A':
abort_resumable = B_TRUE;
break;
+ case 'c':
+ flags.heal = B_TRUE;
+ break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@@ -5951,8 +6097,8 @@ construct_fsacl_list(boolean_t un, struct allow_opts *opts, nvlist_t **nvlp)
if (p != NULL)
rid = p->pw_uid;
else if (*endch != '\0') {
- (void) snprintf(errbuf, 256, gettext(
- "invalid user %s\n"), curr);
+ (void) snprintf(errbuf, sizeof (errbuf),
+ gettext("invalid user %s\n"), curr);
allow_usage(un, B_TRUE, errbuf);
}
} else if (opts->group) {
@@ -5965,8 +6111,9 @@ construct_fsacl_list(boolean_t un, struct allow_opts *opts, nvlist_t **nvlp)
if (g != NULL)
rid = g->gr_gid;
else if (*endch != '\0') {
- (void) snprintf(errbuf, 256, gettext(
- "invalid group %s\n"), curr);
+ (void) snprintf(errbuf, sizeof (errbuf),
+ gettext("invalid group %s\n"),
+ curr);
allow_usage(un, B_TRUE, errbuf);
}
} else {
@@ -5991,8 +6138,9 @@ construct_fsacl_list(boolean_t un, struct allow_opts *opts, nvlist_t **nvlp)
who_type = ZFS_DELEG_GROUP;
rid = g->gr_gid;
} else {
- (void) snprintf(errbuf, 256, gettext(
- "invalid user/group %s\n"), curr);
+ (void) snprintf(errbuf, sizeof (errbuf),
+ gettext("invalid user/group %s\n"),
+ curr);
allow_usage(un, B_TRUE, errbuf);
}
}
@@ -6267,7 +6415,7 @@ zfs_do_allow_unallow_impl(int argc, char **argv, boolean_t un)
if (un && opts.recursive) {
struct deleg_perms data = { un, update_perm_nvl };
- if (zfs_iter_filesystems(zhp, set_deleg_perms,
+ if (zfs_iter_filesystems_v2(zhp, 0, set_deleg_perms,
&data) != 0)
goto cleanup0;
}
@@ -6351,8 +6499,8 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
++errors;
continue;
}
- (void) strncpy(parent, path, delim - path);
- parent[delim - path] = '\0';
+ (void) strlcpy(parent, path, MIN(sizeof (parent),
+ delim - path + 1));
zhp = zfs_open(g_zfs, parent,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
@@ -6413,7 +6561,8 @@ typedef struct holds_cbdata {
*
*/
static void
-print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl)
+print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl,
+ boolean_t parsable)
{
int i;
nvpair_t *nvp = NULL;
@@ -6432,7 +6581,7 @@ print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl)
}
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
- char *zname = nvpair_name(nvp);
+ const char *zname = nvpair_name(nvp);
nvlist_t *nvl2;
nvpair_t *nvp2 = NULL;
(void) nvpair_value_nvlist(nvp, &nvl2);
@@ -6450,11 +6599,23 @@ print_holds(boolean_t scripted, int nwidth, int tagwidth, nvlist_t *nvl)
gettext(STRFTIME_FMT_STR), &t);
if (scripted) {
- (void) printf("%s\t%s\t%s\n", zname,
- tagname, tsbuf);
+ if (parsable) {
+ (void) printf("%s\t%s\t%ld\n", zname,
+ tagname, time);
+ } else {
+ (void) printf("%s\t%s\t%s\n", zname,
+ tagname, tsbuf);
+ }
} else {
- (void) printf("%-*s %-*s %s\n", nwidth,
- zname, tagwidth, tagname, tsbuf);
+ if (parsable) {
+ (void) printf("%-*s %-*s %ld\n",
+ nwidth, zname, tagwidth,
+ tagname, time);
+ } else {
+ (void) printf("%-*s %-*s %s\n",
+ nwidth, zname, tagwidth,
+ tagname, tsbuf);
+ }
}
}
}
@@ -6501,10 +6662,11 @@ holds_callback(zfs_handle_t *zhp, void *data)
}
/*
- * zfs holds [-rH] <snap> ...
+ * zfs holds [-rHp] <snap> ...
*
* -r Lists holds that are set on the named snapshots recursively.
* -H Scripted mode; elide headers and separate columns by tabs.
+ * -p Display values in parsable (literal) format.
*/
static int
zfs_do_holds(int argc, char **argv)
@@ -6513,6 +6675,7 @@ zfs_do_holds(int argc, char **argv)
boolean_t errors = B_FALSE;
boolean_t scripted = B_FALSE;
boolean_t recursive = B_FALSE;
+ boolean_t parsable = B_FALSE;
int types = ZFS_TYPE_SNAPSHOT;
holds_cbdata_t cb = { 0 };
@@ -6522,7 +6685,7 @@ zfs_do_holds(int argc, char **argv)
int flags = 0;
/* check options */
- while ((c = getopt(argc, argv, "rH")) != -1) {
+ while ((c = getopt(argc, argv, "rHp")) != -1) {
switch (c) {
case 'r':
recursive = B_TRUE;
@@ -6530,6 +6693,9 @@ zfs_do_holds(int argc, char **argv)
case 'H':
scripted = B_TRUE;
break;
+ case 'p':
+ parsable = B_TRUE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -6583,7 +6749,8 @@ zfs_do_holds(int argc, char **argv)
/*
* 2. print holds data
*/
- print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl);
+ print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl,
+ parsable);
if (nvlist_empty(nvl))
(void) fprintf(stderr, gettext("no datasets available\n"));
@@ -6598,6 +6765,8 @@ zfs_do_holds(int argc, char **argv)
#define MOUNT_TIME 1 /* seconds */
typedef struct get_all_state {
+ char **ga_datasets;
+ int ga_count;
boolean_t ga_verbose;
get_all_cb_t *ga_cbp;
} get_all_state_t;
@@ -6626,7 +6795,7 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
/*
* Iterate over any nested datasets.
*/
- if (zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) {
+ if (zfs_iter_filesystems_v2(zhp, 0, get_one_dataset, data) != 0) {
zfs_close(zhp);
return (1);
}
@@ -6644,19 +6813,35 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
return (0);
}
-static void
-get_all_datasets(get_all_cb_t *cbp, boolean_t verbose)
+static int
+get_recursive_datasets(zfs_handle_t *zhp, void *data)
{
- get_all_state_t state = {
- .ga_verbose = verbose,
- .ga_cbp = cbp
- };
+ get_all_state_t *state = data;
+ int len = strlen(zfs_get_name(zhp));
+ for (int i = 0; i < state->ga_count; ++i) {
+ if (strcmp(state->ga_datasets[i], zfs_get_name(zhp)) == 0)
+ return (get_one_dataset(zhp, data));
+ else if ((strncmp(state->ga_datasets[i], zfs_get_name(zhp),
+ len) == 0) && state->ga_datasets[i][len] == '/') {
+ (void) zfs_iter_filesystems_v2(zhp, 0,
+ get_recursive_datasets, data);
+ }
+ }
+ zfs_close(zhp);
+ return (0);
+}
- if (verbose)
+static void
+get_all_datasets(get_all_state_t *state)
+{
+ if (state->ga_verbose)
set_progress_header(gettext("Reading ZFS config"));
- (void) zfs_iter_root(g_zfs, get_one_dataset, &state);
+ if (state->ga_datasets == NULL)
+ (void) zfs_iter_root(g_zfs, get_one_dataset, state);
+ else
+ (void) zfs_iter_root(g_zfs, get_recursive_datasets, state);
- if (verbose)
+ if (state->ga_verbose)
finish_progress(gettext("done."));
}
@@ -7002,18 +7187,22 @@ static int
share_mount(int op, int argc, char **argv)
{
int do_all = 0;
+ int recursive = 0;
boolean_t verbose = B_FALSE;
int c, ret = 0;
char *options = NULL;
int flags = 0;
/* check options */
- while ((c = getopt(argc, argv, op == OP_MOUNT ? ":alvo:Of" : "al"))
+ while ((c = getopt(argc, argv, op == OP_MOUNT ? ":aRlvo:Of" : "al"))
!= -1) {
switch (c) {
case 'a':
do_all = 1;
break;
+ case 'R':
+ recursive = 1;
+ break;
case 'v':
verbose = B_TRUE;
break;
@@ -7055,7 +7244,7 @@ share_mount(int op, int argc, char **argv)
argv += optind;
/* check number of arguments */
- if (do_all) {
+ if (do_all || recursive) {
enum sa_protocol protocol = SA_NO_PROTOCOL;
if (op == OP_SHARE && argc > 0) {
@@ -7064,14 +7253,38 @@ share_mount(int op, int argc, char **argv)
argv++;
}
- if (argc != 0) {
+ if (argc != 0 && do_all) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
+ if (argc == 0 && recursive) {
+ (void) fprintf(stderr,
+ gettext("no dataset provided\n"));
+ usage(B_FALSE);
+ }
+
start_progress_timer();
get_all_cb_t cb = { 0 };
- get_all_datasets(&cb, verbose);
+ get_all_state_t state = { 0 };
+ if (argc == 0) {
+ state.ga_datasets = NULL;
+ state.ga_count = -1;
+ } else {
+ zfs_handle_t *zhp;
+ for (int i = 0; i < argc; i++) {
+ zhp = zfs_open(g_zfs, argv[i],
+ ZFS_TYPE_FILESYSTEM);
+ if (zhp == NULL)
+ usage(B_FALSE);
+ zfs_close(zhp);
+ }
+ state.ga_datasets = argv;
+ state.ga_count = argc;
+ }
+ state.ga_verbose = verbose;
+ state.ga_cbp = &cb;
+ get_all_datasets(&state);
if (cb.cb_used == 0) {
free(options);
@@ -7087,6 +7300,10 @@ share_mount(int op, int argc, char **argv)
share_mount_state.sm_total = cb.cb_used;
pthread_mutex_init(&share_mount_state.sm_lock, NULL);
+ /* For a 'zfs share -a' operation start with a clean slate. */
+ if (op == OP_SHARE)
+ zfs_truncate_shares(NULL);
+
/*
* libshare isn't mt-safe, so only do the operation in parallel
* if we're mounting. Additionally, the key-loading option must
@@ -7386,8 +7603,11 @@ unshare_unmount(int op, int argc, char **argv)
((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL))
nomem();
- if ((mnttab = fopen(MNTTAB, "re")) == NULL)
+ if ((mnttab = fopen(MNTTAB, "re")) == NULL) {
+ uu_avl_destroy(tree);
+ uu_avl_pool_destroy(pool);
return (ENOENT);
+ }
while (getmntent(mnttab, &entry) == 0) {
@@ -8008,7 +8228,7 @@ zfs_do_channel_program(int argc, char **argv)
const char *msg = gettext("Channel program execution failed");
uint64_t instructions = 0;
if (outnvl != NULL && nvlist_exists(outnvl, ZCP_RET_ERROR)) {
- char *es = NULL;
+ const char *es = NULL;
(void) nvlist_lookup_string(outnvl,
ZCP_RET_ERROR, &es);
if (es == NULL)
@@ -8505,7 +8725,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. */
@@ -8593,6 +8813,25 @@ zfs_do_version(int argc, char **argv)
return (zfs_version_print() != 0);
}
+/* Display documentation */
+static int
+zfs_do_help(int argc, char **argv)
+{
+ char page[MAXNAMELEN];
+ if (argc < 3 || strcmp(argv[2], "zfs") == 0)
+ strcpy(page, "zfs");
+ else if (strcmp(argv[2], "concepts") == 0 ||
+ strcmp(argv[2], "props") == 0)
+ snprintf(page, sizeof (page), "zfs%s", argv[2]);
+ else
+ snprintf(page, sizeof (page), "zfs-%s", argv[2]);
+
+ execlp("man", "man", page, NULL);
+
+ fprintf(stderr, "couldn't run man program: %s", strerror(errno));
+ return (-1);
+}
+
int
main(int argc, char **argv)
{
@@ -8648,6 +8887,12 @@ main(int argc, char **argv)
if ((strcmp(cmdname, "-V") == 0) || (strcmp(cmdname, "--version") == 0))
return (zfs_do_version(argc, argv));
+ /*
+ * Special case 'help'
+ */
+ if (strcmp(cmdname, "help") == 0)
+ return (zfs_do_help(argc, argv));
+
if ((g_zfs = libzfs_init()) == NULL) {
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
return (1);
@@ -8657,6 +8902,8 @@ main(int argc, char **argv)
libzfs_print_on_error(g_zfs, B_TRUE);
+ zfs_setproctitle_init(argc, argv, environ);
+
/*
* Many commands modify input strings for string parsing reasons.
* We create a copy to protect the original argv.
diff --git a/cmd/zfs/zfs_project.c b/cmd/zfs/zfs_project.c
index bc127ed121df..8a010e103bef 100644
--- a/cmd/zfs/zfs_project.c
+++ b/cmd/zfs/zfs_project.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zfs/zfs_projectutil.h b/cmd/zfs/zfs_projectutil.h
index 1792a3383a03..e4038d885cdd 100644
--- a/cmd/zfs/zfs_projectutil.h
+++ b/cmd/zfs/zfs_projectutil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zfs/zfs_util.h b/cmd/zfs/zfs_util.h
index cd0dc3ed04cc..07ade72dd28c 100644
--- a/cmd/zfs/zfs_util.h
+++ b/cmd/zfs/zfs_util.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zfs_ids_to_path.c b/cmd/zfs_ids_to_path.c
index 1d3bb6b29ee1..4db7e949ead0 100644
--- a/cmd/zfs_ids_to_path.c
+++ b/cmd/zfs_ids_to_path.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zgenhostid.c b/cmd/zgenhostid.c
index 853931c6ad6e..04433b0d973c 100644
--- a/cmd/zgenhostid.c
+++ b/cmd/zgenhostid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zhack.c b/cmd/zhack.c
index 8221a67d5131..f15a6ece538c 100644
--- a/cmd/zhack.c
+++ b/cmd/zhack.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,6 +30,7 @@
* result in corrupted pools.
*/
+#include <zfs_prop.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
@@ -57,6 +58,12 @@ static importargs_t g_importargs;
static char *g_pool;
static boolean_t g_readonly;
+typedef enum {
+ ZHACK_REPAIR_OP_UNKNOWN = 0,
+ ZHACK_REPAIR_OP_CKSUM = (1 << 0),
+ ZHACK_REPAIR_OP_UNDETACH = (1 << 1)
+} zhack_repair_op_t;
+
static __attribute__((noreturn)) void
usage(void)
{
@@ -80,7 +87,10 @@ usage(void)
" <feature> : should be a feature guid\n"
"\n"
" label repair <device>\n"
- " repair corrupted label checksums\n"
+ " repair labels of a specified device according to options\n"
+ " which may be combined to do their functions in one call\n"
+ " -c repair corrupted label checksums\n"
+ " -u restore the label on a detached device\n"
"\n"
" <device> : path to vdev\n");
exit(1);
@@ -140,8 +150,12 @@ zhack_import(char *target, boolean_t readonly)
g_importargs.can_be_active = readonly;
g_pool = strdup(target);
- error = zpool_find_config(NULL, target, &config, &g_importargs,
- &libzpool_config_ops);
+ libpc_handle_t lpch = {
+ .lpc_lib_handle = NULL,
+ .lpc_ops = &libzpool_config_ops,
+ .lpc_printerr = B_TRUE
+ };
+ error = zpool_find_config(&lpch, target, &config, &g_importargs);
if (error)
fatal(NULL, FTAG, "cannot import '%s'", target);
@@ -295,6 +309,8 @@ zhack_do_feature_enable(int argc, char **argv)
feature.fi_flags |= ZFEATURE_FLAG_READONLY_COMPAT;
break;
case 'd':
+ if (desc != NULL)
+ free(desc);
desc = strdup(optarg);
break;
default:
@@ -478,119 +494,398 @@ zhack_do_feature(int argc, char **argv)
return (0);
}
+#define ASHIFT_UBERBLOCK_SHIFT(ashift) \
+ MIN(MAX(ashift, UBERBLOCK_SHIFT), \
+ MAX_UBERBLOCK_SHIFT)
+#define ASHIFT_UBERBLOCK_SIZE(ashift) \
+ (1ULL << ASHIFT_UBERBLOCK_SHIFT(ashift))
+
+#define REPAIR_LABEL_STATUS_CKSUM (1 << 0)
+#define REPAIR_LABEL_STATUS_UB (1 << 1)
+
static int
-zhack_repair_label_cksum(int argc, char **argv)
+zhack_repair_read_label(const int fd, vdev_label_t *vl,
+ const uint64_t label_offset, const int l)
{
- zio_checksum_info_t *ci = &zio_checksum_table[ZIO_CHECKSUM_LABEL];
- const char *cfg_keys[] = { ZPOOL_CONFIG_VERSION,
- ZPOOL_CONFIG_POOL_STATE, ZPOOL_CONFIG_GUID };
- boolean_t labels_repaired[VDEV_LABELS] = {0};
- boolean_t repaired = B_FALSE;
- vdev_label_t labels[VDEV_LABELS] = {{{0}}};
- struct stat st;
- int fd;
+ const int err = pread64(fd, vl, sizeof (vdev_label_t), label_offset);
- abd_init();
+ if (err == -1) {
+ (void) fprintf(stderr,
+ "error: cannot read label %d: %s\n",
+ l, strerror(errno));
+ return (err);
+ } else if (err != sizeof (vdev_label_t)) {
+ (void) fprintf(stderr,
+ "error: bad label %d read size\n", l);
+ return (err);
+ }
- argc -= 1;
- argv += 1;
+ return (0);
+}
- if (argc < 1) {
- (void) fprintf(stderr, "error: missing device\n");
- usage();
- }
+static void
+zhack_repair_calc_cksum(const int byteswap, void *data, const uint64_t offset,
+ const uint64_t abdsize, zio_eck_t *eck, zio_cksum_t *cksum)
+{
+ zio_cksum_t verifier;
+ zio_cksum_t current_cksum;
+ zio_checksum_info_t *ci;
+ abd_t *abd;
- if ((fd = open(argv[0], O_RDWR)) == -1)
- fatal(NULL, FTAG, "cannot open '%s': %s", argv[0],
- strerror(errno));
+ ZIO_SET_CHECKSUM(&verifier, offset, 0, 0, 0);
- if (stat(argv[0], &st) != 0)
- fatal(NULL, FTAG, "cannot stat '%s': %s", argv[0],
- strerror(errno));
+ if (byteswap)
+ byteswap_uint64_array(&verifier, sizeof (zio_cksum_t));
- for (int l = 0; l < VDEV_LABELS; l++) {
- uint64_t label_offset, offset;
- zio_cksum_t expected_cksum;
- zio_cksum_t actual_cksum;
- zio_cksum_t verifier;
- zio_eck_t *eck;
- nvlist_t *cfg;
- int byteswap;
+ current_cksum = eck->zec_cksum;
+ eck->zec_cksum = verifier;
+
+ ci = &zio_checksum_table[ZIO_CHECKSUM_LABEL];
+ abd = abd_get_from_buf(data, abdsize);
+ ci->ci_func[byteswap](abd, abdsize, NULL, cksum);
+ abd_free(abd);
+
+ eck->zec_cksum = current_cksum;
+}
+
+static int
+zhack_repair_check_label(uberblock_t *ub, const int l, const char **cfg_keys,
+ const size_t cfg_keys_len, nvlist_t *cfg, nvlist_t *vdev_tree_cfg,
+ uint64_t *ashift)
+{
+ int err;
+
+ if (ub->ub_txg != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: UB TXG of 0 expected, but got %"
+ PRIu64 "\n",
+ l, ub->ub_txg);
+ (void) fprintf(stderr, "It would appear the device was not "
+ "properly removed.\n");
+ return (1);
+ }
+
+ for (int i = 0; i < cfg_keys_len; i++) {
uint64_t val;
- ssize_t err;
-
- vdev_label_t *vl = &labels[l];
-
- label_offset = vdev_label_offset(st.st_size, l, 0);
- err = pread64(fd, vl, sizeof (vdev_label_t), label_offset);
- if (err == -1) {
- (void) fprintf(stderr, "error: cannot read "
- "label %d: %s\n", l, strerror(errno));
- continue;
- } else if (err != sizeof (vdev_label_t)) {
- (void) fprintf(stderr, "error: bad label %d read size "
- "\n", l);
- continue;
+ err = nvlist_lookup_uint64(cfg, cfg_keys[i], &val);
+ if (err) {
+ (void) fprintf(stderr,
+ "error: label %d, %d: "
+ "cannot find nvlist key %s\n",
+ l, i, cfg_keys[i]);
+ return (err);
}
+ }
- err = nvlist_unpack(vl->vl_vdev_phys.vp_nvlist,
- VDEV_PHYS_SIZE - sizeof (zio_eck_t), &cfg, 0);
- if (err) {
- (void) fprintf(stderr, "error: cannot unpack nvlist "
- "label %d\n", l);
- continue;
+ err = nvlist_lookup_nvlist(cfg,
+ ZPOOL_CONFIG_VDEV_TREE, &vdev_tree_cfg);
+ if (err) {
+ (void) fprintf(stderr,
+ "error: label %d: cannot find nvlist key %s\n",
+ l, ZPOOL_CONFIG_VDEV_TREE);
+ return (err);
+ }
+
+ err = nvlist_lookup_uint64(vdev_tree_cfg,
+ ZPOOL_CONFIG_ASHIFT, ashift);
+ if (err) {
+ (void) fprintf(stderr,
+ "error: label %d: cannot find nvlist key %s\n",
+ l, ZPOOL_CONFIG_ASHIFT);
+ return (err);
+ }
+
+ if (*ashift == 0) {
+ (void) fprintf(stderr,
+ "error: label %d: nvlist key %s is zero\n",
+ l, ZPOOL_CONFIG_ASHIFT);
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+zhack_repair_undetach(uberblock_t *ub, nvlist_t *cfg, const int l)
+{
+ /*
+ * Uberblock root block pointer has valid birth TXG.
+ * Copying it to the label NVlist
+ */
+ if (BP_GET_LOGICAL_BIRTH(&ub->ub_rootbp) != 0) {
+ const uint64_t txg = BP_GET_LOGICAL_BIRTH(&ub->ub_rootbp);
+ ub->ub_txg = txg;
+
+ if (nvlist_remove_all(cfg, ZPOOL_CONFIG_CREATE_TXG) != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: "
+ "Failed to remove pool creation TXG\n",
+ l);
+ return (1);
}
- for (int i = 0; i < ARRAY_SIZE(cfg_keys); i++) {
- err = nvlist_lookup_uint64(cfg, cfg_keys[i], &val);
- if (err) {
- (void) fprintf(stderr, "error: label %d: "
- "cannot find nvlist key %s\n",
- l, cfg_keys[i]);
- continue;
- }
+ if (nvlist_remove_all(cfg, ZPOOL_CONFIG_POOL_TXG) != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: Failed to remove pool TXG to "
+ "be replaced.\n",
+ l);
+ return (1);
}
- void *data = (char *)vl + offsetof(vdev_label_t, vl_vdev_phys);
- eck = (zio_eck_t *)((char *)(data) + VDEV_PHYS_SIZE) - 1;
+ if (nvlist_add_uint64(cfg, ZPOOL_CONFIG_POOL_TXG, txg) != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: "
+ "Failed to add pool TXG of %" PRIu64 "\n",
+ l, txg);
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+static boolean_t
+zhack_repair_write_label(const int l, const int fd, const int byteswap,
+ void *data, zio_eck_t *eck, const uint64_t offset, const uint64_t abdsize)
+{
+ zio_cksum_t actual_cksum;
+ zhack_repair_calc_cksum(byteswap, data, offset, abdsize, eck,
+ &actual_cksum);
+ zio_cksum_t expected_cksum = eck->zec_cksum;
+ ssize_t err;
+
+ if (ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum))
+ return (B_FALSE);
+
+ eck->zec_cksum = actual_cksum;
+
+ err = pwrite64(fd, data, abdsize, offset);
+ if (err == -1) {
+ (void) fprintf(stderr, "error: cannot write label %d: %s\n",
+ l, strerror(errno));
+ return (B_FALSE);
+ } else if (err != abdsize) {
+ (void) fprintf(stderr, "error: bad write size label %d\n", l);
+ return (B_FALSE);
+ } else {
+ (void) fprintf(stderr,
+ "label %d: wrote %" PRIu64 " bytes at offset %" PRIu64 "\n",
+ l, abdsize, offset);
+ }
+
+ return (B_TRUE);
+}
+
+static void
+zhack_repair_write_uberblock(vdev_label_t *vl, const int l,
+ const uint64_t ashift, const int fd, const int byteswap,
+ const uint64_t label_offset, uint32_t *labels_repaired)
+{
+ void *ub_data =
+ (char *)vl + offsetof(vdev_label_t, vl_uberblock);
+ zio_eck_t *ub_eck =
+ (zio_eck_t *)
+ ((char *)(ub_data) + (ASHIFT_UBERBLOCK_SIZE(ashift))) - 1;
+
+ if (ub_eck->zec_magic != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: "
+ "Expected Uberblock checksum magic number to "
+ "be 0, but got %" PRIu64 "\n",
+ l, ub_eck->zec_magic);
+ (void) fprintf(stderr, "It would appear there's already "
+ "a checksum for the uberblock.\n");
+ return;
+ }
+
- offset = label_offset + offsetof(vdev_label_t, vl_vdev_phys);
- ZIO_SET_CHECKSUM(&verifier, offset, 0, 0, 0);
+ ub_eck->zec_magic = byteswap ? BSWAP_64(ZEC_MAGIC) : ZEC_MAGIC;
- byteswap = (eck->zec_magic == BSWAP_64(ZEC_MAGIC));
- if (byteswap)
- byteswap_uint64_array(&verifier, sizeof (zio_cksum_t));
+ if (zhack_repair_write_label(l, fd, byteswap,
+ ub_data, ub_eck,
+ label_offset + offsetof(vdev_label_t, vl_uberblock),
+ ASHIFT_UBERBLOCK_SIZE(ashift)))
+ labels_repaired[l] |= REPAIR_LABEL_STATUS_UB;
+}
- expected_cksum = eck->zec_cksum;
- eck->zec_cksum = verifier;
+static void
+zhack_repair_print_cksum(FILE *stream, const zio_cksum_t *cksum)
+{
+ (void) fprintf(stream,
+ "%016llx:%016llx:%016llx:%016llx",
+ (u_longlong_t)cksum->zc_word[0],
+ (u_longlong_t)cksum->zc_word[1],
+ (u_longlong_t)cksum->zc_word[2],
+ (u_longlong_t)cksum->zc_word[3]);
+}
- abd_t *abd = abd_get_from_buf(data, VDEV_PHYS_SIZE);
- ci->ci_func[byteswap](abd, VDEV_PHYS_SIZE, NULL, &actual_cksum);
- abd_free(abd);
+static int
+zhack_repair_test_cksum(const int byteswap, void *vdev_data,
+ zio_eck_t *vdev_eck, const uint64_t vdev_phys_offset, const int l)
+{
+ const zio_cksum_t expected_cksum = vdev_eck->zec_cksum;
+ zio_cksum_t actual_cksum;
+ zhack_repair_calc_cksum(byteswap, vdev_data, vdev_phys_offset,
+ VDEV_PHYS_SIZE, vdev_eck, &actual_cksum);
+ const uint64_t expected_magic = byteswap ?
+ BSWAP_64(ZEC_MAGIC) : ZEC_MAGIC;
+ const uint64_t actual_magic = vdev_eck->zec_magic;
+ int err = 0;
+ if (actual_magic != expected_magic) {
+ (void) fprintf(stderr, "error: label %d: "
+ "Expected "
+ "the nvlist checksum magic number to not be %"
+ PRIu64 " not %" PRIu64 "\n",
+ l, expected_magic, actual_magic);
+ err = ECKSUM;
+ }
+ if (!ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum)) {
+ (void) fprintf(stderr, "error: label %d: "
+ "Expected the nvlist checksum to be ", l);
+ (void) zhack_repair_print_cksum(stderr,
+ &expected_cksum);
+ (void) fprintf(stderr, " not ");
+ zhack_repair_print_cksum(stderr, &actual_cksum);
+ (void) fprintf(stderr, "\n");
+ err = ECKSUM;
+ }
+ return (err);
+}
- if (byteswap)
- byteswap_uint64_array(&expected_cksum,
- sizeof (zio_cksum_t));
+static void
+zhack_repair_one_label(const zhack_repair_op_t op, const int fd,
+ vdev_label_t *vl, const uint64_t label_offset, const int l,
+ uint32_t *labels_repaired)
+{
+ ssize_t err;
+ uberblock_t *ub = (uberblock_t *)vl->vl_uberblock;
+ void *vdev_data =
+ (char *)vl + offsetof(vdev_label_t, vl_vdev_phys);
+ zio_eck_t *vdev_eck =
+ (zio_eck_t *)((char *)(vdev_data) + VDEV_PHYS_SIZE) - 1;
+ const uint64_t vdev_phys_offset =
+ label_offset + offsetof(vdev_label_t, vl_vdev_phys);
+ const char *cfg_keys[] = { ZPOOL_CONFIG_VERSION,
+ ZPOOL_CONFIG_POOL_STATE, ZPOOL_CONFIG_GUID };
+ nvlist_t *cfg;
+ nvlist_t *vdev_tree_cfg = NULL;
+ uint64_t ashift;
+ int byteswap;
+
+ err = zhack_repair_read_label(fd, vl, label_offset, l);
+ if (err)
+ return;
+
+ if (vdev_eck->zec_magic == 0) {
+ (void) fprintf(stderr, "error: label %d: "
+ "Expected the nvlist checksum magic number to not be zero"
+ "\n",
+ l);
+ (void) fprintf(stderr, "There should already be a checksum "
+ "for the label.\n");
+ return;
+ }
+
+ byteswap =
+ (vdev_eck->zec_magic == BSWAP_64((uint64_t)ZEC_MAGIC));
- if (ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum))
- continue;
+ if (byteswap) {
+ byteswap_uint64_array(&vdev_eck->zec_cksum,
+ sizeof (zio_cksum_t));
+ vdev_eck->zec_magic = BSWAP_64(vdev_eck->zec_magic);
+ }
- eck->zec_cksum = actual_cksum;
+ if ((op & ZHACK_REPAIR_OP_CKSUM) == 0 &&
+ zhack_repair_test_cksum(byteswap, vdev_data, vdev_eck,
+ vdev_phys_offset, l) != 0) {
+ (void) fprintf(stderr, "It would appear checksums are "
+ "corrupted. Try zhack repair label -c <device>\n");
+ return;
+ }
- err = pwrite64(fd, data, VDEV_PHYS_SIZE, offset);
- if (err == -1) {
- (void) fprintf(stderr, "error: cannot write "
- "label %d: %s\n", l, strerror(errno));
- continue;
- } else if (err != VDEV_PHYS_SIZE) {
- (void) fprintf(stderr, "error: bad write size "
- "label %d\n", l);
- continue;
+ err = nvlist_unpack(vl->vl_vdev_phys.vp_nvlist,
+ VDEV_PHYS_SIZE - sizeof (zio_eck_t), &cfg, 0);
+ if (err) {
+ (void) fprintf(stderr,
+ "error: cannot unpack nvlist label %d\n", l);
+ return;
+ }
+
+ err = zhack_repair_check_label(ub,
+ l, cfg_keys, ARRAY_SIZE(cfg_keys), cfg, vdev_tree_cfg, &ashift);
+ if (err)
+ return;
+
+ if ((op & ZHACK_REPAIR_OP_UNDETACH) != 0) {
+ char *buf;
+ size_t buflen;
+
+ err = zhack_repair_undetach(ub, cfg, l);
+ if (err)
+ return;
+
+ buf = vl->vl_vdev_phys.vp_nvlist;
+ buflen = VDEV_PHYS_SIZE - sizeof (zio_eck_t);
+ if (nvlist_pack(cfg, &buf, &buflen, NV_ENCODE_XDR, 0) != 0) {
+ (void) fprintf(stderr,
+ "error: label %d: Failed to pack nvlist\n", l);
+ return;
}
- fsync(fd);
+ zhack_repair_write_uberblock(vl,
+ l, ashift, fd, byteswap, label_offset, labels_repaired);
+ }
+
+ if (zhack_repair_write_label(l, fd, byteswap, vdev_data, vdev_eck,
+ vdev_phys_offset, VDEV_PHYS_SIZE))
+ labels_repaired[l] |= REPAIR_LABEL_STATUS_CKSUM;
+
+ fsync(fd);
+}
+
+static const char *
+zhack_repair_label_status(const uint32_t label_status,
+ const uint32_t to_check)
+{
+ return ((label_status & to_check) != 0 ? "repaired" : "skipped");
+}
+
+static int
+zhack_label_repair(const zhack_repair_op_t op, const int argc, char **argv)
+{
+ uint32_t labels_repaired[VDEV_LABELS] = {0};
+ vdev_label_t labels[VDEV_LABELS] = {{{0}}};
+ struct stat64 st;
+ int fd;
+ off_t filesize;
+ uint32_t repaired = 0;
+
+ abd_init();
- labels_repaired[l] = B_TRUE;
+ if (argc < 1) {
+ (void) fprintf(stderr, "error: missing device\n");
+ usage();
+ }
+
+ if ((fd = open(argv[0], O_RDWR)) == -1)
+ fatal(NULL, FTAG, "cannot open '%s': %s", argv[0],
+ strerror(errno));
+
+ if (fstat64_blk(fd, &st) != 0)
+ fatal(NULL, FTAG, "cannot stat '%s': %s", argv[0],
+ strerror(errno));
+
+ filesize = st.st_size;
+ (void) fprintf(stderr, "Calculated filesize to be %jd\n",
+ (intmax_t)filesize);
+
+ if (filesize % sizeof (vdev_label_t) != 0)
+ filesize =
+ (filesize / sizeof (vdev_label_t)) * sizeof (vdev_label_t);
+
+ for (int l = 0; l < VDEV_LABELS; l++) {
+ zhack_repair_one_label(op, fd, &labels[l],
+ vdev_label_offset(filesize, l, 0), l, labels_repaired);
}
close(fd);
@@ -598,18 +893,52 @@ zhack_repair_label_cksum(int argc, char **argv)
abd_fini();
for (int l = 0; l < VDEV_LABELS; l++) {
- (void) printf("label %d: %s\n", l,
- labels_repaired[l] ? "repaired" : "skipped");
- repaired |= labels_repaired[l];
+ const uint32_t lr = labels_repaired[l];
+ (void) printf("label %d: ", l);
+ (void) printf("uberblock: %s ",
+ zhack_repair_label_status(lr, REPAIR_LABEL_STATUS_UB));
+ (void) printf("checksum: %s\n",
+ zhack_repair_label_status(lr, REPAIR_LABEL_STATUS_CKSUM));
+ repaired |= lr;
}
- if (repaired)
+ if (repaired > 0)
return (0);
return (1);
}
static int
+zhack_do_label_repair(int argc, char **argv)
+{
+ zhack_repair_op_t op = ZHACK_REPAIR_OP_UNKNOWN;
+ int c;
+
+ optind = 1;
+ while ((c = getopt(argc, argv, "+cu")) != -1) {
+ switch (c) {
+ case 'c':
+ op |= ZHACK_REPAIR_OP_CKSUM;
+ break;
+ case 'u':
+ op |= ZHACK_REPAIR_OP_UNDETACH;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (op == ZHACK_REPAIR_OP_UNKNOWN)
+ op = ZHACK_REPAIR_OP_CKSUM;
+
+ return (zhack_label_repair(op, argc, argv));
+}
+
+static int
zhack_do_label(int argc, char **argv)
{
char *subcommand;
@@ -625,7 +954,7 @@ zhack_do_label(int argc, char **argv)
subcommand = argv[0];
if (strcmp(subcommand, "repair") == 0) {
- err = zhack_repair_label_cksum(argc, argv);
+ err = zhack_do_label_repair(argc, argv);
} else {
(void) fprintf(stderr, "error: unknown subcommand: %s\n",
subcommand);
@@ -640,8 +969,6 @@ zhack_do_label(int argc, char **argv)
int
main(int argc, char **argv)
{
- extern void zfs_prop_init(void);
-
char *path[MAX_NUM_PATHS];
const char *subcommand;
int rv = 0;
diff --git a/cmd/zilstat.in b/cmd/zilstat.in
new file mode 100755
index 000000000000..e8678e20cafa
--- /dev/null
+++ b/cmd/zilstat.in
@@ -0,0 +1,551 @@
+#!/usr/bin/env @PYTHON_SHEBANG@
+#
+# Print out statistics for all zil stats. This information is
+# available through the zil kstat.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# This script must remain compatible with Python 3.6+.
+#
+
+import sys
+import subprocess
+import time
+import copy
+import os
+import re
+import signal
+from collections import defaultdict
+import argparse
+from argparse import RawTextHelpFormatter
+
+cols = {
+ # hdr: [size, scale, kstat name]
+ "time": [8, -1, "time"],
+ "pool": [12, -1, "pool"],
+ "ds": [12, -1, "dataset_name"],
+ "obj": [12, -1, "objset"],
+ "cc": [5, 1000, "zil_commit_count"],
+ "cwc": [5, 1000, "zil_commit_writer_count"],
+ "ic": [5, 1000, "zil_itx_count"],
+ "iic": [5, 1000, "zil_itx_indirect_count"],
+ "iib": [5, 1024, "zil_itx_indirect_bytes"],
+ "icc": [5, 1000, "zil_itx_copied_count"],
+ "icb": [5, 1024, "zil_itx_copied_bytes"],
+ "inc": [5, 1000, "zil_itx_needcopy_count"],
+ "inb": [5, 1024, "zil_itx_needcopy_bytes"],
+ "idc": [5, 1000, "icc+inc"],
+ "idb": [5, 1024, "icb+inb"],
+ "iwc": [5, 1000, "iic+idc"],
+ "iwb": [5, 1024, "iib+idb"],
+ "imnc": [6, 1000, "zil_itx_metaslab_normal_count"],
+ "imnb": [6, 1024, "zil_itx_metaslab_normal_bytes"],
+ "imnw": [6, 1024, "zil_itx_metaslab_normal_write"],
+ "imna": [6, 1024, "zil_itx_metaslab_normal_alloc"],
+ "imsc": [6, 1000, "zil_itx_metaslab_slog_count"],
+ "imsb": [6, 1024, "zil_itx_metaslab_slog_bytes"],
+ "imsw": [6, 1024, "zil_itx_metaslab_slog_write"],
+ "imsa": [6, 1024, "zil_itx_metaslab_slog_alloc"],
+ "imc": [5, 1000, "imnc+imsc"],
+ "imb": [5, 1024, "imnb+imsb"],
+ "imw": [5, 1024, "imnw+imsw"],
+ "ima": [5, 1024, "imna+imsa"],
+ "se%": [3, 100, "imb/ima"],
+ "sen%": [4, 100, "imnb/imna"],
+ "ses%": [4, 100, "imsb/imsa"],
+ "te%": [3, 100, "imb/imw"],
+ "ten%": [4, 100, "imnb/imnw"],
+ "tes%": [4, 100, "imsb/imsw"],
+}
+
+hdr = ["time", "ds", "cc", "ic", "idc", "idb", "iic", "iib",
+ "imnc", "imnw", "imsc", "imsw"]
+
+ghdr = ["time", "cc", "ic", "idc", "idb", "iic", "iib",
+ "imnc", "imnw", "imsc", "imsw"]
+
+cmd = ("Usage: zilstat [-hgdv] [-i interval] [-p pool_name]")
+
+curr = {}
+diff = {}
+kstat = {}
+ds_pairs = {}
+pool_name = None
+dataset_name = None
+interval = 0
+sep = " "
+gFlag = True
+dsFlag = False
+
+def prettynum(sz, scale, num=0):
+ suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
+ index = 0
+ save = 0
+
+ if scale == -1:
+ return "%*s" % (sz, num)
+
+ # Rounding error, return 0
+ elif 0 < num < 1:
+ num = 0
+
+ while num > scale and index < 5:
+ save = num
+ num = num / scale
+ index += 1
+
+ if index == 0:
+ return "%*d" % (sz, num)
+
+ if (save / scale) < 10:
+ return "%*.1f%s" % (sz - 1, num, suffix[index])
+ else:
+ return "%*d%s" % (sz - 1, num, suffix[index])
+
+def print_header():
+ global hdr
+ global sep
+ for col in hdr:
+ new_col = col
+ if interval > 0 and cols[col][1] > 100:
+ new_col += "/s"
+ sys.stdout.write("%*s%s" % (cols[col][0], new_col, sep))
+ sys.stdout.write("\n")
+
+def print_values(v):
+ global hdr
+ global sep
+ for col in hdr:
+ val = v[cols[col][2]]
+ if interval > 0 and cols[col][1] > 100:
+ val = v[cols[col][2]] // interval
+ sys.stdout.write("%s%s" % (
+ prettynum(cols[col][0], cols[col][1], val), sep))
+ sys.stdout.write("\n")
+
+def print_dict(d):
+ for pool in d:
+ for objset in d[pool]:
+ print_values(d[pool][objset])
+
+def detailed_usage():
+ sys.stderr.write("%s\n" % cmd)
+ sys.stderr.write("Field definitions are as follows:\n")
+ for key in cols:
+ sys.stderr.write("%11s : %s\n" % (key, cols[key][2]))
+ sys.stderr.write("\n")
+ sys.exit(0)
+
+def init():
+ global pool_name
+ global dataset_name
+ global interval
+ global hdr
+ global curr
+ global gFlag
+ global sep
+
+ curr = dict()
+
+ parser = argparse.ArgumentParser(description='Program to print zilstats',
+ add_help=True,
+ formatter_class=RawTextHelpFormatter,
+ epilog="\nUsage Examples\n"\
+ "Note: Global zilstats is shown by default,"\
+ " if none of a|p|d option is not provided\n"\
+ "\tzilstat -a\n"\
+ '\tzilstat -v\n'\
+ '\tzilstat -p tank\n'\
+ '\tzilstat -d tank/d1,tank/d2,tank/zv1\n'\
+ '\tzilstat -i 1\n'\
+ '\tzilstat -s \"***\"\n'\
+ '\tzilstat -f zcwc,zimnb,zimsb\n')
+
+ parser.add_argument(
+ "-v", "--verbose",
+ action="store_true",
+ help="List field headers and definitions"
+ )
+
+ pool_grp = parser.add_mutually_exclusive_group()
+
+ pool_grp.add_argument(
+ "-a", "--all",
+ action="store_true",
+ dest="all",
+ help="Print all dataset stats"
+ )
+
+ pool_grp.add_argument(
+ "-p", "--pool",
+ type=str,
+ help="Print stats for all datasets of a speicfied pool"
+ )
+
+ pool_grp.add_argument(
+ "-d", "--dataset",
+ type=str,
+ help="Print given dataset(s) (Comma separated)"
+ )
+
+ parser.add_argument(
+ "-f", "--columns",
+ type=str,
+ help="Specify specific fields to print (see -v)"
+ )
+
+ parser.add_argument(
+ "-s", "--separator",
+ type=str,
+ help="Override default field separator with custom "
+ "character or string"
+ )
+
+ parser.add_argument(
+ "-i", "--interval",
+ type=int,
+ dest="interval",
+ help="Print stats between specified interval"
+ " (in seconds)"
+ )
+
+ parsed_args = parser.parse_args()
+
+ if parsed_args.verbose:
+ detailed_usage()
+
+ if parsed_args.all:
+ gFlag = False
+
+ if parsed_args.interval:
+ interval = parsed_args.interval
+
+ if parsed_args.pool:
+ pool_name = parsed_args.pool
+ gFlag = False
+
+ if parsed_args.dataset:
+ dataset_name = parsed_args.dataset
+ gFlag = False
+
+ if parsed_args.separator:
+ sep = parsed_args.separator
+
+ if gFlag:
+ hdr = ghdr
+
+ if parsed_args.columns:
+ hdr = parsed_args.columns.split(",")
+
+ invalid = []
+ for ele in hdr:
+ if ele not in cols:
+ invalid.append(ele)
+
+ if len(invalid) > 0:
+ sys.stderr.write("Invalid column definition! -- %s\n" % invalid)
+ sys.exit(1)
+
+ if pool_name and dataset_name:
+ print ("Error: Can not filter both dataset and pool")
+ sys.exit(1)
+
+def FileCheck(fname):
+ try:
+ return (open(fname))
+ except IOError:
+ print ("Unable to open zilstat proc file: " + fname)
+ sys.exit(1)
+
+if sys.platform.startswith('freebsd'):
+ # Requires py-sysctl on FreeBSD
+ import sysctl
+
+ def kstat_update(pool = None, objid = None):
+ global kstat
+ kstat = {}
+ if not pool:
+ file = "kstat.zfs.misc.zil"
+ k = [ctl for ctl in sysctl.filter(file) \
+ if ctl.type != sysctl.CTLTYPE_NODE]
+ kstat_process_str(k, file, "GLOBAL", len(file + "."))
+ elif objid:
+ file = "kstat.zfs." + pool + ".dataset.objset-" + objid
+ k = [ctl for ctl in sysctl.filter(file) if ctl.type \
+ != sysctl.CTLTYPE_NODE]
+ kstat_process_str(k, file, objid, len(file + "."))
+ else:
+ file = "kstat.zfs." + pool + ".dataset"
+ zil_start = len(file + ".")
+ obj_start = len("kstat.zfs." + pool + ".")
+ k = [ctl for ctl in sysctl.filter(file)
+ if ctl.type != sysctl.CTLTYPE_NODE]
+ for s in k:
+ if not s or (s.name.find("zil") == -1 and \
+ s.name.find("dataset_name") == -1):
+ continue
+ name, value = s.name, s.value
+ objid = re.findall(r'0x[0-9A-F]+', \
+ name[obj_start:], re.I)[0]
+ if objid not in kstat:
+ kstat[objid] = dict()
+ zil_start = len(file + ".objset-" + \
+ objid + ".")
+ kstat[objid][name[zil_start:]] = value \
+ if (name.find("dataset_name")) \
+ else int(value)
+
+ def kstat_process_str(k, file, objset = "GLOBAL", zil_start = 0):
+ global kstat
+ if not k:
+ print("Unable to process kstat for: " + file)
+ sys.exit(1)
+ kstat[objset] = dict()
+ for s in k:
+ if not s or (s.name.find("zil") == -1 and \
+ s.name.find("dataset_name") == -1):
+ continue
+ name, value = s.name, s.value
+ kstat[objset][name[zil_start:]] = value \
+ if (name.find("dataset_name")) else int(value)
+
+elif sys.platform.startswith('linux'):
+ def kstat_update(pool = None, objid = None):
+ global kstat
+ kstat = {}
+ if not pool:
+ k = [line.strip() for line in \
+ FileCheck("/proc/spl/kstat/zfs/zil")]
+ kstat_process_str(k, "/proc/spl/kstat/zfs/zil")
+ elif objid:
+ file = "/proc/spl/kstat/zfs/" + pool + "/objset-" + objid
+ k = [line.strip() for line in FileCheck(file)]
+ kstat_process_str(k, file, objid)
+ else:
+ if not os.path.exists(f"/proc/spl/kstat/zfs/{pool}"):
+ print("Pool \"" + pool + "\" does not exist, Exitting")
+ sys.exit(1)
+ objsets = os.listdir(f'/proc/spl/kstat/zfs/{pool}')
+ for objid in objsets:
+ if objid.find("objset-") == -1:
+ continue
+ file = "/proc/spl/kstat/zfs/" + pool + "/" + objid
+ k = [line.strip() for line in FileCheck(file)]
+ kstat_process_str(k, file, objid.replace("objset-", ""))
+
+ def kstat_process_str(k, file, objset = "GLOBAL", zil_start = 0):
+ global kstat
+ if not k:
+ print("Unable to process kstat for: " + file)
+ sys.exit(1)
+
+ kstat[objset] = dict()
+ for s in k:
+ if not s or (s.find("zil") == -1 and \
+ s.find("dataset_name") == -1):
+ continue
+ name, unused, value = s.split()
+ kstat[objset][name] = value \
+ if (name == "dataset_name") else int(value)
+
+def zil_process_kstat():
+ global curr, pool_name, dataset_name, dsFlag, ds_pairs
+ curr.clear()
+ if gFlag == True:
+ kstat_update()
+ zil_build_dict()
+ else:
+ if pool_name:
+ kstat_update(pool_name)
+ zil_build_dict(pool_name)
+ elif dataset_name:
+ if dsFlag == False:
+ dsFlag = True
+ datasets = dataset_name.split(',')
+ ds_pairs = defaultdict(list)
+ for ds in datasets:
+ try:
+ objid = subprocess.check_output(['zfs',
+ 'list', '-Hpo', 'objsetid', ds], \
+ stderr=subprocess.DEVNULL) \
+ .decode('utf-8').strip()
+ except subprocess.CalledProcessError as e:
+ print("Command: \"zfs list -Hpo objset "\
+ + str(ds) + "\" failed with error code:"\
+ + str(e.returncode))
+ print("Please make sure that dataset \""\
+ + str(ds) + "\" exists")
+ sys.exit(1)
+ if not objid:
+ continue
+ ds_pairs[ds.split('/')[0]]. \
+ append(hex(int(objid)))
+ for pool, objids in ds_pairs.items():
+ for objid in objids:
+ kstat_update(pool, objid)
+ zil_build_dict(pool)
+ else:
+ try:
+ pools = subprocess.check_output(['zpool', 'list', '-Hpo',\
+ 'name']).decode('utf-8').split()
+ except subprocess.CalledProcessError as e:
+ print("Command: \"zpool list -Hpo name\" failed with error"\
+ "code: " + str(e.returncode))
+ sys.exit(1)
+ for pool in pools:
+ kstat_update(pool)
+ zil_build_dict(pool)
+
+def calculate_diff():
+ global curr, diff
+ prev = copy.deepcopy(curr)
+ zil_process_kstat()
+ diff = copy.deepcopy(curr)
+ for pool in curr:
+ for objset in curr[pool]:
+ for key in curr[pool][objset]:
+ if not isinstance(diff[pool][objset][key], int):
+ continue
+ # If prev is NULL, this is the
+ # first time we are here
+ if not prev:
+ diff[pool][objset][key] = 0
+ else:
+ diff[pool][objset][key] \
+ = curr[pool][objset][key] \
+ - prev[pool][objset][key]
+
+def zil_build_dict(pool = "GLOBAL"):
+ global kstat
+ for objset in kstat:
+ for key in kstat[objset]:
+ val = kstat[objset][key]
+ if pool not in curr:
+ curr[pool] = dict()
+ if objset not in curr[pool]:
+ curr[pool][objset] = dict()
+ curr[pool][objset][key] = val
+
+def zil_extend_dict():
+ global diff
+ for pool in diff:
+ for objset in diff[pool]:
+ diff[pool][objset]["pool"] = pool
+ diff[pool][objset]["objset"] = objset
+ diff[pool][objset]["time"] = time.strftime("%H:%M:%S", \
+ time.localtime())
+ diff[pool][objset]["icc+inc"] = \
+ diff[pool][objset]["zil_itx_copied_count"] + \
+ diff[pool][objset]["zil_itx_needcopy_count"]
+ diff[pool][objset]["icb+inb"] = \
+ diff[pool][objset]["zil_itx_copied_bytes"] + \
+ diff[pool][objset]["zil_itx_needcopy_bytes"]
+ diff[pool][objset]["iic+idc"] = \
+ diff[pool][objset]["zil_itx_indirect_count"] + \
+ diff[pool][objset]["zil_itx_copied_count"] + \
+ diff[pool][objset]["zil_itx_needcopy_count"]
+ diff[pool][objset]["iib+idb"] = \
+ diff[pool][objset]["zil_itx_indirect_bytes"] + \
+ diff[pool][objset]["zil_itx_copied_bytes"] + \
+ diff[pool][objset]["zil_itx_needcopy_bytes"]
+ diff[pool][objset]["imnc+imsc"] = \
+ diff[pool][objset]["zil_itx_metaslab_normal_count"] + \
+ diff[pool][objset]["zil_itx_metaslab_slog_count"]
+ diff[pool][objset]["imnb+imsb"] = \
+ diff[pool][objset]["zil_itx_metaslab_normal_bytes"] + \
+ diff[pool][objset]["zil_itx_metaslab_slog_bytes"]
+ diff[pool][objset]["imnw+imsw"] = \
+ diff[pool][objset]["zil_itx_metaslab_normal_write"] + \
+ diff[pool][objset]["zil_itx_metaslab_slog_write"]
+ diff[pool][objset]["imna+imsa"] = \
+ diff[pool][objset]["zil_itx_metaslab_normal_alloc"] + \
+ diff[pool][objset]["zil_itx_metaslab_slog_alloc"]
+ if diff[pool][objset]["imna+imsa"] > 0:
+ diff[pool][objset]["imb/ima"] = 100 * \
+ diff[pool][objset]["imnb+imsb"] // \
+ diff[pool][objset]["imna+imsa"]
+ else:
+ diff[pool][objset]["imb/ima"] = 100
+ if diff[pool][objset]["zil_itx_metaslab_normal_alloc"] > 0:
+ diff[pool][objset]["imnb/imna"] = 100 * \
+ diff[pool][objset]["zil_itx_metaslab_normal_bytes"] // \
+ diff[pool][objset]["zil_itx_metaslab_normal_alloc"]
+ else:
+ diff[pool][objset]["imnb/imna"] = 100
+ if diff[pool][objset]["zil_itx_metaslab_slog_alloc"] > 0:
+ diff[pool][objset]["imsb/imsa"] = 100 * \
+ diff[pool][objset]["zil_itx_metaslab_slog_bytes"] // \
+ diff[pool][objset]["zil_itx_metaslab_slog_alloc"]
+ else:
+ diff[pool][objset]["imsb/imsa"] = 100
+ if diff[pool][objset]["imnw+imsw"] > 0:
+ diff[pool][objset]["imb/imw"] = 100 * \
+ diff[pool][objset]["imnb+imsb"] // \
+ diff[pool][objset]["imnw+imsw"]
+ else:
+ diff[pool][objset]["imb/imw"] = 100
+ if diff[pool][objset]["zil_itx_metaslab_normal_alloc"] > 0:
+ diff[pool][objset]["imnb/imnw"] = 100 * \
+ diff[pool][objset]["zil_itx_metaslab_normal_bytes"] // \
+ diff[pool][objset]["zil_itx_metaslab_normal_write"]
+ else:
+ diff[pool][objset]["imnb/imnw"] = 100
+ if diff[pool][objset]["zil_itx_metaslab_slog_alloc"] > 0:
+ diff[pool][objset]["imsb/imsw"] = 100 * \
+ diff[pool][objset]["zil_itx_metaslab_slog_bytes"] // \
+ diff[pool][objset]["zil_itx_metaslab_slog_write"]
+ else:
+ diff[pool][objset]["imsb/imsw"] = 100
+
+def sign_handler_epipe(sig, frame):
+ print("Caught EPIPE signal: " + str(frame))
+ print("Exitting...")
+ sys.exit(0)
+
+def main():
+ global interval
+ global curr, diff
+ hprint = False
+ init()
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGPIPE, sign_handler_epipe)
+
+ zil_process_kstat()
+ if not curr:
+ print ("Error: No stats to show")
+ sys.exit(0)
+ print_header()
+ if interval > 0:
+ time.sleep(interval)
+ while True:
+ calculate_diff()
+ if not diff:
+ print ("Error: No stats to show")
+ sys.exit(0)
+ zil_extend_dict()
+ print_dict(diff)
+ time.sleep(interval)
+ else:
+ diff = curr
+ zil_extend_dict()
+ print_dict(diff)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/cmd/zinject/translate.c b/cmd/zinject/translate.c
index 2b5f1fcd99be..c63caedd1583 100644
--- a/cmd/zinject/translate.c
+++ b/cmd/zinject/translate.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -115,12 +115,12 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
return (-1);
}
- (void) strcpy(dataset, mp.mnt_special);
+ (void) strlcpy(dataset, mp.mnt_special, MAXNAMELEN);
rel = fullpath + strlen(mp.mnt_mountp);
if (rel[0] == '/')
rel++;
- (void) strcpy(relpath, rel);
+ (void) strlcpy(relpath, rel, MAXPATHLEN);
return (0);
}
@@ -258,7 +258,7 @@ translate_record(err_type_t type, const char *object, const char *range,
}
dataset[0] = '\0';
- (void) strcpy(poolname, object);
+ (void) strlcpy(poolname, object, MAXNAMELEN);
return (0);
}
@@ -298,7 +298,7 @@ translate_record(err_type_t type, const char *object, const char *range,
/*
* Copy the pool name
*/
- (void) strcpy(poolname, dataset);
+ (void) strlcpy(poolname, dataset, MAXNAMELEN);
if ((slash = strchr(poolname, '/')) != NULL)
*slash = '\0';
diff --git a/cmd/zinject/zinject.c b/cmd/zinject/zinject.c
index 74c54baebf6f..ed60cce3dd16 100644
--- a/cmd/zinject/zinject.c
+++ b/cmd/zinject/zinject.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
+ * Copyright (c) 2023-2024, Klara Inc.
*/
/*
@@ -208,6 +209,38 @@ type_to_name(uint64_t type)
}
}
+struct errstr {
+ int err;
+ const char *str;
+};
+static const struct errstr errstrtable[] = {
+ { EIO, "io" },
+ { ECKSUM, "checksum" },
+ { EINVAL, "decompress" },
+ { EACCES, "decrypt" },
+ { ENXIO, "nxio" },
+ { ECHILD, "dtl" },
+ { EILSEQ, "corrupt" },
+ { ENOSYS, "noop" },
+ { 0, NULL },
+};
+
+static int
+str_to_err(const char *str)
+{
+ for (int i = 0; errstrtable[i].str != NULL; i++)
+ if (strcasecmp(errstrtable[i].str, str) == 0)
+ return (errstrtable[i].err);
+ return (-1);
+}
+static const char *
+err_to_str(int err)
+{
+ for (int i = 0; errstrtable[i].str != NULL; i++)
+ if (errstrtable[i].err == err)
+ return (errstrtable[i].str);
+ return ("[unknown]");
+}
/*
* Print usage message.
@@ -233,12 +266,12 @@ usage(void)
"\t\tspa_vdev_exit() will trigger a panic.\n"
"\n"
"\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n"
- "\t\t[-T <read|write|free|claim|all>] [-f frequency] pool\n\n"
+ "\t\t[-T <read|write|free|claim|flush|all>] [-f frequency] pool\n\n"
"\t\tInject a fault into a particular device or the device's\n"
"\t\tlabel. Label injection can either be 'nvlist', 'uber',\n "
"\t\t'pad1', or 'pad2'.\n"
- "\t\t'errno' can be 'nxio' (the default), 'io', 'dtl', or\n"
- "\t\t'corrupt' (bit flip).\n"
+ "\t\t'errno' can be 'nxio' (the default), 'io', 'dtl',\n"
+ "\t\t'corrupt' (bit flip), or 'noop' (successfully do nothing).\n"
"\t\t'frequency' is a value between 0.0001 and 100.0 that limits\n"
"\t\tdevice error injection to a percentage of the IOs.\n"
"\n"
@@ -277,6 +310,11 @@ usage(void)
"\t\tcreate 3 lanes on the device; one lane with a latency\n"
"\t\tof 10 ms and two lanes with a 25 ms latency.\n"
"\n"
+ "\tzinject -P import|export -s <seconds> pool\n"
+ "\t\tAdd an artificial delay to a future pool import or export,\n"
+ "\t\tsuch that the operation takes a minimum of supplied seconds\n"
+ "\t\tto complete.\n"
+ "\n"
"\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
"\t\tCause the pool to stop writing blocks yet not\n"
"\t\treport errors for a duration. Simulates buggy hardware\n"
@@ -359,8 +397,10 @@ print_data_handler(int id, const char *pool, zinject_record_t *record,
{
int *count = data;
- if (record->zi_guid != 0 || record->zi_func[0] != '\0')
+ if (record->zi_guid != 0 || record->zi_func[0] != '\0' ||
+ record->zi_duration != 0) {
return (0);
+ }
if (*count == 0) {
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-4s "
@@ -392,6 +432,10 @@ static int
print_device_handler(int id, const char *pool, zinject_record_t *record,
void *data)
{
+ static const char *iotypestr[] = {
+ "null", "read", "write", "free", "claim", "flush", "trim", "all",
+ };
+
int *count = data;
if (record->zi_guid == 0 || record->zi_func[0] != '\0')
@@ -401,14 +445,21 @@ print_device_handler(int id, const char *pool, zinject_record_t *record,
return (0);
if (*count == 0) {
- (void) printf("%3s %-15s %s\n", "ID", "POOL", "GUID");
- (void) printf("--- --------------- ----------------\n");
+ (void) printf("%3s %-15s %-16s %-5s %-10s %-9s\n",
+ "ID", "POOL", "GUID", "TYPE", "ERROR", "FREQ");
+ (void) printf(
+ "--- --------------- ---------------- "
+ "----- ---------- ---------\n");
}
*count += 1;
- (void) printf("%3d %-15s %llx\n", id, pool,
- (u_longlong_t)record->zi_guid);
+ double freq = record->zi_freq == 0 ? 100.0f :
+ (((double)record->zi_freq) / ZI_PERCENTAGE_MAX) * 100.0f;
+
+ (void) printf("%3d %-15s %llx %-5s %-10s %8.4f%%\n", id, pool,
+ (u_longlong_t)record->zi_guid, iotypestr[record->zi_iotype],
+ err_to_str(record->zi_error), freq);
return (0);
}
@@ -463,6 +514,33 @@ print_panic_handler(int id, const char *pool, zinject_record_t *record,
return (0);
}
+static int
+print_pool_delay_handler(int id, const char *pool, zinject_record_t *record,
+ void *data)
+{
+ int *count = data;
+
+ if (record->zi_cmd != ZINJECT_DELAY_IMPORT &&
+ record->zi_cmd != ZINJECT_DELAY_EXPORT) {
+ return (0);
+ }
+
+ if (*count == 0) {
+ (void) printf("%3s %-19s %-11s %s\n",
+ "ID", "POOL", "DELAY (sec)", "COMMAND");
+ (void) printf("--- ------------------- -----------"
+ " -------\n");
+ }
+
+ *count += 1;
+
+ (void) printf("%3d %-19s %-11llu %s\n",
+ id, pool, (u_longlong_t)record->zi_duration,
+ record->zi_cmd == ZINJECT_DELAY_IMPORT ? "import": "export");
+
+ return (0);
+}
+
/*
* Print all registered error handlers. Returns the number of handlers
* registered.
@@ -493,6 +571,13 @@ print_all_handlers(void)
count = 0;
}
+ (void) iter_handlers(print_pool_delay_handler, &count);
+ if (count > 0) {
+ total += count;
+ (void) printf("\n");
+ count = 0;
+ }
+
(void) iter_handlers(print_panic_handler, &count);
return (count + total);
@@ -565,9 +650,27 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
zc.zc_guid = flags;
if (zfs_ioctl(g_zfs, ZFS_IOC_INJECT_FAULT, &zc) != 0) {
- (void) fprintf(stderr, "failed to add handler: %s\n",
- errno == EDOM ? "block level exceeds max level of object" :
- strerror(errno));
+ const char *errmsg = strerror(errno);
+
+ switch (errno) {
+ case EDOM:
+ errmsg = "block level exceeds max level of object";
+ break;
+ case EEXIST:
+ if (record->zi_cmd == ZINJECT_DELAY_IMPORT)
+ errmsg = "pool already imported";
+ if (record->zi_cmd == ZINJECT_DELAY_EXPORT)
+ errmsg = "a handler already exists";
+ break;
+ case ENOENT:
+ /* import delay injector running on older zfs module */
+ if (record->zi_cmd == ZINJECT_DELAY_IMPORT)
+ errmsg = "import delay injector not supported";
+ break;
+ default:
+ break;
+ }
+ (void) fprintf(stderr, "failed to add handler: %s\n", errmsg);
return (1);
}
@@ -592,6 +695,9 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
} else if (record->zi_duration < 0) {
(void) printf(" txgs: %lld \n",
(u_longlong_t)-record->zi_duration);
+ } else if (record->zi_timer > 0) {
+ (void) printf(" timer: %lld ms\n",
+ (u_longlong_t)NSEC2MSEC(record->zi_timer));
} else {
(void) printf("objset: %llu\n",
(u_longlong_t)record->zi_objset);
@@ -790,7 +896,7 @@ main(int argc, char **argv)
}
while ((c = getopt(argc, argv,
- ":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
+ ":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) {
switch (c) {
case 'a':
flags |= ZINJECT_FLUSH_ARC;
@@ -842,24 +948,12 @@ main(int argc, char **argv)
}
break;
case 'e':
- if (strcasecmp(optarg, "io") == 0) {
- error = EIO;
- } else if (strcasecmp(optarg, "checksum") == 0) {
- error = ECKSUM;
- } else if (strcasecmp(optarg, "decompress") == 0) {
- error = EINVAL;
- } else if (strcasecmp(optarg, "decrypt") == 0) {
- error = EACCES;
- } else if (strcasecmp(optarg, "nxio") == 0) {
- error = ENXIO;
- } else if (strcasecmp(optarg, "dtl") == 0) {
- error = ECHILD;
- } else if (strcasecmp(optarg, "corrupt") == 0) {
- error = EILSEQ;
- } else {
+ error = str_to_err(optarg);
+ if (error < 0) {
(void) fprintf(stderr, "invalid error type "
- "'%s': must be 'io', 'checksum' or "
- "'nxio'\n", optarg);
+ "'%s': must be one of: io decompress "
+ "decrypt nxio dtl corrupt noop\n",
+ optarg);
usage();
libzfs_fini(g_zfs);
return (1);
@@ -920,6 +1014,19 @@ main(int argc, char **argv)
sizeof (record.zi_func));
record.zi_cmd = ZINJECT_PANIC;
break;
+ case 'P':
+ if (strcasecmp(optarg, "import") == 0) {
+ record.zi_cmd = ZINJECT_DELAY_IMPORT;
+ } else if (strcasecmp(optarg, "export") == 0) {
+ record.zi_cmd = ZINJECT_DELAY_EXPORT;
+ } else {
+ (void) fprintf(stderr, "invalid command '%s': "
+ "must be 'import' or 'export'\n", optarg);
+ usage();
+ libzfs_fini(g_zfs);
+ return (1);
+ }
+ break;
case 'q':
quiet = 1;
break;
@@ -947,12 +1054,14 @@ main(int argc, char **argv)
io_type = ZIO_TYPE_FREE;
} else if (strcasecmp(optarg, "claim") == 0) {
io_type = ZIO_TYPE_CLAIM;
+ } else if (strcasecmp(optarg, "flush") == 0) {
+ io_type = ZIO_TYPE_FLUSH;
} else if (strcasecmp(optarg, "all") == 0) {
io_type = ZIO_TYPES;
} else {
(void) fprintf(stderr, "invalid I/O type "
"'%s': must be 'read', 'write', 'free', "
- "'claim' or 'all'\n", optarg);
+ "'claim', 'flush' or 'all'\n", optarg);
usage();
libzfs_fini(g_zfs);
return (1);
@@ -999,7 +1108,7 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (record.zi_duration != 0)
+ if (record.zi_duration != 0 && record.zi_cmd == 0)
record.zi_cmd = ZINJECT_IGNORED_WRITES;
if (cancel != NULL) {
@@ -1083,6 +1192,22 @@ main(int argc, char **argv)
libzfs_fini(g_zfs);
return (1);
}
+
+ if (record.zi_nlanes) {
+ switch (io_type) {
+ case ZIO_TYPE_READ:
+ case ZIO_TYPE_WRITE:
+ case ZIO_TYPES:
+ break;
+ default:
+ (void) fprintf(stderr, "I/O type for a delay "
+ "must be 'read' or 'write'\n");
+ usage();
+ libzfs_fini(g_zfs);
+ return (1);
+ }
+ }
+
if (!error)
error = ENXIO;
@@ -1129,8 +1254,8 @@ main(int argc, char **argv)
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
level != 0 || device != NULL || record.zi_freq > 0 ||
dvas != 0) {
- (void) fprintf(stderr, "panic (-p) incompatible with "
- "other options\n");
+ (void) fprintf(stderr, "%s incompatible with other "
+ "options\n", "import|export delay (-P)");
usage();
libzfs_fini(g_zfs);
return (2);
@@ -1148,6 +1273,28 @@ main(int argc, char **argv)
if (argv[1] != NULL)
record.zi_type = atoi(argv[1]);
dataset[0] = '\0';
+ } else if (record.zi_cmd == ZINJECT_DELAY_IMPORT ||
+ record.zi_cmd == ZINJECT_DELAY_EXPORT) {
+ if (raw != NULL || range != NULL || type != TYPE_INVAL ||
+ level != 0 || device != NULL || record.zi_freq > 0 ||
+ dvas != 0) {
+ (void) fprintf(stderr, "%s incompatible with other "
+ "options\n", "import|export delay (-P)");
+ usage();
+ libzfs_fini(g_zfs);
+ return (2);
+ }
+
+ if (argc != 1 || record.zi_duration <= 0) {
+ (void) fprintf(stderr, "import|export delay (-P) "
+ "injection requires a duration (-s) and a single "
+ "pool name\n");
+ usage();
+ libzfs_fini(g_zfs);
+ return (2);
+ }
+
+ (void) strlcpy(pool, argv[0], sizeof (pool));
} else if (record.zi_cmd == ZINJECT_IGNORED_WRITES) {
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
level != 0 || record.zi_freq > 0 || dvas != 0) {
diff --git a/cmd/zinject/zinject.h b/cmd/zinject/zinject.h
index 46fdcad8b31f..73176a24195a 100644
--- a/cmd/zinject/zinject.h
+++ b/cmd/zinject/zinject.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zpool/Makefile.am b/cmd/zpool/Makefile.am
index 3c7c8a9aebe2..d08b8e1791b6 100644
--- a/cmd/zpool/Makefile.am
+++ b/cmd/zpool/Makefile.am
@@ -145,6 +145,7 @@ dist_zpoolcompat_DATA = \
%D%/compatibility.d/openzfs-2.0-linux \
%D%/compatibility.d/openzfs-2.1-freebsd \
%D%/compatibility.d/openzfs-2.1-linux \
+ %D%/compatibility.d/openzfs-2.2 \
%D%/compatibility.d/openzfsonosx-1.7.0 \
%D%/compatibility.d/openzfsonosx-1.8.1 \
%D%/compatibility.d/openzfsonosx-1.9.3 \
@@ -168,12 +169,20 @@ zpoolcompatlinks = \
"freebsd-11.3 freebsd-12.0" \
"freebsd-11.3 freebsd-12.1" \
"freebsd-11.3 freebsd-12.2" \
+ "freebsd-11.3 freebsd-12.3" \
+ "freebsd-11.3 freebsd-12.4" \
+ "openzfs-2.1-freebsd freebsd-13.0" \
+ "openzfs-2.1-freebsd freebsd-13.1" \
+ "openzfs-2.1-freebsd freebsd-13.2" \
"freebsd-11.3 freenas-11.3" \
"freenas-11.0 freenas-11.1" \
"openzfsonosx-1.9.3 openzfsonosx-1.9.4" \
"openzfs-2.0-freebsd truenas-12.0" \
"zol-0.7 ubuntu-18.04" \
- "zol-0.8 ubuntu-20.04"
+ "zol-0.8 ubuntu-20.04" \
+ "openzfs-2.1-linux ubuntu-22.04" \
+ "openzfs-2.2 openzfs-2.2-linux" \
+ "openzfs-2.2 openzfs-2.2-freebsd"
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
INSTALL_DATA_HOOKS += zpool-install-data-hook
diff --git a/cmd/zpool/compatibility.d/grub2 b/cmd/zpool/compatibility.d/grub2
index 4e8f21362554..6d60e643593b 100644
--- a/cmd/zpool/compatibility.d/grub2
+++ b/cmd/zpool/compatibility.d/grub2
@@ -1,6 +1,9 @@
# Features which are supported by GRUB2
+allocation_classes
async_destroy
+block_cloning
bookmarks
+device_rebuild
embedded_data
empty_bpobj
enabled_txg
@@ -8,5 +11,13 @@ extensible_dataset
filesystem_limits
hole_birth
large_blocks
+livelist
+log_spacemap
lz4_compress
+project_quota
+resilver_defer
spacemap_histogram
+spacemap_v2
+userobj_accounting
+zilsaxattr
+zpool_checkpoint
diff --git a/cmd/zpool/compatibility.d/openzfs-2.2 b/cmd/zpool/compatibility.d/openzfs-2.2
new file mode 100644
index 000000000000..c9491cd8dc42
--- /dev/null
+++ b/cmd/zpool/compatibility.d/openzfs-2.2
@@ -0,0 +1,40 @@
+# Features supported by OpenZFS 2.2 on Linux and FreeBSD
+allocation_classes
+async_destroy
+blake3
+block_cloning
+bookmark_v2
+bookmark_written
+bookmarks
+device_rebuild
+device_removal
+draid
+edonr
+embedded_data
+empty_bpobj
+enabled_txg
+encryption
+extensible_dataset
+filesystem_limits
+head_errlog
+hole_birth
+large_blocks
+large_dnode
+livelist
+log_spacemap
+lz4_compress
+multi_vdev_crash_dump
+obsolete_counts
+project_quota
+redacted_datasets
+redaction_bookmarks
+resilver_defer
+sha512
+skein
+spacemap_histogram
+spacemap_v2
+userobj_accounting
+vdev_zaps_v2
+zilsaxattr
+zpool_checkpoint
+zstd_compress
diff --git a/cmd/zpool/compatibility.d/openzfsonosx-1.8.1 b/cmd/zpool/compatibility.d/openzfsonosx-1.8.1
index 162ff32a7803..125c578344f9 100644
--- a/cmd/zpool/compatibility.d/openzfsonosx-1.8.1
+++ b/cmd/zpool/compatibility.d/openzfsonosx-1.8.1
@@ -6,7 +6,6 @@ edonr
embedded_data
empty_bpobj
enabled_txg
-encryption
extensible_dataset
filesystem_limits
hole_birth
diff --git a/cmd/zpool/os/freebsd/zpool_vdev_os.c b/cmd/zpool/os/freebsd/zpool_vdev_os.c
index 8ebd3e60d5d6..c57c689afa9c 100644
--- a/cmd/zpool/os/freebsd/zpool_vdev_os.c
+++ b/cmd/zpool/os/freebsd/zpool_vdev_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -124,3 +124,24 @@ check_file(const char *file, boolean_t force, boolean_t isspare)
{
return (check_file_generic(file, force, isspare));
}
+
+int
+zpool_power_current_state(zpool_handle_t *zhp, char *vdev)
+{
+
+ (void) zhp;
+ (void) vdev;
+ /* Enclosure slot power not supported on FreeBSD yet */
+ return (-1);
+}
+
+int
+zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on)
+{
+
+ (void) zhp;
+ (void) vdev;
+ (void) turn_on;
+ /* Enclosure slot power not supported on FreeBSD yet */
+ return (ENOTSUP);
+}
diff --git a/cmd/zpool/os/linux/zpool_vdev_os.c b/cmd/zpool/os/linux/zpool_vdev_os.c
index ed157c627db9..f194d28c55a9 100644
--- a/cmd/zpool/os/linux/zpool_vdev_os.c
+++ b/cmd/zpool/os/linux/zpool_vdev_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -416,3 +416,258 @@ check_file(const char *file, boolean_t force, boolean_t isspare)
{
return (check_file_generic(file, force, isspare));
}
+
+/*
+ * Read from a sysfs file and return an allocated string. Removes
+ * the newline from the end of the string if there is one.
+ *
+ * Returns a string on success (which must be freed), or NULL on error.
+ */
+static char *zpool_sysfs_gets(char *path)
+{
+ int fd;
+ struct stat statbuf;
+ char *buf = NULL;
+ ssize_t count = 0;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return (NULL);
+
+ if (fstat(fd, &statbuf) != 0) {
+ close(fd);
+ return (NULL);
+ }
+
+ buf = calloc(statbuf.st_size + 1, sizeof (*buf));
+ if (buf == NULL) {
+ close(fd);
+ return (NULL);
+ }
+
+ /*
+ * Note, we can read less bytes than st_size, and that's ok. Sysfs
+ * files will report their size is 4k even if they only return a small
+ * string.
+ */
+ count = read(fd, buf, statbuf.st_size);
+ if (count < 0) {
+ /* Error doing read() or we overran the buffer */
+ close(fd);
+ free(buf);
+ return (NULL);
+ }
+
+ /* Remove trailing newline */
+ if (count > 0 && buf[count - 1] == '\n')
+ buf[count - 1] = 0;
+
+ close(fd);
+
+ return (buf);
+}
+
+/*
+ * Write a string to a sysfs file.
+ *
+ * Returns 0 on success, non-zero otherwise.
+ */
+static int zpool_sysfs_puts(char *path, char *str)
+{
+ FILE *file;
+
+ file = fopen(path, "w");
+ if (!file) {
+ return (-1);
+ }
+
+ if (fputs(str, file) < 0) {
+ fclose(file);
+ return (-2);
+ }
+ fclose(file);
+ return (0);
+}
+
+/* Given a vdev nvlist_t, rescan its enclosure sysfs path */
+static void
+rescan_vdev_config_dev_sysfs_path(nvlist_t *vdev_nv)
+{
+ update_vdev_config_dev_sysfs_path(vdev_nv,
+ fnvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH),
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
+}
+
+/*
+ * Given a power string: "on", "off", "1", or "0", return 0 if it's an
+ * off value, 1 if it's an on value, and -1 if the value is unrecognized.
+ */
+static int zpool_power_parse_value(char *str)
+{
+ if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0))
+ return (0);
+
+ if ((strcmp(str, "on") == 0) || (strcmp(str, "1") == 0))
+ return (1);
+
+ return (-1);
+}
+
+/*
+ * Given a vdev string return an allocated string containing the sysfs path to
+ * its power control file. Also do a check if the power control file really
+ * exists and has correct permissions.
+ *
+ * Example returned strings:
+ *
+ * /sys/class/enclosure/0:0:122:0/10/power_status
+ * /sys/bus/pci/slots/10/power
+ *
+ * Returns allocated string on success (which must be freed), NULL on failure.
+ */
+static char *
+zpool_power_sysfs_path(zpool_handle_t *zhp, char *vdev)
+{
+ const char *enc_sysfs_dir = NULL;
+ char *path = NULL;
+ nvlist_t *vdev_nv = zpool_find_vdev(zhp, vdev, NULL, NULL, NULL);
+
+ if (vdev_nv == NULL) {
+ return (NULL);
+ }
+
+ /* Make sure we're getting the updated enclosure sysfs path */
+ rescan_vdev_config_dev_sysfs_path(vdev_nv);
+
+ if (nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
+ &enc_sysfs_dir) != 0) {
+ return (NULL);
+ }
+
+ if (asprintf(&path, "%s/power_status", enc_sysfs_dir) == -1)
+ return (NULL);
+
+ if (access(path, W_OK) != 0) {
+ free(path);
+ path = NULL;
+ /* No HDD 'power_control' file, maybe it's NVMe? */
+ if (asprintf(&path, "%s/power", enc_sysfs_dir) == -1) {
+ return (NULL);
+ }
+
+ if (access(path, R_OK | W_OK) != 0) {
+ /* Not NVMe either */
+ free(path);
+ return (NULL);
+ }
+ }
+
+ return (path);
+}
+
+/*
+ * Given a path to a sysfs power control file, return B_TRUE if you should use
+ * "on/off" words to control it, or B_FALSE otherwise ("0/1" to control).
+ */
+static boolean_t
+zpool_power_use_word(char *sysfs_path)
+{
+ if (strcmp(&sysfs_path[strlen(sysfs_path) - strlen("power_status")],
+ "power_status") == 0) {
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+/*
+ * Check the sysfs power control value for a vdev.
+ *
+ * Returns:
+ * 0 - Power is off
+ * 1 - Power is on
+ * -1 - Error or unsupported
+ */
+int
+zpool_power_current_state(zpool_handle_t *zhp, char *vdev)
+{
+ char *val;
+ int rc;
+
+ char *path = zpool_power_sysfs_path(zhp, vdev);
+ if (path == NULL)
+ return (-1);
+
+ val = zpool_sysfs_gets(path);
+ if (val == NULL) {
+ free(path);
+ return (-1);
+ }
+
+ rc = zpool_power_parse_value(val);
+ free(val);
+ free(path);
+ return (rc);
+}
+
+/*
+ * Turn on or off the slot to a device
+ *
+ * Device path is the full path to the device (like /dev/sda or /dev/sda1).
+ *
+ * Return code:
+ * 0: Success
+ * ENOTSUP: Power control not supported for OS
+ * EBADSLT: Couldn't read current power state
+ * ENOENT: No sysfs path to power control
+ * EIO: Couldn't write sysfs power value
+ * EBADE: Sysfs power value didn't change
+ */
+int
+zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on)
+{
+ char *sysfs_path;
+ const char *val;
+ int rc;
+ int timeout_ms;
+
+ rc = zpool_power_current_state(zhp, vdev);
+ if (rc == -1) {
+ return (EBADSLT);
+ }
+
+ /* Already correct value? */
+ if (rc == (int)turn_on)
+ return (0);
+
+ sysfs_path = zpool_power_sysfs_path(zhp, vdev);
+ if (sysfs_path == NULL)
+ return (ENOENT);
+
+ if (zpool_power_use_word(sysfs_path)) {
+ val = turn_on ? "on" : "off";
+ } else {
+ val = turn_on ? "1" : "0";
+ }
+
+ rc = zpool_sysfs_puts(sysfs_path, (char *)val);
+
+ free(sysfs_path);
+ if (rc != 0) {
+ return (EIO);
+ }
+
+ /*
+ * Wait up to 30 seconds for sysfs power value to change after
+ * writing it.
+ */
+ timeout_ms = zpool_getenv_int("ZPOOL_POWER_ON_SLOT_TIMEOUT_MS", 30000);
+ for (int i = 0; i < MAX(1, timeout_ms / 200); i++) {
+ rc = zpool_power_current_state(zhp, vdev);
+ if (rc == (int)turn_on)
+ return (0); /* success */
+
+ fsleep(0.200); /* 200ms */
+ }
+
+ /* sysfs value never changed */
+ return (EBADE);
+}
diff --git a/cmd/zpool/zpool.d/ses b/cmd/zpool/zpool.d/ses
index 638145c95d47..19ef92ad67b2 100755
--- a/cmd/zpool/zpool.d/ses
+++ b/cmd/zpool/zpool.d/ses
@@ -33,10 +33,18 @@ for i in $scripts ; do
val=""
case $i in
enc)
- val=$(ls "$VDEV_ENC_SYSFS_PATH/../../" 2>/dev/null)
+ if echo "$VDEV_ENC_SYSFS_PATH" | grep -q '/sys/bus/pci/slots' ; then
+ val="$VDEV_ENC_SYSFS_PATH"
+ else
+ val="$(ls """$VDEV_ENC_SYSFS_PATH/../../""" 2>/dev/null)"
+ fi
;;
slot)
- val=$(cat "$VDEV_ENC_SYSFS_PATH/slot" 2>/dev/null)
+ if echo "$VDEV_ENC_SYSFS_PATH" | grep -q '/sys/bus/pci/slots' ; then
+ val="$(basename """$VDEV_ENC_SYSFS_PATH""")"
+ else
+ val="$(cat """$VDEV_ENC_SYSFS_PATH/slot""" 2>/dev/null)"
+ fi
;;
encdev)
val=$(ls "$VDEV_ENC_SYSFS_PATH/../device/scsi_generic" 2>/dev/null)
diff --git a/cmd/zpool/zpool_iter.c b/cmd/zpool/zpool_iter.c
index a08f27992cb0..ae2e9da9108d 100644
--- a/cmd/zpool/zpool_iter.c
+++ b/cmd/zpool/zpool_iter.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -443,37 +443,22 @@ vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
{
int rc;
char *argv[2] = {cmd};
- char *env[5] = {(char *)"PATH=/bin:/sbin:/usr/bin:/usr/sbin"};
+ char **env;
char **lines = NULL;
int lines_cnt = 0;
int i;
- /* Setup our custom environment variables */
- rc = asprintf(&env[1], "VDEV_PATH=%s",
- data->path ? data->path : "");
- if (rc == -1) {
- env[1] = NULL;
+ env = zpool_vdev_script_alloc_env(data->pool, data->path, data->upath,
+ data->vdev_enc_sysfs_path, NULL, NULL);
+ if (env == NULL)
goto out;
- }
-
- rc = asprintf(&env[2], "VDEV_UPATH=%s",
- data->upath ? data->upath : "");
- if (rc == -1) {
- env[2] = NULL;
- goto out;
- }
-
- rc = asprintf(&env[3], "VDEV_ENC_SYSFS_PATH=%s",
- data->vdev_enc_sysfs_path ?
- data->vdev_enc_sysfs_path : "");
- if (rc == -1) {
- env[3] = NULL;
- goto out;
- }
/* Run the command */
rc = libzfs_run_process_get_stdout_nopath(cmd, argv, env, &lines,
&lines_cnt);
+
+ zpool_vdev_script_free_env(env);
+
if (rc != 0)
goto out;
@@ -485,10 +470,6 @@ vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
out:
if (lines != NULL)
libzfs_free_str_array(lines, lines_cnt);
-
- /* Start with i = 1 since env[0] was statically allocated */
- for (i = 1; i < ARRAY_SIZE(env); i++)
- free(env[i]);
}
/*
@@ -564,15 +545,19 @@ for_each_vdev_run_cb(void *zhp_data, nvlist_t *nv, void *cb_vcdl)
{
vdev_cmd_data_list_t *vcdl = cb_vcdl;
vdev_cmd_data_t *data;
- char *path = NULL;
+ const char *path = NULL;
char *vname = NULL;
- char *vdev_enc_sysfs_path = NULL;
+ const char *vdev_enc_sysfs_path = NULL;
int i, match = 0;
zpool_handle_t *zhp = zhp_data;
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
return (1);
+ /* Make sure we're getting the updated enclosure sysfs path */
+ update_vdev_config_dev_sysfs_path(nv, path,
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
+
nvlist_lookup_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
&vdev_enc_sysfs_path);
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index c59829152cb4..300b383af4f6 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
* Copyright (c) 2012 by Cyril Plisko. All rights reserved.
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
@@ -50,6 +50,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <thread_pool.h>
#include <time.h>
#include <unistd.h>
#include <pwd.h>
@@ -126,9 +127,18 @@ static int zpool_do_version(int, char **);
static int zpool_do_wait(int, char **);
+static int zpool_do_help(int argc, char **argv);
+
static zpool_compat_status_t zpool_do_load_compat(
const char *, boolean_t *);
+enum zpool_options {
+ ZPOOL_OPTION_POWER = 1024,
+ ZPOOL_OPTION_ALLOW_INUSE,
+ ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH,
+ ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH
+};
+
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
@@ -345,13 +355,13 @@ get_usage(zpool_help_t idx)
{
switch (idx) {
case HELP_ADD:
- return (gettext("\tadd [-fgLnP] [-o property=value] "
+ return (gettext("\tadd [-afgLnP] [-o property=value] "
"<pool> <vdev> ...\n"));
case HELP_ATTACH:
return (gettext("\tattach [-fsw] [-o property=value] "
"<pool> <device> <new-device>\n"));
case HELP_CLEAR:
- return (gettext("\tclear [-nF] <pool> [device]\n"));
+ return (gettext("\tclear [[--power]|[-nF]] <pool> [device]\n"));
case HELP_CREATE:
return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
"\t [-O file-system-property=value] ... \n"
@@ -387,9 +397,11 @@ get_usage(zpool_help_t idx)
"[-T d|u] [pool] ... \n"
"\t [interval [count]]\n"));
case HELP_OFFLINE:
- return (gettext("\toffline [-f] [-t] <pool> <device> ...\n"));
+ return (gettext("\toffline [--power]|[[-f][-t]] <pool> "
+ "<device> ...\n"));
case HELP_ONLINE:
- return (gettext("\tonline [-e] <pool> <device> ...\n"));
+ return (gettext("\tonline [--power][-e] <pool> <device> "
+ "...\n"));
case HELP_REPLACE:
return (gettext("\treplace [-fsw] [-o property=value] "
"<pool> <device> [new-device]\n"));
@@ -398,18 +410,18 @@ get_usage(zpool_help_t idx)
case HELP_REOPEN:
return (gettext("\treopen [-n] <pool>\n"));
case HELP_INITIALIZE:
- return (gettext("\tinitialize [-c | -s] [-w] <pool> "
+ return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
"[<device> ...]\n"));
case HELP_SCRUB:
- return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n"));
+ return (gettext("\tscrub [-s | -p] [-w] [-e] <pool> ...\n"));
case HELP_RESILVER:
return (gettext("\tresilver <pool> ...\n"));
case HELP_TRIM:
return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
"[<device> ...]\n"));
case HELP_STATUS:
- return (gettext("\tstatus [-c [script1,script2,...]] "
- "[-igLpPstvxD] [-T d|u] [pool] ... \n"
+ return (gettext("\tstatus [--power] [-c [script1,script2,...]] "
+ "[-DegiLpPstvx] [-T d|u] [pool] ...\n"
"\t [interval [count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
@@ -421,7 +433,8 @@ get_usage(zpool_help_t idx)
return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
"<\"all\" | property[,...]> <pool> ...\n"));
case HELP_SET:
- return (gettext("\tset <property=value> <pool> \n"));
+ return (gettext("\tset <property=value> <pool>\n"
+ "\tset <vdev_property=value> <pool> <vdev>\n"));
case HELP_SPLIT:
return (gettext("\tsplit [-gLnPl] [-R altroot] [-o mntopts]\n"
"\t [-o property=value] <pool> <newpool> "
@@ -514,6 +527,77 @@ print_vdev_prop_cb(int prop, void *cb)
}
/*
+ * Given a leaf vdev name like 'L5' return its VDEV_CONFIG_PATH like
+ * '/dev/disk/by-vdev/L5'.
+ */
+static const char *
+vdev_name_to_path(zpool_handle_t *zhp, char *vdev)
+{
+ nvlist_t *vdev_nv = zpool_find_vdev(zhp, vdev, NULL, NULL, NULL);
+ if (vdev_nv == NULL) {
+ return (NULL);
+ }
+ return (fnvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH));
+}
+
+static int
+zpool_power_on(zpool_handle_t *zhp, char *vdev)
+{
+ return (zpool_power(zhp, vdev, B_TRUE));
+}
+
+static int
+zpool_power_on_and_disk_wait(zpool_handle_t *zhp, char *vdev)
+{
+ int rc;
+
+ rc = zpool_power_on(zhp, vdev);
+ if (rc != 0)
+ return (rc);
+
+ zpool_disk_wait(vdev_name_to_path(zhp, vdev));
+
+ return (0);
+}
+
+static int
+zpool_power_on_pool_and_wait_for_devices(zpool_handle_t *zhp)
+{
+ nvlist_t *nv;
+ const char *path = NULL;
+ int rc;
+
+ /* Power up all the devices first */
+ FOR_EACH_REAL_LEAF_VDEV(zhp, nv) {
+ path = fnvlist_lookup_string(nv, ZPOOL_CONFIG_PATH);
+ if (path != NULL) {
+ rc = zpool_power_on(zhp, (char *)path);
+ if (rc != 0) {
+ return (rc);
+ }
+ }
+ }
+
+ /*
+ * Wait for their devices to show up. Since we powered them on
+ * at roughly the same time, they should all come online around
+ * the same time.
+ */
+ FOR_EACH_REAL_LEAF_VDEV(zhp, nv) {
+ path = fnvlist_lookup_string(nv, ZPOOL_CONFIG_PATH);
+ zpool_disk_wait(path);
+ }
+
+ return (0);
+}
+
+static int
+zpool_power_off(zpool_handle_t *zhp, char *vdev)
+{
+ return (zpool_power(zhp, vdev, B_FALSE));
+}
+
+/*
* Display usage message. If we're inside a command, display only the usage for
* that command. Otherwise, iterate over the entire command table and display
* a complete usage message.
@@ -537,6 +621,10 @@ usage(boolean_t requested)
(void) fprintf(fp, "%s",
get_usage(command_table[i].usage));
}
+
+ (void) fprintf(fp,
+ gettext("\nFor further help on a command or topic, "
+ "run: %s\n"), "zpool help [<topic>]");
} else {
(void) fprintf(fp, gettext("usage:\n"));
(void) fprintf(fp, "%s", get_usage(current_command->usage));
@@ -548,7 +636,7 @@ usage(boolean_t requested)
(strcmp(current_command->name, "get") == 0) ||
(strcmp(current_command->name, "list") == 0))) {
- (void) fprintf(fp,
+ (void) fprintf(fp, "%s",
gettext("\nthe following properties are supported:\n"));
(void) fprintf(fp, "\n\t%-19s %s %s\n\n",
@@ -584,12 +672,13 @@ usage(boolean_t requested)
}
/*
- * zpool initialize [-c | -s] [-w] <pool> [<vdev> ...]
+ * zpool initialize [-c | -s | -u] [-w] <pool> [<vdev> ...]
* Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
* if none specified.
*
* -c Cancel. Ends active initializing.
* -s Suspend. Initializing can then be restarted with no flags.
+ * -u Uninitialize. Clears initialization state.
* -w Wait. Blocks until initializing has completed.
*/
int
@@ -605,12 +694,14 @@ zpool_do_initialize(int argc, char **argv)
struct option long_options[] = {
{"cancel", no_argument, NULL, 'c'},
{"suspend", no_argument, NULL, 's'},
+ {"uninit", no_argument, NULL, 'u'},
{"wait", no_argument, NULL, 'w'},
{0, 0, 0, 0}
};
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
- while ((c = getopt_long(argc, argv, "csw", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "csuw", long_options,
+ NULL)) != -1) {
switch (c) {
case 'c':
if (cmd_type != POOL_INITIALIZE_START &&
@@ -630,6 +721,15 @@ zpool_do_initialize(int argc, char **argv)
}
cmd_type = POOL_INITIALIZE_SUSPEND;
break;
+ case 'u':
+ if (cmd_type != POOL_INITIALIZE_START &&
+ cmd_type != POOL_INITIALIZE_UNINIT) {
+ (void) fprintf(stderr, gettext("-u cannot be "
+ "combined with other options\n"));
+ usage(B_FALSE);
+ }
+ cmd_type = POOL_INITIALIZE_UNINIT;
+ break;
case 'w':
wait = B_TRUE;
break;
@@ -656,8 +756,8 @@ zpool_do_initialize(int argc, char **argv)
}
if (wait && (cmd_type != POOL_INITIALIZE_START)) {
- (void) fprintf(stderr, gettext("-w cannot be used with -c or "
- "-s\n"));
+ (void) fprintf(stderr, gettext("-w cannot be used with -c, -s"
+ "or -u\n"));
usage(B_FALSE);
}
@@ -711,7 +811,7 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
for (c = 0; c < children; c++) {
uint64_t is_log = B_FALSE, is_hole = B_FALSE;
- char *class = (char *)"";
+ const char *class = "";
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
&is_hole);
@@ -723,7 +823,7 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&is_log);
if (is_log)
- class = (char *)VDEV_ALLOC_BIAS_LOG;
+ class = VDEV_ALLOC_BIAS_LOG;
(void) nvlist_lookup_string(child[c],
ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
if (strcmp(match, class) != 0)
@@ -810,7 +910,7 @@ add_prop_list(const char *propname, const char *propval, nvlist_t **props,
zpool_prop_t prop = ZPOOL_PROP_INVAL;
nvlist_t *proplist;
const char *normnm;
- char *strval;
+ const char *strval;
if (*props == NULL &&
nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
@@ -908,7 +1008,7 @@ static int
add_prop_list_default(const char *propname, const char *propval,
nvlist_t **props)
{
- char *pval;
+ const char *pval;
if (nvlist_lookup_string(*props, propname, &pval) == 0)
return (0);
@@ -917,8 +1017,9 @@ add_prop_list_default(const char *propname, const char *propval,
}
/*
- * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
+ * zpool add [-afgLnP] [-o property=value] <pool> <vdev> ...
*
+ * -a Disable the ashift validation checks
* -f Force addition of devices, even if they appear in use
* -g Display guid for individual vdev name.
* -L Follow links when resolving vdev path name.
@@ -934,8 +1035,11 @@ add_prop_list_default(const char *propname, const char *propval,
int
zpool_do_add(int argc, char **argv)
{
- boolean_t force = B_FALSE;
+ boolean_t check_replication = B_TRUE;
+ boolean_t check_inuse = B_TRUE;
boolean_t dryrun = B_FALSE;
+ boolean_t check_ashift = B_TRUE;
+ boolean_t force = B_FALSE;
int name_flags = 0;
int c;
nvlist_t *nvroot;
@@ -946,8 +1050,18 @@ zpool_do_add(int argc, char **argv)
nvlist_t *props = NULL;
char *propval;
+ struct option long_options[] = {
+ {"allow-in-use", no_argument, NULL, ZPOOL_OPTION_ALLOW_INUSE},
+ {"allow-replication-mismatch", no_argument, NULL,
+ ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH},
+ {"allow-ashift-mismatch", no_argument, NULL,
+ ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH},
+ {0, 0, 0, 0}
+ };
+
/* check options */
- while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
+ while ((c = getopt_long(argc, argv, "fgLno:P", long_options, NULL))
+ != -1) {
switch (c) {
case 'f':
force = B_TRUE;
@@ -977,6 +1091,15 @@ zpool_do_add(int argc, char **argv)
case 'P':
name_flags |= VDEV_NAME_PATH;
break;
+ case ZPOOL_OPTION_ALLOW_INUSE:
+ check_inuse = B_FALSE;
+ break;
+ case ZPOOL_OPTION_ALLOW_REPLICATION_MISMATCH:
+ check_replication = B_FALSE;
+ break;
+ case ZPOOL_OPTION_ALLOW_ASHIFT_MISMATCH:
+ check_ashift = B_FALSE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -997,6 +1120,19 @@ zpool_do_add(int argc, char **argv)
usage(B_FALSE);
}
+ if (force) {
+ if (!check_inuse || !check_replication || !check_ashift) {
+ (void) fprintf(stderr, gettext("'-f' option is not "
+ "allowed with '--allow-replication-mismatch', "
+ "'--allow-ashift-mismatch', or "
+ "'--allow-in-use'\n"));
+ usage(B_FALSE);
+ }
+ check_inuse = B_FALSE;
+ check_replication = B_FALSE;
+ check_ashift = B_FALSE;
+ }
+
poolname = argv[0];
argc--;
@@ -1027,8 +1163,8 @@ zpool_do_add(int argc, char **argv)
}
/* pass off to make_root_vdev for processing */
- nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
- argc, argv);
+ nvroot = make_root_vdev(zhp, props, !check_inuse,
+ check_replication, B_FALSE, dryrun, argc, argv);
if (nvroot == NULL) {
zpool_close(zhp);
return (1);
@@ -1132,7 +1268,7 @@ zpool_do_add(int argc, char **argv)
ret = 0;
} else {
- ret = (zpool_add(zhp, nvroot) != 0);
+ ret = (zpool_add(zhp, nvroot, check_ashift) != 0);
}
nvlist_free(props);
@@ -1196,6 +1332,7 @@ zpool_do_remove(int argc, char **argv)
return (1);
if (stop && noop) {
+ zpool_close(zhp);
(void) fprintf(stderr, gettext("stop request ignored\n"));
return (0);
}
@@ -1286,7 +1423,6 @@ zpool_do_labelclear(int argc, char **argv)
{
char vdev[MAXPATHLEN];
char *name = NULL;
- struct stat st;
int c, fd = -1, ret = 0;
nvlist_t *config;
pool_state_t state;
@@ -1319,14 +1455,20 @@ zpool_do_labelclear(int argc, char **argv)
usage(B_FALSE);
}
+ (void) strlcpy(vdev, argv[0], sizeof (vdev));
+
/*
- * Check if we were given absolute path and use it as is.
+ * If we cannot open an absolute path, we quit.
* Otherwise if the provided vdev name doesn't point to a file,
* try prepending expected disk paths and partition numbers.
*/
- (void) strlcpy(vdev, argv[0], sizeof (vdev));
- if (vdev[0] != '/' && stat(vdev, &st) != 0) {
+ if ((fd = open(vdev, O_RDWR)) < 0) {
int error;
+ if (vdev[0] == '/') {
+ (void) fprintf(stderr, gettext("failed to open "
+ "%s: %s\n"), vdev, strerror(errno));
+ return (1);
+ }
error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN);
if (error == 0 && zfs_dev_is_whole_disk(vdev)) {
@@ -1334,20 +1476,21 @@ zpool_do_labelclear(int argc, char **argv)
error = ENOENT;
}
- if (error || (stat(vdev, &st) != 0)) {
- (void) fprintf(stderr, gettext(
- "failed to find device %s, try specifying absolute "
- "path instead\n"), argv[0]);
+ if (error || ((fd = open(vdev, O_RDWR)) < 0)) {
+ if (errno == ENOENT) {
+ (void) fprintf(stderr, gettext(
+ "failed to find device %s, try "
+ "specifying absolute path instead\n"),
+ argv[0]);
+ return (1);
+ }
+
+ (void) fprintf(stderr, gettext("failed to open %s:"
+ " %s\n"), vdev, strerror(errno));
return (1);
}
}
- if ((fd = open(vdev, O_RDWR)) < 0) {
- (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
- vdev, strerror(errno));
- return (1);
- }
-
/*
* Flush all dirty pages for the block device. This should not be
* fatal when the device does not support BLKFLSBUF as would be the
@@ -1753,7 +1896,7 @@ zpool_do_create(int argc, char **argv)
*/
for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
char propname[MAXPATHLEN];
- char *propval;
+ const char *propval;
zfeature_info_t *feat = &spa_feature_table[i];
(void) snprintf(propname, sizeof (propname),
@@ -2062,11 +2205,13 @@ typedef struct status_cbdata {
boolean_t cb_explain;
boolean_t cb_first;
boolean_t cb_dedup_stats;
+ boolean_t cb_print_unhealthy;
boolean_t cb_print_status;
boolean_t cb_print_slow_ios;
boolean_t cb_print_vdev_init;
boolean_t cb_print_vdev_trim;
vdev_cmd_data_list_t *vcdl;
+ boolean_t cb_print_power;
} status_cbdata_t;
/* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */
@@ -2081,7 +2226,7 @@ is_blank_str(const char *str)
/* Print command output lines for specific vdev in a specific pool */
static void
-zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path)
+zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, const char *path)
{
vdev_cmd_data_t *data;
int i, j;
@@ -2145,7 +2290,6 @@ print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
!vs->vs_scan_removing) {
char zbuf[1024];
char tbuf[256];
- struct tm zaction_ts;
time_t t = vs->vs_initialize_action_time;
int initialize_pct = 100;
@@ -2155,8 +2299,8 @@ print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
100 / (vs->vs_initialize_bytes_est + 1));
}
- (void) localtime_r(&t, &zaction_ts);
- (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
+ (void) ctime_r(&t, tbuf);
+ tbuf[24] = 0;
switch (vs->vs_initialize_state) {
case VDEV_INITIALIZE_SUSPENDED:
@@ -2196,7 +2340,6 @@ print_status_trim(vdev_stat_t *vs, boolean_t verbose)
!vs->vs_scan_removing) {
char zbuf[1024];
char tbuf[256];
- struct tm zaction_ts;
time_t t = vs->vs_trim_action_time;
int trim_pct = 100;
@@ -2205,8 +2348,8 @@ print_status_trim(vdev_stat_t *vs, boolean_t verbose)
100 / (vs->vs_trim_bytes_est + 1));
}
- (void) localtime_r(&t, &zaction_ts);
- (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
+ (void) ctime_r(&t, tbuf);
+ tbuf[24] = 0;
switch (vs->vs_trim_state) {
case VDEV_TRIM_SUSPENDED:
@@ -2258,6 +2401,35 @@ health_str_to_color(const char *health)
}
/*
+ * Called for each leaf vdev. Returns 0 if the vdev is healthy.
+ * A vdev is unhealthy if any of the following are true:
+ * 1) there are read, write, or checksum errors,
+ * 2) its state is not ONLINE, or
+ * 3) slow IO reporting was requested (-s) and there are slow IOs.
+ */
+static int
+vdev_health_check_cb(void *hdl_data, nvlist_t *nv, void *data)
+{
+ status_cbdata_t *cb = data;
+ vdev_stat_t *vs;
+ uint_t vsc;
+ (void) hdl_data;
+
+ if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
+ (uint64_t **)&vs, &vsc) != 0)
+ return (1);
+
+ if (vs->vs_checksum_errors || vs->vs_read_errors ||
+ vs->vs_write_errors || vs->vs_state != VDEV_STATE_HEALTHY)
+ return (1);
+
+ if (cb->cb_print_slow_ios && vs->vs_slow_ios)
+ return (1);
+
+ return (0);
+}
+
+/*
* Print out configuration state as requested by status_callback.
*/
static void
@@ -2273,9 +2445,10 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
uint64_t notpresent;
spare_cbdata_t spare_cb;
const char *state;
- char *type;
- char *path = NULL;
- const char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
+ const char *type;
+ const char *path = NULL;
+ const char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL,
+ *scolor = NULL;
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0)
@@ -2302,6 +2475,15 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
state = gettext("AVAIL");
}
+ /*
+ * If '-e' is specified then top-level vdevs and their children
+ * can be pruned if all of their leaves are healthy.
+ */
+ if (cb->cb_print_unhealthy && depth > 0 &&
+ for_each_vdev_in_nvlist(nv, vdev_health_check_cb, cb) == 0) {
+ return;
+ }
+
printf_color(health_str_to_color(state),
"\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
name, state);
@@ -2316,6 +2498,9 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
if (vs->vs_checksum_errors)
ccolor = ANSI_RED;
+ if (vs->vs_slow_ios)
+ scolor = ANSI_BLUE;
+
if (cb->cb_literal) {
fputc(' ', stdout);
printf_color(rcolor, "%5llu",
@@ -2348,9 +2533,30 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
}
if (cb->cb_literal)
- printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
+ printf_color(scolor, " %5llu",
+ (u_longlong_t)vs->vs_slow_ios);
else
- printf(" %5s", rbuf);
+ printf_color(scolor, " %5s", rbuf);
+ }
+ if (cb->cb_print_power) {
+ if (children == 0) {
+ /* Only leaf vdevs have physical slots */
+ switch (zpool_power_current_state(zhp, (char *)
+ fnvlist_lookup_string(nv,
+ ZPOOL_CONFIG_PATH))) {
+ case 0:
+ printf_color(ANSI_RED, " %5s",
+ gettext("off"));
+ break;
+ case 1:
+ printf(" %5s", gettext("on"));
+ break;
+ default:
+ printf(" %5s", "-");
+ }
+ } else {
+ printf(" %5s", "-");
+ }
}
}
@@ -2405,7 +2611,13 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
break;
case VDEV_AUX_ERR_EXCEEDED:
- (void) printf(gettext("too many errors"));
+ if (vs->vs_read_errors + vs->vs_write_errors +
+ vs->vs_checksum_errors == 0 && children == 0 &&
+ vs->vs_slow_ios > 0) {
+ (void) printf(gettext("too many slow I/Os"));
+ } else {
+ (void) printf(gettext("too many errors"));
+ }
break;
case VDEV_AUX_IO_FAILURE:
@@ -2462,7 +2674,14 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
(void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
(uint64_t **)&ps, &c);
- if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
+ /*
+ * If you force fault a drive that's resilvering, its scan stats can
+ * get frozen in time, giving the false impression that it's
+ * being resilvered. That's why we check the state to see if the vdev
+ * is healthy before reporting "resilvering" or "repairing".
+ */
+ if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0 &&
+ vs->vs_state == VDEV_STATE_HEALTHY) {
if (vs->vs_scan_processed != 0) {
(void) printf(gettext(" (%s)"),
(ps->pss_func == POOL_SCAN_RESILVER) ?
@@ -2474,7 +2693,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
/* The top-level vdevs have the rebuild stats */
if (vrs != NULL && vrs->vrs_state == VDEV_REBUILD_ACTIVE &&
- children == 0) {
+ children == 0 && vs->vs_state == VDEV_STATE_HEALTHY) {
if (vs->vs_rebuild_processed != 0) {
(void) printf(gettext(" (resilvering)"));
}
@@ -2535,7 +2754,8 @@ print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
nvlist_t **child;
uint_t c, children;
vdev_stat_t *vs;
- char *type, *vname;
+ const char *type;
+ char *vname;
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
@@ -2663,8 +2883,8 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
for (c = 0; c < children; c++) {
uint64_t is_log = B_FALSE;
- char *bias = NULL;
- char *type = NULL;
+ const char *bias = NULL;
+ const char *type = NULL;
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&is_log);
@@ -2707,7 +2927,7 @@ show_import(nvlist_t *config, boolean_t report_error)
{
uint64_t pool_state;
vdev_stat_t *vs;
- char *name;
+ const char *name;
uint64_t guid;
uint64_t hostid = 0;
const char *msgid;
@@ -2717,7 +2937,7 @@ show_import(nvlist_t *config, boolean_t report_error)
zpool_errata_t errata;
const char *health;
uint_t vsc;
- char *comment;
+ const char *comment;
status_cbdata_t cb = { 0 };
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
@@ -3088,12 +3308,22 @@ zfs_force_import_required(nvlist_t *config)
nvlist_t *nvinfo;
state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
- (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
+ nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
+
+ /*
+ * The hostid on LOAD_INFO comes from the MOS label via
+ * spa_tryimport(). If its not there then we're likely talking to an
+ * older kernel, so use the top one, which will be from the label
+ * discovered in zpool_find_import(), or if a cachefile is in use, the
+ * local hostid.
+ */
+ if (nvlist_lookup_uint64(nvinfo, ZPOOL_CONFIG_HOSTID, &hostid) != 0)
+ (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
+ &hostid);
if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
return (B_TRUE);
- nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
ZPOOL_CONFIG_MMP_STATE);
@@ -3115,6 +3345,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
nvlist_t *props, int flags)
{
int ret = 0;
+ int ms_status = 0;
zpool_handle_t *zhp;
const char *name;
uint64_t version;
@@ -3163,7 +3394,10 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
time_t timestamp = 0;
uint64_t hostid = 0;
- if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
+ if (nvlist_exists(nvinfo, ZPOOL_CONFIG_HOSTNAME))
+ hostname = fnvlist_lookup_string(nvinfo,
+ ZPOOL_CONFIG_HOSTNAME);
+ else if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
hostname = fnvlist_lookup_string(config,
ZPOOL_CONFIG_HOSTNAME);
@@ -3171,7 +3405,10 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
timestamp = fnvlist_lookup_uint64(config,
ZPOOL_CONFIG_TIMESTAMP);
- if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
+ if (nvlist_exists(nvinfo, ZPOOL_CONFIG_HOSTID))
+ hostid = fnvlist_lookup_uint64(nvinfo,
+ ZPOOL_CONFIG_HOSTID);
+ else if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
hostid = fnvlist_lookup_uint64(config,
ZPOOL_CONFIG_HOSTID);
@@ -3204,25 +3441,55 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
ret = 1;
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
- !(flags & ZFS_IMPORT_ONLY) &&
- zpool_enable_datasets(zhp, mntopts, 0) != 0) {
- zpool_close(zhp);
- return (1);
+ !(flags & ZFS_IMPORT_ONLY)) {
+ ms_status = zpool_enable_datasets(zhp, mntopts, 0);
+ if (ms_status == EZFS_SHAREFAILED) {
+ (void) fprintf(stderr, gettext("Import was "
+ "successful, but unable to share some datasets\n"));
+ } else if (ms_status == EZFS_MOUNTFAILED) {
+ (void) fprintf(stderr, gettext("Import was "
+ "successful, but unable to mount some datasets\n"));
+ }
}
zpool_close(zhp);
return (ret);
}
+typedef struct import_parameters {
+ nvlist_t *ip_config;
+ const char *ip_mntopts;
+ nvlist_t *ip_props;
+ int ip_flags;
+ int *ip_err;
+} import_parameters_t;
+
+static void
+do_import_task(void *arg)
+{
+ import_parameters_t *ip = arg;
+ *ip->ip_err |= do_import(ip->ip_config, NULL, ip->ip_mntopts,
+ ip->ip_props, ip->ip_flags);
+ free(ip);
+}
+
+
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)
+ char *orig_name, char *new_name, importargs_t *import)
{
nvlist_t *config = NULL;
nvlist_t *found_config = NULL;
uint64_t pool_state;
+ boolean_t pool_specified = (import->poolname != NULL ||
+ import->guid != 0);
+
+
+ tpool_t *tp = NULL;
+ if (import->do_all) {
+ tp = tpool_create(1, 5 * sysconf(_SC_NPROCESSORS_ONLN),
+ 0, NULL);
+ }
/*
* At this point we have a list of import candidate configs. Even if
@@ -3239,9 +3506,11 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
&pool_state) == 0);
- if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
+ if (!import->do_destroyed &&
+ pool_state == POOL_STATE_DESTROYED)
continue;
- if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
+ if (import->do_destroyed &&
+ pool_state != POOL_STATE_DESTROYED)
continue;
verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
@@ -3250,12 +3519,21 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
if (!pool_specified) {
if (first)
first = B_FALSE;
- else if (!do_all)
+ else if (!import->do_all)
(void) fputc('\n', stdout);
- if (do_all) {
- err |= do_import(config, NULL, mntopts,
- props, flags);
+ if (import->do_all) {
+ import_parameters_t *ip = safe_malloc(
+ sizeof (import_parameters_t));
+
+ ip->ip_config = config;
+ ip->ip_mntopts = mntopts;
+ ip->ip_props = props;
+ ip->ip_flags = flags;
+ ip->ip_err = &err;
+
+ (void) tpool_dispatch(tp, do_import_task,
+ (void *)ip);
} else {
/*
* If we're importing from cachefile, then
@@ -3270,7 +3548,7 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
(void) show_import(config, B_TRUE);
}
} else if (import->poolname != NULL) {
- char *name;
+ const char *name;
/*
* We are searching for a pool based on name.
@@ -3303,6 +3581,10 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
found_config = config;
}
}
+ if (import->do_all) {
+ tpool_wait(tp);
+ tpool_destroy(tp);
+ }
/*
* If we were searching for a specific pool, verify that we found a
@@ -3345,7 +3627,7 @@ name_or_guid_exists(zpool_handle_t *zhp, void *data)
return (0);
if (args->poolname != NULL) {
- char *pool_name;
+ const char *pool_name;
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
&pool_name) == 0);
@@ -3532,7 +3814,6 @@ 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;
- boolean_t pool_specified = B_FALSE;
uint64_t txg = -1ULL;
char *cachefile = NULL;
importargs_t idata = { 0 };
@@ -3731,7 +4012,6 @@ zpool_do_import(int argc, char **argv)
searchname = argv[0];
searchguid = 0;
}
- pool_specified = B_TRUE;
/*
* User specified a name or guid. Ensure it's unique.
@@ -3764,8 +4044,15 @@ zpool_do_import(int argc, char **argv)
idata.cachefile = cachefile;
idata.scan = do_scan;
idata.policy = policy;
+ idata.do_destroyed = do_destroyed;
+ idata.do_all = do_all;
- pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
+ libpc_handle_t lpch = {
+ .lpc_lib_handle = g_zfs,
+ .lpc_ops = &libzfs_config_ops,
+ .lpc_printerr = B_TRUE
+ };
+ pools = zpool_search_import(&lpch, &idata);
if (pools != NULL && pool_exists &&
(argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
@@ -3801,9 +4088,7 @@ zpool_do_import(int argc, char **argv)
}
err = import_pools(pools, props, mntopts, flags,
- argc >= 1 ? argv[0] : NULL,
- argc >= 2 ? argv[1] : NULL,
- do_destroyed, pool_specified, do_all, &idata);
+ argc >= 1 ? argv[0] : NULL, argc >= 2 ? argv[1] : NULL, &idata);
/*
* If we're using the cachefile and we failed to import, then
@@ -3821,12 +4106,11 @@ zpool_do_import(int argc, char **argv)
*/
idata.scan = B_TRUE;
nvlist_free(pools);
- pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
+ pools = zpool_search_import(&lpch, &idata);
err = import_pools(pools, props, mntopts, flags,
- argc >= 1 ? argv[0] : NULL,
- argc >= 2 ? argv[1] : NULL,
- do_destroyed, pool_specified, do_all, &idata);
+ argc >= 1 ? argv[0] : NULL, argc >= 2 ? argv[1] : NULL,
+ &idata);
}
error:
@@ -4200,6 +4484,8 @@ print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
unsigned int namewidth;
const char *title;
+ color_start(ANSI_BOLD);
+
if (cb->cb_flags & IOS_ANYHISTO_M) {
title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
} else if (cb->cb_vdevs.cb_names_count) {
@@ -4233,6 +4519,8 @@ print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
if (cb->vcdl != NULL)
print_cmd_columns(cb->vcdl, 1);
+ color_end();
+
printf("\n");
}
@@ -4242,6 +4530,37 @@ print_iostat_header(iostat_cbdata_t *cb)
print_iostat_header_impl(cb, 0, NULL);
}
+/*
+ * Prints a size string (i.e. 120M) with the suffix ("M") colored
+ * by order of magnitude. Uses column_size to add padding.
+ */
+static void
+print_stat_color(const char *statbuf, unsigned int column_size)
+{
+ fputs(" ", stdout);
+ size_t len = strlen(statbuf);
+ while (len < column_size) {
+ fputc(' ', stdout);
+ column_size--;
+ }
+ if (*statbuf == '0') {
+ color_start(ANSI_GRAY);
+ fputc('0', stdout);
+ } else {
+ for (; *statbuf; statbuf++) {
+ if (*statbuf == 'K') color_start(ANSI_GREEN);
+ else if (*statbuf == 'M') color_start(ANSI_YELLOW);
+ else if (*statbuf == 'G') color_start(ANSI_RED);
+ else if (*statbuf == 'T') color_start(ANSI_BOLD_BLUE);
+ else if (*statbuf == 'P') color_start(ANSI_MAGENTA);
+ else if (*statbuf == 'E') color_start(ANSI_CYAN);
+ fputc(*statbuf, stdout);
+ if (--column_size <= 0)
+ break;
+ }
+ }
+ color_end();
+}
/*
* Display a single statistic.
@@ -4257,7 +4576,7 @@ print_one_stat(uint64_t value, enum zfs_nicenum_format format,
if (scripted)
printf("\t%s", buf);
else
- printf(" %*s", column_size, buf);
+ print_stat_color(buf, column_size);
}
/*
@@ -4776,7 +5095,7 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
}
if (cb->vcdl != NULL) {
- char *path;
+ const char *path;
if (nvlist_lookup_string(newnv, ZPOOL_CONFIG_PATH,
&path) == 0) {
printf(" ");
@@ -4841,13 +5160,13 @@ children:
for (c = 0; c < children; c++) {
uint64_t islog = B_FALSE;
- char *bias = NULL;
- char *type = NULL;
+ const char *bias = NULL;
+ const char *type = NULL;
(void) nvlist_lookup_uint64(newchild[c],
ZPOOL_CONFIG_IS_LOG, &islog);
if (islog) {
- bias = (char *)VDEV_ALLOC_CLASS_LOGS;
+ bias = VDEV_ALLOC_CLASS_LOGS;
} else {
(void) nvlist_lookup_string(newchild[c],
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
@@ -5171,21 +5490,14 @@ get_stat_flags(zpool_list_t *list)
static int
is_vdev_cb(void *zhp_data, nvlist_t *nv, void *cb_data)
{
+ uint64_t guid;
vdev_cbdata_t *cb = cb_data;
- char *name = NULL;
- int ret = 1; /* assume match */
zpool_handle_t *zhp = zhp_data;
- name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags);
-
- if (strcmp(name, cb->cb_names[0])) {
- free(name);
- name = zpool_vdev_name(g_zfs, zhp, nv, VDEV_NAME_GUID);
- ret = (strcmp(name, cb->cb_names[0]) == 0);
- }
- free(name);
+ if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) != 0)
+ return (0);
- return (ret);
+ return (guid == zpool_vdev_path_to_guid(zhp, cb->cb_names[0]));
}
/*
@@ -5341,19 +5653,6 @@ get_interval_count_filter_guids(int *argc, char **argv, float *interval,
}
/*
- * Floating point sleep(). Allows you to pass in a floating point value for
- * seconds.
- */
-static void
-fsleep(float sec)
-{
- struct timespec req;
- req.tv_sec = floor(sec);
- req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
- nanosleep(&req, NULL);
-}
-
-/*
* Terminal height, in rows. Returns -1 if stdout is not connected to a TTY or
* if we were unable to determine its size.
*/
@@ -5416,7 +5715,13 @@ print_zpool_dir_scripts(char *dirpath)
if ((dir = opendir(dirpath)) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir(dir)) != NULL) {
- sprintf(fullpath, "%s/%s", dirpath, ent->d_name);
+ if (snprintf(fullpath, sizeof (fullpath), "%s/%s",
+ dirpath, ent->d_name) >= sizeof (fullpath)) {
+ (void) fprintf(stderr,
+ gettext("internal error: "
+ "ZPOOL_SCRIPTS_PATH too large.\n"));
+ exit(1);
+ }
/* Print the scripts */
if (stat(fullpath, &dir_stat) == 0)
@@ -5466,8 +5771,8 @@ get_namewidth_iostat(zpool_handle_t *zhp, void *data)
* get_namewidth() returns the maximum width of any name in that column
* for any pool/vdev/device line that will be output.
*/
- width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_vdevs.cb_name_flags,
- cb->cb_verbose);
+ width = get_namewidth(zhp, cb->cb_namewidth,
+ cb->cb_vdevs.cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
/*
* The width we are calculating is the width of the header and also the
@@ -5856,6 +6161,7 @@ zpool_do_iostat(int argc, char **argv)
print_iostat_header(&cb);
if (skip) {
+ (void) fflush(stdout);
(void) fsleep(interval);
continue;
}
@@ -5886,18 +6192,13 @@ zpool_do_iostat(int argc, char **argv)
}
- /*
- * Flush the output so that redirection to a file isn't buffered
- * indefinitely.
- */
- (void) fflush(stdout);
-
if (interval == 0)
break;
if (count != 0 && --count == 0)
break;
+ (void) fflush(stdout);
(void) fsleep(interval);
}
@@ -6016,11 +6317,14 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
sizeof (property)) == 0) {
propstr = property;
+ } else if (zfs_prop_user(pl->pl_user_prop) &&
+ zpool_get_userprop(zhp, pl->pl_user_prop, property,
+ sizeof (property), NULL) == 0) {
+ propstr = property;
} else {
propstr = "-";
}
-
/*
* If this is being called in scripted mode, or if this is the
* last column and it is left-justified, don't include a width
@@ -6208,12 +6512,12 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
boolean_t printed = B_FALSE;
for (c = 0; c < children; c++) {
- char *bias = NULL;
- char *type = NULL;
+ const char *bias = NULL;
+ const char *type = NULL;
if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&islog) == 0 && islog) {
- bias = (char *)VDEV_ALLOC_CLASS_LOGS;
+ bias = VDEV_ALLOC_CLASS_LOGS;
} else {
(void) nvlist_lookup_string(child[c],
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
@@ -6298,8 +6602,8 @@ get_namewidth_list(zpool_handle_t *zhp, void *data)
list_cbdata_t *cb = data;
int width;
- width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
- cb->cb_verbose);
+ width = get_namewidth(zhp, cb->cb_namewidth,
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
if (width < 9)
width = 9;
@@ -6417,6 +6721,8 @@ zpool_do_list(int argc, char **argv)
break;
pool_list_free(list);
+
+ (void) fflush(stdout);
(void) fsleep(interval);
}
@@ -6553,9 +6859,17 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing,
rebuild);
- if (ret == 0 && wait)
- ret = zpool_wait(zhp,
- replacing ? ZPOOL_WAIT_REPLACE : ZPOOL_WAIT_RESILVER);
+ if (ret == 0 && wait) {
+ zpool_wait_activity_t activity = ZPOOL_WAIT_RESILVER;
+ char raidz_prefix[] = "raidz";
+ if (replacing) {
+ activity = ZPOOL_WAIT_REPLACE;
+ } else if (strncmp(old_disk,
+ raidz_prefix, strlen(raidz_prefix)) == 0) {
+ activity = ZPOOL_WAIT_RAIDZ_EXPAND;
+ }
+ ret = zpool_wait(zhp, activity);
+ }
nvlist_free(props);
nvlist_free(nvroot);
@@ -6581,17 +6895,21 @@ zpool_do_replace(int argc, char **argv)
}
/*
- * zpool attach [-fsw] [-o property=value] <pool> <device> <new_device>
+ * zpool attach [-fsw] [-o property=value] <pool> <device>|<vdev> <new_device>
*
* -f Force attach, even if <new_device> appears to be in use.
* -s Use sequential instead of healing reconstruction for resilver.
* -o Set property=value.
- * -w Wait for resilvering to complete before returning
+ * -w Wait for resilvering (mirror) or expansion (raidz) to complete
+ * before returning.
*
- * Attach <new_device> to the mirror containing <device>. If <device> is not
- * part of a mirror, then <device> will be transformed into a mirror of
- * <device> and <new_device>. In either case, <new_device> will begin life
- * with a DTL of [0, now], and will immediately begin to resilver itself.
+ * Attach <new_device> to a <device> or <vdev>, where the vdev can be of type
+ * mirror or raidz. If <device> is not part of a mirror, then <device> will
+ * be transformed into a mirror of <device> and <new_device>. When a mirror
+ * is involved, <new_device> will begin life with a DTL of [0, now], and will
+ * immediately begin to resilver itself. For the raidz case, a expansion will
+ * commence and reflow the raidz data across all the disks including the
+ * <new_device>.
*/
int
zpool_do_attach(int argc, char **argv)
@@ -6685,6 +7003,7 @@ zpool_do_split(int argc, char **argv)
char *mntopts = NULL;
splitflags_t flags;
int c, ret = 0;
+ int ms_status = 0;
boolean_t loadkeys = B_FALSE;
zpool_handle_t *zhp;
nvlist_t *config, *props = NULL;
@@ -6821,13 +7140,18 @@ zpool_do_split(int argc, char **argv)
ret = 1;
}
- if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
- zpool_enable_datasets(zhp, mntopts, 0) != 0) {
- ret = 1;
- (void) fprintf(stderr, gettext("Split was successful, but "
- "the datasets could not all be mounted\n"));
- (void) fprintf(stderr, gettext("Try doing '%s' with a "
- "different altroot\n"), "zpool import");
+ if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
+ ms_status = zpool_enable_datasets(zhp, mntopts, 0);
+ if (ms_status == EZFS_SHAREFAILED) {
+ (void) fprintf(stderr, gettext("Split was successful, "
+ "datasets are mounted but sharing of some datasets "
+ "has failed\n"));
+ } else if (ms_status == EZFS_MOUNTFAILED) {
+ (void) fprintf(stderr, gettext("Split was successful"
+ ", but some datasets could not be mounted\n"));
+ (void) fprintf(stderr, gettext("Try doing '%s' with a "
+ "different altroot\n"), "zpool import");
+ }
}
zpool_close(zhp);
nvlist_free(config);
@@ -6837,9 +7161,10 @@ zpool_do_split(int argc, char **argv)
}
-
/*
- * zpool online <pool> <device> ...
+ * zpool online [--power] <pool> <device> ...
+ *
+ * --power: Power on the enclosure slot to the drive (if possible)
*/
int
zpool_do_online(int argc, char **argv)
@@ -6850,13 +7175,21 @@ zpool_do_online(int argc, char **argv)
int ret = 0;
vdev_state_t newstate;
int flags = 0;
+ boolean_t is_power_on = B_FALSE;
+ struct option long_options[] = {
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
+ {0, 0, 0, 0}
+ };
/* check options */
- while ((c = getopt(argc, argv, "e")) != -1) {
+ while ((c = getopt_long(argc, argv, "e", long_options, NULL)) != -1) {
switch (c) {
case 'e':
flags |= ZFS_ONLINE_EXPAND;
break;
+ case ZPOOL_OPTION_POWER:
+ is_power_on = B_TRUE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -6864,6 +7197,9 @@ zpool_do_online(int argc, char **argv)
}
}
+ if (libzfs_envvar_is_set("ZPOOL_AUTO_POWER_ON_SLOT"))
+ is_power_on = B_TRUE;
+
argc -= optind;
argv += optind;
@@ -6883,6 +7219,29 @@ zpool_do_online(int argc, char **argv)
return (1);
for (i = 1; i < argc; i++) {
+ vdev_state_t oldstate;
+ boolean_t avail_spare, l2cache;
+ int rc;
+
+ if (is_power_on) {
+ rc = zpool_power_on_and_disk_wait(zhp, argv[i]);
+ if (rc == ENOTSUP) {
+ (void) fprintf(stderr,
+ gettext("Power control not supported\n"));
+ }
+ if (rc != 0)
+ return (rc);
+ }
+
+ nvlist_t *tgt = zpool_find_vdev(zhp, argv[i], &avail_spare,
+ &l2cache, NULL);
+ if (tgt == NULL) {
+ ret = 1;
+ continue;
+ }
+ uint_t vsc;
+ oldstate = ((vdev_stat_t *)fnvlist_lookup_uint64_array(tgt,
+ ZPOOL_CONFIG_VDEV_STATS, &vsc))->vs_state;
if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
if (newstate != VDEV_STATE_HEALTHY) {
(void) printf(gettext("warning: device '%s' "
@@ -6896,6 +7255,17 @@ zpool_do_online(int argc, char **argv)
(void) printf(gettext("use 'zpool "
"replace' to replace devices "
"that are no longer present\n"));
+ if ((flags & ZFS_ONLINE_EXPAND)) {
+ (void) printf(gettext("%s: failed "
+ "to expand usable space on "
+ "unhealthy device '%s'\n"),
+ (oldstate >= VDEV_STATE_DEGRADED ?
+ "error" : "warning"), argv[i]);
+ if (oldstate >= VDEV_STATE_DEGRADED) {
+ ret = 1;
+ break;
+ }
+ }
}
} else {
ret = 1;
@@ -6908,12 +7278,15 @@ zpool_do_online(int argc, char **argv)
}
/*
- * zpool offline [-ft] <pool> <device> ...
+ * zpool offline [-ft]|[--power] <pool> <device> ...
+ *
*
* -f Force the device into a faulted state.
*
* -t Only take the device off-line temporarily. The offline/faulted
* state will not be persistent across reboots.
+ *
+ * --power Power off the enclosure slot to the drive (if possible)
*/
int
zpool_do_offline(int argc, char **argv)
@@ -6924,9 +7297,15 @@ zpool_do_offline(int argc, char **argv)
int ret = 0;
boolean_t istmp = B_FALSE;
boolean_t fault = B_FALSE;
+ boolean_t is_power_off = B_FALSE;
+
+ struct option long_options[] = {
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
+ {0, 0, 0, 0}
+ };
/* check options */
- while ((c = getopt(argc, argv, "ft")) != -1) {
+ while ((c = getopt_long(argc, argv, "ft", long_options, NULL)) != -1) {
switch (c) {
case 'f':
fault = B_TRUE;
@@ -6934,6 +7313,9 @@ zpool_do_offline(int argc, char **argv)
case 't':
istmp = B_TRUE;
break;
+ case ZPOOL_OPTION_POWER:
+ is_power_off = B_TRUE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -6941,6 +7323,20 @@ zpool_do_offline(int argc, char **argv)
}
}
+ if (is_power_off && fault) {
+ (void) fprintf(stderr,
+ gettext("-0 and -f cannot be used together\n"));
+ usage(B_FALSE);
+ return (1);
+ }
+
+ if (is_power_off && istmp) {
+ (void) fprintf(stderr,
+ gettext("-0 and -t cannot be used together\n"));
+ usage(B_FALSE);
+ return (1);
+ }
+
argc -= optind;
argv += optind;
@@ -6960,8 +7356,22 @@ zpool_do_offline(int argc, char **argv)
return (1);
for (i = 1; i < argc; i++) {
- if (fault) {
- uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]);
+ uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]);
+ if (is_power_off) {
+ /*
+ * Note: we have to power off first, then set REMOVED,
+ * or else zpool_vdev_set_removed_state() returns
+ * EAGAIN.
+ */
+ ret = zpool_power_off(zhp, argv[i]);
+ if (ret != 0) {
+ (void) fprintf(stderr, "%s %s %d\n",
+ gettext("unable to power off slot for"),
+ argv[i], ret);
+ }
+ zpool_vdev_set_removed_state(zhp, guid, VDEV_AUX_NONE);
+
+ } else if (fault) {
vdev_aux_t aux;
if (istmp == B_FALSE) {
/* Force the fault to persist across imports */
@@ -6984,7 +7394,7 @@ zpool_do_offline(int argc, char **argv)
}
/*
- * zpool clear <pool> [device]
+ * zpool clear [-nF]|[--power] <pool> [device]
*
* Clear all errors associated with a pool or a particular device.
*/
@@ -6996,13 +7406,20 @@ zpool_do_clear(int argc, char **argv)
boolean_t dryrun = B_FALSE;
boolean_t do_rewind = B_FALSE;
boolean_t xtreme_rewind = B_FALSE;
+ boolean_t is_power_on = B_FALSE;
uint32_t rewind_policy = ZPOOL_NO_REWIND;
nvlist_t *policy = NULL;
zpool_handle_t *zhp;
char *pool, *device;
+ struct option long_options[] = {
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
+ {0, 0, 0, 0}
+ };
+
/* check options */
- while ((c = getopt(argc, argv, "FnX")) != -1) {
+ while ((c = getopt_long(argc, argv, "FnX", long_options,
+ NULL)) != -1) {
switch (c) {
case 'F':
do_rewind = B_TRUE;
@@ -7013,6 +7430,9 @@ zpool_do_clear(int argc, char **argv)
case 'X':
xtreme_rewind = B_TRUE;
break;
+ case ZPOOL_OPTION_POWER:
+ is_power_on = B_TRUE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -7020,6 +7440,9 @@ zpool_do_clear(int argc, char **argv)
}
}
+ if (libzfs_envvar_is_set("ZPOOL_AUTO_POWER_ON_SLOT"))
+ is_power_on = B_TRUE;
+
argc -= optind;
argv += optind;
@@ -7060,6 +7483,14 @@ zpool_do_clear(int argc, char **argv)
return (1);
}
+ if (is_power_on) {
+ if (device == NULL) {
+ zpool_power_on_pool_and_wait_for_devices(zhp);
+ } else {
+ zpool_power_on_and_disk_wait(zhp, device);
+ }
+ }
+
if (zpool_clear(zhp, device, policy) != 0)
ret = 1;
@@ -7217,8 +7648,9 @@ wait_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool scrub [-s | -p] [-w] <pool> ...
+ * zpool scrub [-s | -p] [-w] [-e] <pool> ...
*
+ * -e Only scrub blocks in the error log.
* -s Stop. Stops any in-progress scrub.
* -p Pause. Pause in-progress scrub.
* -w Wait. Blocks until scrub has completed.
@@ -7234,14 +7666,21 @@ zpool_do_scrub(int argc, char **argv)
cb.cb_type = POOL_SCAN_SCRUB;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ boolean_t is_error_scrub = B_FALSE;
+ boolean_t is_pause = B_FALSE;
+ boolean_t is_stop = B_FALSE;
+
/* check options */
- while ((c = getopt(argc, argv, "spw")) != -1) {
+ while ((c = getopt(argc, argv, "spwe")) != -1) {
switch (c) {
+ case 'e':
+ is_error_scrub = B_TRUE;
+ break;
case 's':
- cb.cb_type = POOL_SCAN_NONE;
+ is_stop = B_TRUE;
break;
case 'p':
- cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
+ is_pause = B_TRUE;
break;
case 'w':
wait = B_TRUE;
@@ -7253,11 +7692,21 @@ zpool_do_scrub(int argc, char **argv)
}
}
- if (cb.cb_type == POOL_SCAN_NONE &&
- cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
- (void) fprintf(stderr, gettext("invalid option combination: "
- "-s and -p are mutually exclusive\n"));
+ if (is_pause && is_stop) {
+ (void) fprintf(stderr, gettext("invalid option "
+ "combination :-s and -p are mutually exclusive\n"));
usage(B_FALSE);
+ } else {
+ if (is_error_scrub)
+ cb.cb_type = POOL_SCAN_ERRORSCRUB;
+
+ if (is_pause) {
+ cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
+ } else if (is_stop) {
+ cb.cb_type = POOL_SCAN_NONE;
+ } else {
+ cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ }
}
if (wait && (cb.cb_type == POOL_SCAN_NONE ||
@@ -7482,17 +7931,81 @@ secs_to_dhms(uint64_t total, char *buf)
}
/*
+ * Print out detailed error scrub status.
+ */
+static void
+print_err_scrub_status(pool_scan_stat_t *ps)
+{
+ time_t start, end, pause;
+ uint64_t total_secs_left;
+ uint64_t secs_left, mins_left, hours_left, days_left;
+ uint64_t examined, to_be_examined;
+
+ if (ps == NULL || ps->pss_error_scrub_func != POOL_SCAN_ERRORSCRUB) {
+ return;
+ }
+
+ (void) printf(gettext(" scrub: "));
+
+ start = ps->pss_error_scrub_start;
+ end = ps->pss_error_scrub_end;
+ pause = ps->pss_pass_error_scrub_pause;
+ examined = ps->pss_error_scrub_examined;
+ to_be_examined = ps->pss_error_scrub_to_be_examined;
+
+ assert(ps->pss_error_scrub_func == POOL_SCAN_ERRORSCRUB);
+
+ if (ps->pss_error_scrub_state == DSS_FINISHED) {
+ total_secs_left = end - start;
+ days_left = total_secs_left / 60 / 60 / 24;
+ hours_left = (total_secs_left / 60 / 60) % 24;
+ mins_left = (total_secs_left / 60) % 60;
+ secs_left = (total_secs_left % 60);
+
+ (void) printf(gettext("scrubbed %llu error blocks in %llu days "
+ "%02llu:%02llu:%02llu on %s"), (u_longlong_t)examined,
+ (u_longlong_t)days_left, (u_longlong_t)hours_left,
+ (u_longlong_t)mins_left, (u_longlong_t)secs_left,
+ ctime(&end));
+
+ return;
+ } else if (ps->pss_error_scrub_state == DSS_CANCELED) {
+ (void) printf(gettext("error scrub canceled on %s"),
+ ctime(&end));
+ return;
+ }
+ assert(ps->pss_error_scrub_state == DSS_ERRORSCRUBBING);
+
+ /* Error scrub is in progress. */
+ if (pause == 0) {
+ (void) printf(gettext("error scrub in progress since %s"),
+ ctime(&start));
+ } else {
+ (void) printf(gettext("error scrub paused since %s"),
+ ctime(&pause));
+ (void) printf(gettext("\terror scrub started on %s"),
+ ctime(&start));
+ }
+
+ double fraction_done = (double)examined / (to_be_examined + examined);
+ (void) printf(gettext("\t%.2f%% done, issued I/O for %llu error"
+ " blocks"), 100 * fraction_done, (u_longlong_t)examined);
+
+ (void) printf("\n");
+}
+
+/*
* Print out detailed scrub status.
*/
static void
print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
{
time_t start, end, pause;
- uint64_t pass_scanned, scanned, pass_issued, issued, total;
+ uint64_t pass_scanned, scanned, pass_issued, issued, total_s, total_i;
uint64_t elapsed, scan_rate, issue_rate;
double fraction_done;
- char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
- char srate_buf[7], irate_buf[7], time_buf[32];
+ char processed_buf[7], scanned_buf[7], issued_buf[7], total_s_buf[7];
+ char total_i_buf[7], srate_buf[7], irate_buf[7], time_buf[32];
printf(" ");
printf_color(ANSI_BOLD, gettext("scan:"));
@@ -7511,19 +8024,20 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf));
- assert(ps->pss_func == POOL_SCAN_SCRUB ||
- ps->pss_func == POOL_SCAN_RESILVER);
+ int is_resilver = ps->pss_func == POOL_SCAN_RESILVER;
+ int is_scrub = ps->pss_func == POOL_SCAN_SCRUB;
+ assert(is_resilver || is_scrub);
/* Scan is finished or canceled. */
if (ps->pss_state == DSS_FINISHED) {
secs_to_dhms(end - start, time_buf);
- if (ps->pss_func == POOL_SCAN_SCRUB) {
+ if (is_scrub) {
(void) printf(gettext("scrub repaired %s "
"in %s with %llu errors on %s"), processed_buf,
time_buf, (u_longlong_t)ps->pss_errors,
ctime(&end));
- } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ } else if (is_resilver) {
(void) printf(gettext("resilvered %s "
"in %s with %llu errors on %s"), processed_buf,
time_buf, (u_longlong_t)ps->pss_errors,
@@ -7531,10 +8045,10 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
}
return;
} else if (ps->pss_state == DSS_CANCELED) {
- if (ps->pss_func == POOL_SCAN_SCRUB) {
+ if (is_scrub) {
(void) printf(gettext("scrub canceled on %s"),
ctime(&end));
- } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ } else if (is_resilver) {
(void) printf(gettext("resilver canceled on %s"),
ctime(&end));
}
@@ -7544,7 +8058,7 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
assert(ps->pss_state == DSS_SCANNING);
/* Scan is in progress. Resilvers can't be paused. */
- if (ps->pss_func == POOL_SCAN_SCRUB) {
+ if (is_scrub) {
if (pause == 0) {
(void) printf(gettext("scrub in progress since %s"),
ctime(&start));
@@ -7554,7 +8068,7 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
(void) printf(gettext("\tscrub started on %s"),
ctime(&start));
}
- } else if (ps->pss_func == POOL_SCAN_RESILVER) {
+ } else if (is_resilver) {
(void) printf(gettext("resilver in progress since %s"),
ctime(&start));
}
@@ -7563,10 +8077,11 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
pass_scanned = ps->pss_pass_exam;
issued = ps->pss_issued;
pass_issued = ps->pss_pass_issued;
- total = ps->pss_to_examine;
+ total_s = ps->pss_to_examine;
+ total_i = ps->pss_to_examine - ps->pss_skipped;
/* we are only done with a block once we have issued the IO for it */
- fraction_done = (double)issued / total;
+ fraction_done = (double)issued / total_i;
/* elapsed time for this pass, rounding up to 1 if it's 0 */
elapsed = time(NULL) - ps->pss_pass_start;
@@ -7575,38 +8090,47 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
scan_rate = pass_scanned / elapsed;
issue_rate = pass_issued / elapsed;
- uint64_t total_secs_left = (issue_rate != 0 && total >= issued) ?
- ((total - issued) / issue_rate) : UINT64_MAX;
- secs_to_dhms(total_secs_left, time_buf);
/* format all of the numbers we will be reporting */
zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf));
zfs_nicebytes(issued, issued_buf, sizeof (issued_buf));
- zfs_nicebytes(total, total_buf, sizeof (total_buf));
- zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
- zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
+ zfs_nicebytes(total_s, total_s_buf, sizeof (total_s_buf));
+ zfs_nicebytes(total_i, total_i_buf, sizeof (total_i_buf));
/* do not print estimated time if we have a paused scrub */
- if (pause == 0) {
- (void) printf(gettext("\t%s scanned at %s/s, "
- "%s issued at %s/s, %s total\n"),
- scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
- } else {
- (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
- scanned_buf, issued_buf, total_buf);
+ (void) printf(gettext("\t%s / %s scanned"), scanned_buf, total_s_buf);
+ if (pause == 0 && scan_rate > 0) {
+ zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
+ (void) printf(gettext(" at %s/s"), srate_buf);
+ }
+ (void) printf(gettext(", %s / %s issued"), issued_buf, total_i_buf);
+ if (pause == 0 && issue_rate > 0) {
+ zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
+ (void) printf(gettext(" at %s/s"), irate_buf);
}
+ (void) printf(gettext("\n"));
- if (ps->pss_func == POOL_SCAN_RESILVER) {
+ if (is_resilver) {
(void) printf(gettext("\t%s resilvered, %.2f%% done"),
processed_buf, 100 * fraction_done);
- } else if (ps->pss_func == POOL_SCAN_SCRUB) {
+ } else if (is_scrub) {
(void) printf(gettext("\t%s repaired, %.2f%% done"),
processed_buf, 100 * fraction_done);
}
if (pause == 0) {
- if (total_secs_left != UINT64_MAX &&
- issue_rate >= 10 * 1024 * 1024) {
+ /*
+ * Only provide an estimate iff:
+ * 1) we haven't yet issued all we expected, and
+ * 2) the issue rate exceeds 10 MB/s, and
+ * 3) it's either:
+ * a) a resilver which has started repairs, or
+ * b) a scrub which has entered the issue phase.
+ */
+ if (total_i >= issued && issue_rate >= 10 * 1024 * 1024 &&
+ ((is_resilver && ps->pss_processed > 0) ||
+ (is_scrub && issued > 0))) {
+ secs_to_dhms((total_i - issued) / issue_rate, time_buf);
(void) printf(gettext(", %s to go\n"), time_buf);
} else {
(void) printf(gettext(", no estimated "
@@ -7618,7 +8142,7 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
}
static void
-print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
+print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, uint_t c, char *vdev_name)
{
if (vrs == NULL || vrs->vrs_state == VDEV_REBUILD_NONE)
return;
@@ -7630,17 +8154,20 @@ print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
uint64_t bytes_scanned = vrs->vrs_bytes_scanned;
uint64_t bytes_issued = vrs->vrs_bytes_issued;
uint64_t bytes_rebuilt = vrs->vrs_bytes_rebuilt;
- uint64_t bytes_est = vrs->vrs_bytes_est;
+ uint64_t bytes_est_s = vrs->vrs_bytes_est;
+ uint64_t bytes_est_i = vrs->vrs_bytes_est;
+ if (c > offsetof(vdev_rebuild_stat_t, vrs_pass_bytes_skipped) / 8)
+ bytes_est_i -= vrs->vrs_pass_bytes_skipped;
uint64_t scan_rate = (vrs->vrs_pass_bytes_scanned /
(vrs->vrs_pass_time_ms + 1)) * 1000;
uint64_t issue_rate = (vrs->vrs_pass_bytes_issued /
(vrs->vrs_pass_time_ms + 1)) * 1000;
double scan_pct = MIN((double)bytes_scanned * 100 /
- (bytes_est + 1), 100);
+ (bytes_est_s + 1), 100);
/* Format all of the numbers we will be reporting */
char bytes_scanned_buf[7], bytes_issued_buf[7];
- char bytes_rebuilt_buf[7], bytes_est_buf[7];
+ char bytes_rebuilt_buf[7], bytes_est_s_buf[7], bytes_est_i_buf[7];
char scan_rate_buf[7], issue_rate_buf[7], time_buf[32];
zfs_nicebytes(bytes_scanned, bytes_scanned_buf,
sizeof (bytes_scanned_buf));
@@ -7648,9 +8175,8 @@ print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
sizeof (bytes_issued_buf));
zfs_nicebytes(bytes_rebuilt, bytes_rebuilt_buf,
sizeof (bytes_rebuilt_buf));
- zfs_nicebytes(bytes_est, bytes_est_buf, sizeof (bytes_est_buf));
- zfs_nicebytes(scan_rate, scan_rate_buf, sizeof (scan_rate_buf));
- zfs_nicebytes(issue_rate, issue_rate_buf, sizeof (issue_rate_buf));
+ zfs_nicebytes(bytes_est_s, bytes_est_s_buf, sizeof (bytes_est_s_buf));
+ zfs_nicebytes(bytes_est_i, bytes_est_i_buf, sizeof (bytes_est_i_buf));
time_t start = vrs->vrs_start_time;
time_t end = vrs->vrs_end_time;
@@ -7673,17 +8199,29 @@ print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
assert(vrs->vrs_state == VDEV_REBUILD_ACTIVE);
- secs_to_dhms(MAX((int64_t)bytes_est - (int64_t)bytes_scanned, 0) /
- MAX(scan_rate, 1), time_buf);
+ (void) printf(gettext("\t%s / %s scanned"), bytes_scanned_buf,
+ bytes_est_s_buf);
+ if (scan_rate > 0) {
+ zfs_nicebytes(scan_rate, scan_rate_buf, sizeof (scan_rate_buf));
+ (void) printf(gettext(" at %s/s"), scan_rate_buf);
+ }
+ (void) printf(gettext(", %s / %s issued"), bytes_issued_buf,
+ bytes_est_i_buf);
+ if (issue_rate > 0) {
+ zfs_nicebytes(issue_rate, issue_rate_buf,
+ sizeof (issue_rate_buf));
+ (void) printf(gettext(" at %s/s"), issue_rate_buf);
+ }
+ (void) printf(gettext("\n"));
- (void) printf(gettext("\t%s scanned at %s/s, %s issued %s/s, "
- "%s total\n"), bytes_scanned_buf, scan_rate_buf,
- bytes_issued_buf, issue_rate_buf, bytes_est_buf);
(void) printf(gettext("\t%s resilvered, %.2f%% done"),
bytes_rebuilt_buf, scan_pct);
if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
- if (scan_rate >= 10 * 1024 * 1024) {
+ if (bytes_est_s >= bytes_scanned &&
+ scan_rate >= 10 * 1024 * 1024) {
+ secs_to_dhms((bytes_est_s - bytes_scanned) / scan_rate,
+ time_buf);
(void) printf(gettext(", %s to go\n"), time_buf);
} else {
(void) printf(gettext(", no estimated "
@@ -7715,7 +8253,7 @@ print_rebuild_status(zpool_handle_t *zhp, nvlist_t *nvroot)
ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) {
char *name = zpool_vdev_name(g_zfs, zhp,
child[c], VDEV_NAME_TYPE_ID);
- print_rebuild_status_impl(vrs, name);
+ print_rebuild_status_impl(vrs, i, name);
free(name);
}
}
@@ -7806,10 +8344,12 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
{
uint64_t rebuild_end_time = 0, resilver_end_time = 0;
boolean_t have_resilver = B_FALSE, have_scrub = B_FALSE;
+ boolean_t have_errorscrub = B_FALSE;
boolean_t active_resilver = B_FALSE;
pool_checkpoint_stat_t *pcs = NULL;
pool_scan_stat_t *ps = NULL;
uint_t c;
+ time_t scrub_start = 0, errorscrub_start = 0;
if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
(uint64_t **)&ps, &c) == 0) {
@@ -7820,14 +8360,23 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
have_resilver = (ps->pss_func == POOL_SCAN_RESILVER);
have_scrub = (ps->pss_func == POOL_SCAN_SCRUB);
+ scrub_start = ps->pss_start_time;
+ if (c > offsetof(pool_scan_stat_t,
+ pss_pass_error_scrub_pause) / 8) {
+ have_errorscrub = (ps->pss_error_scrub_func ==
+ POOL_SCAN_ERRORSCRUB);
+ errorscrub_start = ps->pss_error_scrub_start;
+ }
}
boolean_t active_rebuild = check_rebuilding(nvroot, &rebuild_end_time);
boolean_t have_rebuild = (active_rebuild || (rebuild_end_time > 0));
/* Always print the scrub status when available. */
- if (have_scrub)
+ if (have_scrub && scrub_start > errorscrub_start)
print_scan_scrub_resilver_status(ps);
+ else if (have_errorscrub && errorscrub_start >= scrub_start)
+ print_err_scrub_status(ps);
/*
* When there is an active resilver or rebuild print its status.
@@ -7952,6 +8501,97 @@ print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
}
}
+/*
+ * Print out detailed raidz expansion status.
+ */
+static void
+print_raidz_expand_status(zpool_handle_t *zhp, pool_raidz_expand_stat_t *pres)
+{
+ char copied_buf[7];
+
+ if (pres == NULL || pres->pres_state == DSS_NONE)
+ return;
+
+ /*
+ * Determine name of vdev.
+ */
+ nvlist_t *config = zpool_get_config(zhp, NULL);
+ nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
+ ZPOOL_CONFIG_VDEV_TREE);
+ nvlist_t **child;
+ uint_t children;
+ verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
+ &child, &children) == 0);
+ assert(pres->pres_expanding_vdev < children);
+
+ printf_color(ANSI_BOLD, gettext("expand: "));
+
+ time_t start = pres->pres_start_time;
+ time_t end = pres->pres_end_time;
+ char *vname =
+ zpool_vdev_name(g_zfs, zhp, child[pres->pres_expanding_vdev], 0);
+ zfs_nicenum(pres->pres_reflowed, copied_buf, sizeof (copied_buf));
+
+ /*
+ * Expansion is finished or canceled.
+ */
+ if (pres->pres_state == DSS_FINISHED) {
+ char time_buf[32];
+ secs_to_dhms(end - start, time_buf);
+
+ (void) printf(gettext("expanded %s-%u copied %s in %s, "
+ "on %s"), vname, (int)pres->pres_expanding_vdev,
+ copied_buf, time_buf, ctime((time_t *)&end));
+ } else {
+ char examined_buf[7], total_buf[7], rate_buf[7];
+ uint64_t copied, total, elapsed, secs_left;
+ double fraction_done;
+ uint_t rate;
+
+ assert(pres->pres_state == DSS_SCANNING);
+
+ /*
+ * Expansion is in progress.
+ */
+ (void) printf(gettext(
+ "expansion of %s-%u in progress since %s"),
+ vname, (int)pres->pres_expanding_vdev, ctime(&start));
+
+ copied = pres->pres_reflowed > 0 ? pres->pres_reflowed : 1;
+ total = pres->pres_to_reflow;
+ fraction_done = (double)copied / total;
+
+ /* elapsed time for this pass */
+ elapsed = time(NULL) - pres->pres_start_time;
+ elapsed = elapsed > 0 ? elapsed : 1;
+ rate = copied / elapsed;
+ rate = rate > 0 ? rate : 1;
+ secs_left = (total - copied) / rate;
+
+ zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
+ zfs_nicenum(total, total_buf, sizeof (total_buf));
+ zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
+
+ /*
+ * do not print estimated time if hours_left is more than
+ * 30 days
+ */
+ (void) printf(gettext("\t%s / %s copied at %s/s, %.2f%% done"),
+ examined_buf, total_buf, rate_buf, 100 * fraction_done);
+ if (pres->pres_waiting_for_resilver) {
+ (void) printf(gettext(", paused for resilver or "
+ "clear\n"));
+ } else if (secs_left < (30 * 24 * 3600)) {
+ char time_buf[32];
+ secs_to_dhms(secs_left, time_buf);
+ (void) printf(gettext(", %s to go\n"), time_buf);
+ } else {
+ (void) printf(gettext(
+ ", (copy is slow, no estimated time)\n"));
+ }
+ }
+ free(vname);
+}
static void
print_checkpoint_status(pool_checkpoint_stat_t *pcs)
{
@@ -8410,7 +9050,7 @@ status_callback(zpool_handle_t *zhp, void *data)
printf_color(ANSI_BOLD, gettext("action: "));
printf_color(ANSI_YELLOW, gettext("Make sure the pool's devices"
" are connected, then reboot your system and\n\timport the "
- "pool.\n"));
+ "pool or run 'zpool clear' to resume the pool.\n"));
break;
case ZPOOL_STATUS_IO_FAILURE_WAIT:
@@ -8529,19 +9169,24 @@ status_callback(zpool_handle_t *zhp, void *data)
uint64_t nerr;
nvlist_t **spares, **l2cache;
uint_t nspares, nl2cache;
- pool_checkpoint_stat_t *pcs = NULL;
- pool_removal_stat_t *prs = NULL;
print_scan_status(zhp, nvroot);
+ pool_removal_stat_t *prs = NULL;
(void) nvlist_lookup_uint64_array(nvroot,
ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
print_removal_status(zhp, prs);
+ pool_checkpoint_stat_t *pcs = NULL;
(void) nvlist_lookup_uint64_array(nvroot,
ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
print_checkpoint_status(pcs);
+ pool_raidz_expand_stat_t *pres = NULL;
+ (void) nvlist_lookup_uint64_array(nvroot,
+ ZPOOL_CONFIG_RAIDZ_EXPAND_STATS, (uint64_t **)&pres, &c);
+ print_raidz_expand_status(zhp, pres);
+
cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
cbp->cb_name_flags | VDEV_NAME_TYPE_ID);
if (cbp->cb_namewidth < 10)
@@ -8558,6 +9203,10 @@ status_callback(zpool_handle_t *zhp, void *data)
printf_color(ANSI_BOLD, " %5s", gettext("SLOW"));
}
+ if (cbp->cb_print_power) {
+ printf_color(ANSI_BOLD, " %5s", gettext("POWER"));
+ }
+
if (cbp->vcdl != NULL)
print_cmd_columns(cbp->vcdl, 0);
@@ -8580,37 +9229,19 @@ status_callback(zpool_handle_t *zhp, void *data)
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
&nerr) == 0) {
- nvlist_t *nverrlist = NULL;
-
- /*
- * If the approximate error count is small, get a
- * precise count by fetching the entire log and
- * uniquifying the results.
- */
- if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
- zpool_get_errlog(zhp, &nverrlist) == 0) {
- nvpair_t *elem;
-
- elem = NULL;
- nerr = 0;
- while ((elem = nvlist_next_nvpair(nverrlist,
- elem)) != NULL) {
- nerr++;
- }
- }
- nvlist_free(nverrlist);
-
(void) printf("\n");
-
- if (nerr == 0)
- (void) printf(gettext("errors: No known data "
- "errors\n"));
- else if (!cbp->cb_verbose)
+ if (nerr == 0) {
+ (void) printf(gettext(
+ "errors: No known data errors\n"));
+ } else if (!cbp->cb_verbose) {
+ color_start(ANSI_RED);
(void) printf(gettext("errors: %llu data "
"errors, use '-v' for a list\n"),
(u_longlong_t)nerr);
- else
+ color_end();
+ } else {
print_error_log(zhp);
+ }
}
if (cbp->cb_dedup_stats)
@@ -8624,21 +9255,23 @@ status_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool status [-c [script1,script2,...]] [-igLpPstvx] [-T d|u] [pool] ...
- * [interval [count]]
+ * zpool status [-c [script1,script2,...]] [-DegiLpPstvx] [--power] [-T d|u] ...
+ * [pool] [interval [count]]
*
* -c CMD For each vdev, run command CMD
- * -i Display vdev initialization status.
+ * -D Display dedup status (undocumented)
+ * -e Display only unhealthy vdevs
* -g Display guid for individual vdev name.
+ * -i Display vdev initialization status.
* -L Follow links when resolving vdev path name.
* -p Display values in parsable (exact) format.
* -P Display full path for vdev name.
* -s Display slow IOs column.
- * -v Display complete error logs
- * -x Display only pools with potential problems
- * -D Display dedup status (undocumented)
* -t Display vdev TRIM status.
* -T Display a timestamp in date(1) or Unix format
+ * -v Display complete error logs
+ * -x Display only pools with potential problems
+ * --power Display vdev enclosure slot power status
*
* Describes the health status of all pools or some subset.
*/
@@ -8652,8 +9285,14 @@ zpool_do_status(int argc, char **argv)
status_cbdata_t cb = { 0 };
char *cmd = NULL;
+ struct option long_options[] = {
+ {"power", no_argument, NULL, ZPOOL_OPTION_POWER},
+ {0, 0, 0, 0}
+ };
+
/* check options */
- while ((c = getopt(argc, argv, "c:igLpPsvxDtT:")) != -1) {
+ while ((c = getopt_long(argc, argv, "c:DegiLpPstT:vx", long_options,
+ NULL)) != -1) {
switch (c) {
case 'c':
if (cmd != NULL) {
@@ -8679,12 +9318,18 @@ zpool_do_status(int argc, char **argv)
}
cmd = optarg;
break;
- case 'i':
- cb.cb_print_vdev_init = B_TRUE;
+ case 'D':
+ cb.cb_dedup_stats = B_TRUE;
+ break;
+ case 'e':
+ cb.cb_print_unhealthy = B_TRUE;
break;
case 'g':
cb.cb_name_flags |= VDEV_NAME_GUID;
break;
+ case 'i':
+ cb.cb_print_vdev_init = B_TRUE;
+ break;
case 'L':
cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
break;
@@ -8697,20 +9342,20 @@ zpool_do_status(int argc, char **argv)
case 's':
cb.cb_print_slow_ios = B_TRUE;
break;
+ case 't':
+ cb.cb_print_vdev_trim = B_TRUE;
+ break;
+ case 'T':
+ get_timestamp_arg(*optarg);
+ break;
case 'v':
cb.cb_verbose = B_TRUE;
break;
case 'x':
cb.cb_explain = B_TRUE;
break;
- case 'D':
- cb.cb_dedup_stats = B_TRUE;
- break;
- case 't':
- cb.cb_print_vdev_trim = B_TRUE;
- break;
- case 'T':
- get_timestamp_arg(*optarg);
+ case ZPOOL_OPTION_POWER:
+ cb.cb_print_power = B_TRUE;
break;
case '?':
if (optopt == 'c') {
@@ -8748,7 +9393,6 @@ zpool_do_status(int argc, char **argv)
if (cb.vcdl != NULL)
free_vdev_cmd_data_list(cb.vcdl);
-
if (argc == 0 && cb.cb_count == 0)
(void) fprintf(stderr, gettext("no pools available\n"));
else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
@@ -8763,6 +9407,7 @@ zpool_do_status(int argc, char **argv)
if (count != 0 && --count == 0)
break;
+ (void) fflush(stdout);
(void) fsleep(interval);
}
@@ -8789,7 +9434,7 @@ check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
(*count)++;
}
- zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs);
+ zfs_iter_filesystems_v2(zhp, 0, check_unsupp_fs, unsupp_fs);
zfs_close(zhp);
@@ -9521,7 +10166,8 @@ typedef struct ev_opts {
static void
zpool_do_events_short(nvlist_t *nvl, ev_opts_t *opts)
{
- char ctime_str[26], str[32], *ptr;
+ char ctime_str[26], str[32];
+ const char *ptr;
int64_t *tv;
uint_t n;
@@ -9557,7 +10203,7 @@ zpool_do_events_nvprint(nvlist_t *nvl, int depth)
uint16_t i16;
uint32_t i32;
uint64_t i64;
- char *str;
+ const char *str;
nvlist_t *cnv;
printf(gettext("%*s%s = "), depth, "", name);
@@ -9755,7 +10401,7 @@ zpool_do_events_nvprint(nvlist_t *nvl, int depth)
}
case DATA_TYPE_STRING_ARRAY: {
- char **str;
+ const char **str;
uint_t i, nelem;
(void) nvpair_value_string_array(nvp, &str, &nelem);
@@ -9784,7 +10430,7 @@ zpool_do_events_next(ev_opts_t *opts)
{
nvlist_t *nvl;
int zevent_fd, ret, dropped;
- char *pool;
+ const char *pool;
zevent_fd = open(ZFS_DEV, O_RDWR);
VERIFY(zevent_fd >= 0);
@@ -9933,32 +10579,32 @@ get_callback_vdev(zpool_handle_t *zhp, char *vdevname, void *data)
}
static int
-get_callback_vdev_width_cb(void *zhp_data, nvlist_t *nv, void *data)
+get_callback_vdev_cb(void *zhp_data, nvlist_t *nv, void *data)
{
zpool_handle_t *zhp = zhp_data;
zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
- char *vdevname = zpool_vdev_name(g_zfs, zhp, nv,
- cbp->cb_vdevs.cb_name_flags);
+ char *vdevname;
+ const char *type;
int ret;
- /* Adjust the column widths for the vdev properties */
- ret = vdev_expand_proplist(zhp, vdevname, &cbp->cb_proplist);
-
- return (ret);
-}
+ /*
+ * zpool_vdev_name() transforms the root vdev name (i.e., root-0) to the
+ * pool name for display purposes, which is not desired. Fallback to
+ * zpool_vdev_name() when not dealing with the root vdev.
+ */
+ type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE);
+ if (zhp != NULL && strcmp(type, "root") == 0)
+ vdevname = strdup("root-0");
+ else
+ vdevname = zpool_vdev_name(g_zfs, zhp, nv,
+ cbp->cb_vdevs.cb_name_flags);
-static int
-get_callback_vdev_cb(void *zhp_data, nvlist_t *nv, void *data)
-{
- zpool_handle_t *zhp = zhp_data;
- zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
- char *vdevname = zpool_vdev_name(g_zfs, zhp, nv,
- cbp->cb_vdevs.cb_name_flags);
- int ret;
+ (void) vdev_expand_proplist(zhp, vdevname, &cbp->cb_proplist);
- /* Display the properties */
ret = get_callback_vdev(zhp, vdevname, data);
+ free(vdevname);
+
return (ret);
}
@@ -9966,14 +10612,13 @@ static int
get_callback(zpool_handle_t *zhp, void *data)
{
zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
- char value[MAXNAMELEN];
+ char value[ZFS_MAXPROPLEN];
zprop_source_t srctype;
zprop_list_t *pl;
int vid;
if (cbp->cb_type == ZFS_TYPE_VDEV) {
if (strcmp(cbp->cb_vdevs.cb_names[0], "all-vdevs") == 0) {
- for_each_vdev(zhp, get_callback_vdev_width_cb, data);
for_each_vdev(zhp, get_callback_vdev_cb, data);
} else {
/* Adjust column widths for vdev properties */
@@ -10002,6 +10647,17 @@ get_callback(zpool_handle_t *zhp, void *data)
continue;
if (pl->pl_prop == ZPROP_INVAL &&
+ zfs_prop_user(pl->pl_user_prop)) {
+ srctype = ZPROP_SRC_LOCAL;
+
+ if (zpool_get_userprop(zhp, pl->pl_user_prop,
+ value, sizeof (value), &srctype) != 0)
+ continue;
+
+ zprop_print_one_property(zpool_get_name(zhp),
+ cbp, pl->pl_user_prop, value, srctype,
+ NULL, NULL);
+ } else if (pl->pl_prop == ZPROP_INVAL &&
(zpool_prop_feature(pl->pl_user_prop) ||
zpool_prop_unsupported(pl->pl_user_prop))) {
srctype = ZPROP_SRC_LOCAL;
@@ -10050,6 +10706,7 @@ zpool_do_get(int argc, char **argv)
int ret;
int c, i;
char *propstr = NULL;
+ char *vdev = NULL;
cb.cb_first = B_TRUE;
@@ -10147,10 +10804,17 @@ found:
} else if (are_all_pools(1, argv)) {
/* The first arg is a pool name */
if ((argc == 2 && strcmp(argv[1], "all-vdevs") == 0) ||
+ (argc == 2 && strcmp(argv[1], "root") == 0) ||
are_vdevs_in_pool(argc - 1, argv + 1, argv[0],
&cb.cb_vdevs)) {
+
+ if (strcmp(argv[1], "root") == 0)
+ vdev = strdup("root-0");
+ else
+ vdev = strdup(argv[1]);
+
/* ... and the rest are vdev names */
- cb.cb_vdevs.cb_names = argv + 1;
+ cb.cb_vdevs.cb_names = &vdev;
cb.cb_vdevs.cb_names_count = argc - 1;
cb.cb_type = ZFS_TYPE_VDEV;
argc = 1; /* One pool to process */
@@ -10165,11 +10829,10 @@ found:
}
} else {
/*
- * The first arg isn't a pool name,
+ * The first arg isn't the name of a valid pool.
*/
- fprintf(stderr, gettext("missing pool name.\n"));
- fprintf(stderr, "\n");
- usage(B_FALSE);
+ fprintf(stderr, gettext("Cannot get properties of %s: "
+ "no such pool available.\n"), argv[0]);
return (1);
}
@@ -10195,6 +10858,9 @@ found:
else
zprop_free_list(cb.cb_proplist);
+ if (vdev != NULL)
+ free(vdev);
+
return (ret);
}
@@ -10296,6 +10962,7 @@ zpool_do_set(int argc, char **argv)
{
set_cbdata_t cb = { 0 };
int error;
+ char *vdev = NULL;
current_prop_type = ZFS_TYPE_POOL;
if (argc > 1 && argv[1][0] == '-') {
@@ -10335,31 +11002,39 @@ zpool_do_set(int argc, char **argv)
argc -= 2;
argv += 2;
- if (are_vdevs_in_pool(argc, argv, NULL, &cb.cb_vdevs)) {
- /* Argument is a vdev */
- cb.cb_vdevs.cb_names = argv;
+ /* argv[0] is pool name */
+ if (!is_pool(argv[0])) {
+ (void) fprintf(stderr,
+ gettext("cannot open '%s': is not a pool\n"), argv[0]);
+ return (EINVAL);
+ }
+
+ /* argv[1], when supplied, is vdev name */
+ if (argc == 2) {
+
+ if (strcmp(argv[1], "root") == 0)
+ vdev = strdup("root-0");
+ else
+ vdev = strdup(argv[1]);
+
+ if (!are_vdevs_in_pool(1, &vdev, argv[0], &cb.cb_vdevs)) {
+ (void) fprintf(stderr, gettext(
+ "cannot find '%s' in '%s': device not in pool\n"),
+ vdev, argv[0]);
+ free(vdev);
+ return (EINVAL);
+ }
+ cb.cb_vdevs.cb_names = &vdev;
cb.cb_vdevs.cb_names_count = 1;
cb.cb_type = ZFS_TYPE_VDEV;
- argc = 0; /* No pools to process */
- } else if (are_all_pools(1, argv)) {
- /* The first arg is a pool name */
- if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0],
- &cb.cb_vdevs)) {
- /* 2nd argument is a vdev */
- cb.cb_vdevs.cb_names = argv + 1;
- cb.cb_vdevs.cb_names_count = 1;
- cb.cb_type = ZFS_TYPE_VDEV;
- argc = 1; /* One pool to process */
- } else if (argc > 1) {
- (void) fprintf(stderr,
- gettext("too many pool names\n"));
- usage(B_FALSE);
- }
}
- error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
+ error = for_each_pool(1, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
B_FALSE, set_callback, &cb);
+ if (vdev != NULL)
+ free(vdev);
+
return (error);
}
@@ -10435,7 +11110,7 @@ vdev_any_spare_replacing(nvlist_t *nv)
{
nvlist_t **child;
uint_t c, children;
- char *vdev_type;
+ const char *vdev_type;
(void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &vdev_type);
@@ -10484,8 +11159,9 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
pool_checkpoint_stat_t *pcs = NULL;
pool_scan_stat_t *pss = NULL;
pool_removal_stat_t *prs = NULL;
+ pool_raidz_expand_stat_t *pres = NULL;
const char *const headers[] = {"DISCARD", "FREE", "INITIALIZE",
- "REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM"};
+ "REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM", "RAIDZ_EXPAND"};
int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES];
/* Calculate the width of each column */
@@ -10498,6 +11174,9 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
col_widths[i] = MAX(strlen(headers[i]), 6) + 2;
}
+ if (timestamp_fmt != NODATE)
+ print_timestamp(timestamp_fmt);
+
/* Print header if appropriate */
int term_height = terminal_height();
boolean_t reprint_header = (!wd->wd_headers_once && term_height > 0 &&
@@ -10544,6 +11223,13 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
vdev_activity_top_remaining(nvroot);
}
+ (void) nvlist_lookup_uint64_array(nvroot,
+ ZPOOL_CONFIG_RAIDZ_EXPAND_STATS, (uint64_t **)&pres, &c);
+ if (pres != NULL && pres->pres_state == DSS_SCANNING) {
+ int64_t rem = pres->pres_to_reflow - pres->pres_reflowed;
+ bytes_rem[ZPOOL_WAIT_RAIDZ_EXPAND] = rem;
+ }
+
bytes_rem[ZPOOL_WAIT_INITIALIZE] =
vdev_activity_remaining(nvroot, ZPOOL_WAIT_INITIALIZE);
bytes_rem[ZPOOL_WAIT_TRIM] =
@@ -10565,19 +11251,17 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
if (vdev_any_spare_replacing(nvroot))
bytes_rem[ZPOOL_WAIT_REPLACE] = bytes_rem[ZPOOL_WAIT_RESILVER];
- if (timestamp_fmt != NODATE)
- print_timestamp(timestamp_fmt);
-
for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
char buf[64];
if (!wd->wd_enabled[i])
continue;
- if (wd->wd_exact)
+ if (wd->wd_exact) {
(void) snprintf(buf, sizeof (buf), "%" PRIi64,
bytes_rem[i]);
- else
+ } else {
zfs_nicenum(bytes_rem[i], buf, sizeof (buf));
+ }
if (wd->wd_scripted)
(void) printf(i == 0 ? "%s" : "\t%s", buf);
@@ -10683,7 +11367,8 @@ zpool_do_wait(int argc, char **argv)
for (char *tok; (tok = strsep(&optarg, ",")); ) {
static const char *const col_opts[] = {
"discard", "free", "initialize", "replace",
- "remove", "resilver", "scrub", "trim" };
+ "remove", "resilver", "scrub", "trim",
+ "raidz_expand" };
for (i = 0; i < ARRAY_SIZE(col_opts); ++i)
if (strcmp(tok, col_opts[i]) == 0) {
@@ -10818,6 +11503,25 @@ zpool_do_version(int argc, char **argv)
return (zfs_version_print() != 0);
}
+/* Display documentation */
+static int
+zpool_do_help(int argc, char **argv)
+{
+ char page[MAXNAMELEN];
+ if (argc < 3 || strcmp(argv[2], "zpool") == 0)
+ strcpy(page, "zpool");
+ else if (strcmp(argv[2], "concepts") == 0 ||
+ strcmp(argv[2], "props") == 0)
+ snprintf(page, sizeof (page), "zpool%s", argv[2]);
+ else
+ snprintf(page, sizeof (page), "zpool-%s", argv[2]);
+
+ execlp("man", "man", page, NULL);
+
+ fprintf(stderr, "couldn't run man program: %s", strerror(errno));
+ return (-1);
+}
+
/*
* Do zpool_load_compat() and print error message on failure
*/
@@ -10885,6 +11589,12 @@ main(int argc, char **argv)
if ((strcmp(cmdname, "-V") == 0) || (strcmp(cmdname, "--version") == 0))
return (zpool_do_version(argc, argv));
+ /*
+ * Special case 'help'
+ */
+ if (strcmp(cmdname, "help") == 0)
+ return (zpool_do_help(argc, argv));
+
if ((g_zfs = libzfs_init()) == NULL) {
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
return (1);
diff --git a/cmd/zpool/zpool_util.c b/cmd/zpool/zpool_util.c
index 91dbb8ec4f75..e7ff739e5b49 100644
--- a/cmd/zpool/zpool_util.c
+++ b/cmd/zpool/zpool_util.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/cmd/zpool/zpool_util.h b/cmd/zpool/zpool_util.h
index 583f48cca82a..7f5406f063e1 100644
--- a/cmd/zpool/zpool_util.h
+++ b/cmd/zpool/zpool_util.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -126,6 +126,10 @@ vdev_cmd_data_list_t *all_pools_for_each_vdev_run(int argc, char **argv,
void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
+void free_vdev_cmd_data(vdev_cmd_data_t *data);
+
+int vdev_run_cmd_simple(char *path, char *cmd);
+
int check_device(const char *path, boolean_t force,
boolean_t isspare, boolean_t iswholedisk);
boolean_t check_sector_size_database(char *path, int *sector_size);
@@ -134,6 +138,9 @@ int check_file(const char *file, boolean_t force, boolean_t isspare);
void after_zpool_upgrade(zpool_handle_t *zhp);
int check_file_generic(const char *file, boolean_t force, boolean_t isspare);
+int zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on);
+int zpool_power_current_state(zpool_handle_t *zhp, char *vdev);
+
#ifdef __cplusplus
}
#endif
diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c
index a7ab36d0b497..fbd4b81dfacc 100644
--- a/cmd/zpool/zpool_vdev.c
+++ b/cmd/zpool/zpool_vdev.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -372,6 +372,10 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
+ /* Lookup and add the enclosure sysfs path (if exists) */
+ update_vdev_config_dev_sysfs_path(vdev, path,
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
+
if (strcmp(type, VDEV_TYPE_DISK) == 0)
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
(uint64_t)wholedisk) == 0);
@@ -380,7 +384,7 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
* Override defaults if custom properties are provided.
*/
if (props != NULL) {
- char *value = NULL;
+ const char *value = NULL;
if (nvlist_lookup_string(props,
zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) {
@@ -435,7 +439,7 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
* one general purpose vdev.
*/
typedef struct replication_level {
- char *zprl_type;
+ const char *zprl_type;
uint64_t zprl_children;
uint64_t zprl_parity;
} replication_level_t;
@@ -489,7 +493,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
nvlist_t **child;
uint_t c, children;
nvlist_t *nv;
- char *type;
+ const char *type;
replication_level_t lastrep = {0};
replication_level_t rep;
replication_level_t *ret;
@@ -514,9 +518,14 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
if (is_log)
continue;
- /* Ignore holes introduced by removing aux devices */
+ /*
+ * Ignore holes introduced by removing aux devices, along
+ * with indirect vdevs introduced by previously removed
+ * vdevs.
+ */
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
- if (strcmp(type, VDEV_TYPE_HOLE) == 0)
+ if (strcmp(type, VDEV_TYPE_HOLE) == 0 ||
+ strcmp(type, VDEV_TYPE_INDIRECT) == 0)
continue;
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
@@ -562,10 +571,10 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
vdev_size = -1LL;
for (c = 0; c < children; c++) {
nvlist_t *cnv = child[c];
- char *path;
+ const char *path;
struct stat64 statbuf;
int64_t size = -1LL;
- char *childtype;
+ const char *childtype;
int fd, err;
rep.zprl_children++;
@@ -899,7 +908,7 @@ check_replication(nvlist_t *config, nvlist_t *newroot)
}
static int
-zero_label(char *path)
+zero_label(const char *path)
{
const int size = 4096;
char buf[size];
@@ -931,6 +940,15 @@ zero_label(char *path)
return (0);
}
+static void
+lines_to_stderr(char *lines[], int lines_cnt)
+{
+ int i;
+ for (i = 0; i < lines_cnt; i++) {
+ fprintf(stderr, "%s\n", lines[i]);
+ }
+}
+
/*
* Go through and find any whole disks in the vdev specification, labelling them
* as appropriate. When constructing the vdev spec, we were unable to open this
@@ -942,11 +960,11 @@ zero_label(char *path)
* need to get the devid after we label the disk.
*/
static int
-make_disks(zpool_handle_t *zhp, nvlist_t *nv)
+make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing)
{
nvlist_t **child;
uint_t c, children;
- char *type, *path;
+ const char *type, *path;
char devpath[MAXPATHLEN];
char udevpath[MAXPATHLEN];
uint64_t wholedisk;
@@ -1027,6 +1045,8 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
*/
if (!is_exclusive && !is_spare(NULL, udevpath)) {
char *devnode = strrchr(devpath, '/') + 1;
+ char **lines = NULL;
+ int lines_cnt = 0;
ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
if (ret == 0) {
@@ -1038,9 +1058,27 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
/*
* When labeling a pool the raw device node name
* is provided as it appears under /dev/.
+ *
+ * Note that 'zhp' will be NULL when we're creating a
+ * pool.
*/
- if (zpool_label_disk(g_zfs, zhp, devnode) == -1)
+ if (zpool_prepare_and_label_disk(g_zfs, zhp, devnode,
+ nv, zhp == NULL ? "create" :
+ replacing ? "replace" : "add", &lines,
+ &lines_cnt) != 0) {
+ (void) fprintf(stderr,
+ gettext(
+ "Error preparing/labeling disk.\n"));
+ if (lines_cnt > 0) {
+ (void) fprintf(stderr,
+ gettext("zfs_prepare_disk output:\n"));
+ lines_to_stderr(lines, lines_cnt);
+ }
+
+ libzfs_free_str_array(lines, lines_cnt);
return (-1);
+ }
+ libzfs_free_str_array(lines, lines_cnt);
/*
* Wait for udev to signal the device is available
@@ -1077,19 +1115,19 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
}
for (c = 0; c < children; c++)
- if ((ret = make_disks(zhp, child[c])) != 0)
+ if ((ret = make_disks(zhp, child[c], replacing)) != 0)
return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
&child, &children) == 0)
for (c = 0; c < children; c++)
- if ((ret = make_disks(zhp, child[c])) != 0)
+ if ((ret = make_disks(zhp, child[c], replacing)) != 0)
return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) == 0)
for (c = 0; c < children; c++)
- if ((ret = make_disks(zhp, child[c])) != 0)
+ if ((ret = make_disks(zhp, child[c], replacing)) != 0)
return (ret);
return (0);
@@ -1105,7 +1143,7 @@ is_device_in_use(nvlist_t *config, nvlist_t *nv, boolean_t force,
{
nvlist_t **child;
uint_t c, children;
- char *type, *path;
+ const char *type, *path;
int ret = 0;
char buf[MAXPATHLEN];
uint64_t wholedisk = B_FALSE;
@@ -1324,8 +1362,13 @@ draid_config_by_type(nvlist_t *nv, const char *type, uint64_t children)
return (EINVAL);
nparity = (uint64_t)get_parity(type);
- if (nparity == 0)
+ if (nparity == 0 || nparity > VDEV_DRAID_MAXPARITY) {
+ fprintf(stderr,
+ gettext("invalid dRAID parity level %llu; must be "
+ "between 1 and %d\n"), (u_longlong_t)nparity,
+ VDEV_DRAID_MAXPARITY);
return (EINVAL);
+ }
char *p = (char *)type;
while ((p = strchr(p, ':')) != NULL) {
@@ -1396,14 +1439,6 @@ draid_config_by_type(nvlist_t *nv, const char *type, uint64_t children)
return (EINVAL);
}
- if (nparity == 0 || nparity > VDEV_DRAID_MAXPARITY) {
- fprintf(stderr,
- gettext("invalid dRAID parity level %llu; must be "
- "between 1 and %d\n"), (u_longlong_t)nparity,
- VDEV_DRAID_MAXPARITY);
- return (EINVAL);
- }
-
/*
* Verify the requested number of spares can be satisfied.
* An arbitrary limit of 100 distributed spares is applied.
@@ -1750,7 +1785,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
return (NULL);
}
- if (!flags.dryrun && make_disks(zhp, newroot) != 0) {
+ if (!flags.dryrun && make_disks(zhp, newroot, B_FALSE) != 0) {
nvlist_free(newroot);
return (NULL);
}
@@ -1759,7 +1794,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
verify(nvlist_lookup_nvlist_array(newroot,
ZPOOL_CONFIG_CHILDREN, &child, &children) == 0);
for (c = 0; c < children; c++) {
- char *path;
+ const char *path;
const char *type;
int min, max;
@@ -1871,7 +1906,7 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
/*
* Run through the vdev specification and label any whole disks found.
*/
- if (!dryrun && make_disks(zhp, newroot) != 0) {
+ if (!dryrun && make_disks(zhp, newroot, replacing) != 0) {
nvlist_free(newroot);
return (NULL);
}
diff --git a/cmd/zpool_influxdb/zpool_influxdb.c b/cmd/zpool_influxdb/zpool_influxdb.c
index 251d588d832a..520e56926905 100644
--- a/cmd/zpool_influxdb/zpool_influxdb.c
+++ b/cmd/zpool_influxdb/zpool_influxdb.c
@@ -238,6 +238,7 @@ print_scan_status(nvlist_t *nvroot, const char *pool_name)
print_kv("end_ts", ps->pss_end_time);
print_kv(",errors", ps->pss_errors);
print_kv(",examined", examined);
+ print_kv(",skipped", ps->pss_skipped);
print_kv(",issued", ps->pss_issued);
print_kv(",pass_examined", pass_exam);
print_kv(",pass_issued", ps->pss_pass_issued);
@@ -249,7 +250,6 @@ print_scan_status(nvlist_t *nvroot, const char *pool_name)
print_kv(",remaining_t", remaining_time);
print_kv(",start_ts", ps->pss_start_time);
print_kv(",to_examine", ps->pss_to_examine);
- print_kv(",to_process", ps->pss_to_process);
printf(" %llu\n", (u_longlong_t)timestamp);
return (0);
}
@@ -264,8 +264,8 @@ get_vdev_name(nvlist_t *nvroot, const char *parent_name)
static char vdev_name[256];
uint64_t vdev_id = 0;
- char *vdev_type = (char *)"unknown";
- nvlist_lookup_string(nvroot, ZPOOL_CONFIG_TYPE, &vdev_type);
+ const char *vdev_type = "unknown";
+ (void) nvlist_lookup_string(nvroot, ZPOOL_CONFIG_TYPE, &vdev_type);
if (nvlist_lookup_uint64(
nvroot, ZPOOL_CONFIG_ID, &vdev_id) != 0)
@@ -299,12 +299,12 @@ get_vdev_desc(nvlist_t *nvroot, const char *parent_name)
char vdev_value[MAXPATHLEN];
char *s, *t;
- char *vdev_type = (char *)"unknown";
+ const char *vdev_type = "unknown";
uint64_t vdev_id = UINT64_MAX;
- char *vdev_path = NULL;
- nvlist_lookup_string(nvroot, ZPOOL_CONFIG_TYPE, &vdev_type);
- nvlist_lookup_uint64(nvroot, ZPOOL_CONFIG_ID, &vdev_id);
- nvlist_lookup_string(nvroot, ZPOOL_CONFIG_PATH, &vdev_path);
+ const char *vdev_path = NULL;
+ (void) nvlist_lookup_string(nvroot, ZPOOL_CONFIG_TYPE, &vdev_type);
+ (void) nvlist_lookup_uint64(nvroot, ZPOOL_CONFIG_ID, &vdev_id);
+ (void) nvlist_lookup_string(nvroot, ZPOOL_CONFIG_PATH, &vdev_path);
if (parent_name == NULL) {
s = escape_string(vdev_type);
@@ -687,8 +687,10 @@ print_recursive_stats(stat_printer_f func, nvlist_t *nvroot,
sizeof (vdev_name));
for (c = 0; c < children; c++) {
- print_recursive_stats(func, child[c], pool_name,
+ err = print_recursive_stats(func, child[c], pool_name,
vdev_name, descend);
+ if (err)
+ return (err);
}
}
return (0);
diff --git a/cmd/zstream/Makefile.am b/cmd/zstream/Makefile.am
index 9ae33179e5d6..8506b351165e 100644
--- a/cmd/zstream/Makefile.am
+++ b/cmd/zstream/Makefile.am
@@ -6,6 +6,7 @@ zstream_SOURCES = \
%D%/zstream.h \
%D%/zstream_decompress.c \
%D%/zstream_dump.c \
+ %D%/zstream_recompress.c \
%D%/zstream_redup.c \
%D%/zstream_token.c
diff --git a/cmd/zstream/zstream.c b/cmd/zstream/zstream.c
index eeceba2475ca..b1509c1f29ea 100644
--- a/cmd/zstream/zstream.c
+++ b/cmd/zstream/zstream.c
@@ -42,6 +42,8 @@ zstream_usage(void)
"\n"
"\tzstream decompress [-v] [OBJECT,OFFSET[,TYPE]] ...\n"
"\n"
+ "\tzstream recompress [ -l level] TYPE\n"
+ "\n"
"\tzstream token resume_token\n"
"\n"
"\tzstream redup [-v] FILE | ...\n");
@@ -65,6 +67,8 @@ main(int argc, char *argv[])
return (zstream_do_dump(argc - 1, argv + 1));
} else if (strcmp(subcommand, "decompress") == 0) {
return (zstream_do_decompress(argc - 1, argv + 1));
+ } else if (strcmp(subcommand, "recompress") == 0) {
+ return (zstream_do_recompress(argc - 1, argv + 1));
} else if (strcmp(subcommand, "token") == 0) {
return (zstream_do_token(argc - 1, argv + 1));
} else if (strcmp(subcommand, "redup") == 0) {
diff --git a/cmd/zstream/zstream.h b/cmd/zstream/zstream.h
index 931d4e13fec0..f629a6cdfbab 100644
--- a/cmd/zstream/zstream.h
+++ b/cmd/zstream/zstream.h
@@ -30,6 +30,7 @@ extern void *safe_malloc(size_t size);
extern int zstream_do_redup(int, char *[]);
extern int zstream_do_dump(int, char *[]);
extern int zstream_do_decompress(int argc, char *argv[]);
+extern int zstream_do_recompress(int argc, char *argv[]);
extern int zstream_do_token(int, char *[]);
extern void zstream_usage(void);
diff --git a/cmd/zstream/zstream_decompress.c b/cmd/zstream/zstream_decompress.c
index 4c924e0e10a0..0cef36c0441f 100644
--- a/cmd/zstream/zstream_decompress.c
+++ b/cmd/zstream/zstream_decompress.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -115,7 +115,9 @@ zstream_do_decompress(int argc, char *argv[])
if (errno || *end != '\0')
errx(1, "invalid value for offset");
if (argv[i]) {
- if (0 == strcmp("lz4", argv[i]))
+ if (0 == strcmp("off", argv[i]))
+ type = ZIO_COMPRESS_OFF;
+ else if (0 == strcmp("lz4", argv[i]))
type = ZIO_COMPRESS_LZ4;
else if (0 == strcmp("lzjb", argv[i]))
type = ZIO_COMPRESS_LZJB;
@@ -127,8 +129,8 @@ zstream_do_decompress(int argc, char *argv[])
type = ZIO_COMPRESS_ZSTD;
else {
fprintf(stderr, "Invalid compression type %s.\n"
- "Supported types are lz4, lzjb, gzip, zle, "
- "and zstd\n",
+ "Supported types are off, lz4, lzjb, gzip, "
+ "zle, and zstd\n",
argv[i]);
exit(2);
}
@@ -144,7 +146,7 @@ zstream_do_decompress(int argc, char *argv[])
p = hsearch(e, ENTER);
if (p == NULL)
errx(1, "hsearch");
- p->data = (void*)type;
+ p->data = (void*)(intptr_t)type;
}
if (isatty(STDIN_FILENO)) {
@@ -156,6 +158,8 @@ zstream_do_decompress(int argc, char *argv[])
}
fletcher_4_init();
+ int begin = 0;
+ boolean_t seen = B_FALSE;
while (sfread(drr, sizeof (*drr), stdin) != 0) {
struct drr_write *drrw;
uint64_t payload_size = 0;
@@ -172,8 +176,13 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_BEGIN:
{
ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
+ VERIFY0(begin++);
+ seen = B_TRUE;
+
+ uint32_t sz = drr->drr_payloadlen;
+
+ VERIFY3U(sz, <=, 1U << 28);
- int sz = drr->drr_payloadlen;
if (sz != 0) {
if (sz > bufsz) {
buf = realloc(buf, sz);
@@ -190,6 +199,13 @@ zstream_do_decompress(int argc, char *argv[])
{
struct drr_end *drre = &drr->drr_u.drr_end;
/*
+ * We would prefer to just check --begin == 0, but
+ * replication streams have an end of stream END
+ * record, so we must avoid tripping it.
+ */
+ VERIFY3B(seen, ==, B_TRUE);
+ begin--;
+ /*
* Use the recalculated checksum, unless this is
* the END record of a stream package, which has
* no checksum.
@@ -202,6 +218,7 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_OBJECT:
{
struct drr_object *drro = &drr->drr_u.drr_object;
+ VERIFY3S(begin, ==, 1);
if (drro->drr_bonuslen > 0) {
payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
@@ -213,12 +230,14 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_SPILL:
{
struct drr_spill *drrs = &drr->drr_u.drr_spill;
+ VERIFY3S(begin, ==, 1);
payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
(void) sfread(buf, payload_size, stdin);
break;
}
case DRR_WRITE_BYREF:
+ VERIFY3S(begin, ==, 1);
fprintf(stderr,
"Deduplicated streams are not supported\n");
exit(1);
@@ -226,6 +245,7 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_WRITE:
{
+ VERIFY3S(begin, ==, 1);
drrw = &thedrr.drr_u.drr_write;
payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
ENTRY *p;
@@ -240,6 +260,9 @@ zstream_do_decompress(int argc, char *argv[])
if (p != NULL) {
zio_decompress_func_t *xfunc = NULL;
switch ((enum zio_compress)(intptr_t)p->data) {
+ case ZIO_COMPRESS_OFF:
+ xfunc = NULL;
+ break;
case ZIO_COMPRESS_LZJB:
xfunc = lzjb_decompress;
break;
@@ -258,7 +281,6 @@ zstream_do_decompress(int argc, char *argv[])
default:
assert(B_FALSE);
}
- assert(xfunc != NULL);
/*
@@ -266,12 +288,27 @@ zstream_do_decompress(int argc, char *argv[])
*/
char *lzbuf = safe_calloc(payload_size);
(void) sfread(lzbuf, payload_size, stdin);
- if (0 != xfunc(lzbuf, buf,
+ if (xfunc == NULL) {
+ memcpy(buf, lzbuf, payload_size);
+ drrw->drr_compressiontype =
+ ZIO_COMPRESS_OFF;
+ if (verbose)
+ fprintf(stderr, "Resetting "
+ "compression type to off "
+ "for ino %llu offset "
+ "%llu\n",
+ (u_longlong_t)
+ drrw->drr_object,
+ (u_longlong_t)
+ drrw->drr_offset);
+ } else if (0 != xfunc(lzbuf, buf,
payload_size, payload_size, 0)) {
/*
* The block must not be compressed,
- * possibly because it gets written
- * multiple times in this stream.
+ * at least not with this compression
+ * type, possibly because it gets
+ * written multiple times in this
+ * stream.
*/
warnx("decompression failed for "
"ino %llu offset %llu",
@@ -279,11 +316,16 @@ zstream_do_decompress(int argc, char *argv[])
(u_longlong_t)drrw->drr_offset);
memcpy(buf, lzbuf, payload_size);
} else if (verbose) {
+ drrw->drr_compressiontype =
+ ZIO_COMPRESS_OFF;
fprintf(stderr, "successfully "
"decompressed ino %llu "
"offset %llu\n",
(u_longlong_t)drrw->drr_object,
(u_longlong_t)drrw->drr_offset);
+ } else {
+ drrw->drr_compressiontype =
+ ZIO_COMPRESS_OFF;
}
free(lzbuf);
} else {
@@ -297,6 +339,7 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_WRITE_EMBEDDED:
{
+ VERIFY3S(begin, ==, 1);
struct drr_write_embedded *drrwe =
&drr->drr_u.drr_write_embedded;
payload_size =
@@ -308,6 +351,7 @@ zstream_do_decompress(int argc, char *argv[])
case DRR_FREEOBJECTS:
case DRR_FREE:
case DRR_OBJECT_RANGE:
+ VERIFY3S(begin, ==, 1);
break;
default:
diff --git a/cmd/zstream/zstream_dump.c b/cmd/zstream/zstream_dump.c
index 170d84fed092..9955a1361e8d 100644
--- a/cmd/zstream/zstream_dump.c
+++ b/cmd/zstream/zstream_dump.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -54,10 +54,10 @@
*/
#define DUMP_GROUPING 4
-uint64_t total_stream_len = 0;
-FILE *send_stream = 0;
-boolean_t do_byteswap = B_FALSE;
-boolean_t do_cksum = B_TRUE;
+static uint64_t total_stream_len = 0;
+static FILE *send_stream = 0;
+static boolean_t do_byteswap = B_FALSE;
+static boolean_t do_cksum = B_TRUE;
void *
safe_malloc(size_t size)
@@ -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/zstream/zstream_recompress.c b/cmd/zstream/zstream_recompress.c
new file mode 100644
index 000000000000..8392ef3de72f
--- /dev/null
+++ b/cmd/zstream/zstream_recompress.c
@@ -0,0 +1,376 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2022 Axcient. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2022 by Delphix. All rights reserved.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/zfs_ioctl.h>
+#include <sys/zio_checksum.h>
+#include <sys/zstd/zstd.h>
+#include "zfs_fletcher.h"
+#include "zstream.h"
+
+static int
+dump_record(dmu_replay_record_t *drr, void *payload, int payload_len,
+ zio_cksum_t *zc, int outfd)
+{
+ assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum)
+ == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
+ fletcher_4_incremental_native(drr,
+ offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc);
+ if (drr->drr_type != DRR_BEGIN) {
+ assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.
+ drr_checksum.drr_checksum));
+ drr->drr_u.drr_checksum.drr_checksum = *zc;
+ }
+ fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum,
+ sizeof (zio_cksum_t), zc);
+ if (write(outfd, drr, sizeof (*drr)) == -1)
+ return (errno);
+ if (payload_len != 0) {
+ fletcher_4_incremental_native(payload, payload_len, zc);
+ if (write(outfd, payload, payload_len) == -1)
+ return (errno);
+ }
+ return (0);
+}
+
+int
+zstream_do_recompress(int argc, char *argv[])
+{
+ int bufsz = SPA_MAXBLOCKSIZE;
+ char *buf = safe_malloc(bufsz);
+ dmu_replay_record_t thedrr;
+ dmu_replay_record_t *drr = &thedrr;
+ zio_cksum_t stream_cksum;
+ int c;
+ int level = -1;
+
+ while ((c = getopt(argc, argv, "l:")) != -1) {
+ switch (c) {
+ case 'l':
+ if (sscanf(optarg, "%d", &level) != 0) {
+ fprintf(stderr,
+ "failed to parse level '%s'\n",
+ optarg);
+ zstream_usage();
+ }
+ break;
+ case '?':
+ (void) fprintf(stderr, "invalid option '%c'\n",
+ optopt);
+ zstream_usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ zstream_usage();
+ int type = 0;
+ zio_compress_info_t *cinfo = NULL;
+ if (0 == strcmp(argv[0], "off")) {
+ type = ZIO_COMPRESS_OFF;
+ cinfo = &zio_compress_table[type];
+ } else if (0 == strcmp(argv[0], "inherit") ||
+ 0 == strcmp(argv[0], "empty") ||
+ 0 == strcmp(argv[0], "on")) {
+ // Fall through to invalid compression type case
+ } else {
+ for (int i = 0; i < ZIO_COMPRESS_FUNCTIONS; i++) {
+ if (0 == strcmp(zio_compress_table[i].ci_name,
+ argv[0])) {
+ cinfo = &zio_compress_table[i];
+ type = i;
+ break;
+ }
+ }
+ }
+ if (cinfo == NULL) {
+ fprintf(stderr, "Invalid compression type %s.\n",
+ argv[0]);
+ exit(2);
+ }
+
+ if (cinfo->ci_compress == NULL) {
+ type = 0;
+ cinfo = &zio_compress_table[0];
+ }
+
+ if (isatty(STDIN_FILENO)) {
+ (void) fprintf(stderr,
+ "Error: The send stream is a binary format "
+ "and can not be read from a\n"
+ "terminal. Standard input must be redirected.\n");
+ exit(1);
+ }
+
+ fletcher_4_init();
+ zio_init();
+ zstd_init();
+ int begin = 0;
+ boolean_t seen = B_FALSE;
+ while (sfread(drr, sizeof (*drr), stdin) != 0) {
+ struct drr_write *drrw;
+ uint64_t payload_size = 0;
+
+ /*
+ * We need to regenerate the checksum.
+ */
+ if (drr->drr_type != DRR_BEGIN) {
+ memset(&drr->drr_u.drr_checksum.drr_checksum, 0,
+ sizeof (drr->drr_u.drr_checksum.drr_checksum));
+ }
+
+
+ switch (drr->drr_type) {
+ case DRR_BEGIN:
+ {
+ ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
+ VERIFY0(begin++);
+ seen = B_TRUE;
+
+ uint32_t sz = drr->drr_payloadlen;
+
+ VERIFY3U(sz, <=, 1U << 28);
+
+ if (sz != 0) {
+ if (sz > bufsz) {
+ buf = realloc(buf, sz);
+ if (buf == NULL)
+ err(1, "realloc");
+ bufsz = sz;
+ }
+ (void) sfread(buf, sz, stdin);
+ }
+ payload_size = sz;
+ break;
+ }
+ case DRR_END:
+ {
+ struct drr_end *drre = &drr->drr_u.drr_end;
+ /*
+ * We would prefer to just check --begin == 0, but
+ * replication streams have an end of stream END
+ * record, so we must avoid tripping it.
+ */
+ VERIFY3B(seen, ==, B_TRUE);
+ begin--;
+ /*
+ * Use the recalculated checksum, unless this is
+ * the END record of a stream package, which has
+ * no checksum.
+ */
+ if (!ZIO_CHECKSUM_IS_ZERO(&drre->drr_checksum))
+ drre->drr_checksum = stream_cksum;
+ break;
+ }
+
+ case DRR_OBJECT:
+ {
+ struct drr_object *drro = &drr->drr_u.drr_object;
+ VERIFY3S(begin, ==, 1);
+
+ if (drro->drr_bonuslen > 0) {
+ payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
+ (void) sfread(buf, payload_size, stdin);
+ }
+ break;
+ }
+
+ case DRR_SPILL:
+ {
+ struct drr_spill *drrs = &drr->drr_u.drr_spill;
+ VERIFY3S(begin, ==, 1);
+ payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
+ (void) sfread(buf, payload_size, stdin);
+ break;
+ }
+
+ case DRR_WRITE_BYREF:
+ VERIFY3S(begin, ==, 1);
+ fprintf(stderr,
+ "Deduplicated streams are not supported\n");
+ exit(1);
+ break;
+
+ case DRR_WRITE:
+ {
+ VERIFY3S(begin, ==, 1);
+ drrw = &thedrr.drr_u.drr_write;
+ payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
+ /*
+ * In order to recompress an encrypted block, you have
+ * to decrypt, decompress, recompress, and
+ * re-encrypt. That can be a future enhancement (along
+ * with decryption or re-encryption), but for now we
+ * skip encrypted blocks.
+ */
+ boolean_t encrypted = B_FALSE;
+ for (int i = 0; i < ZIO_DATA_SALT_LEN; i++) {
+ if (drrw->drr_salt[i] != 0) {
+ encrypted = B_TRUE;
+ break;
+ }
+ }
+ if (encrypted) {
+ (void) sfread(buf, payload_size, stdin);
+ break;
+ }
+ if (drrw->drr_compressiontype >=
+ ZIO_COMPRESS_FUNCTIONS) {
+ fprintf(stderr, "Invalid compression type in "
+ "stream: %d\n", drrw->drr_compressiontype);
+ exit(3);
+ }
+ zio_compress_info_t *dinfo =
+ &zio_compress_table[drrw->drr_compressiontype];
+
+ /* Set up buffers to minimize memcpys */
+ char *cbuf, *dbuf;
+ if (cinfo->ci_compress == NULL)
+ dbuf = buf;
+ else
+ dbuf = safe_calloc(bufsz);
+
+ if (dinfo->ci_decompress == NULL)
+ cbuf = dbuf;
+ else
+ cbuf = safe_calloc(payload_size);
+
+ /* Read and decompress the payload */
+ (void) sfread(cbuf, payload_size, stdin);
+ if (dinfo->ci_decompress != NULL) {
+ if (0 != dinfo->ci_decompress(cbuf, dbuf,
+ payload_size, MIN(bufsz,
+ drrw->drr_logical_size), dinfo->ci_level)) {
+ warnx("decompression type %d failed "
+ "for ino %llu offset %llu",
+ type,
+ (u_longlong_t)drrw->drr_object,
+ (u_longlong_t)drrw->drr_offset);
+ exit(4);
+ }
+ payload_size = drrw->drr_logical_size;
+ free(cbuf);
+ }
+
+ /* Recompress the payload */
+ if (cinfo->ci_compress != NULL) {
+ payload_size = P2ROUNDUP(cinfo->ci_compress(
+ dbuf, buf, drrw->drr_logical_size,
+ MIN(payload_size, bufsz), (level == -1 ?
+ cinfo->ci_level : level)),
+ SPA_MINBLOCKSIZE);
+ if (payload_size != drrw->drr_logical_size) {
+ drrw->drr_compressiontype = type;
+ drrw->drr_compressed_size =
+ payload_size;
+ } else {
+ memcpy(buf, dbuf, payload_size);
+ drrw->drr_compressiontype = 0;
+ drrw->drr_compressed_size = 0;
+ }
+ free(dbuf);
+ } else {
+ drrw->drr_compressiontype = type;
+ drrw->drr_compressed_size = 0;
+ }
+ break;
+ }
+
+ case DRR_WRITE_EMBEDDED:
+ {
+ struct drr_write_embedded *drrwe =
+ &drr->drr_u.drr_write_embedded;
+ VERIFY3S(begin, ==, 1);
+ payload_size =
+ P2ROUNDUP((uint64_t)drrwe->drr_psize, 8);
+ (void) sfread(buf, payload_size, stdin);
+ break;
+ }
+
+ case DRR_FREEOBJECTS:
+ case DRR_FREE:
+ case DRR_OBJECT_RANGE:
+ VERIFY3S(begin, ==, 1);
+ break;
+
+ default:
+ (void) fprintf(stderr, "INVALID record type 0x%x\n",
+ drr->drr_type);
+ /* should never happen, so assert */
+ assert(B_FALSE);
+ }
+
+ if (feof(stdout)) {
+ fprintf(stderr, "Error: unexpected end-of-file\n");
+ exit(1);
+ }
+ if (ferror(stdout)) {
+ fprintf(stderr, "Error while reading file: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * We need to recalculate the checksum, and it needs to be
+ * initially zero to do that. BEGIN records don't have
+ * a checksum.
+ */
+ if (drr->drr_type != DRR_BEGIN) {
+ memset(&drr->drr_u.drr_checksum.drr_checksum, 0,
+ sizeof (drr->drr_u.drr_checksum.drr_checksum));
+ }
+ if (dump_record(drr, buf, payload_size,
+ &stream_cksum, STDOUT_FILENO) != 0)
+ break;
+ if (drr->drr_type == DRR_END) {
+ /*
+ * Typically the END record is either the last
+ * thing in the stream, or it is followed
+ * by a BEGIN record (which also zeros the checksum).
+ * However, a stream package ends with two END
+ * records. The last END record's checksum starts
+ * from zero.
+ */
+ ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
+ }
+ }
+ free(buf);
+ fletcher_4_fini();
+ zio_fini();
+ zstd_fini();
+
+ return (0);
+}
diff --git a/cmd/zstream/zstream_redup.c b/cmd/zstream/zstream_redup.c
index 5807fabcecb5..c56a09cee75d 100644
--- a/cmd/zstream/zstream_redup.c
+++ b/cmd/zstream/zstream_redup.c
@@ -222,6 +222,8 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
char *buf = safe_calloc(bufsz);
FILE *ofp = fdopen(infd, "r");
long offset = ftell(ofp);
+ int begin = 0;
+ boolean_t seen = B_FALSE;
while (sfread(drr, sizeof (*drr), ofp) != 0) {
num_records++;
@@ -240,6 +242,8 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
struct drr_begin *drrb = &drr->drr_u.drr_begin;
int fflags;
ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
+ VERIFY0(begin++);
+ seen = B_TRUE;
assert(drrb->drr_magic == DMU_BACKUP_MAGIC);
@@ -250,7 +254,10 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
/* cppcheck-suppress syntaxError */
DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
- int sz = drr->drr_payloadlen;
+ uint32_t sz = drr->drr_payloadlen;
+
+ VERIFY3U(sz, <=, 1U << 28);
+
if (sz != 0) {
if (sz > bufsz) {
free(buf);
@@ -267,6 +274,13 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
{
struct drr_end *drre = &drr->drr_u.drr_end;
/*
+ * We would prefer to just check --begin == 0, but
+ * replication streams have an end of stream END
+ * record, so we must avoid tripping it.
+ */
+ VERIFY3B(seen, ==, B_TRUE);
+ begin--;
+ /*
* Use the recalculated checksum, unless this is
* the END record of a stream package, which has
* no checksum.
@@ -279,6 +293,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
case DRR_OBJECT:
{
struct drr_object *drro = &drr->drr_u.drr_object;
+ VERIFY3S(begin, ==, 1);
if (drro->drr_bonuslen > 0) {
payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
@@ -290,6 +305,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
case DRR_SPILL:
{
struct drr_spill *drrs = &drr->drr_u.drr_spill;
+ VERIFY3S(begin, ==, 1);
payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
(void) sfread(buf, payload_size, ofp);
break;
@@ -299,6 +315,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
{
struct drr_write_byref drrwb =
drr->drr_u.drr_write_byref;
+ VERIFY3S(begin, ==, 1);
num_write_byref_records++;
@@ -334,6 +351,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
case DRR_WRITE:
{
struct drr_write *drrw = &drr->drr_u.drr_write;
+ VERIFY3S(begin, ==, 1);
payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
(void) sfread(buf, payload_size, ofp);
@@ -346,6 +364,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
{
struct drr_write_embedded *drrwe =
&drr->drr_u.drr_write_embedded;
+ VERIFY3S(begin, ==, 1);
payload_size =
P2ROUNDUP((uint64_t)drrwe->drr_psize, 8);
(void) sfread(buf, payload_size, ofp);
@@ -355,6 +374,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
case DRR_FREEOBJECTS:
case DRR_FREE:
case DRR_OBJECT_RANGE:
+ VERIFY3S(begin, ==, 1);
break;
default:
diff --git a/cmd/zstream/zstream_token.c b/cmd/zstream/zstream_token.c
index bedb6893c508..795a372633ef 100644
--- a/cmd/zstream/zstream_token.c
+++ b/cmd/zstream/zstream_token.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -49,6 +49,7 @@ int
zstream_do_token(int argc, char *argv[])
{
char *resume_token = NULL;
+ libzfs_handle_t *hdl;
if (argc < 2) {
(void) fprintf(stderr, "Need to pass the resume token\n");
@@ -57,7 +58,10 @@ zstream_do_token(int argc, char *argv[])
resume_token = argv[1];
- libzfs_handle_t *hdl = libzfs_init();
+ if ((hdl = libzfs_init()) == NULL) {
+ (void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
+ return (1);
+ }
nvlist_t *resume_nvl =
zfs_send_resume_token_to_nvlist(hdl, resume_token);
diff --git a/cmd/ztest.c b/cmd/ztest.c
index b7093ce950b9..b0fea8b3cfb4 100644
--- a/cmd/ztest.c
+++ b/cmd/ztest.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -135,6 +135,7 @@
#include <libnvpair.h>
#include <libzutil.h>
#include <sys/crypto/icp.h>
+#include <sys/zfs_impl.h>
#if (__GLIBC__ && !__UCLIBC__)
#include <execinfo.h> /* for backtrace() */
#endif
@@ -150,6 +151,7 @@ typedef struct ztest_shared_hdr {
uint64_t zh_stats_count;
uint64_t zh_ds_size;
uint64_t zh_ds_count;
+ uint64_t zh_scratch_state_size;
} ztest_shared_hdr_t;
static ztest_shared_hdr_t *ztest_shared_hdr;
@@ -160,6 +162,16 @@ enum ztest_class_state {
ZTEST_VDEV_CLASS_RND
};
+/* Dedicated RAIDZ Expansion test states */
+typedef enum {
+ RAIDZ_EXPAND_NONE, /* Default is none, must opt-in */
+ RAIDZ_EXPAND_REQUESTED, /* The '-X' option was used */
+ RAIDZ_EXPAND_STARTED, /* Testing has commenced */
+ RAIDZ_EXPAND_KILLED, /* Reached the proccess kill */
+ RAIDZ_EXPAND_CHECKED, /* Pool scrub verification done */
+} raidz_expand_test_state_t;
+
+
#define ZO_GVARS_MAX_ARGLEN ((size_t)64)
#define ZO_GVARS_MAX_COUNT ((size_t)10)
@@ -173,6 +185,7 @@ typedef struct ztest_shared_opts {
size_t zo_vdev_size;
int zo_ashift;
int zo_mirrors;
+ int zo_raid_do_expand;
int zo_raid_children;
int zo_raid_parity;
char zo_raid_type[8];
@@ -187,6 +200,7 @@ typedef struct ztest_shared_opts {
uint64_t zo_time;
uint64_t zo_maxloops;
uint64_t zo_metaslab_force_ganging;
+ raidz_expand_test_state_t zo_raidz_expand_test;
int zo_mmp_test;
int zo_special_vdevs;
int zo_dump_dbgmsg;
@@ -248,18 +262,21 @@ static const ztest_shared_opts_t ztest_opts_defaults = {
.zo_metaslab_force_ganging = DEFAULT_FORCE_GANGING,
.zo_special_vdevs = ZTEST_VDEV_CLASS_RND,
.zo_gvars_count = 0,
+ .zo_raidz_expand_test = RAIDZ_EXPAND_NONE,
};
extern uint64_t metaslab_force_ganging;
extern uint64_t metaslab_df_alloc_threshold;
-extern unsigned long zfs_deadman_synctime_ms;
-extern int metaslab_preload_limit;
+extern uint64_t zfs_deadman_synctime_ms;
+extern uint_t metaslab_preload_limit;
extern int zfs_compressed_arc_enabled;
extern int zfs_abd_scatter_enabled;
-extern int dmu_object_alloc_chunk_shift;
+extern uint_t dmu_object_alloc_chunk_shift;
extern boolean_t zfs_force_some_double_word_sm_entries;
extern unsigned long zio_decompress_fail_fraction;
extern unsigned long zfs_reconstruct_indirect_damage_fraction;
+extern uint64_t raidz_expand_max_reflow_bytes;
+extern uint_t raidz_expand_pause_point;
static ztest_shared_opts_t *ztest_shared_opts;
@@ -273,6 +290,12 @@ typedef struct ztest_shared_ds {
static ztest_shared_ds_t *ztest_shared_ds;
#define ZTEST_GET_SHARED_DS(d) (&ztest_shared_ds[d])
+typedef struct ztest_scratch_state {
+ uint64_t zs_raidz_scratch_verify_pause;
+} ztest_shared_scratch_state_t;
+
+static ztest_shared_scratch_state_t *ztest_scratch_state;
+
#define BT_MAGIC 0x123456789abcdefULL
#define MAXFAULTS(zs) \
(MAX((zs)->zs_mirrors, 1) * (ztest_opts.zo_raid_parity + 1) - 1)
@@ -310,9 +333,9 @@ typedef struct bufwad {
* still need to map from object ID to rangelock_t.
*/
typedef enum {
- RL_READER,
- RL_WRITER,
- RL_APPEND
+ ZTRL_READER,
+ ZTRL_WRITER,
+ ZTRL_APPEND
} rl_type_t;
typedef struct rll {
@@ -407,6 +430,7 @@ ztest_func_t ztest_mmp_enable_disable;
ztest_func_t ztest_scrub;
ztest_func_t ztest_dsl_dataset_promote_busy;
ztest_func_t ztest_vdev_attach_detach;
+ztest_func_t ztest_vdev_raidz_attach;
ztest_func_t ztest_vdev_LUN_growth;
ztest_func_t ztest_vdev_add_remove;
ztest_func_t ztest_vdev_class_add;
@@ -423,11 +447,11 @@ ztest_func_t ztest_fletcher;
ztest_func_t ztest_fletcher_incr;
ztest_func_t ztest_verify_dnode_bt;
-uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
-uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
-uint64_t zopt_often = 1ULL * NANOSEC; /* every second */
-uint64_t zopt_sometimes = 10ULL * NANOSEC; /* every 10 seconds */
-uint64_t zopt_rarely = 60ULL * NANOSEC; /* every 60 seconds */
+static uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
+static uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
+static uint64_t zopt_often = 1ULL * NANOSEC; /* every second */
+static uint64_t zopt_sometimes = 10ULL * NANOSEC; /* every 10 seconds */
+static uint64_t zopt_rarely = 60ULL * NANOSEC; /* every 60 seconds */
#define ZTI_INIT(func, iters, interval) \
{ .zi_func = (func), \
@@ -435,7 +459,7 @@ uint64_t zopt_rarely = 60ULL * NANOSEC; /* every 60 seconds */
.zi_interval = (interval), \
.zi_funcname = # func }
-ztest_info_t ztest_info[] = {
+static ztest_info_t ztest_info[] = {
ZTI_INIT(ztest_dmu_read_write, 1, &zopt_always),
ZTI_INIT(ztest_dmu_write_parallel, 10, &zopt_always),
ZTI_INIT(ztest_dmu_object_alloc_free, 1, &zopt_always),
@@ -443,7 +467,7 @@ ztest_info_t ztest_info[] = {
ZTI_INIT(ztest_dmu_commit_callbacks, 1, &zopt_always),
ZTI_INIT(ztest_zap, 30, &zopt_always),
ZTI_INIT(ztest_zap_parallel, 100, &zopt_always),
- ZTI_INIT(ztest_split_pool, 1, &zopt_always),
+ ZTI_INIT(ztest_split_pool, 1, &zopt_sometimes),
ZTI_INIT(ztest_zil_commit, 1, &zopt_incessant),
ZTI_INIT(ztest_zil_remount, 1, &zopt_sometimes),
ZTI_INIT(ztest_dmu_read_write_zcopy, 1, &zopt_often),
@@ -464,6 +488,7 @@ ztest_info_t ztest_info[] = {
ZTI_INIT(ztest_spa_upgrade, 1, &zopt_rarely),
ZTI_INIT(ztest_dsl_dataset_promote_busy, 1, &zopt_rarely),
ZTI_INIT(ztest_vdev_attach_detach, 1, &zopt_sometimes),
+ ZTI_INIT(ztest_vdev_raidz_attach, 1, &zopt_sometimes),
ZTI_INIT(ztest_vdev_LUN_growth, 1, &zopt_rarely),
ZTI_INIT(ztest_vdev_add_remove, 1, &ztest_opts.zo_vdevtime),
ZTI_INIT(ztest_vdev_class_add, 1, &ztest_opts.zo_vdevtime),
@@ -515,7 +540,7 @@ typedef struct ztest_shared {
static char ztest_dev_template[] = "%s/%s.%llua";
static char ztest_aux_template[] = "%s/%s.%s.%llu";
-ztest_shared_t *ztest_shared;
+static ztest_shared_t *ztest_shared;
static spa_t *ztest_spa = NULL;
static ztest_ds_t *ztest_ds;
@@ -744,7 +769,7 @@ static ztest_option_t option_table[] = {
DEFAULT_RAID_CHILDREN, NULL},
{ 'R', "raid-parity", "INTEGER", "Raid parity",
DEFAULT_RAID_PARITY, NULL},
- { 'K', "raid-kind", "raidz|draid|random", "Raid kind",
+ { 'K', "raid-kind", "raidz|eraidz|draid|random", "Raid kind",
NO_DEFAULT, "random"},
{ 'D', "draid-data", "INTEGER", "Number of draid data drives",
DEFAULT_DRAID_DATA, NULL},
@@ -780,6 +805,9 @@ static ztest_option_t option_table[] = {
NO_DEFAULT, NULL},
{ 'C', "vdev-class-state", "on|off|random", "vdev class state",
NO_DEFAULT, "random"},
+ { 'X', "raidz-expansion", NULL,
+ "Perform a dedicated raidz expansion test",
+ NO_DEFAULT, NULL},
{ 'o', "option", "\"OPTION=INTEGER\"",
"Set global variable to an unsigned 32-bit integer value",
NO_DEFAULT, NULL},
@@ -852,7 +880,7 @@ usage(boolean_t requested)
option_table[i].short_opt,
option_table[i].long_opt);
}
- (void) fprintf(fp, " %-40s%s", option,
+ (void) fprintf(fp, " %-43s%s", option,
option_table[i].comment);
if (option_table[i].long_opt_param != NULL) {
@@ -1026,6 +1054,9 @@ process_options(int argc, char **argv)
case 'V':
zo->zo_verbose++;
break;
+ case 'X':
+ zo->zo_raidz_expand_test = RAIDZ_EXPAND_REQUESTED;
+ break;
case 'E':
zo->zo_init = 0;
break;
@@ -1077,9 +1108,28 @@ process_options(int argc, char **argv)
fini_options();
- /* When raid choice is 'random' add a draid pool 50% of the time */
+ /* Force compatible options for raidz expansion run */
+ if (zo->zo_raidz_expand_test == RAIDZ_EXPAND_REQUESTED) {
+ zo->zo_mmp_test = 0;
+ zo->zo_mirrors = 0;
+ zo->zo_vdevs = 1;
+ zo->zo_vdev_size = DEFAULT_VDEV_SIZE * 2;
+ zo->zo_raid_do_expand = B_FALSE;
+ raid_kind = "raidz";
+ }
+
if (strcmp(raid_kind, "random") == 0) {
- raid_kind = (ztest_random(2) == 0) ? "draid" : "raidz";
+ switch (ztest_random(3)) {
+ case 0:
+ raid_kind = "raidz";
+ break;
+ case 1:
+ raid_kind = "eraidz";
+ break;
+ case 2:
+ raid_kind = "draid";
+ break;
+ }
if (ztest_opts.zo_verbose >= 3)
(void) printf("choosing RAID type '%s'\n", raid_kind);
@@ -1118,6 +1168,18 @@ process_options(int argc, char **argv)
(void) strlcpy(zo->zo_raid_type, VDEV_TYPE_DRAID,
sizeof (zo->zo_raid_type));
+ } else if (strcmp(raid_kind, "eraidz") == 0) {
+ /* using eraidz (expandable raidz) */
+ zo->zo_raid_do_expand = B_TRUE;
+
+ /* tests expect top-level to be raidz */
+ zo->zo_mirrors = 0;
+ zo->zo_vdevs = 1;
+
+ /* Make sure parity is less than data columns */
+ zo->zo_raid_parity = MIN(zo->zo_raid_parity,
+ zo->zo_raid_children - 1);
+
} else /* using raidz */ {
ASSERT0(strcmp(raid_kind, "raidz"));
@@ -1133,13 +1195,14 @@ process_options(int argc, char **argv)
const char *invalid_what = "ztest";
char *val = zo->zo_alt_ztest;
if (0 != access(val, X_OK) ||
- (strrchr(val, '/') == NULL && (errno = EINVAL)))
+ (strrchr(val, '/') == NULL && (errno == EINVAL)))
goto invalid;
int dirlen = strrchr(val, '/') - val;
- strncpy(zo->zo_alt_libpath, val, dirlen);
+ strlcpy(zo->zo_alt_libpath, val,
+ MIN(sizeof (zo->zo_alt_libpath), dirlen + 1));
invalid_what = "library path", val = zo->zo_alt_libpath;
- if (strrchr(val, '/') == NULL && (errno = EINVAL))
+ if (strrchr(val, '/') == NULL && (errno == EINVAL))
goto invalid;
*strrchr(val, '/') = '\0';
strlcat(val, "/lib", sizeof (zo->zo_alt_libpath));
@@ -1164,9 +1227,29 @@ ztest_kill(ztest_shared_t *zs)
* Before we kill ourselves, make sure that the config is updated.
* See comment above spa_write_cachefile().
*/
- mutex_enter(&spa_namespace_lock);
- spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE);
- mutex_exit(&spa_namespace_lock);
+ if (raidz_expand_pause_point != RAIDZ_EXPAND_PAUSE_NONE) {
+ if (mutex_tryenter(&spa_namespace_lock)) {
+ spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE,
+ B_FALSE);
+ mutex_exit(&spa_namespace_lock);
+
+ ztest_scratch_state->zs_raidz_scratch_verify_pause =
+ raidz_expand_pause_point;
+ } else {
+ /*
+ * Do not verify scratch object in case if
+ * spa_namespace_lock cannot be acquired,
+ * it can cause deadlock in spa_config_update().
+ */
+ raidz_expand_pause_point = RAIDZ_EXPAND_PAUSE_NONE;
+
+ return;
+ }
+ } else {
+ mutex_enter(&spa_namespace_lock);
+ spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE, B_FALSE);
+ mutex_exit(&spa_namespace_lock);
+ }
(void) raise(SIGKILL);
}
@@ -1543,7 +1626,7 @@ ztest_dmu_objset_own(const char *name, dmu_objset_type_t type,
char *cp = NULL;
char ddname[ZFS_MAX_DATASET_NAME_LEN];
- strcpy(ddname, name);
+ strlcpy(ddname, name, sizeof (ddname));
cp = strchr(ddname, '@');
if (cp != NULL)
*cp = '\0';
@@ -1613,7 +1696,7 @@ ztest_rll_lock(rll_t *rll, rl_type_t type)
{
mutex_enter(&rll->rll_lock);
- if (type == RL_READER) {
+ if (type == ZTRL_READER) {
while (rll->rll_writer != NULL)
(void) cv_wait(&rll->rll_cv, &rll->rll_lock);
rll->rll_readers++;
@@ -1900,7 +1983,7 @@ ztest_log_write(ztest_ds_t *zd, dmu_tx_t *tx, lr_write_t *lr)
if (zil_replaying(zd->zd_zilog, tx))
return;
- if (lr->lr_length > zil_max_log_data(zd->zd_zilog))
+ if (lr->lr_length > zil_max_log_data(zd->zd_zilog, sizeof (lr_write_t)))
write_state = WR_INDIRECT;
itx = zil_itx_create(TX_WRITE,
@@ -2069,7 +2152,7 @@ ztest_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
zap_lookup(os, lr->lr_doid, name, sizeof (object), 1, &object));
ASSERT3U(object, !=, 0);
- ztest_object_lock(zd, object, RL_WRITER);
+ ztest_object_lock(zd, object, ZTRL_WRITER);
VERIFY0(dmu_object_info(os, object, &doi));
@@ -2139,8 +2222,8 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap)
if (bt->bt_magic != BT_MAGIC)
bt = NULL;
- ztest_object_lock(zd, lr->lr_foid, RL_READER);
- rl = ztest_range_lock(zd, lr->lr_foid, offset, length, RL_WRITER);
+ ztest_object_lock(zd, lr->lr_foid, ZTRL_READER);
+ rl = ztest_range_lock(zd, lr->lr_foid, offset, length, ZTRL_WRITER);
VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db));
@@ -2176,6 +2259,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) ?
@@ -2214,7 +2298,7 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_write(os, lr->lr_foid, offset, length, data, tx);
} else {
memcpy(abuf->b_data, data, length);
- dmu_assign_arcbuf_by_dbuf(db, offset, abuf, tx);
+ VERIFY0(dmu_assign_arcbuf_by_dbuf(db, offset, abuf, tx));
}
(void) ztest_log_write(zd, tx, lr);
@@ -2242,9 +2326,9 @@ ztest_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
- ztest_object_lock(zd, lr->lr_foid, RL_READER);
+ ztest_object_lock(zd, lr->lr_foid, ZTRL_READER);
rl = ztest_range_lock(zd, lr->lr_foid, lr->lr_offset, lr->lr_length,
- RL_WRITER);
+ ZTRL_WRITER);
tx = dmu_tx_create(os);
@@ -2284,7 +2368,7 @@ ztest_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
- ztest_object_lock(zd, lr->lr_foid, RL_WRITER);
+ ztest_object_lock(zd, lr->lr_foid, ZTRL_WRITER);
VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db));
@@ -2345,7 +2429,7 @@ ztest_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
return (0);
}
-zil_replay_func_t *ztest_replay_vector[TX_MAX_TYPE] = {
+static zil_replay_func_t *ztest_replay_vector[TX_MAX_TYPE] = {
NULL, /* 0 no such transaction type */
ztest_replay_create, /* TX_CREATE */
NULL, /* TX_MKDIR */
@@ -2367,6 +2451,8 @@ zil_replay_func_t *ztest_replay_vector[TX_MAX_TYPE] = {
NULL, /* TX_MKDIR_ACL_ATTR */
NULL, /* TX_WRITE2 */
NULL, /* TX_SETSAXATTR */
+ NULL, /* TX_RENAME_EXCHANGE */
+ NULL, /* TX_RENAME_WHITEOUT */
};
/*
@@ -2407,10 +2493,9 @@ ztest_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
int error;
ASSERT3P(lwb, !=, NULL);
- ASSERT3P(zio, !=, NULL);
ASSERT3U(size, !=, 0);
- ztest_object_lock(zd, object, RL_READER);
+ ztest_object_lock(zd, object, ZTRL_READER);
error = dmu_bonus_hold(os, object, FTAG, &db);
if (error) {
ztest_object_unlock(zd, object);
@@ -2435,12 +2520,13 @@ ztest_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
if (buf != NULL) { /* immediate write */
zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd,
- object, offset, size, RL_READER);
+ object, offset, size, ZTRL_READER);
error = dmu_read(os, object, offset, size, buf,
DMU_READ_NO_PREFETCH);
ASSERT0(error);
} else {
+ ASSERT3P(zio, !=, NULL);
size = doi.doi_data_block_size;
if (ISP2(size)) {
offset = P2ALIGN(offset, size);
@@ -2450,10 +2536,9 @@ ztest_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
}
zgd->zgd_lr = (struct zfs_locked_range *)ztest_range_lock(zd,
- object, offset, size, RL_READER);
+ object, offset, size, ZTRL_READER);
- error = dmu_buf_hold(os, object, offset, zgd, &db,
- DMU_READ_NO_PREFETCH);
+ error = dmu_buf_hold_noread(os, object, offset, zgd, &db);
if (error == 0) {
blkptr_t *bp = &lr->lr_blkptr;
@@ -2527,7 +2612,7 @@ ztest_lookup(ztest_ds_t *zd, ztest_od_t *od, int count)
ASSERT3U(od->od_object, !=, 0);
ASSERT0(missing); /* there should be no gaps */
- ztest_object_lock(zd, od->od_object, RL_READER);
+ ztest_object_lock(zd, od->od_object, ZTRL_READER);
VERIFY0(dmu_bonus_hold(zd->zd_os, od->od_object,
FTAG, &db));
dmu_object_info_from_db(db, &doi);
@@ -2630,7 +2715,7 @@ ztest_remove(ztest_ds_t *zd, ztest_od_t *od, int count)
static int
ztest_write(ztest_ds_t *zd, uint64_t object, uint64_t offset, uint64_t size,
- void *data)
+ const void *data)
{
lr_write_t *lr;
int error;
@@ -2700,8 +2785,8 @@ ztest_prealloc(ztest_ds_t *zd, uint64_t object, uint64_t offset, uint64_t size)
txg_wait_synced(dmu_objset_pool(os), 0);
- ztest_object_lock(zd, object, RL_READER);
- rl = ztest_range_lock(zd, object, offset, size, RL_WRITER);
+ ztest_object_lock(zd, object, ZTRL_READER);
+ rl = ztest_range_lock(zd, object, offset, size, ZTRL_WRITER);
tx = dmu_tx_create(os);
@@ -2786,12 +2871,12 @@ ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset)
err = ztest_dsl_prop_set_uint64(zd->zd_name,
ZFS_PROP_CHECKSUM, spa_dedup_checksum(ztest_spa),
B_FALSE);
- VERIFY(err == 0 || err == ENOSPC);
+ ASSERT(err == 0 || err == ENOSPC);
err = ztest_dsl_prop_set_uint64(zd->zd_name,
ZFS_PROP_COMPRESSION,
ztest_random_dsl_prop(ZFS_PROP_COMPRESSION),
B_FALSE);
- VERIFY(err == 0 || err == ENOSPC);
+ ASSERT(err == 0 || err == ENOSPC);
(void) pthread_rwlock_unlock(&ztest_name_lock);
VERIFY0(dmu_read(zd->zd_os, object, offset, blocksize, data,
@@ -2908,7 +2993,7 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id)
zil_close(zd->zd_zilog);
/* zfsvfs_setup() */
- VERIFY3P(zil_open(os, ztest_get_data), ==, zd->zd_zilog);
+ VERIFY3P(zil_open(os, ztest_get_data, NULL), ==, zd->zd_zilog);
zil_replay(os, zd, ztest_replay_vector);
(void) pthread_rwlock_unlock(&zd->zd_zilog_lock);
@@ -3029,13 +3114,32 @@ ztest_mmp_enable_disable(ztest_ds_t *zd, uint64_t id)
spa_config_exit(spa, SCL_CONFIG, FTAG);
}
+static int
+ztest_get_raidz_children(spa_t *spa)
+{
+ (void) spa;
+ vdev_t *raidvd;
+
+ ASSERT(MUTEX_HELD(&ztest_vdev_lock));
+
+ if (ztest_opts.zo_raid_do_expand) {
+ raidvd = ztest_spa->spa_root_vdev->vdev_child[0];
+
+ ASSERT(raidvd->vdev_ops == &vdev_raidz_ops);
+
+ return (raidvd->vdev_children);
+ }
+
+ return (ztest_opts.zo_raid_children);
+}
+
void
ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
{
(void) zd, (void) id;
spa_t *spa;
uint64_t initial_version = SPA_VERSION_INITIAL;
- uint64_t version, newversion;
+ uint64_t raidz_children, version, newversion;
nvlist_t *nvroot, *props;
char *name;
@@ -3054,8 +3158,10 @@ ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
*/
(void) spa_destroy(name);
+ raidz_children = ztest_get_raidz_children(ztest_spa);
+
nvroot = make_vdev_root(NULL, NULL, name, ztest_opts.zo_vdev_size, 0,
- NULL, ztest_opts.zo_raid_children, ztest_opts.zo_mirrors, 1);
+ NULL, raidz_children, ztest_opts.zo_mirrors, 1);
/*
* If we're configuring a RAIDZ device then make sure that the
@@ -3121,6 +3227,7 @@ ztest_spa_checkpoint(spa_t *spa)
case ZFS_ERR_DEVRM_IN_PROGRESS:
case ZFS_ERR_DISCARDING_CHECKPOINT:
case ZFS_ERR_CHECKPOINT_EXISTS:
+ case ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS:
break;
case ENOSPC:
ztest_record_enospc(FTAG);
@@ -3201,6 +3308,8 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
spa_t *spa = ztest_spa;
uint64_t leaves;
uint64_t guid;
+ uint64_t raidz_children;
+
nvlist_t *nvroot;
int error;
@@ -3208,8 +3317,8 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
return;
mutex_enter(&ztest_vdev_lock);
- leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) *
- ztest_opts.zo_raid_children;
+ raidz_children = ztest_get_raidz_children(spa);
+ leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * raidz_children;
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
@@ -3263,10 +3372,10 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
*/
nvroot = make_vdev_root(NULL, NULL, NULL,
ztest_opts.zo_vdev_size, 0, (ztest_random(4) == 0) ?
- "log" : NULL, ztest_opts.zo_raid_children, zs->zs_mirrors,
+ "log" : NULL, raidz_children, zs->zs_mirrors,
1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
fnvlist_free(nvroot);
switch (error) {
@@ -3291,6 +3400,7 @@ ztest_vdev_class_add(ztest_ds_t *zd, uint64_t id)
spa_t *spa = ztest_spa;
uint64_t leaves;
nvlist_t *nvroot;
+ uint64_t raidz_children;
const char *class = (ztest_random(2) == 0) ?
VDEV_ALLOC_BIAS_SPECIAL : VDEV_ALLOC_BIAS_DEDUP;
int error;
@@ -3318,17 +3428,17 @@ ztest_vdev_class_add(ztest_ds_t *zd, uint64_t id)
return;
}
- leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) *
- ztest_opts.zo_raid_children;
+ raidz_children = ztest_get_raidz_children(spa);
+ leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * raidz_children;
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
ztest_shared->zs_vdev_next_leaf = spa_num_top_vdevs(spa) * leaves;
spa_config_exit(spa, SCL_VDEV, FTAG);
nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0,
- class, ztest_opts.zo_raid_children, zs->zs_mirrors, 1);
+ class, raidz_children, zs->zs_mirrors, 1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
fnvlist_free(nvroot);
if (error == ENOSPC)
@@ -3343,8 +3453,9 @@ ztest_vdev_class_add(ztest_ds_t *zd, uint64_t id)
spa_special_class(spa)->mc_groups == 1 && ztest_random(2) == 0) {
if (ztest_opts.zo_verbose >= 3)
(void) printf("Enabling special VDEV small blocks\n");
- (void) ztest_dsl_prop_set_uint64(zd->zd_name,
+ error = ztest_dsl_prop_set_uint64(zd->zd_name,
ZFS_PROP_SPECIAL_SMALL_BLOCKS, 32768, B_FALSE);
+ ASSERT(error == 0 || error == ENOSPC);
}
mutex_exit(&ztest_vdev_lock);
@@ -3434,7 +3545,7 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
*/
nvlist_t *nvroot = make_vdev_root(NULL, aux, NULL,
(ztest_opts.zo_vdev_size * 5) / 4, 0, NULL, 0, 0, 1);
- error = spa_vdev_add(spa, nvroot);
+ error = spa_vdev_add(spa, nvroot, B_FALSE);
switch (error) {
case 0:
@@ -3511,7 +3622,8 @@ ztest_split_pool(ztest_ds_t *zd, uint64_t id)
VERIFY0(nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN,
&child, &children));
- schild = malloc(rvd->vdev_children * sizeof (nvlist_t *));
+ schild = umem_alloc(rvd->vdev_children * sizeof (nvlist_t *),
+ UMEM_NOFAIL);
for (c = 0; c < children; c++) {
vdev_t *tvd = rvd->vdev_child[c];
nvlist_t **mchild;
@@ -3545,7 +3657,7 @@ ztest_split_pool(ztest_ds_t *zd, uint64_t id)
for (c = 0; c < schildren; c++)
fnvlist_free(schild[c]);
- free(schild);
+ umem_free(schild, rvd->vdev_children * sizeof (nvlist_t *));
fnvlist_free(split);
spa_config_exit(spa, SCL_VDEV, FTAG);
@@ -3586,12 +3698,14 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
uint64_t ashift = ztest_get_ashift();
uint64_t oldguid, pguid;
uint64_t oldsize, newsize;
+ uint64_t raidz_children;
char *oldpath, *newpath;
int replacing;
int oldvd_has_siblings = B_FALSE;
int newvd_is_spare = B_FALSE;
int newvd_is_dspare = B_FALSE;
int oldvd_is_log;
+ int oldvd_is_special;
int error, expected_error;
if (ztest_opts.zo_mmp_test)
@@ -3601,7 +3715,8 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
newpath = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
mutex_enter(&ztest_vdev_lock);
- leaves = MAX(zs->zs_mirrors, 1) * ztest_opts.zo_raid_children;
+ raidz_children = ztest_get_raidz_children(spa);
+ leaves = MAX(zs->zs_mirrors, 1) * raidz_children;
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
@@ -3617,6 +3732,15 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
}
/*
+ * RAIDZ leaf VDEV mirrors are not currently supported while a
+ * RAIDZ expansion is in progress.
+ */
+ if (ztest_opts.zo_raid_do_expand) {
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ goto out;
+ }
+
+ /*
* Decide whether to do an attach or a replace.
*/
replacing = ztest_random(2);
@@ -3640,7 +3764,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
if (zs->zs_mirrors >= 1) {
ASSERT3P(oldvd->vdev_ops, ==, &vdev_mirror_ops);
ASSERT3U(oldvd->vdev_children, >=, zs->zs_mirrors);
- oldvd = oldvd->vdev_child[leaf / ztest_opts.zo_raid_children];
+ oldvd = oldvd->vdev_child[leaf / raidz_children];
}
/* pick a child out of the raidz group */
@@ -3649,8 +3773,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
ASSERT3P(oldvd->vdev_ops, ==, &vdev_raidz_ops);
else
ASSERT3P(oldvd->vdev_ops, ==, &vdev_draid_ops);
- ASSERT3U(oldvd->vdev_children, ==, ztest_opts.zo_raid_children);
- oldvd = oldvd->vdev_child[leaf % ztest_opts.zo_raid_children];
+ oldvd = oldvd->vdev_child[leaf % raidz_children];
}
/*
@@ -3666,7 +3789,10 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
oldguid = oldvd->vdev_guid;
oldsize = vdev_get_min_asize(oldvd);
oldvd_is_log = oldvd->vdev_top->vdev_islog;
- (void) strcpy(oldpath, oldvd->vdev_path);
+ oldvd_is_special =
+ oldvd->vdev_top->vdev_alloc_bias == VDEV_BIAS_SPECIAL ||
+ oldvd->vdev_top->vdev_alloc_bias == VDEV_BIAS_DEDUP;
+ (void) strlcpy(oldpath, oldvd->vdev_path, MAXPATHLEN);
pvd = oldvd->vdev_parent;
pguid = pvd->vdev_guid;
@@ -3702,7 +3828,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
if (newvd->vdev_ops == &vdev_draid_spare_ops)
newvd_is_dspare = B_TRUE;
- (void) strcpy(newpath, newvd->vdev_path);
+ (void) strlcpy(newpath, newvd->vdev_path, MAXPATHLEN);
} else {
(void) snprintf(newpath, MAXPATHLEN, ztest_dev_template,
ztest_opts.zo_dir, ztest_opts.zo_pool,
@@ -3744,7 +3870,8 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
pvd->vdev_ops == &vdev_replacing_ops ||
pvd->vdev_ops == &vdev_spare_ops))
expected_error = ENOTSUP;
- else if (newvd_is_spare && (!replacing || oldvd_is_log))
+ else if (newvd_is_spare &&
+ (!replacing || oldvd_is_log || oldvd_is_special))
expected_error = ENOTSUP;
else if (newvd == oldvd)
expected_error = replacing ? 0 : EBUSY;
@@ -3755,7 +3882,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
else if (ashift > oldvd->vdev_top->vdev_ashift)
expected_error = EDOM;
else if (newvd_is_dspare && pvd != vdev_draid_spare_get_parent(newvd))
- expected_error = ENOTSUP;
+ expected_error = EINVAL;
else
expected_error = 0;
@@ -3814,6 +3941,226 @@ out:
umem_free(newpath, MAXPATHLEN);
}
+static void
+raidz_scratch_verify(void)
+{
+ spa_t *spa;
+ uint64_t write_size, logical_size, offset;
+ raidz_reflow_scratch_state_t state;
+ vdev_raidz_expand_t *vre;
+ vdev_t *raidvd;
+
+ ASSERT(raidz_expand_pause_point == RAIDZ_EXPAND_PAUSE_NONE);
+
+ if (ztest_scratch_state->zs_raidz_scratch_verify_pause == 0)
+ return;
+
+ kernel_init(SPA_MODE_READ);
+
+ mutex_enter(&spa_namespace_lock);
+ spa = spa_lookup(ztest_opts.zo_pool);
+ ASSERT(spa);
+ spa->spa_import_flags |= ZFS_IMPORT_SKIP_MMP;
+ mutex_exit(&spa_namespace_lock);
+
+ VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
+
+ ASSERT3U(RRSS_GET_OFFSET(&spa->spa_uberblock), !=, UINT64_MAX);
+
+ mutex_enter(&ztest_vdev_lock);
+
+ spa_config_enter(spa, SCL_ALL, FTAG, RW_READER);
+
+ vre = spa->spa_raidz_expand;
+ if (vre == NULL)
+ goto out;
+
+ raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ offset = RRSS_GET_OFFSET(&spa->spa_uberblock);
+ state = RRSS_GET_STATE(&spa->spa_uberblock);
+ write_size = P2ALIGN(VDEV_BOOT_SIZE, 1 << raidvd->vdev_ashift);
+ logical_size = write_size * raidvd->vdev_children;
+
+ switch (state) {
+ /*
+ * Initial state of reflow process. RAIDZ expansion was
+ * requested by user, but scratch object was not created.
+ */
+ case RRSS_SCRATCH_NOT_IN_USE:
+ ASSERT3U(offset, ==, 0);
+ break;
+
+ /*
+ * Scratch object was synced and stored in boot area.
+ */
+ case RRSS_SCRATCH_VALID:
+
+ /*
+ * Scratch object was synced back to raidz start offset,
+ * raidz is ready for sector by sector reflow process.
+ */
+ case RRSS_SCRATCH_INVALID_SYNCED:
+
+ /*
+ * Scratch object was synced back to raidz start offset
+ * on zpool importing, raidz is ready for sector by sector
+ * reflow process.
+ */
+ case RRSS_SCRATCH_INVALID_SYNCED_ON_IMPORT:
+ ASSERT3U(offset, ==, logical_size);
+ break;
+
+ /*
+ * Sector by sector reflow process started.
+ */
+ case RRSS_SCRATCH_INVALID_SYNCED_REFLOW:
+ ASSERT3U(offset, >=, logical_size);
+ break;
+ }
+
+out:
+ spa_config_exit(spa, SCL_ALL, FTAG);
+
+ mutex_exit(&ztest_vdev_lock);
+
+ ztest_scratch_state->zs_raidz_scratch_verify_pause = 0;
+
+ spa_close(spa, FTAG);
+ kernel_fini();
+}
+
+static void
+ztest_scratch_thread(void *arg)
+{
+ (void) arg;
+
+ /* wait up to 10 seconds */
+ for (int t = 100; t > 0; t -= 1) {
+ if (raidz_expand_pause_point == RAIDZ_EXPAND_PAUSE_NONE)
+ thread_exit();
+
+ (void) poll(NULL, 0, 100);
+ }
+
+ /* killed when the scratch area progress reached a certain point */
+ ztest_kill(ztest_shared);
+}
+
+/*
+ * Verify that we can attach raidz device.
+ */
+void
+ztest_vdev_raidz_attach(ztest_ds_t *zd, uint64_t id)
+{
+ (void) zd, (void) id;
+ ztest_shared_t *zs = ztest_shared;
+ spa_t *spa = ztest_spa;
+ uint64_t leaves, raidz_children, newsize, ashift = ztest_get_ashift();
+ kthread_t *scratch_thread = NULL;
+ vdev_t *newvd, *pvd;
+ nvlist_t *root;
+ char *newpath = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
+ int error, expected_error = 0;
+
+ mutex_enter(&ztest_vdev_lock);
+
+ spa_config_enter(spa, SCL_ALL, FTAG, RW_READER);
+
+ /* Only allow attach when raid-kind = 'eraidz' */
+ if (!ztest_opts.zo_raid_do_expand) {
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ goto out;
+ }
+
+ if (ztest_opts.zo_mmp_test) {
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ goto out;
+ }
+
+ if (ztest_device_removal_active) {
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ goto out;
+ }
+
+ pvd = vdev_lookup_top(spa, 0);
+
+ ASSERT(pvd->vdev_ops == &vdev_raidz_ops);
+
+ /*
+ * Get size of a child of the raidz group,
+ * make sure device is a bit bigger
+ */
+ newvd = pvd->vdev_child[ztest_random(pvd->vdev_children)];
+ newsize = 10 * vdev_get_min_asize(newvd) / (9 + ztest_random(2));
+
+ /*
+ * Get next attached leaf id
+ */
+ raidz_children = ztest_get_raidz_children(spa);
+ leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * raidz_children;
+ zs->zs_vdev_next_leaf = spa_num_top_vdevs(spa) * leaves;
+
+ if (spa->spa_raidz_expand)
+ expected_error = ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS;
+
+ spa_config_exit(spa, SCL_ALL, FTAG);
+
+ /*
+ * Path to vdev to be attached
+ */
+ (void) snprintf(newpath, MAXPATHLEN, ztest_dev_template,
+ ztest_opts.zo_dir, ztest_opts.zo_pool, zs->zs_vdev_next_leaf);
+
+ /*
+ * Build the nvlist describing newpath.
+ */
+ root = make_vdev_root(newpath, NULL, NULL, newsize, ashift, NULL,
+ 0, 0, 1);
+
+ /*
+ * 50% of the time, set raidz_expand_pause_point to cause
+ * raidz_reflow_scratch_sync() to pause at a certain point and
+ * then kill the test after 10 seconds so raidz_scratch_verify()
+ * can confirm consistency when the pool is imported.
+ */
+ if (ztest_random(2) == 0 && expected_error == 0) {
+ raidz_expand_pause_point =
+ ztest_random(RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_2) + 1;
+ scratch_thread = thread_create(NULL, 0, ztest_scratch_thread,
+ ztest_shared, 0, NULL, TS_RUN | TS_JOINABLE, defclsyspri);
+ }
+
+ error = spa_vdev_attach(spa, pvd->vdev_guid, root, B_FALSE, B_FALSE);
+
+ nvlist_free(root);
+
+ if (error == EOVERFLOW || error == ENXIO ||
+ error == ZFS_ERR_CHECKPOINT_EXISTS ||
+ error == ZFS_ERR_DISCARDING_CHECKPOINT)
+ expected_error = error;
+
+ if (error != 0 && error != expected_error) {
+ fatal(0, "raidz attach (%s %"PRIu64") returned %d, expected %d",
+ newpath, newsize, error, expected_error);
+ }
+
+ if (raidz_expand_pause_point) {
+ if (error != 0) {
+ /*
+ * Do not verify scratch object in case of error
+ * returned by vdev attaching.
+ */
+ raidz_expand_pause_point = RAIDZ_EXPAND_PAUSE_NONE;
+ }
+
+ VERIFY0(thread_join(scratch_thread));
+ }
+out:
+ mutex_exit(&ztest_vdev_lock);
+
+ umem_free(newpath, MAXPATHLEN);
+}
+
void
ztest_device_removal(ztest_ds_t *zd, uint64_t id)
{
@@ -4020,6 +4367,18 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
return;
}
+ /*
+ * If we are under raidz expansion, the test can failed because the
+ * metaslabs count will not increase immediately after the vdev is
+ * expanded. It will happen only after raidz expansion completion.
+ */
+ if (spa->spa_raidz_expand) {
+ spa_config_exit(spa, SCL_STATE, spa);
+ mutex_exit(&ztest_vdev_lock);
+ mutex_exit(&ztest_checkpoint_lock);
+ return;
+ }
+
top = ztest_random_vdev_top(spa, B_TRUE);
tvd = spa->spa_root_vdev->vdev_child[top];
@@ -4288,7 +4647,7 @@ ztest_snapshot_create(char *osname, uint64_t id)
ztest_record_enospc(FTAG);
return (B_FALSE);
}
- if (error != 0 && error != EEXIST) {
+ if (error != 0 && error != EEXIST && error != ECHRNG) {
fatal(B_FALSE, "ztest_snapshot_create(%s@%s) = %d", osname,
snapname, error);
}
@@ -4305,7 +4664,7 @@ ztest_snapshot_destroy(char *osname, uint64_t id)
osname, id);
error = dsl_destroy_snapshot(snapname, B_FALSE);
- if (error != 0 && error != ENOENT)
+ if (error != 0 && error != ENOENT && error != ECHRNG)
fatal(B_FALSE, "ztest_snapshot_destroy(%s) = %d",
snapname, error);
return (B_TRUE);
@@ -4354,9 +4713,16 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
/*
* Verify that the destroyed dataset is no longer in the namespace.
+ * It may still be present if the destroy above fails with ENOSPC.
*/
- VERIFY3U(ENOENT, ==, ztest_dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
- B_TRUE, FTAG, &os));
+ error = ztest_dmu_objset_own(name, DMU_OST_OTHER, B_TRUE, B_TRUE,
+ FTAG, &os);
+ if (error == 0) {
+ dmu_objset_disown(os, B_TRUE, FTAG);
+ ztest_record_enospc(FTAG);
+ goto out;
+ }
+ VERIFY3U(ENOENT, ==, error);
/*
* Verify that we can create a new dataset.
@@ -4378,7 +4744,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
/*
* Open the intent log for it.
*/
- zilog = zil_open(os, ztest_get_data);
+ zilog = zil_open(os, ztest_get_data, NULL);
/*
* Put some objects in there, do a little I/O to them,
@@ -4620,8 +4986,11 @@ ztest_dmu_object_alloc_free(ztest_ds_t *zd, uint64_t id)
* Destroy the previous batch of objects, create a new batch,
* and do some I/O on the new objects.
*/
- if (ztest_object_init(zd, od, size, B_TRUE) != 0)
+ if (ztest_object_init(zd, od, size, B_TRUE) != 0) {
+ zd->zd_od = NULL;
+ umem_free(od, size);
return;
+ }
while (ztest_random(4 * batchsize) != 0)
ztest_io(zd, od[ztest_random(batchsize)].od_object,
@@ -4638,7 +5007,7 @@ ztest_dmu_object_next_chunk(ztest_ds_t *zd, uint64_t id)
{
(void) id;
objset_t *os = zd->zd_os;
- int dnodes_per_chunk = 1 << dmu_object_alloc_chunk_shift;
+ uint_t dnodes_per_chunk = 1 << dmu_object_alloc_chunk_shift;
uint64_t object;
/*
@@ -5794,7 +6163,7 @@ ztest_verify_dnode_bt(ztest_ds_t *zd, uint64_t id)
dmu_object_info_t doi;
dmu_buf_t *db;
- ztest_object_lock(zd, obj, RL_READER);
+ ztest_object_lock(zd, obj, ZTRL_READER);
if (dmu_bonus_hold(os, obj, FTAG, &db) != 0) {
ztest_object_unlock(zd, obj);
continue;
@@ -5829,12 +6198,15 @@ ztest_dsl_prop_get_set(ztest_ds_t *zd, uint64_t id)
(void) pthread_rwlock_rdlock(&ztest_name_lock);
- for (int p = 0; p < sizeof (proplist) / sizeof (proplist[0]); p++)
- (void) ztest_dsl_prop_set_uint64(zd->zd_name, proplist[p],
+ for (int p = 0; p < sizeof (proplist) / sizeof (proplist[0]); p++) {
+ int error = ztest_dsl_prop_set_uint64(zd->zd_name, proplist[p],
ztest_random_dsl_prop(proplist[p]), (int)ztest_random(2));
+ ASSERT(error == 0 || error == ENOSPC);
+ }
- VERIFY0(ztest_dsl_prop_set_uint64(zd->zd_name, ZFS_PROP_RECORDSIZE,
- ztest_random_blocksize(), (int)ztest_random(2)));
+ int error = ztest_dsl_prop_set_uint64(zd->zd_name, ZFS_PROP_RECORDSIZE,
+ ztest_random_blocksize(), (int)ztest_random(2));
+ ASSERT(error == 0 || error == ENOSPC);
(void) pthread_rwlock_unlock(&ztest_name_lock);
}
@@ -6014,6 +6386,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
uint64_t leaves;
uint64_t bad = 0x1990c0ffeedecadeull;
uint64_t top, leaf;
+ uint64_t raidz_children;
char *path0;
char *pathrand;
size_t fsize;
@@ -6024,6 +6397,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
vdev_t *vd0 = NULL;
uint64_t guid0 = 0;
boolean_t islog = B_FALSE;
+ boolean_t injected = B_FALSE;
path0 = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
pathrand = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
@@ -6036,15 +6410,23 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
* strategy for damaging blocks does not take in to account evacuated
* blocks which may have already been damaged.
*/
- if (ztest_device_removal_active) {
- mutex_exit(&ztest_vdev_lock);
+ if (ztest_device_removal_active)
+ goto out;
+
+ /*
+ * The fault injection strategy for damaging blocks cannot be used
+ * if raidz expansion is in progress. The leaves value
+ * (attached raidz children) is variable and strategy for damaging
+ * blocks will corrupt same data blocks on different child vdevs
+ * because of the reflow process.
+ */
+ if (spa->spa_raidz_expand != NULL)
goto out;
- }
maxfaults = MAXFAULTS(zs);
- leaves = MAX(zs->zs_mirrors, 1) * ztest_opts.zo_raid_children;
+ raidz_children = ztest_get_raidz_children(spa);
+ leaves = MAX(zs->zs_mirrors, 1) * raidz_children;
mirror_save = zs->zs_mirrors;
- mutex_exit(&ztest_vdev_lock);
ASSERT3U(leaves, >=, 1);
@@ -6144,8 +6526,8 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
}
vd0 = sav->sav_vdevs[ztest_random(sav->sav_count)];
guid0 = vd0->vdev_guid;
- (void) strcpy(path0, vd0->vdev_path);
- (void) strcpy(pathrand, vd0->vdev_path);
+ (void) strlcpy(path0, vd0->vdev_path, MAXPATHLEN);
+ (void) strlcpy(pathrand, vd0->vdev_path, MAXPATHLEN);
leaf = 0;
leaves = 1;
@@ -6185,13 +6567,9 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
* call vdev_[on|off]line without holding locks
* to force unpredictable failures but the side
* effects of vdev_[on|off]line prevent us from
- * doing so. We grab the ztest_vdev_lock here to
- * prevent a race between injection testing and
- * aux_vdev removal.
+ * doing so.
*/
- mutex_enter(&ztest_vdev_lock);
(void) vdev_online(spa, guid0, 0, NULL);
- mutex_exit(&ztest_vdev_lock);
}
}
@@ -6265,9 +6643,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
offset + sizeof (bad) > psize - VDEV_LABEL_END_SIZE)
continue;
- mutex_enter(&ztest_vdev_lock);
if (mirror_save != zs->zs_mirrors) {
- mutex_exit(&ztest_vdev_lock);
(void) close(fd);
goto out;
}
@@ -6277,15 +6653,25 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
"can't inject bad word at 0x%"PRIx64" in %s",
offset, pathrand);
- mutex_exit(&ztest_vdev_lock);
-
if (ztest_opts.zo_verbose >= 7)
(void) printf("injected bad word into %s,"
" offset 0x%"PRIx64"\n", pathrand, offset);
+
+ injected = B_TRUE;
}
(void) close(fd);
out:
+ mutex_exit(&ztest_vdev_lock);
+
+ if (injected && ztest_opts.zo_raid_do_expand) {
+ int error = spa_scan(spa, POOL_SCAN_SCRUB);
+ if (error == 0) {
+ while (dsl_scan_scrubbing(spa_get_dsl(spa)))
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ }
+ }
+
umem_free(path0, MAXPATHLEN);
umem_free(pathrand, MAXPATHLEN);
}
@@ -6308,7 +6694,7 @@ ztest_scrub_impl(spa_t *spa)
while (dsl_scan_scrubbing(spa_get_dsl(spa)))
txg_wait_synced(spa_get_dsl(spa), 0);
- if (spa_get_errlog_size(spa) > 0)
+ if (spa_approx_errlog_size(spa) > 0)
return (ECKSUM);
ztest_pool_scrubbed = B_TRUE;
@@ -6354,6 +6740,7 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
spa_t *spa = ztest_spa;
uint64_t orig, load;
int error;
+ ztest_shared_t *zs = ztest_shared;
if (ztest_opts.zo_mmp_test)
return;
@@ -6363,6 +6750,7 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
(void) pthread_rwlock_wrlock(&ztest_name_lock);
error = spa_change_guid(spa);
+ zs->zs_guid = spa_guid(spa);
(void) pthread_rwlock_unlock(&ztest_name_lock);
if (error != 0)
@@ -6389,6 +6777,7 @@ ztest_blake3(ztest_ds_t *zd, uint64_t id)
int i, *ptr;
uint32_t size;
BLAKE3_CTX ctx;
+ const zfs_impl_t *blake3 = zfs_impl_get_ops("blake3");
size = ztest_random_blocksize();
buf = umem_alloc(size, UMEM_NOFAIL);
@@ -6413,7 +6802,7 @@ ztest_blake3(ztest_ds_t *zd, uint64_t id)
void *res2 = &zc_res2;
/* BLAKE3_KEY_LEN = 32 */
- VERIFY0(blake3_set_impl_name("generic"));
+ VERIFY0(blake3->setname("generic"));
templ = abd_checksum_blake3_tmpl_init(&salt);
Blake3_InitKeyed(&ctx, salt_ptr);
Blake3_Update(&ctx, buf, size);
@@ -6422,7 +6811,7 @@ ztest_blake3(ztest_ds_t *zd, uint64_t id)
ZIO_CHECKSUM_BSWAP(&zc_ref2);
abd_checksum_blake3_tmpl_free(templ);
- VERIFY0(blake3_set_impl_name("cycle"));
+ VERIFY0(blake3->setname("cycle"));
while (run_count-- > 0) {
/* Test current implementation */
@@ -6636,6 +7025,8 @@ ztest_global_vars_to_zdb_args(void)
{
char **args = calloc(2*ztest_opts.zo_gvars_count + 1, sizeof (char *));
char **cur = args;
+ if (args == NULL)
+ return (NULL);
for (size_t i = 0; i < ztest_opts.zo_gvars_count; i++) {
*cur++ = (char *)"-o";
*cur++ = ztest_opts.zo_gvars[i];
@@ -6660,7 +7051,7 @@ join_strings(char **strings, const char *sep)
}
size_t buflen = totallen + 1;
- char *o = malloc(buflen); /* trailing 0 byte */
+ char *o = umem_alloc(buflen, UMEM_NOFAIL); /* trailing 0 byte */
o[0] = '\0';
for (char **sp = strings; *sp != NULL; sp++) {
size_t would;
@@ -6889,7 +7280,7 @@ ztest_trim(ztest_ds_t *zd, uint64_t id)
* Verify pool integrity by running zdb.
*/
static void
-ztest_run_zdb(const char *pool)
+ztest_run_zdb(uint64_t guid)
{
int status;
char *bin;
@@ -6905,20 +7296,24 @@ ztest_run_zdb(const char *pool)
ztest_get_zdb_bin(bin, len);
char **set_gvars_args = ztest_global_vars_to_zdb_args();
+ if (set_gvars_args == NULL) {
+ fatal(B_FALSE, "Failed to allocate memory in "
+ "ztest_global_vars_to_zdb_args(). Cannot run zdb.\n");
+ }
char *set_gvars_args_joined = join_strings(set_gvars_args, " ");
free(set_gvars_args);
size_t would = snprintf(zdb, len,
- "%s -bcc%s%s -G -d -Y -e -y %s -p %s %s",
+ "%s -bcc%s%s -G -d -Y -e -y %s -p %s %"PRIu64,
bin,
ztest_opts.zo_verbose >= 3 ? "s" : "",
ztest_opts.zo_verbose >= 4 ? "v" : "",
set_gvars_args_joined,
ztest_opts.zo_dir,
- pool);
+ guid);
ASSERT3U(would, <, len);
- free(set_gvars_args_joined);
+ umem_free(set_gvars_args_joined, strlen(set_gvars_args_joined) + 1);
if (ztest_opts.zo_verbose >= 5)
(void) printf("Executing %s\n", zdb);
@@ -7111,9 +7506,9 @@ ztest_deadman_thread(void *arg)
*/
if (spa_suspended(spa) || spa->spa_root_vdev == NULL) {
fatal(B_FALSE,
- "aborting test after %lu seconds because "
+ "aborting test after %llu seconds because "
"pool has transitioned to a suspended state.",
- zfs_deadman_synctime_ms / 1000);
+ (u_longlong_t)zfs_deadman_synctime_ms / 1000);
}
vdev_deadman(spa->spa_root_vdev, FTAG);
@@ -7161,6 +7556,75 @@ ztest_execute(int test, ztest_info_t *zi, uint64_t id)
(double)functime / NANOSEC, zi->zi_funcname);
}
+typedef struct ztest_raidz_expand_io {
+ uint64_t rzx_id;
+ uint64_t rzx_amount;
+ uint64_t rzx_bufsize;
+ const void *rzx_buffer;
+ uint64_t rzx_alloc_max;
+ spa_t *rzx_spa;
+} ztest_expand_io_t;
+
+#undef OD_ARRAY_SIZE
+#define OD_ARRAY_SIZE 10
+
+/*
+ * Write a request amount of data to some dataset objects.
+ * There will be ztest_opts.zo_threads count of these running in parallel.
+ */
+static __attribute__((noreturn)) void
+ztest_rzx_thread(void *arg)
+{
+ ztest_expand_io_t *info = (ztest_expand_io_t *)arg;
+ ztest_od_t *od;
+ int batchsize;
+ int od_size;
+ ztest_ds_t *zd = &ztest_ds[info->rzx_id % ztest_opts.zo_datasets];
+ spa_t *spa = info->rzx_spa;
+
+ od_size = sizeof (ztest_od_t) * OD_ARRAY_SIZE;
+ od = umem_alloc(od_size, UMEM_NOFAIL);
+ batchsize = OD_ARRAY_SIZE;
+
+ /* Create objects to write to */
+ for (int b = 0; b < batchsize; b++) {
+ ztest_od_init(od + b, info->rzx_id, FTAG, b,
+ DMU_OT_UINT64_OTHER, 0, 0, 0);
+ }
+ if (ztest_object_init(zd, od, od_size, B_FALSE) != 0) {
+ umem_free(od, od_size);
+ thread_exit();
+ }
+
+ for (uint64_t offset = 0, written = 0; written < info->rzx_amount;
+ offset += info->rzx_bufsize) {
+ /* write to 10 objects */
+ for (int i = 0; i < batchsize && written < info->rzx_amount;
+ i++) {
+ (void) pthread_rwlock_rdlock(&zd->zd_zilog_lock);
+ ztest_write(zd, od[i].od_object, offset,
+ info->rzx_bufsize, info->rzx_buffer);
+ (void) pthread_rwlock_unlock(&zd->zd_zilog_lock);
+ written += info->rzx_bufsize;
+ }
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ /* due to inflation, we'll typically bail here */
+ if (metaslab_class_get_alloc(spa_normal_class(spa)) >
+ info->rzx_alloc_max) {
+ break;
+ }
+ }
+
+ /* Remove a few objects to leave some holes in allocation space */
+ mutex_enter(&zd->zd_dirobj_lock);
+ (void) ztest_remove(zd, od, 2);
+ mutex_exit(&zd->zd_dirobj_lock);
+
+ umem_free(od, od_size);
+
+ thread_exit();
+}
+
static __attribute__((noreturn)) void
ztest_thread(void *arg)
{
@@ -7176,8 +7640,10 @@ ztest_thread(void *arg)
/*
* See if it's time to force a crash.
*/
- if (now > zs->zs_thread_kill)
+ if (now > zs->zs_thread_kill &&
+ raidz_expand_pause_point == RAIDZ_EXPAND_PAUSE_NONE) {
ztest_kill(zs);
+ }
/*
* If we're getting ENOSPC with some regularity, stop.
@@ -7304,7 +7770,7 @@ ztest_dataset_open(int d)
zilog->zl_parse_lr_count,
zilog->zl_replaying_seq);
- zilog = zil_open(os, ztest_get_data);
+ zilog = zil_open(os, ztest_get_data, NULL);
if (zilog->zl_replaying_seq != 0 &&
zilog->zl_replaying_seq < committed_seq)
@@ -7367,9 +7833,14 @@ ztest_freeze(void)
spa_t *spa;
int numloops = 0;
+ /* freeze not supported during RAIDZ expansion */
+ if (ztest_opts.zo_raid_do_expand)
+ return;
+
if (ztest_opts.zo_verbose >= 3)
(void) printf("testing spa_freeze()...\n");
+ raidz_scratch_verify();
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE);
VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
VERIFY0(ztest_dataset_open(0));
@@ -7437,6 +7908,7 @@ ztest_freeze(void)
/*
* Open and close the pool and dataset to induce log replay.
*/
+ raidz_scratch_verify();
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE);
VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
ASSERT3U(spa_freeze_txg(spa), ==, UINT64_MAX);
@@ -7464,8 +7936,12 @@ ztest_import_impl(void)
args.path = searchdirs;
args.can_be_active = B_FALSE;
- VERIFY0(zpool_find_config(NULL, ztest_opts.zo_pool, &cfg, &args,
- &libzpool_config_ops));
+ libpc_handle_t lpch = {
+ .lpc_lib_handle = NULL,
+ .lpc_ops = &libzpool_config_ops,
+ .lpc_printerr = B_TRUE
+ };
+ VERIFY0(zpool_find_config(&lpch, ztest_opts.zo_pool, &cfg, &args));
VERIFY0(spa_import(ztest_opts.zo_pool, cfg, NULL, flags));
fnvlist_free(cfg);
}
@@ -7482,6 +7958,7 @@ ztest_import(ztest_shared_t *zs)
mutex_init(&ztest_checkpoint_lock, NULL, MUTEX_DEFAULT, NULL);
VERIFY0(pthread_rwlock_init(&ztest_name_lock, NULL));
+ raidz_scratch_verify();
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE);
ztest_import_impl();
@@ -7489,14 +7966,15 @@ ztest_import(ztest_shared_t *zs)
VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
zs->zs_metaslab_sz =
1ULL << spa->spa_root_vdev->vdev_child[0]->vdev_ms_shift;
+ zs->zs_guid = spa_guid(spa);
spa_close(spa, FTAG);
kernel_fini();
if (!ztest_opts.zo_mmp_test) {
- ztest_run_zdb(ztest_opts.zo_pool);
+ ztest_run_zdb(zs->zs_guid);
ztest_freeze();
- ztest_run_zdb(ztest_opts.zo_pool);
+ ztest_run_zdb(zs->zs_guid);
}
(void) pthread_rwlock_destroy(&ztest_name_lock);
@@ -7505,7 +7983,291 @@ ztest_import(ztest_shared_t *zs)
}
/*
- * Kick off threads to run tests on all datasets in parallel.
+ * After the expansion was killed, check that the pool is healthy
+ */
+static void
+ztest_raidz_expand_check(spa_t *spa)
+{
+ ASSERT3U(ztest_opts.zo_raidz_expand_test, ==, RAIDZ_EXPAND_KILLED);
+ /*
+ * Set pool check done flag, main program will run a zdb check
+ * of the pool when we exit.
+ */
+ ztest_shared_opts->zo_raidz_expand_test = RAIDZ_EXPAND_CHECKED;
+
+ /* Wait for reflow to finish */
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("\nwaiting for reflow to finish ...\n");
+ }
+ pool_raidz_expand_stat_t rzx_stats;
+ pool_raidz_expand_stat_t *pres = &rzx_stats;
+ do {
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ (void) poll(NULL, 0, 500); /* wait 1/2 second */
+
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ (void) spa_raidz_expand_get_stats(spa, pres);
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ } while (pres->pres_state != DSS_FINISHED &&
+ pres->pres_reflowed < pres->pres_to_reflow);
+
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("verifying an interrupted raidz "
+ "expansion using a pool scrub ...\n");
+ }
+ /* Will fail here if there is non-recoverable corruption detected */
+ VERIFY0(ztest_scrub_impl(spa));
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("raidz expansion scrub check complete\n");
+ }
+}
+
+/*
+ * Start a raidz expansion test. We run some I/O on the pool for a while
+ * to get some data in the pool. Then we grow the raidz and
+ * kill the test at the requested offset into the reflow, verifying that
+ * doing such does not lead to pool corruption.
+ */
+static void
+ztest_raidz_expand_run(ztest_shared_t *zs, spa_t *spa)
+{
+ nvlist_t *root;
+ pool_raidz_expand_stat_t rzx_stats;
+ pool_raidz_expand_stat_t *pres = &rzx_stats;
+ kthread_t **run_threads;
+ vdev_t *cvd, *rzvd = spa->spa_root_vdev->vdev_child[0];
+ int total_disks = rzvd->vdev_children;
+ int data_disks = total_disks - vdev_get_nparity(rzvd);
+ uint64_t alloc_goal;
+ uint64_t csize;
+ int error, t;
+ int threads = ztest_opts.zo_threads;
+ ztest_expand_io_t *thread_args;
+
+ ASSERT3U(ztest_opts.zo_raidz_expand_test, !=, RAIDZ_EXPAND_NONE);
+ ASSERT3P(rzvd->vdev_ops, ==, &vdev_raidz_ops);
+ ztest_opts.zo_raidz_expand_test = RAIDZ_EXPAND_STARTED;
+
+ /* Setup a 1 MiB buffer of random data */
+ uint64_t bufsize = 1024 * 1024;
+ void *buffer = umem_alloc(bufsize, UMEM_NOFAIL);
+
+ if (read(ztest_fd_rand, buffer, bufsize) != bufsize) {
+ fatal(B_TRUE, "short read from /dev/urandom");
+ }
+ /*
+ * Put some data in the pool and then attach a vdev to initiate
+ * reflow.
+ */
+ run_threads = umem_zalloc(threads * sizeof (kthread_t *), UMEM_NOFAIL);
+ thread_args = umem_zalloc(threads * sizeof (ztest_expand_io_t),
+ UMEM_NOFAIL);
+ /* Aim for roughly 25% of allocatable space up to 1GB */
+ alloc_goal = (vdev_get_min_asize(rzvd) * data_disks) / total_disks;
+ alloc_goal = MIN(alloc_goal >> 2, 1024*1024*1024);
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("adding data to pool '%s', goal %llu bytes\n",
+ ztest_opts.zo_pool, (u_longlong_t)alloc_goal);
+ }
+
+ /*
+ * Kick off all the I/O generators that run in parallel.
+ */
+ for (t = 0; t < threads; t++) {
+ if (t < ztest_opts.zo_datasets && ztest_dataset_open(t) != 0) {
+ umem_free(run_threads, threads * sizeof (kthread_t *));
+ umem_free(buffer, bufsize);
+ return;
+ }
+ thread_args[t].rzx_id = t;
+ thread_args[t].rzx_amount = alloc_goal / threads;
+ thread_args[t].rzx_bufsize = bufsize;
+ thread_args[t].rzx_buffer = buffer;
+ thread_args[t].rzx_alloc_max = alloc_goal;
+ thread_args[t].rzx_spa = spa;
+ run_threads[t] = thread_create(NULL, 0, ztest_rzx_thread,
+ &thread_args[t], 0, NULL, TS_RUN | TS_JOINABLE,
+ defclsyspri);
+ }
+
+ /*
+ * Wait for all of the writers to complete.
+ */
+ for (t = 0; t < threads; t++)
+ VERIFY0(thread_join(run_threads[t]));
+
+ /*
+ * Close all datasets. This must be done after all the threads
+ * are joined so we can be sure none of the datasets are in-use
+ * by any of the threads.
+ */
+ for (t = 0; t < ztest_opts.zo_threads; t++) {
+ if (t < ztest_opts.zo_datasets)
+ ztest_dataset_close(t);
+ }
+
+ txg_wait_synced(spa_get_dsl(spa), 0);
+
+ zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
+ zs->zs_space = metaslab_class_get_space(spa_normal_class(spa));
+
+ umem_free(buffer, bufsize);
+ umem_free(run_threads, threads * sizeof (kthread_t *));
+ umem_free(thread_args, threads * sizeof (ztest_expand_io_t));
+
+ /* Set our reflow target to 25%, 50% or 75% of allocated size */
+ uint_t multiple = ztest_random(3) + 1;
+ uint64_t reflow_max = (rzvd->vdev_stat.vs_alloc * multiple) / 4;
+ raidz_expand_max_reflow_bytes = reflow_max;
+
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("running raidz expansion test, killing when "
+ "reflow reaches %llu bytes (%u/4 of allocated space)\n",
+ (u_longlong_t)reflow_max, multiple);
+ }
+
+ /* XXX - do we want some I/O load during the reflow? */
+
+ /*
+ * Use a disk size that is larger than existing ones
+ */
+ cvd = rzvd->vdev_child[0];
+ csize = vdev_get_min_asize(cvd);
+ csize += csize / 10;
+ /*
+ * Path to vdev to be attached
+ */
+ char *newpath = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
+ (void) snprintf(newpath, MAXPATHLEN, ztest_dev_template,
+ ztest_opts.zo_dir, ztest_opts.zo_pool, rzvd->vdev_children);
+ /*
+ * Build the nvlist describing newpath.
+ */
+ root = make_vdev_root(newpath, NULL, NULL, csize, ztest_get_ashift(),
+ NULL, 0, 0, 1);
+ /*
+ * Expand the raidz vdev by attaching the new disk
+ */
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("expanding raidz: %d wide to %d wide with '%s'\n",
+ (int)rzvd->vdev_children, (int)rzvd->vdev_children + 1,
+ newpath);
+ }
+ error = spa_vdev_attach(spa, rzvd->vdev_guid, root, B_FALSE, B_FALSE);
+ nvlist_free(root);
+ if (error != 0) {
+ fatal(0, "raidz expand: attach (%s %llu) returned %d",
+ newpath, (long long)csize, error);
+ }
+
+ /*
+ * Wait for reflow to begin
+ */
+ while (spa->spa_raidz_expand == NULL) {
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ (void) poll(NULL, 0, 100); /* wait 1/10 second */
+ }
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ (void) spa_raidz_expand_get_stats(spa, pres);
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ while (pres->pres_state != DSS_SCANNING) {
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ (void) poll(NULL, 0, 100); /* wait 1/10 second */
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ (void) spa_raidz_expand_get_stats(spa, pres);
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ }
+
+ ASSERT3U(pres->pres_state, ==, DSS_SCANNING);
+ ASSERT3U(pres->pres_to_reflow, !=, 0);
+ /*
+ * Set so when we are killed we go to raidz checking rather than
+ * restarting test.
+ */
+ ztest_shared_opts->zo_raidz_expand_test = RAIDZ_EXPAND_KILLED;
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("raidz expansion reflow started, waiting for "
+ "%llu bytes to be copied\n", (u_longlong_t)reflow_max);
+ }
+
+ /*
+ * Wait for reflow maximum to be reached and then kill the test
+ */
+ while (pres->pres_reflowed < reflow_max) {
+ txg_wait_synced(spa_get_dsl(spa), 0);
+ (void) poll(NULL, 0, 100); /* wait 1/10 second */
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ (void) spa_raidz_expand_get_stats(spa, pres);
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ }
+
+ /* Reset the reflow pause before killing */
+ raidz_expand_max_reflow_bytes = 0;
+
+ if (ztest_opts.zo_verbose >= 1) {
+ (void) printf("killing raidz expansion test after reflow "
+ "reached %llu bytes\n", (u_longlong_t)pres->pres_reflowed);
+ }
+
+ /*
+ * Kill ourself to simulate a panic during a reflow. Our parent will
+ * restart the test and the changed flag value will drive the test
+ * through the scrub/check code to verify the pool is not corrupted.
+ */
+ ztest_kill(zs);
+}
+
+static void
+ztest_generic_run(ztest_shared_t *zs, spa_t *spa)
+{
+ kthread_t **run_threads;
+ int t;
+
+ run_threads = umem_zalloc(ztest_opts.zo_threads * sizeof (kthread_t *),
+ UMEM_NOFAIL);
+
+ /*
+ * Kick off all the tests that run in parallel.
+ */
+ for (t = 0; t < ztest_opts.zo_threads; t++) {
+ if (t < ztest_opts.zo_datasets && ztest_dataset_open(t) != 0) {
+ umem_free(run_threads, ztest_opts.zo_threads *
+ sizeof (kthread_t *));
+ return;
+ }
+
+ run_threads[t] = thread_create(NULL, 0, ztest_thread,
+ (void *)(uintptr_t)t, 0, NULL, TS_RUN | TS_JOINABLE,
+ defclsyspri);
+ }
+
+ /*
+ * Wait for all of the tests to complete.
+ */
+ for (t = 0; t < ztest_opts.zo_threads; t++)
+ VERIFY0(thread_join(run_threads[t]));
+
+ /*
+ * Close all datasets. This must be done after all the threads
+ * are joined so we can be sure none of the datasets are in-use
+ * by any of the threads.
+ */
+ for (t = 0; t < ztest_opts.zo_threads; t++) {
+ if (t < ztest_opts.zo_datasets)
+ ztest_dataset_close(t);
+ }
+
+ txg_wait_synced(spa_get_dsl(spa), 0);
+
+ zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
+ zs->zs_space = metaslab_class_get_space(spa_normal_class(spa));
+
+ umem_free(run_threads, ztest_opts.zo_threads * sizeof (kthread_t *));
+}
+
+/*
+ * Setup our test context and kick off threads to run tests on all datasets
+ * in parallel.
*/
static void
ztest_run(ztest_shared_t *zs)
@@ -7513,7 +8275,6 @@ ztest_run(ztest_shared_t *zs)
spa_t *spa;
objset_t *os;
kthread_t *resume_thread, *deadman_thread;
- kthread_t **run_threads;
uint64_t object;
int error;
int t, d;
@@ -7546,6 +8307,7 @@ ztest_run(ztest_shared_t *zs)
* Open our pool. It may need to be imported first depending on
* what tests were running when the previous pass was terminated.
*/
+ raidz_scratch_verify();
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE);
error = spa_open(ztest_opts.zo_pool, &spa, FTAG);
if (error) {
@@ -7559,7 +8321,11 @@ ztest_run(ztest_shared_t *zs)
metaslab_preload_limit = ztest_random(20) + 1;
ztest_spa = spa;
- VERIFY0(vdev_raidz_impl_set("cycle"));
+ /*
+ * XXX - BUGBUG raidz expansion do not run this for generic for now
+ */
+ if (ztest_opts.zo_raidz_expand_test != RAIDZ_EXPAND_NONE)
+ VERIFY0(vdev_raidz_impl_set("cycle"));
dmu_objset_stats_t dds;
VERIFY0(ztest_dmu_objset_own(ztest_opts.zo_pool,
@@ -7567,9 +8333,12 @@ ztest_run(ztest_shared_t *zs)
dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
dmu_objset_fast_stat(os, &dds);
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
- zs->zs_guid = dds.dds_guid;
dmu_objset_disown(os, B_TRUE, FTAG);
+ /* Give the dedicated raidz expansion test more grace time */
+ if (ztest_opts.zo_raidz_expand_test != RAIDZ_EXPAND_NONE)
+ zfs_deadman_synctime_ms *= 2;
+
/*
* Create a thread to periodically resume suspended I/O.
*/
@@ -7603,6 +8372,10 @@ ztest_run(ztest_shared_t *zs)
* If we got any ENOSPC errors on the previous run, destroy something.
*/
if (zs->zs_enospc_count != 0) {
+ /* Not expecting ENOSPC errors during raidz expansion tests */
+ ASSERT3U(ztest_opts.zo_raidz_expand_test, ==,
+ RAIDZ_EXPAND_NONE);
+
int d = ztest_random(ztest_opts.zo_datasets);
ztest_dataset_destroy(d);
}
@@ -7617,9 +8390,12 @@ ztest_run(ztest_shared_t *zs)
* that we always run the scrub whenever an indirect vdev exists
* because we have no way of knowing for sure if ztest_device_removal()
* fully completed its scrub before the pool was reimported.
+ *
+ * Does not apply for the RAIDZ expansion specific test runs
*/
- if (spa->spa_removing_phys.sr_state == DSS_SCANNING ||
- spa->spa_removing_phys.sr_prev_indirect_vdev != -1) {
+ if (ztest_opts.zo_raidz_expand_test == RAIDZ_EXPAND_NONE &&
+ (spa->spa_removing_phys.sr_state == DSS_SCANNING ||
+ spa->spa_removing_phys.sr_prev_indirect_vdev != -1)) {
while (spa->spa_removing_phys.sr_state == DSS_SCANNING)
txg_wait_synced(spa_get_dsl(spa), 0);
@@ -7629,9 +8405,6 @@ ztest_run(ztest_shared_t *zs)
ASSERT0(error);
}
- run_threads = umem_zalloc(ztest_opts.zo_threads * sizeof (kthread_t *),
- UMEM_NOFAIL);
-
if (ztest_opts.zo_verbose >= 4)
(void) printf("starting main threads...\n");
@@ -7644,43 +8417,12 @@ ztest_run(ztest_shared_t *zs)
(void) dmu_objset_find(ztest_opts.zo_pool, ztest_replay_zil_cb,
NULL, DS_FIND_CHILDREN);
- /*
- * Kick off all the tests that run in parallel.
- */
- for (t = 0; t < ztest_opts.zo_threads; t++) {
- if (t < ztest_opts.zo_datasets && ztest_dataset_open(t) != 0) {
- umem_free(run_threads, ztest_opts.zo_threads *
- sizeof (kthread_t *));
- return;
- }
-
- run_threads[t] = thread_create(NULL, 0, ztest_thread,
- (void *)(uintptr_t)t, 0, NULL, TS_RUN | TS_JOINABLE,
- defclsyspri);
- }
-
- /*
- * Wait for all of the tests to complete.
- */
- for (t = 0; t < ztest_opts.zo_threads; t++)
- VERIFY0(thread_join(run_threads[t]));
-
- /*
- * Close all datasets. This must be done after all the threads
- * are joined so we can be sure none of the datasets are in-use
- * by any of the threads.
- */
- for (t = 0; t < ztest_opts.zo_threads; t++) {
- if (t < ztest_opts.zo_datasets)
- ztest_dataset_close(t);
- }
-
- txg_wait_synced(spa_get_dsl(spa), 0);
-
- zs->zs_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
- zs->zs_space = metaslab_class_get_space(spa_normal_class(spa));
-
- umem_free(run_threads, ztest_opts.zo_threads * sizeof (kthread_t *));
+ if (ztest_opts.zo_raidz_expand_test == RAIDZ_EXPAND_REQUESTED)
+ ztest_raidz_expand_run(zs, spa);
+ else if (ztest_opts.zo_raidz_expand_test == RAIDZ_EXPAND_KILLED)
+ ztest_raidz_expand_check(spa);
+ else
+ ztest_generic_run(zs, spa);
/* Kill the resume and deadman threads */
ztest_exiting = B_TRUE;
@@ -7789,6 +8531,7 @@ ztest_init(ztest_shared_t *zs)
mutex_init(&ztest_checkpoint_lock, NULL, MUTEX_DEFAULT, NULL);
VERIFY0(pthread_rwlock_init(&ztest_name_lock, NULL));
+ raidz_scratch_verify();
kernel_init(SPA_MODE_READ | SPA_MODE_WRITE);
/*
@@ -7838,14 +8581,15 @@ ztest_init(ztest_shared_t *zs)
VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
zs->zs_metaslab_sz =
1ULL << spa->spa_root_vdev->vdev_child[0]->vdev_ms_shift;
+ zs->zs_guid = spa_guid(spa);
spa_close(spa, FTAG);
kernel_fini();
if (!ztest_opts.zo_mmp_test) {
- ztest_run_zdb(ztest_opts.zo_pool);
+ ztest_run_zdb(zs->zs_guid);
ztest_freeze();
- ztest_run_zdb(ztest_opts.zo_pool);
+ ztest_run_zdb(zs->zs_guid);
}
(void) pthread_rwlock_destroy(&ztest_name_lock);
@@ -7873,6 +8617,7 @@ shared_data_size(ztest_shared_hdr_t *hdr)
size += hdr->zh_size;
size += hdr->zh_stats_size * hdr->zh_stats_count;
size += hdr->zh_ds_size * hdr->zh_ds_count;
+ size += hdr->zh_scratch_state_size;
return (size);
}
@@ -7896,6 +8641,7 @@ setup_hdr(void)
hdr->zh_stats_count = ZTEST_FUNCS;
hdr->zh_ds_size = sizeof (ztest_shared_ds_t);
hdr->zh_ds_count = ztest_opts.zo_datasets;
+ hdr->zh_scratch_state_size = sizeof (ztest_shared_scratch_state_t);
size = shared_data_size(hdr);
VERIFY0(ftruncate(ztest_fd_data, size));
@@ -7930,6 +8676,8 @@ setup_data(void)
ztest_shared_callstate = (void *)&buf[offset];
offset += hdr->zh_stats_size * hdr->zh_stats_count;
ztest_shared_ds = (void *)&buf[offset];
+ offset += hdr->zh_ds_size * hdr->zh_ds_count;
+ ztest_scratch_state = (void *)&buf[offset];
}
static boolean_t
@@ -7966,6 +8714,7 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
VERIFY3S(-1, !=,
asprintf(&newlp, "%s:%s", libpath, curlp));
VERIFY0(setenv("LD_LIBRARY_PATH", newlp, 1));
+ free(newlp);
}
}
(void) execl(cmd, cmd, (char *)NULL);
@@ -8149,13 +8898,14 @@ main(int argc, char **argv)
hasalt = (strlen(ztest_opts.zo_alt_ztest) != 0);
if (ztest_opts.zo_verbose >= 1) {
- (void) printf("%"PRIu64" vdevs, %d datasets, %d threads,"
- "%d %s disks, %"PRIu64" seconds...\n\n",
+ (void) printf("%"PRIu64" vdevs, %d datasets, %d threads, "
+ "%d %s disks, parity %d, %"PRIu64" seconds...\n\n",
ztest_opts.zo_vdevs,
ztest_opts.zo_datasets,
ztest_opts.zo_threads,
ztest_opts.zo_raid_children,
ztest_opts.zo_raid_type,
+ ztest_opts.zo_raid_parity,
ztest_opts.zo_time);
}
@@ -8267,7 +9017,10 @@ main(int argc, char **argv)
}
if (!ztest_opts.zo_mmp_test)
- ztest_run_zdb(ztest_opts.zo_pool);
+ ztest_run_zdb(zs->zs_guid);
+ if (ztest_shared_opts->zo_raidz_expand_test ==
+ RAIDZ_EXPAND_CHECKED)
+ break; /* raidz expand test complete */
}
if (ztest_opts.zo_verbose >= 1) {
diff --git a/cmd/zvol_wait b/cmd/zvol_wait
index f1fa42e27dc9..0b2a8a3e60c3 100755
--- a/cmd/zvol_wait
+++ b/cmd/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/Rules.am b/config/Rules.am
index 7162b771869d..30c5f353cd23 100644
--- a/config/Rules.am
+++ b/config/Rules.am
@@ -21,7 +21,9 @@ AM_CFLAGS += $(IMPLICIT_FALLTHROUGH)
AM_CFLAGS += $(DEBUG_CFLAGS)
AM_CFLAGS += $(ASAN_CFLAGS)
AM_CFLAGS += $(UBSAN_CFLAGS)
-AM_CFLAGS += $(CODE_COVERAGE_CFLAGS) $(NO_FORMAT_ZERO_LENGTH)
+AM_CFLAGS += $(CODE_COVERAGE_CFLAGS)
+AM_CFLAGS += $(NO_FORMAT_ZERO_LENGTH)
+AM_CFLAGS += $(NO_FORMAT_TRUNCATION)
if BUILD_FREEBSD
AM_CFLAGS += -fPIC -Werror -Wno-unknown-pragmas -Wno-enum-conversion
AM_CFLAGS += -include $(top_srcdir)/include/os/freebsd/spl/sys/ccompile.h
@@ -33,6 +35,7 @@ AM_CPPFLAGS += -D_REENTRANT
AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE
AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\"
+AM_CPPFLAGS += -DZFSEXECDIR=\"$(zfsexecdir)\"
AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\"
AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\"
AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\"
@@ -41,19 +44,6 @@ AM_CPPFLAGS += $(DEBUG_CPPFLAGS)
AM_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS)
AM_CPPFLAGS += -DTEXT_DOMAIN=\"zfs-@ac_system_l@-user\"
-AM_CPPFLAGS_NOCHECK = -D"strtok(...)=strtok(__VA_ARGS__) __attribute__((deprecated(\"Use strtok_r(3) instead!\")))"
-AM_CPPFLAGS_NOCHECK += -D"__xpg_basename(...)=__xpg_basename(__VA_ARGS__) __attribute__((deprecated(\"basename(3) is underspecified. Use zfs_basename() instead!\")))"
-AM_CPPFLAGS_NOCHECK += -D"basename(...)=basename(__VA_ARGS__) __attribute__((deprecated(\"basename(3) is underspecified. Use zfs_basename() instead!\")))"
-AM_CPPFLAGS_NOCHECK += -D"dirname(...)=dirname(__VA_ARGS__) __attribute__((deprecated(\"dirname(3) is underspecified. Use zfs_dirnamelen() instead!\")))"
-AM_CPPFLAGS_NOCHECK += -D"bcopy(...)=__attribute__((deprecated(\"bcopy(3) is deprecated. Use memcpy(3)/memmove(3) instead!\"))) bcopy(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"bcmp(...)=__attribute__((deprecated(\"bcmp(3) is deprecated. Use memcmp(3) instead!\"))) bcmp(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"bzero(...)=__attribute__((deprecated(\"bzero(3) is deprecated. Use memset(3) instead!\"))) bzero(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"asctime(...)=__attribute__((deprecated(\"Use strftime(3) instead!\"))) asctime(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"asctime_r(...)=__attribute__((deprecated(\"Use strftime(3) instead!\"))) asctime_r(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"gmtime(...)=__attribute__((deprecated(\"gmtime(3) isn't thread-safe. Use gmtime_r(3) instead!\"))) gmtime(__VA_ARGS__)"
-AM_CPPFLAGS_NOCHECK += -D"localtime(...)=__attribute__((deprecated(\"localtime(3) isn't thread-safe. Use localtime_r(3) instead!\"))) localtime(__VA_ARGS__)"
-AM_CPPFLAGS += $(AM_CPPFLAGS_NOCHECK)
-
if ASAN_ENABLED
AM_CPPFLAGS += -DZFS_ASAN_ENABLED
endif
diff --git a/config/Shellcheck.am b/config/Shellcheck.am
index 878919575321..1ab13516066c 100644
--- a/config/Shellcheck.am
+++ b/config/Shellcheck.am
@@ -3,6 +3,8 @@
# ShellCheck can't follow non-constant source. Use a directive to specify location. [SC1090]
# Not following: a was not specified as input (see shellcheck -x). [SC1091]
# Prefer putting braces around variable references even when not strictly required. [SC2250]
+# Consider invoking this command separately to avoid masking its return value (or use '|| true' to ignore). [SC2312]
+# Command appears to be unreachable. Check usage (or ignore if invoked indirectly). [SC2317]
# In POSIX sh, 'local' is undefined. [SC2039] # older ShellCheck versions
# In POSIX sh, 'local' is undefined. [SC3043] # newer ShellCheck versions
@@ -17,7 +19,7 @@ PHONY += shellcheck
_STGT = $(subst ^,/,$(subst shellcheck-here-,,$@))
shellcheck-here-%:
if HAVE_SHELLCHECK
- shellcheck --format=gcc --enable=all --exclude=SC1090,SC1091,SC2039,SC2250,SC3043 $$([ -n "$(SHELLCHECK_SHELL)" ] && echo "--shell=$(SHELLCHECK_SHELL)") "$$([ -e "$(_STGT)" ] || echo "$(srcdir)/")$(_STGT)"
+ shellcheck --format=gcc --enable=all --exclude=SC1090,SC1091,SC2039,SC2250,SC2312,SC2317,SC3043 $$([ -n "$(SHELLCHECK_SHELL)" ] && echo "--shell=$(SHELLCHECK_SHELL)") "$$([ -e "$(_STGT)" ] || echo "$(srcdir)/")$(_STGT)"
else
@echo "skipping shellcheck of" $(_STGT) "because shellcheck is not installed"
endif
diff --git a/config/Substfiles.am b/config/Substfiles.am
index 38e870b2f501..2459637abe6e 100644
--- a/config/Substfiles.am
+++ b/config/Substfiles.am
@@ -18,6 +18,7 @@ subst_sed_cmd = \
-e 's|@ASAN_ENABLED[@]|$(ASAN_ENABLED)|g' \
-e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \
-e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g' \
+ -e 's|@IS_SYSV_RC[@]|$(IS_SYSV_RC)|g' \
-e 's|@LIBFETCH_DYNAMIC[@]|$(LIBFETCH_DYNAMIC)|g' \
-e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g' \
-e 's|@PYTHON[@]|$(PYTHON)|g' \
@@ -43,4 +44,4 @@ SUBSTFILES =
CLEANFILES += $(SUBSTFILES)
dist_noinst_DATA += $(SUBSTFILES:=.in)
-$(call SUBST,%,)
+$(SUBSTFILES): $(call SUBST,%,)
diff --git a/config/always-arch.m4 b/config/always-arch.m4
index f7090a4826ba..9f413eeddf95 100644
--- a/config/always-arch.m4
+++ b/config/always-arch.m4
@@ -22,6 +22,9 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_ARCH], [
aarch64*)
TARGET_CPU=aarch64
;;
+ armv*)
+ TARGET_CPU=arm
+ ;;
sparc64)
TARGET_CPU=sparc64
;;
@@ -31,7 +34,8 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_ARCH], [
esac
AM_CONDITIONAL([TARGET_CPU_AARCH64], test $TARGET_CPU = aarch64)
- AM_CONDITIONAL([TARGET_CPU_X86_64], test $TARGET_CPU = x86_64)
+ AM_CONDITIONAL([TARGET_CPU_X86_64], test $TARGET_CPU = x86_64)
AM_CONDITIONAL([TARGET_CPU_POWERPC], test $TARGET_CPU = powerpc)
AM_CONDITIONAL([TARGET_CPU_SPARC64], test $TARGET_CPU = sparc64)
+ AM_CONDITIONAL([TARGET_CPU_ARM], test $TARGET_CPU = arm)
])
diff --git a/config/always-compiler-options.m4 b/config/always-compiler-options.m4
index a67319691523..6383b12506ee 100644
--- a/config/always-compiler-options.m4
+++ b/config/always-compiler-options.m4
@@ -228,6 +228,62 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_INFINITE_RECURSION], [
])
dnl #
+dnl # Check if kernel cc supports -Winfinite-recursion option.
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_INFINITE_RECURSION], [
+ AC_MSG_CHECKING([whether $KERNEL_CC supports -Winfinite-recursion])
+
+ saved_cc="$CC"
+ saved_flags="$CFLAGS"
+ CC="gcc"
+ CFLAGS="$CFLAGS -Werror -Winfinite-recursion"
+
+ AS_IF([ test -n "$KERNEL_CC" ], [
+ CC="$KERNEL_CC"
+ ])
+ AS_IF([ test -n "$KERNEL_LLVM" ], [
+ CC="clang"
+ ])
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
+ KERNEL_INFINITE_RECURSION=-Winfinite-recursion
+ AC_DEFINE([HAVE_KERNEL_INFINITE_RECURSION], 1,
+ [Define if compiler supports -Winfinite-recursion])
+ AC_MSG_RESULT([yes])
+ ], [
+ KERNEL_INFINITE_RECURSION=
+ AC_MSG_RESULT([no])
+ ])
+
+ CC="$saved_cc"
+ CFLAGS="$saved_flags"
+ AC_SUBST([KERNEL_INFINITE_RECURSION])
+])
+
+dnl #
+dnl # Check if cc supports -Wformat-overflow option.
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_FORMAT_OVERFLOW], [
+ AC_MSG_CHECKING([whether $CC supports -Wformat-overflow])
+
+ saved_flags="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wformat-overflow"
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
+ FORMAT_OVERFLOW=-Wformat-overflow
+ AC_DEFINE([HAVE_FORMAT_OVERFLOW], 1,
+ [Define if compiler supports -Wformat-overflow])
+ AC_MSG_RESULT([yes])
+ ], [
+ FORMAT_OVERFLOW=
+ AC_MSG_RESULT([no])
+ ])
+
+ CFLAGS="$saved_flags"
+ AC_SUBST([FORMAT_OVERFLOW])
+])
+
+dnl #
dnl # Check if cc supports -fno-omit-frame-pointer option.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_OMIT_FRAME_POINTER], [
@@ -268,3 +324,34 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_IPA_SRA], [
CFLAGS="$saved_flags"
AC_SUBST([NO_IPA_SRA])
])
+
+dnl #
+dnl # Check if kernel cc supports -fno-ipa-sra option.
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_NO_IPA_SRA], [
+ AC_MSG_CHECKING([whether $KERNEL_CC supports -fno-ipa-sra])
+
+ saved_cc="$CC"
+ saved_flags="$CFLAGS"
+ CC="gcc"
+ CFLAGS="$CFLAGS -Werror -fno-ipa-sra"
+
+ AS_IF([ test -n "$KERNEL_CC" ], [
+ CC="$KERNEL_CC"
+ ])
+ AS_IF([ test -n "$KERNEL_LLVM" ], [
+ CC="clang"
+ ])
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
+ KERNEL_NO_IPA_SRA=-fno-ipa-sra
+ AC_MSG_RESULT([yes])
+ ], [
+ KERNEL_NO_IPA_SRA=
+ AC_MSG_RESULT([no])
+ ])
+
+ CC="$saved_cc"
+ CFLAGS="$saved_flags"
+ AC_SUBST([KERNEL_NO_IPA_SRA])
+])
diff --git a/config/always-pyzfs.m4 b/config/always-pyzfs.m4
index 996a2a6e2401..98c1cc230205 100644
--- a/config/always-pyzfs.m4
+++ b/config/always-pyzfs.m4
@@ -47,6 +47,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 #
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
@@ -70,10 +80,11 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
[AC_MSG_ERROR("Python $PYTHON_VERSION unknown")]
)
- AX_PYTHON_DEVEL([$PYTHON_REQUIRED_VERSION], [
- AS_IF([test "x$enable_pyzfs" = xyes], [
- AC_MSG_ERROR("Python $PYTHON_REQUIRED_VERSION development library is not installed")
- ], [test "x$enable_pyzfs" != xno], [
+ AS_IF([test "x$enable_pyzfs" = xyes], [
+ AX_PYTHON_DEVEL([$PYTHON_REQUIRED_VERSION])
+ ], [
+ AX_PYTHON_DEVEL([$PYTHON_REQUIRED_VERSION], [true])
+ AS_IF([test "x$ax_python_devel_found" = xno], [
enable_pyzfs=no
])
])
diff --git a/config/ax_python_devel.m4 b/config/ax_python_devel.m4
index 7adcf01a04cd..1f480db6d233 100644
--- a/config/ax_python_devel.m4
+++ b/config/ax_python_devel.m4
@@ -4,18 +4,13 @@
#
# SYNOPSIS
#
-# AX_PYTHON_DEVEL([version], [action-if-not-found])
+# AX_PYTHON_DEVEL([version[,optional]])
#
# DESCRIPTION
#
# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it
# in your configure.ac.
#
-# Note: this is a slightly modified version of the original AX_PYTHON_DEVEL
-# macro which accepts an additional [action-if-not-found] argument. This
-# allow to detect if Python development is available without aborting the
-# configure phase with an hard error in case it is not.
-#
# This macro checks for Python and tries to get the include path to
# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LIBS) output
# variables. It also exports $(PYTHON_EXTRA_LIBS) and
@@ -28,6 +23,11 @@
# version number. Don't use "PYTHON_VERSION" for this: that environment
# variable is declared as precious and thus reserved for the end-user.
#
+# By default this will fail if it does not detect a development version of
+# python. If you want it to continue, set optional to true, like
+# AX_PYTHON_DEVEL([], [true]). The ax_python_devel_found variable will be
+# "no" if it fails.
+#
# This macro should work for all versions of Python >= 2.1.0. As an end
# user, you can disable the check for the python version by setting the
# PYTHON_NOVERSIONCHECK environment variable to something else than the
@@ -45,7 +45,6 @@
# Copyright (c) 2009 Matteo Settenvini <matteo@member.fsf.org>
# Copyright (c) 2009 Horst Knorr <hk_classes@knoda.org>
# Copyright (c) 2013 Daniel Mullner <muellner@math.stanford.edu>
-# Copyright (c) 2018 loli10K <ezomori.nozomu@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@@ -73,10 +72,18 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 21
+#serial 36
AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
AC_DEFUN([AX_PYTHON_DEVEL],[
+ # Get whether it's optional
+ if test -z "$2"; then
+ ax_python_devel_optional=false
+ else
+ ax_python_devel_optional=$2
+ fi
+ ax_python_devel_found=yes
+
#
# Allow the use of a (user set) custom python version
#
@@ -87,33 +94,26 @@ AC_DEFUN([AX_PYTHON_DEVEL],[
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
if test -z "$PYTHON"; then
- m4_ifvaln([$2],[$2],[
- AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
- PYTHON_VERSION=""
- ])
+ AC_MSG_WARN([Cannot find python$PYTHON_VERSION in your system path])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_ERROR([Giving up, python development not available])
+ fi
+ ax_python_devel_found=no
+ PYTHON_VERSION=""
fi
- #
- # Check for a version of Python >= 2.1.0
- #
- AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
- ac_supports_python_ver=`cat<<EOD | $PYTHON -
-from __future__ import print_function;
-import sys;
-try:
- from packaging import version;
-except ImportError:
- from distlib import version;
-ver = sys.version.split ()[[0]];
-(tst_cmp, tst_ver) = ">= '2.1.0'".split ();
-tst_ver = tst_ver.strip ("'");
-eval ("print (version.LegacyVersion (ver)"+ tst_cmp +"version.LegacyVersion (tst_ver))")
-EOD`
- if test "$ac_supports_python_ver" != "True"; then
+ if test $ax_python_devel_found = yes; then
+ #
+ # Check for a version of Python >= 2.1.0
+ #
+ AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[[0]]; \
+ print (ver >= '2.1.0')"`
+ if test "$ac_supports_python_ver" != "True"; then
if test -z "$PYTHON_NOVERSIONCHECK"; then
AC_MSG_RESULT([no])
- m4_ifvaln([$2],[$2],[
- AC_MSG_FAILURE([
+ AC_MSG_WARN([
This version of the AC@&t@_PYTHON_DEVEL macro
doesn't work properly with versions of Python before
2.1.0. You may need to re-run configure, setting the
@@ -122,74 +122,119 @@ PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
to something else than an empty string.
])
- ])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_FAILURE([Giving up])
+ fi
+ ax_python_devel_found=no
+ PYTHON_VERSION=""
else
AC_MSG_RESULT([skip at user request])
fi
- else
+ else
AC_MSG_RESULT([yes])
+ fi
fi
- #
- # if the macro parameter ``version'' is set, honour it
- #
- if test -n "$1"; then
+ if test $ax_python_devel_found = yes; then
+ #
+ # If the macro parameter ``version'' is set, honour it.
+ # A Python shim class, VPy, is used to implement correct version comparisons via
+ # string expressions, since e.g. a naive textual ">= 2.7.3" won't work for
+ # Python 2.7.10 (the ".1" being evaluated as less than ".3").
+ #
+ if test -n "$1"; then
AC_MSG_CHECKING([for a version of Python $1])
- # Why the strip ()? Because if we don't, version.parse
- # will, for example, report 3.10.0 >= '3.11.0'
- ac_supports_python_ver=`cat<<EOD | $PYTHON -
-
-from __future__ import print_function;
-import sys;
-try:
- from packaging import version;
-except ImportError:
- from distlib import version;
-ver = sys.version.split ()[[0]];
-(tst_cmp, tst_ver) = "$1".split ();
-tst_ver = tst_ver.strip ("'");
-eval ("print (version.LegacyVersion (ver)"+ tst_cmp +"version.LegacyVersion (tst_ver))")
-EOD`
+ cat << EOF > ax_python_devel_vpy.py
+class VPy:
+ def vtup(self, s):
+ return tuple(map(int, s.strip().replace("rc", ".").split(".")))
+ def __init__(self):
+ import sys
+ self.vpy = tuple(sys.version_info)[[:3]]
+ def __eq__(self, s):
+ return self.vpy == self.vtup(s)
+ def __ne__(self, s):
+ return self.vpy != self.vtup(s)
+ def __lt__(self, s):
+ return self.vpy < self.vtup(s)
+ def __gt__(self, s):
+ return self.vpy > self.vtup(s)
+ def __le__(self, s):
+ return self.vpy <= self.vtup(s)
+ def __ge__(self, s):
+ return self.vpy >= self.vtup(s)
+EOF
+ ac_supports_python_ver=`$PYTHON -c "import ax_python_devel_vpy; \
+ ver = ax_python_devel_vpy.VPy(); \
+ print (ver $1)"`
+ rm -rf ax_python_devel_vpy*.py* __pycache__/ax_python_devel_vpy*.py*
if test "$ac_supports_python_ver" = "True"; then
- AC_MSG_RESULT([yes])
+ AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
- m4_ifvaln([$2],[$2],[
- AC_MSG_ERROR([this package requires Python $1.
+ AC_MSG_WARN([this package requires Python $1.
If you have it installed, but it isn't the default Python
interpreter in your system path, please pass the PYTHON_VERSION
variable to configure. See ``configure --help'' for reference.
])
- PYTHON_VERSION=""
- ])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_ERROR([Giving up])
+ fi
+ ax_python_devel_found=no
+ PYTHON_VERSION=""
fi
+ fi
fi
- #
- # Check if you have distutils, else fail
- #
- AC_MSG_CHECKING([for the distutils Python package])
- if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
+ if test $ax_python_devel_found = yes; then
+ #
+ # Check if you have distutils, else fail
+ #
+ AC_MSG_CHECKING([for the sysconfig Python package])
+ ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`
+ if test $? -eq 0; then
AC_MSG_RESULT([yes])
- else
+ IMPORT_SYSCONFIG="import sysconfig"
+ else
AC_MSG_RESULT([no])
- m4_ifvaln([$2],[$2],[
- AC_MSG_ERROR([cannot import Python module "distutils".
+
+ AC_MSG_CHECKING([for the distutils Python package])
+ ac_sysconfig_result=`$PYTHON -c "from distutils import sysconfig" 2>&1`
+ if test $? -eq 0; then
+ AC_MSG_RESULT([yes])
+ IMPORT_SYSCONFIG="from distutils import sysconfig"
+ else
+ AC_MSG_WARN([cannot import Python module "distutils".
Please check your Python installation. The error was:
-$ac_distutils_result])
+$ac_sysconfig_result])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_ERROR([Giving up])
+ fi
+ ax_python_devel_found=no
PYTHON_VERSION=""
- ])
+ fi
+ fi
fi
- #
- # Check for Python include path
- #
- AC_MSG_CHECKING([for Python include path])
- if test -z "$PYTHON_CPPFLAGS"; then
- python_path=`$PYTHON -c "import distutils.sysconfig; \
- print (distutils.sysconfig.get_python_inc ());"`
- plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
- print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
+ if test $ax_python_devel_found = yes; then
+ #
+ # Check for Python include path
+ #
+ AC_MSG_CHECKING([for Python include path])
+ if test -z "$PYTHON_CPPFLAGS"; then
+ if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+ # sysconfig module has different functions
+ python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_path ('include'));"`
+ plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_path ('platinclude'));"`
+ else
+ # old distutils way
+ python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_python_inc ());"`
+ plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_python_inc (plat_specific=1));"`
+ fi
if test -n "${python_path}"; then
if test "${plat_python_path}" != "${python_path}"; then
python_path="-I$python_path -I$plat_python_path"
@@ -198,22 +243,22 @@ $ac_distutils_result])
fi
fi
PYTHON_CPPFLAGS=$python_path
- fi
- AC_MSG_RESULT([$PYTHON_CPPFLAGS])
- AC_SUBST([PYTHON_CPPFLAGS])
+ fi
+ AC_MSG_RESULT([$PYTHON_CPPFLAGS])
+ AC_SUBST([PYTHON_CPPFLAGS])
- #
- # Check for Python library path
- #
- AC_MSG_CHECKING([for Python library path])
- if test -z "$PYTHON_LIBS"; then
+ #
+ # Check for Python library path
+ #
+ AC_MSG_CHECKING([for Python library path])
+ if test -z "$PYTHON_LIBS"; then
# (makes two attempts to ensure we've got a version number
# from the interpreter)
ac_python_version=`cat<<EOD | $PYTHON -
# join all versioning strings, on some systems
# major/minor numbers could be in different list elements
-from distutils.sysconfig import *
+from sysconfig import *
e = get_config_var('VERSION')
if e is not None:
print(e)
@@ -224,7 +269,7 @@ EOD`
ac_python_version=$PYTHON_VERSION
else
ac_python_version=`$PYTHON -c "import sys; \
- print ('.'.join(sys.version.split('.')[[:2]]))"`
+ print ("%d.%d" % sys.version_info[[:2]])"`
fi
fi
@@ -236,8 +281,8 @@ EOD`
ac_python_libdir=`cat<<EOD | $PYTHON -
# There should be only one
-import distutils.sysconfig
-e = distutils.sysconfig.get_config_var('LIBDIR')
+$IMPORT_SYSCONFIG
+e = sysconfig.get_config_var('LIBDIR')
if e is not None:
print (e)
EOD`
@@ -245,8 +290,8 @@ EOD`
# Now, for the library:
ac_python_library=`cat<<EOD | $PYTHON -
-import distutils.sysconfig
-c = distutils.sysconfig.get_config_vars()
+$IMPORT_SYSCONFIG
+c = sysconfig.get_config_vars()
if 'LDVERSION' in c:
print ('python'+c[['LDVERSION']])
else:
@@ -265,86 +310,140 @@ EOD`
else
# old way: use libpython from python_configdir
ac_python_libdir=`$PYTHON -c \
- "from distutils.sysconfig import get_python_lib as f; \
+ "from sysconfig import get_python_lib as f; \
import os; \
print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version"
fi
if test -z "PYTHON_LIBS"; then
- m4_ifvaln([$2],[$2],[
- AC_MSG_ERROR([
+ AC_MSG_WARN([
Cannot determine location of your Python DSO. Please check it was installed with
dynamic libraries enabled, or try setting PYTHON_LIBS by hand.
- ])
])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_ERROR([Giving up])
+ fi
+ ax_python_devel_found=no
+ PYTHON_VERSION=""
fi
+ fi
fi
- AC_MSG_RESULT([$PYTHON_LIBS])
- AC_SUBST([PYTHON_LIBS])
- #
- # Check for site packages
- #
- AC_MSG_CHECKING([for Python site-packages path])
- if test -z "$PYTHON_SITE_PKG"; then
- PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
- print (distutils.sysconfig.get_python_lib(0,0));"`
- fi
- AC_MSG_RESULT([$PYTHON_SITE_PKG])
- AC_SUBST([PYTHON_SITE_PKG])
+ if test $ax_python_devel_found = yes; then
+ AC_MSG_RESULT([$PYTHON_LIBS])
+ AC_SUBST([PYTHON_LIBS])
- #
- # libraries which must be linked in when embedding
- #
- AC_MSG_CHECKING(python extra libraries)
- if test -z "$PYTHON_EXTRA_LIBS"; then
- PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
- conf = distutils.sysconfig.get_config_var; \
+ #
+ # Check for site packages
+ #
+ AC_MSG_CHECKING([for Python site-packages path])
+ if test -z "$PYTHON_SITE_PKG"; then
+ if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+ PYTHON_SITE_PKG=`$PYTHON -c "
+$IMPORT_SYSCONFIG;
+if hasattr(sysconfig, 'get_default_scheme'):
+ scheme = sysconfig.get_default_scheme()
+else:
+ scheme = sysconfig._get_default_scheme()
+if scheme == 'posix_local':
+ # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/
+ scheme = 'posix_prefix'
+prefix = '$prefix'
+if prefix == 'NONE':
+ prefix = '$ac_default_prefix'
+sitedir = sysconfig.get_path('purelib', scheme, vars={'base': prefix})
+print(sitedir)"`
+ else
+ # distutils.sysconfig way
+ PYTHON_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_python_lib(0,0));"`
+ fi
+ fi
+ AC_MSG_RESULT([$PYTHON_SITE_PKG])
+ AC_SUBST([PYTHON_SITE_PKG])
+
+ #
+ # Check for platform-specific site packages
+ #
+ AC_MSG_CHECKING([for Python platform specific site-packages path])
+ if test -z "$PYTHON_PLATFORM_SITE_PKG"; then
+ if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+ PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c "
+$IMPORT_SYSCONFIG;
+if hasattr(sysconfig, 'get_default_scheme'):
+ scheme = sysconfig.get_default_scheme()
+else:
+ scheme = sysconfig._get_default_scheme()
+if scheme == 'posix_local':
+ # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/
+ scheme = 'posix_prefix'
+prefix = '$prefix'
+if prefix == 'NONE':
+ prefix = '$ac_default_prefix'
+sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase': prefix})
+print(sitedir)"`
+ else
+ # distutils.sysconfig way
+ PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ print (sysconfig.get_python_lib(1,0));"`
+ fi
+ fi
+ AC_MSG_RESULT([$PYTHON_PLATFORM_SITE_PKG])
+ AC_SUBST([PYTHON_PLATFORM_SITE_PKG])
+
+ #
+ # libraries which must be linked in when embedding
+ #
+ AC_MSG_CHECKING(python extra libraries)
+ if test -z "$PYTHON_EXTRA_LIBS"; then
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ conf = sysconfig.get_config_var; \
print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
- fi
- AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
- AC_SUBST(PYTHON_EXTRA_LIBS)
+ fi
+ AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+ AC_SUBST(PYTHON_EXTRA_LIBS)
- #
- # linking flags needed when embedding
- #
- AC_MSG_CHECKING(python extra linking flags)
- if test -z "$PYTHON_EXTRA_LDFLAGS"; then
- PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
- conf = distutils.sysconfig.get_config_var; \
+ #
+ # linking flags needed when embedding
+ #
+ AC_MSG_CHECKING(python extra linking flags)
+ if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+ PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+ conf = sysconfig.get_config_var; \
print (conf('LINKFORSHARED'))"`
- fi
- AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
- AC_SUBST(PYTHON_EXTRA_LDFLAGS)
+ # Hack for macos, it sticks this in here.
+ PYTHON_EXTRA_LDFLAGS=`echo $PYTHON_EXTRA_LDFLAGS | sed 's/CoreFoundation.*$/CoreFoundation/'`
+ fi
+ AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+ AC_SUBST(PYTHON_EXTRA_LDFLAGS)
- #
- # final check to see if everything compiles alright
- #
- AC_MSG_CHECKING([consistency of all components of python development environment])
- # save current global flags
- ac_save_LIBS="$LIBS"
- ac_save_LDFLAGS="$LDFLAGS"
- ac_save_CPPFLAGS="$CPPFLAGS"
- LIBS="$ac_save_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_EXTRA_LIBS"
- LDFLAGS="$ac_save_LDFLAGS $PYTHON_EXTRA_LDFLAGS"
- CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
- AC_LANG_PUSH([C])
- AC_LINK_IFELSE([
+ #
+ # final check to see if everything compiles alright
+ #
+ AC_MSG_CHECKING([consistency of all components of python development environment])
+ # save current global flags
+ ac_save_LIBS="$LIBS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ LIBS="$ac_save_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS"
+ LDFLAGS="$ac_save_LDFLAGS $PYTHON_EXTRA_LDFLAGS"
+ CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([
AC_LANG_PROGRAM([[#include <Python.h>]],
[[Py_Initialize();]])
],[pythonexists=yes],[pythonexists=no])
- AC_LANG_POP([C])
- # turn back to default flags
- CPPFLAGS="$ac_save_CPPFLAGS"
- LIBS="$ac_save_LIBS"
- LDFLAGS="$ac_save_LDFLAGS"
+ AC_LANG_POP([C])
+ # turn back to default flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+ LDFLAGS="$ac_save_LDFLAGS"
- AC_MSG_RESULT([$pythonexists])
+ AC_MSG_RESULT([$pythonexists])
- if test ! "x$pythonexists" = "xyes"; then
- m4_ifvaln([$2],[$2],[
- AC_MSG_FAILURE([
+ if test ! "x$pythonexists" = "xyes"; then
+ AC_MSG_WARN([
Could not link test program to Python. Maybe the main Python library has been
installed in some non-standard library path. If so, pass it to configure,
via the LIBS environment variable.
@@ -354,9 +453,13 @@ EOD`
You probably have to install the development version of the Python package
for your distribution. The exact name of this package varies among them.
============================================================================
- ])
- PYTHON_VERSION=""
- ])
+ ])
+ if ! $ax_python_devel_optional; then
+ AC_MSG_ERROR([Giving up])
+ fi
+ ax_python_devel_found=no
+ PYTHON_VERSION=""
+ fi
fi
#
diff --git a/config/deb.am b/config/deb.am
index 0033dd7591ff..1379e58c40a8 100644
--- a/config/deb.am
+++ b/config/deb.am
@@ -1,14 +1,17 @@
-PHONY += deb-kmod deb-dkms deb-utils deb deb-local
+PHONY += deb-kmod deb-dkms deb-utils deb deb-local native-deb-local \
+ native-deb-utils native-deb-kmod native-deb
-deb-local:
+native-deb-local:
@(if test "${HAVE_DPKGBUILD}" = "no"; then \
echo -e "\n" \
"*** Required util ${DPKGBUILD} missing. Please install the\n" \
"*** package for your distribution which provides ${DPKGBUILD},\n" \
"*** re-run configure, and try again.\n"; \
exit 1; \
- fi; \
- if test "${HAVE_ALIEN}" = "no"; then \
+ fi)
+
+deb-local: native-deb-local
+ @(if test "${HAVE_ALIEN}" = "no"; then \
echo -e "\n" \
"*** Required util ${ALIEN} missing. Please install the\n" \
"*** package for your distribution which provides ${ALIEN},\n" \
@@ -67,7 +70,7 @@ deb-utils: deb-local rpm-utils-initramfs
## to do this, so we install a shim onto the path which calls the real
## dh_shlibdeps with the required arguments.
path_prepend=`mktemp -d /tmp/intercept.XXXXXX`; \
- echo "#$(SHELL)" > $${path_prepend}/dh_shlibdeps; \
+ echo "#!$(SHELL)" > $${path_prepend}/dh_shlibdeps; \
echo "`which dh_shlibdeps` -- \
-xlibuutil3linux -xlibnvpair3linux -xlibzfs5linux -xlibzpool5linux" \
>> $${path_prepend}/dh_shlibdeps; \
@@ -75,7 +78,7 @@ deb-utils: deb-local rpm-utils-initramfs
## Debianized packages from the auto-generated dependencies of the new debs,
## which should NOT be mixed with the alien-generated debs created here
chmod +x $${path_prepend}/dh_shlibdeps; \
- env PATH=$${path_prepend}:$${PATH} \
+ env "PATH=$${path_prepend}:$${PATH}" \
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \
$$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
$$pkg8 $$pkg9 $$pkg10 $$pkg11 || exit 1; \
@@ -85,3 +88,16 @@ deb-utils: deb-local rpm-utils-initramfs
$$pkg8 $$pkg9 $$pkg10 $$pkg11;
deb: deb-kmod deb-dkms deb-utils
+
+debian:
+ cp -r contrib/debian debian; chmod +x debian/rules;
+
+native-deb-utils: native-deb-local debian
+ cp contrib/debian/control debian/control; \
+ $(DPKGBUILD) -b -rfakeroot -us -uc;
+
+native-deb-kmod: native-deb-local debian
+ sh scripts/make_gitrev.sh; \
+ fakeroot debian/rules override_dh_binary-modules;
+
+native-deb: native-deb-utils native-deb-kmod
diff --git a/config/find_system_library.m4 b/config/find_system_library.m4
index 310b44112aea..8b98bd67d2ee 100644
--- a/config/find_system_library.m4
+++ b/config/find_system_library.m4
@@ -90,8 +90,8 @@ AC_DEFUN([ZFS_AC_FIND_SYSTEM_LIBRARY], [
AC_DEFINE([HAVE_][$1], [1], [Define if you have [$5]])
$7
],[dnl ELSE
- AC_SUBST([$1]_CFLAGS, [])
- AC_SUBST([$1]_LIBS, [])
+ AC_SUBST([$1]_CFLAGS, [""])
+ AC_SUBST([$1]_LIBS, [""])
AC_MSG_WARN([cannot find [$5] via pkg-config or in the standard locations])
$8
])
diff --git a/config/kernel-acl.m4 b/config/kernel-acl.m4
index a155b59d006a..3ae5dc6b6dbc 100644
--- a/config/kernel-acl.m4
+++ b/config/kernel-acl.m4
@@ -165,11 +165,14 @@ dnl #
dnl # 5.15 API change,
dnl # Added the bool rcu argument to get_acl for rcu path walk.
dnl #
+dnl # 6.2 API change,
+dnl # get_acl() was renamed to get_inode_acl()
+dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
#include <linux/fs.h>
- struct posix_acl *get_acl_fn(struct inode *inode, int type)
+ static struct posix_acl *get_acl_fn(struct inode *inode, int type)
{ return NULL; }
static const struct inode_operations
@@ -181,7 +184,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_get_acl_rcu], [
#include <linux/fs.h>
- struct posix_acl *get_acl_fn(struct inode *inode, int type,
+ static struct posix_acl *get_acl_fn(struct inode *inode, int type,
bool rcu) { return NULL; }
static const struct inode_operations
@@ -189,6 +192,18 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
.get_acl = get_acl_fn,
};
],[])
+
+ ZFS_LINUX_TEST_SRC([inode_operations_get_inode_acl], [
+ #include <linux/fs.h>
+
+ static struct posix_acl *get_inode_acl_fn(struct inode *inode, int type,
+ bool rcu) { return NULL; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .get_inode_acl = get_inode_acl_fn,
+ };
+ ],[])
])
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
@@ -201,7 +216,12 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_ACL_RCU, 1, [iops->get_acl() takes rcu])
],[
- ZFS_LINUX_TEST_ERROR([iops->get_acl()])
+ ZFS_LINUX_TEST_RESULT([inode_operations_get_inode_acl], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GET_INODE_ACL, 1, [has iops->get_inode_acl()])
+ ],[
+ ZFS_LINUX_TEST_ERROR([iops->get_acl() or iops->get_inode_acl()])
+ ])
])
])
])
@@ -213,11 +233,41 @@ dnl #
dnl # 5.12 API change,
dnl # set_acl() added a user_namespace* parameter first
dnl #
+dnl # 6.2 API change,
+dnl # set_acl() second paramter changed to a struct dentry *
+dnl #
+dnl # 6.3 API change,
+dnl # set_acl() first parameter changed to struct mnt_idmap *
+dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
+ ZFS_LINUX_TEST_SRC([inode_operations_set_acl_mnt_idmap_dentry], [
+ #include <linux/fs.h>
+
+ static int set_acl_fn(struct mnt_idmap *idmap,
+ struct dentry *dent, struct posix_acl *acl,
+ int type) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .set_acl = set_acl_fn,
+ };
+ ],[])
+ ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns_dentry], [
+ #include <linux/fs.h>
+
+ static int set_acl_fn(struct user_namespace *userns,
+ struct dentry *dent, struct posix_acl *acl,
+ int type) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .set_acl = set_acl_fn,
+ };
+ ],[])
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns], [
#include <linux/fs.h>
- int set_acl_fn(struct user_namespace *userns,
+ static int set_acl_fn(struct user_namespace *userns,
struct inode *inode, struct posix_acl *acl,
int type) { return 0; }
@@ -229,7 +279,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [
#include <linux/fs.h>
- int set_acl_fn(struct inode *inode, struct posix_acl *acl,
+ static int set_acl_fn(struct inode *inode, struct posix_acl *acl,
int type) { return 0; }
static const struct inode_operations
@@ -246,11 +296,25 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args])
],[
- ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
+ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_mnt_idmap_dentry], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args])
+ AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
+ AC_DEFINE(HAVE_SET_ACL_IDMAP_DENTRY, 1,
+ [iops->set_acl() takes 4 args, arg1 is struct mnt_idmap *])
],[
- AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns_dentry], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
+ AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1,
+ [iops->set_acl() takes 4 args, arg2 is struct dentry *])
+ ],[
+ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args])
+ ],[
+ ZFS_LINUX_REQUIRE_API([i_op->set_acl()], [3.14])
+ ])
+ ])
])
])
])
diff --git a/config/kernel-automount.m4 b/config/kernel-automount.m4
index f7bb63c68154..52f1931b748e 100644
--- a/config/kernel-automount.m4
+++ b/config/kernel-automount.m4
@@ -8,7 +8,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [
ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [
#include <linux/dcache.h>
- struct vfsmount *d_automount(struct path *p) { return NULL; }
+ static struct vfsmount *d_automount(struct path *p) { return NULL; }
struct dentry_operations dops __attribute__ ((unused)) = {
.d_automount = d_automount,
};
diff --git a/config/kernel-bio.m4 b/config/kernel-bio.m4
index 18620ca5b7e4..b22c1a3de7e1 100644
--- a/config/kernel-bio.m4
+++ b/config/kernel-bio.m4
@@ -247,7 +247,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS], [
ZFS_LINUX_TEST_SRC([bio_end_io_t_args], [
#include <linux/bio.h>
- void wanted_end_io(struct bio *bio) { return; }
+ static void wanted_end_io(struct bio *bio) { return; }
bio_end_io_t *end_io __attribute__ ((unused)) = wanted_end_io;
], [])
])
diff --git a/config/kernel-blk-queue.m4 b/config/kernel-blk-queue.m4
index 29b0a28290ab..15dbe1c7dff0 100644
--- a/config/kernel-blk-queue.m4
+++ b/config/kernel-blk-queue.m4
@@ -109,7 +109,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD], [
int value __attribute__ ((unused));
memset(q, 0, sizeof(r));
value = blk_queue_discard(q);
- ])
+ ],[-Wframe-larger-than=8192])
])
AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_DISCARD], [
@@ -155,7 +155,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE], [
int value __attribute__ ((unused));
memset(q, 0, sizeof(r));
value = blk_queue_secure_erase(q);
- ])
+ ],[-Wframe-larger-than=8192])
ZFS_LINUX_TEST_SRC([blk_queue_secdiscard], [
#include <linux/blkdev.h>
@@ -377,6 +377,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_MQ], [
(void) blk_mq_alloc_tag_set(&tag_set);
return BLK_STS_OK;
], [])
+ ZFS_LINUX_TEST_SRC([blk_mq_rq_hctx], [
+ #include <linux/blk-mq.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct request rq = {0};
+ struct blk_mq_hw_ctx *hctx = NULL;
+ rq.mq_hctx = hctx;
+ ], [])
])
AC_DEFUN([ZFS_AC_KERNEL_BLK_MQ], [
@@ -384,6 +392,13 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_MQ], [
ZFS_LINUX_TEST_RESULT([blk_mq], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_MQ, 1, [block multiqueue is available])
+ AC_MSG_CHECKING([whether block multiqueue hardware context is cached in struct request])
+ ZFS_LINUX_TEST_RESULT([blk_mq_rq_hctx], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLK_MQ_RQ_HCTX, 1, [block multiqueue hardware context is cached in struct request])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
], [
AC_MSG_RESULT(no)
])
diff --git a/config/kernel-blkdev.m4 b/config/kernel-blkdev.m4
index fb7b1a458638..b6ce1e1cf083 100644
--- a/config/kernel-blkdev.m4
+++ b/config/kernel-blkdev.m4
@@ -16,12 +16,119 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH], [
])
])
+dnl #
+dnl # 6.5.x API change,
+dnl # blkdev_get_by_path() takes 4 args
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG], [
+ ZFS_LINUX_TEST_SRC([blkdev_get_by_path_4arg], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct block_device *bdev __attribute__ ((unused)) = NULL;
+ const char *path = "path";
+ fmode_t mode = 0;
+ void *holder = NULL;
+ struct blk_holder_ops h;
+
+ bdev = blkdev_get_by_path(path, mode, holder, &h);
+ ])
+])
+
+dnl #
+dnl # 6.8.x API change
+dnl # bdev_open_by_path() replaces blkdev_get_by_path()
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_OPEN_BY_PATH], [
+ ZFS_LINUX_TEST_SRC([bdev_open_by_path], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct bdev_handle *bdh __attribute__ ((unused)) = NULL;
+ const char *path = "path";
+ fmode_t mode = 0;
+ void *holder = NULL;
+ struct blk_holder_ops h;
+
+ bdh = bdev_open_by_path(path, mode, holder, &h);
+ ])
+])
+
+dnl #
+dnl # 6.9.x API change
+dnl # bdev_file_open_by_path() replaced bdev_open_by_path(),
+dnl # and returns struct file*
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_FILE_OPEN_BY_PATH], [
+ ZFS_LINUX_TEST_SRC([bdev_file_open_by_path], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct file *file __attribute__ ((unused)) = NULL;
+ const char *path = "path";
+ fmode_t mode = 0;
+ void *holder = NULL;
+ struct blk_holder_ops h;
+
+ file = bdev_file_open_by_path(path, mode, holder, &h);
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
- AC_MSG_CHECKING([whether blkdev_get_by_path() exists])
+ AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 3 args])
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path], [
AC_MSG_RESULT(yes)
], [
- ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 4 args])
+ ZFS_LINUX_TEST_RESULT([blkdev_get_by_path_4arg], [
+ AC_DEFINE(HAVE_BLKDEV_GET_BY_PATH_4ARG, 1,
+ [blkdev_get_by_path() exists and takes 4 args])
+ AC_MSG_RESULT(yes)
+ ], [
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether bdev_open_by_path() exists])
+ ZFS_LINUX_TEST_RESULT([bdev_open_by_path], [
+ AC_DEFINE(HAVE_BDEV_OPEN_BY_PATH, 1,
+ [bdev_open_by_path() exists])
+ AC_MSG_RESULT(yes)
+ ], [
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether bdev_file_open_by_path() exists])
+ ZFS_LINUX_TEST_RESULT([bdev_file_open_by_path], [
+ AC_DEFINE(HAVE_BDEV_FILE_OPEN_BY_PATH, 1,
+ [bdev_file_open_by_path() exists])
+ AC_MSG_RESULT(yes)
+ ], [
+ AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
+ ])
+ ])
+ ])
+ ])
+])
+
+dnl #
+dnl # 6.5.x API change
+dnl # blk_mode_t was added as a type to supercede some places where fmode_t
+dnl # is used
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T], [
+ ZFS_LINUX_TEST_SRC([blk_mode_t], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ blk_mode_t m __attribute((unused)) = (blk_mode_t)0;
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T], [
+ AC_MSG_CHECKING([whether blk_mode_t is defined])
+ ZFS_LINUX_TEST_RESULT([blk_mode_t], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLK_MODE_T, 1, [blk_mode_t is defined])
+ ], [
+ AC_MSG_RESULT(no)
])
])
@@ -41,12 +148,67 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT], [
])
])
+dnl #
+dnl # 6.5.x API change.
+dnl # blkdev_put() takes (void* holder) as arg 2
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER], [
+ ZFS_LINUX_TEST_SRC([blkdev_put_holder], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct block_device *bdev = NULL;
+ void *holder = NULL;
+
+ blkdev_put(bdev, holder);
+ ])
+])
+
+dnl #
+dnl # 6.8.x API change
+dnl # bdev_release() replaces blkdev_put()
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE], [
+ ZFS_LINUX_TEST_SRC([bdev_release], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct bdev_handle *bdh = NULL;
+ bdev_release(bdh);
+ ])
+])
+
+dnl #
+dnl # 6.9.x API change
+dnl #
+dnl # bdev_release() now private, but because bdev_file_open_by_path() returns
+dnl # struct file*, we can just use fput(). So the blkdev_put test no longer
+dnl # fails if not found.
+dnl #
+
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
AC_MSG_CHECKING([whether blkdev_put() exists])
ZFS_LINUX_TEST_RESULT([blkdev_put], [
AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_PUT, 1, [blkdev_put() exists])
], [
- ZFS_LINUX_TEST_ERROR([blkdev_put()])
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether blkdev_put() accepts void* as arg 2])
+ ZFS_LINUX_TEST_RESULT([blkdev_put_holder], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_PUT_HOLDER, 1,
+ [blkdev_put() accepts void* as arg 2])
+ ], [
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether bdev_release() exists])
+ ZFS_LINUX_TEST_RESULT([bdev_release], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BDEV_RELEASE, 1,
+ [bdev_release() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+ ])
])
])
@@ -104,6 +266,84 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_CHECK_DISK_CHANGE], [
])
dnl #
+dnl # 6.5.x API change
+dnl # disk_check_media_change() was added
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE], [
+ ZFS_LINUX_TEST_SRC([disk_check_media_change], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct block_device *bdev = NULL;
+ bool error;
+
+ error = disk_check_media_change(bdev->bd_disk);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE], [
+ AC_MSG_CHECKING([whether disk_check_media_change() exists])
+ ZFS_LINUX_TEST_RESULT([disk_check_media_change], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DISK_CHECK_MEDIA_CHANGE, 1,
+ [disk_check_media_change() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
+dnl # bdev_kobj() is introduced from 5.12
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_KOBJ], [
+ ZFS_LINUX_TEST_SRC([bdev_kobj], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ #include <linux/kobject.h>
+ ], [
+ struct block_device *bdev = NULL;
+ struct kobject *disk_kobj;
+ disk_kobj = bdev_kobj(bdev);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BDEV_KOBJ], [
+ AC_MSG_CHECKING([whether bdev_kobj() exists])
+ ZFS_LINUX_TEST_RESULT([bdev_kobj], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BDEV_KOBJ, 1,
+ [bdev_kobj() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
+dnl # part_to_dev() was removed in 5.12
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV], [
+ ZFS_LINUX_TEST_SRC([part_to_dev], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct hd_struct *p = NULL;
+ struct device *pdev;
+ pdev = part_to_dev(p);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV], [
+ AC_MSG_CHECKING([whether part_to_dev() exists])
+ ZFS_LINUX_TEST_RESULT([part_to_dev], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PART_TO_DEV, 1,
+ [part_to_dev() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
dnl # 5.10 API, check_disk_change() is removed, in favor of
dnl # bdev_check_media_change(), which doesn't force revalidation
dnl #
@@ -295,11 +535,55 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BDEV_WHOLE], [
])
dnl #
-dnl # 5.19 API: blkdev_issue_secure_erase()
-dnl # 3.10 API: blkdev_issue_discard(..., BLKDEV_DISCARD_SECURE)
+dnl # 5.20 API change,
+dnl # Removed bdevname(), snprintf(.., %pg) should be used.
dnl #
-AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE], [
- ZFS_LINUX_TEST_SRC([blkdev_issue_secure_erase], [
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BDEVNAME], [
+ ZFS_LINUX_TEST_SRC([bdevname], [
+ #include <linux/fs.h>
+ #include <linux/blkdev.h>
+ ], [
+ struct block_device *bdev __attribute__ ((unused)) = NULL;
+ char path[BDEVNAME_SIZE];
+
+ (void) bdevname(bdev, path);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BDEVNAME], [
+ AC_MSG_CHECKING([whether bdevname() exists])
+ ZFS_LINUX_TEST_RESULT([bdevname], [
+ AC_DEFINE(HAVE_BDEVNAME, 1, [bdevname() is available])
+ AC_MSG_RESULT(yes)
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
+dnl # TRIM support: discard and secure erase. We make use of asynchronous
+dnl # functions when available.
+dnl #
+dnl # 3.10:
+dnl # sync discard: blkdev_issue_discard(..., 0)
+dnl # sync erase: blkdev_issue_discard(..., BLKDEV_DISCARD_SECURE)
+dnl # async discard: [not available]
+dnl # async erase: [not available]
+dnl #
+dnl # 4.7:
+dnl # sync discard: blkdev_issue_discard(..., 0)
+dnl # sync erase: blkdev_issue_discard(..., BLKDEV_DISCARD_SECURE)
+dnl # async discard: __blkdev_issue_discard(..., 0)
+dnl # async erase: __blkdev_issue_discard(..., BLKDEV_DISCARD_SECURE)
+dnl #
+dnl # 5.19:
+dnl # sync discard: blkdev_issue_discard(...)
+dnl # sync erase: blkdev_issue_secure_erase(...)
+dnl # async discard: __blkdev_issue_discard(...)
+dnl # async erase: [not available]
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_DISCARD], [
+ ZFS_LINUX_TEST_SRC([blkdev_issue_discard_noflags], [
#include <linux/blkdev.h>
],[
struct block_device *bdev = NULL;
@@ -307,10 +591,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE], [
sector_t nr_sects = 0;
int error __attribute__ ((unused));
- error = blkdev_issue_secure_erase(bdev,
+ error = blkdev_issue_discard(bdev,
sector, nr_sects, GFP_KERNEL);
])
-
ZFS_LINUX_TEST_SRC([blkdev_issue_discard_flags], [
#include <linux/blkdev.h>
],[
@@ -323,9 +606,77 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE], [
error = blkdev_issue_discard(bdev,
sector, nr_sects, GFP_KERNEL, flags);
])
+ ZFS_LINUX_TEST_SRC([blkdev_issue_discard_async_noflags], [
+ #include <linux/blkdev.h>
+ ],[
+ struct block_device *bdev = NULL;
+ sector_t sector = 0;
+ sector_t nr_sects = 0;
+ struct bio *biop = NULL;
+ int error __attribute__ ((unused));
+
+ error = __blkdev_issue_discard(bdev,
+ sector, nr_sects, GFP_KERNEL, &biop);
+ ])
+ ZFS_LINUX_TEST_SRC([blkdev_issue_discard_async_flags], [
+ #include <linux/blkdev.h>
+ ],[
+ struct block_device *bdev = NULL;
+ sector_t sector = 0;
+ sector_t nr_sects = 0;
+ unsigned long flags = 0;
+ struct bio *biop = NULL;
+ int error __attribute__ ((unused));
+
+ error = __blkdev_issue_discard(bdev,
+ sector, nr_sects, GFP_KERNEL, flags, &biop);
+ ])
+ ZFS_LINUX_TEST_SRC([blkdev_issue_secure_erase], [
+ #include <linux/blkdev.h>
+ ],[
+ struct block_device *bdev = NULL;
+ sector_t sector = 0;
+ sector_t nr_sects = 0;
+ int error __attribute__ ((unused));
+
+ error = blkdev_issue_secure_erase(bdev,
+ sector, nr_sects, GFP_KERNEL);
+ ])
])
-AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE], [
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_ISSUE_DISCARD], [
+ AC_MSG_CHECKING([whether blkdev_issue_discard() is available])
+ ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_noflags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD_NOFLAGS, 1,
+ [blkdev_issue_discard() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+ AC_MSG_CHECKING([whether blkdev_issue_discard(flags) is available])
+ ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_flags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD_FLAGS, 1,
+ [blkdev_issue_discard(flags) is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+ AC_MSG_CHECKING([whether __blkdev_issue_discard() is available])
+ ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_async_noflags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD_ASYNC_NOFLAGS, 1,
+ [__blkdev_issue_discard() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+ AC_MSG_CHECKING([whether __blkdev_issue_discard(flags) is available])
+ ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_async_flags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD_ASYNC_FLAGS, 1,
+ [__blkdev_issue_discard(flags) is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
AC_MSG_CHECKING([whether blkdev_issue_secure_erase() is available])
ZFS_LINUX_TEST_RESULT([blkdev_issue_secure_erase], [
AC_MSG_RESULT(yes)
@@ -333,15 +684,6 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE], [
[blkdev_issue_secure_erase() is available])
],[
AC_MSG_RESULT(no)
-
- AC_MSG_CHECKING([whether blkdev_issue_discard() is available])
- ZFS_LINUX_TEST_RESULT([blkdev_issue_discard_flags], [
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_BLKDEV_ISSUE_DISCARD, 1,
- [blkdev_issue_discard() is available])
- ],[
- ZFS_LINUX_TEST_ERROR([blkdev_issue_discard()])
- ])
])
])
@@ -366,9 +708,37 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_ERESTARTSYS], [
])
])
+dnl #
+dnl # 6.5.x API change
+dnl # BLK_STS_NEXUS replaced with BLK_STS_RESV_CONFLICT
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT], [
+ ZFS_LINUX_TEST_SRC([blk_sts_resv_conflict], [
+ #include <linux/blkdev.h>
+ ],[
+ blk_status_t s __attribute__ ((unused)) = BLK_STS_RESV_CONFLICT;
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT], [
+ AC_MSG_CHECKING([whether BLK_STS_RESV_CONFLICT is defined])
+ ZFS_LINUX_TEST_RESULT([blk_sts_resv_conflict], [
+ AC_DEFINE(HAVE_BLK_STS_RESV_CONFLICT, 1, [BLK_STS_RESV_CONFLICT is defined])
+ AC_MSG_RESULT(yes)
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
+ ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG
+ ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_OPEN_BY_PATH
+ ZFS_AC_KERNEL_SRC_BDEV_FILE_OPEN_BY_PATH
ZFS_AC_KERNEL_SRC_BLKDEV_PUT
+ ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER
+ ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_RELEASE
ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
ZFS_AC_KERNEL_SRC_BLKDEV_INVALIDATE_BDEV
ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV
@@ -377,7 +747,13 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
ZFS_AC_KERNEL_SRC_BLKDEV_CHECK_DISK_CHANGE
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_CHECK_MEDIA_CHANGE
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_WHOLE
- ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE
+ ZFS_AC_KERNEL_SRC_BLKDEV_BDEVNAME
+ ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_DISCARD
+ ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_KOBJ
+ ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV
+ ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE
+ ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT
+ ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T
])
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
@@ -391,6 +767,12 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
ZFS_AC_KERNEL_BLKDEV_CHECK_DISK_CHANGE
ZFS_AC_KERNEL_BLKDEV_BDEV_CHECK_MEDIA_CHANGE
ZFS_AC_KERNEL_BLKDEV_BDEV_WHOLE
+ ZFS_AC_KERNEL_BLKDEV_BDEVNAME
ZFS_AC_KERNEL_BLKDEV_GET_ERESTARTSYS
- ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE
+ ZFS_AC_KERNEL_BLKDEV_ISSUE_DISCARD
+ ZFS_AC_KERNEL_BLKDEV_BDEV_KOBJ
+ ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV
+ ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE
+ ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT
+ ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T
])
diff --git a/config/kernel-block-device-operations.m4 b/config/kernel-block-device-operations.m4
index 84e39dc8a2f6..4ff20b9c413d 100644
--- a/config/kernel-block-device-operations.m4
+++ b/config/kernel-block-device-operations.m4
@@ -5,7 +5,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS], [
ZFS_LINUX_TEST_SRC([block_device_operations_check_events], [
#include <linux/blkdev.h>
- unsigned int blk_check_events(struct gendisk *disk,
+ static unsigned int blk_check_events(struct gendisk *disk,
unsigned int clearing) {
(void) disk, (void) clearing;
return (0);
@@ -34,7 +34,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
ZFS_LINUX_TEST_SRC([block_device_operations_release_void], [
#include <linux/blkdev.h>
- void blk_release(struct gendisk *g, fmode_t mode) {
+ static void blk_release(struct gendisk *g, fmode_t mode) {
(void) g, (void) mode;
return;
}
@@ -49,12 +49,42 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
], [], [])
])
+dnl #
+dnl # 5.9.x API change
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [
+ ZFS_LINUX_TEST_SRC([block_device_operations_release_void_1arg], [
+ #include <linux/blkdev.h>
+
+ static void blk_release(struct gendisk *g) {
+ (void) g;
+ return;
+ }
+
+ static const struct block_device_operations
+ bops __attribute__ ((unused)) = {
+ .open = NULL,
+ .release = blk_release,
+ .ioctl = NULL,
+ .compat_ioctl = NULL,
+ };
+ ], [], [])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
- AC_MSG_CHECKING([whether bops->release() is void])
+ AC_MSG_CHECKING([whether bops->release() is void and takes 2 args])
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
AC_MSG_RESULT(yes)
],[
- ZFS_LINUX_TEST_ERROR([bops->release()])
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether bops->release() is void and takes 1 arg])
+ ZFS_LINUX_TEST_RESULT([block_device_operations_release_void_1arg], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [1],
+ [Define if release() in block_device_operations takes 1 arg])
+ ],[
+ ZFS_LINUX_TEST_ERROR([bops->release()])
+ ])
])
])
@@ -66,7 +96,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
ZFS_LINUX_TEST_SRC([block_device_operations_revalidate_disk], [
#include <linux/blkdev.h>
- int blk_revalidate_disk(struct gendisk *disk) {
+ static int blk_revalidate_disk(struct gendisk *disk) {
(void) disk;
return(0);
}
@@ -92,6 +122,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
+ ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
])
diff --git a/config/kernel-commit-metadata.m4 b/config/kernel-commit-metadata.m4
index 7df9b980290e..49bffbf609d2 100644
--- a/config/kernel-commit-metadata.m4
+++ b/config/kernel-commit-metadata.m4
@@ -7,7 +7,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_COMMIT_METADATA], [
ZFS_LINUX_TEST_SRC([export_operations_commit_metadata], [
#include <linux/exportfs.h>
- int commit_metadata(struct inode *inode) { return 0; }
+ static int commit_metadata(struct inode *inode) { return 0; }
static struct export_operations eops __attribute__ ((unused))={
.commit_metadata = commit_metadata,
};
diff --git a/config/kernel-cpu_has_feature.m4 b/config/kernel-cpu_has_feature.m4
new file mode 100644
index 000000000000..608faf0f89fe
--- /dev/null
+++ b/config/kernel-cpu_has_feature.m4
@@ -0,0 +1,29 @@
+dnl #
+dnl # cpu_has_feature() may referencing GPL-only cpu_feature_keys on powerpc
+dnl #
+
+dnl #
+dnl # Checking if cpu_has_feature is exported GPL-only
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE], [
+ ZFS_LINUX_TEST_SRC([cpu_has_feature], [
+ #include <linux/version.h>
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+ #include <asm/cpu_has_feature.h>
+ #else
+ #include <asm/cputable.h>
+ #endif
+ ], [
+ return cpu_has_feature(CPU_FTR_ALTIVEC) ? 0 : 1;
+ ], [], [ZFS_META_LICENSE])
+])
+AC_DEFUN([ZFS_AC_KERNEL_CPU_HAS_FEATURE], [
+ AC_MSG_CHECKING([whether cpu_has_feature() is GPL-only])
+ ZFS_LINUX_TEST_RESULT([cpu_has_feature_license], [
+ AC_MSG_RESULT(no)
+ ], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_CPU_HAS_FEATURE_GPL_ONLY, 1,
+ [cpu_has_feature() is GPL-only])
+ ])
+])
diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
index 3ceb5f63efa9..ab7d9c5cedba 100644
--- a/config/kernel-current-time.m4
+++ b/config/kernel-current-time.m4
@@ -2,12 +2,15 @@ dnl #
dnl # 4.9, current_time() added
dnl # 4.18, return type changed from timespec to timespec64
dnl #
+dnl # Note that we don't care about the return type in this check. If we have
+dnl # to implement a fallback, we'll know we're <4.9, which was timespec.
+dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_CURRENT_TIME], [
ZFS_LINUX_TEST_SRC([current_time], [
#include <linux/fs.h>
], [
struct inode ip __attribute__ ((unused));
- ip.i_atime = current_time(&ip);
+ (void) current_time(&ip);
])
])
diff --git a/config/kernel-dentry-alias.m4 b/config/kernel-dentry-alias.m4
new file mode 100644
index 000000000000..f0ddb8d010b0
--- /dev/null
+++ b/config/kernel-dentry-alias.m4
@@ -0,0 +1,30 @@
+dnl #
+dnl # 3.18 API change
+dnl # Dentry aliases are in d_u struct dentry member
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U], [
+ ZFS_LINUX_TEST_SRC([dentry_alias_d_u], [
+ #include <linux/fs.h>
+ #include <linux/dcache.h>
+ #include <linux/list.h>
+ ], [
+ struct inode *inode __attribute__ ((unused)) = NULL;
+ struct dentry *dentry __attribute__ ((unused)) = NULL;
+ hlist_for_each_entry(dentry, &inode->i_dentry,
+ d_u.d_alias) {
+ d_drop(dentry);
+ }
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_DENTRY_ALIAS_D_U], [
+ AC_MSG_CHECKING([whether dentry aliases are in d_u member])
+ ZFS_LINUX_TEST_RESULT([dentry_alias_d_u], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DENTRY_D_U_ALIASES, 1,
+ [dentry aliases are in d_u member])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
diff --git a/config/kernel-dentry-operations.m4 b/config/kernel-dentry-operations.m4
index dd470d7607b4..500f61e26aee 100644
--- a/config/kernel-dentry-operations.m4
+++ b/config/kernel-dentry-operations.m4
@@ -98,7 +98,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA], [
#include <linux/dcache.h>
#include <linux/sched.h>
- int revalidate (struct dentry *dentry,
+ static int revalidate (struct dentry *dentry,
struct nameidata *nidata) { return 0; }
static const struct dentry_operations
diff --git a/config/kernel-dirty-inode.m4 b/config/kernel-dirty-inode.m4
index dc7667fa4881..2ef8658748ca 100644
--- a/config/kernel-dirty-inode.m4
+++ b/config/kernel-dirty-inode.m4
@@ -8,7 +8,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_DIRTY_INODE], [
ZFS_LINUX_TEST_SRC([dirty_inode_with_flags], [
#include <linux/fs.h>
- void dirty_inode(struct inode *a, int b) { return; }
+ static void dirty_inode(struct inode *a, int b) { return; }
static const struct super_operations
sops __attribute__ ((unused)) = {
diff --git a/config/kernel-encode-fh-inode.m4 b/config/kernel-encode-fh-inode.m4
index 9d4ba5f0f61f..b3ec040b5e95 100644
--- a/config/kernel-encode-fh-inode.m4
+++ b/config/kernel-encode-fh-inode.m4
@@ -7,7 +7,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_ENCODE_FH_WITH_INODE], [
ZFS_LINUX_TEST_SRC([export_operations_encode_fh], [
#include <linux/exportfs.h>
- int encode_fh(struct inode *inode, __u32 *fh, int *max_len,
+ static int encode_fh(struct inode *inode, __u32 *fh, int *max_len,
struct inode *parent) { return 0; }
static struct export_operations eops __attribute__ ((unused))={
.encode_fh = encode_fh,
diff --git a/config/kernel-evict-inode.m4 b/config/kernel-evict-inode.m4
index 66f10492de54..87082c9a2839 100644
--- a/config/kernel-evict-inode.m4
+++ b/config/kernel-evict-inode.m4
@@ -6,7 +6,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_EVICT_INODE], [
ZFS_LINUX_TEST_SRC([evict_inode], [
#include <linux/fs.h>
- void evict_inode (struct inode * t) { return; }
+ static void evict_inode (struct inode * t) { return; }
static struct super_operations sops __attribute__ ((unused)) = {
.evict_inode = evict_inode,
};
diff --git a/config/kernel-fadvise.m4 b/config/kernel-fadvise.m4
new file mode 100644
index 000000000000..08912de16ed8
--- /dev/null
+++ b/config/kernel-fadvise.m4
@@ -0,0 +1,23 @@
+dnl #
+dnl # Linux 4.19 API
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_FADVISE], [
+ ZFS_LINUX_TEST_SRC([file_fadvise], [
+ #include <linux/fs.h>
+
+ static const struct file_operations
+ fops __attribute__ ((unused)) = {
+ .fadvise = NULL,
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_FADVISE], [
+ AC_MSG_CHECKING([whether fops->fadvise() exists])
+ ZFS_LINUX_TEST_RESULT([file_fadvise], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FILE_FADVISE, 1, [fops->fadvise() exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel-fallocate.m4 b/config/kernel-fallocate.m4
index 815602d3e2c6..95186dada453 100644
--- a/config/kernel-fallocate.m4
+++ b/config/kernel-fallocate.m4
@@ -11,7 +11,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FALLOCATE], [
ZFS_LINUX_TEST_SRC([file_fallocate], [
#include <linux/fs.h>
- long test_fallocate(struct file *file, int mode,
+ static long test_fallocate(struct file *file, int mode,
loff_t offset, loff_t len) { return 0; }
static const struct file_operations
diff --git a/config/kernel-filemap-splice-read.m4 b/config/kernel-filemap-splice-read.m4
new file mode 100644
index 000000000000..4c83b31d738a
--- /dev/null
+++ b/config/kernel-filemap-splice-read.m4
@@ -0,0 +1,25 @@
+AC_DEFUN([ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ], [
+ dnl #
+ dnl # Kernel 6.5 - generic_file_splice_read was removed in favor
+ dnl # of copy_splice_read for the .splice_read member of the
+ dnl # file_operations struct.
+ dnl #
+ ZFS_LINUX_TEST_SRC([has_copy_splice_read], [
+ #include <linux/fs.h>
+
+ struct file_operations fops __attribute__((unused)) = {
+ .splice_read = copy_splice_read,
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_COPY_SPLICE_READ], [
+ AC_MSG_CHECKING([whether copy_splice_read() exists])
+ ZFS_LINUX_TEST_RESULT([has_copy_splice_read], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_COPY_SPLICE_READ, 1,
+ [copy_splice_read exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel-filemap.m4 b/config/kernel-filemap.m4
new file mode 100644
index 000000000000..0b7da828d299
--- /dev/null
+++ b/config/kernel-filemap.m4
@@ -0,0 +1,27 @@
+dnl #
+dnl # filemap_range_has_page was not available till 4.13
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_FILEMAP], [
+ ZFS_LINUX_TEST_SRC([filemap_range_has_page], [
+ #include <linux/fs.h>
+ #include <linux/pagemap.h>
+ ],[
+ struct address_space *mapping = NULL;
+ loff_t lstart = 0;
+ loff_t lend = 0;
+ bool ret __attribute__ ((unused));
+
+ ret = filemap_range_has_page(mapping, lstart, lend);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_FILEMAP], [
+ AC_MSG_CHECKING([whether filemap_range_has_page() is available])
+ ZFS_LINUX_TEST_RESULT([filemap_range_has_page], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FILEMAP_RANGE_HAS_PAGE, 1,
+ [filemap_range_has_page() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel-flush_dcache_page.m4 b/config/kernel-flush_dcache_page.m4
new file mode 100644
index 000000000000..aa916c87d531
--- /dev/null
+++ b/config/kernel-flush_dcache_page.m4
@@ -0,0 +1,27 @@
+dnl #
+dnl # Starting from Linux 5.13, flush_dcache_page() becomes an inline
+dnl # function and may indirectly referencing GPL-only symbols:
+dnl # on powerpc: cpu_feature_keys
+dnl # on riscv: PageHuge (added from 6.2)
+dnl #
+
+dnl #
+dnl # Checking if flush_dcache_page is exported GPL-only
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE], [
+ ZFS_LINUX_TEST_SRC([flush_dcache_page], [
+ #include <asm/cacheflush.h>
+ ], [
+ flush_dcache_page(0);
+ ], [], [ZFS_META_LICENSE])
+])
+AC_DEFUN([ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE], [
+ AC_MSG_CHECKING([whether flush_dcache_page() is GPL-only])
+ ZFS_LINUX_TEST_RESULT([flush_dcache_page_license], [
+ AC_MSG_RESULT(no)
+ ], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY, 1,
+ [flush_dcache_page() is GPL-only])
+ ])
+])
diff --git a/config/kernel-fpu.m4 b/config/kernel-fpu.m4
index c6efebd8cf61..edfde1a02d30 100644
--- a/config/kernel-fpu.m4
+++ b/config/kernel-fpu.m4
@@ -79,6 +79,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
__kernel_fpu_end();
], [], [ZFS_META_LICENSE])
+ ZFS_LINUX_TEST_SRC([kernel_neon], [
+ #include <asm/neon.h>
+ ], [
+ kernel_neon_begin();
+ kernel_neon_end();
+ ], [], [ZFS_META_LICENSE])
])
AC_DEFUN([ZFS_AC_KERNEL_FPU], [
@@ -105,9 +111,20 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
[kernel exports FPU functions])
],[
- AC_MSG_RESULT(internal)
- AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
- [kernel fpu internal])
+ dnl #
+ dnl # ARM neon symbols (only on arm and arm64)
+ dnl # could be GPL-only on arm64 after Linux 6.2
+ dnl #
+ ZFS_LINUX_TEST_RESULT([kernel_neon_license],[
+ AC_MSG_RESULT(kernel_neon_*)
+ AC_DEFINE(HAVE_KERNEL_NEON, 1,
+ [kernel has kernel_neon_* functions])
+ ],[
+ # catch-all
+ AC_MSG_RESULT(internal)
+ AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
+ [kernel fpu internal])
+ ])
])
])
])
diff --git a/config/kernel-fsync-bdev.m4 b/config/kernel-fsync-bdev.m4
new file mode 100644
index 000000000000..c47e236f705f
--- /dev/null
+++ b/config/kernel-fsync-bdev.m4
@@ -0,0 +1,36 @@
+dnl #
+dnl # 6.6 API change,
+dnl # fsync_bdev was removed in favor of sync_blockdev
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_SYNC_BDEV], [
+ ZFS_LINUX_TEST_SRC([fsync_bdev], [
+ #include <linux/blkdev.h>
+ ],[
+ fsync_bdev(NULL);
+ ])
+
+ ZFS_LINUX_TEST_SRC([sync_blockdev], [
+ #include <linux/blkdev.h>
+ ],[
+ sync_blockdev(NULL);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SYNC_BDEV], [
+ AC_MSG_CHECKING([whether fsync_bdev() exists])
+ ZFS_LINUX_TEST_RESULT([fsync_bdev], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FSYNC_BDEV, 1,
+ [fsync_bdev() is declared in include/blkdev.h])
+ ],[
+ AC_MSG_CHECKING([whether sync_blockdev() exists])
+ ZFS_LINUX_TEST_RESULT([sync_blockdev], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SYNC_BLOCKDEV, 1,
+ [sync_blockdev() is declared in include/blkdev.h])
+ ],[
+ ZFS_LINUX_TEST_ERROR(
+ [neither fsync_bdev() nor sync_blockdev() exist])
+ ])
+ ])
+])
diff --git a/config/kernel-fsync.m4 b/config/kernel-fsync.m4
index d198191d3ab9..c155f8af81a8 100644
--- a/config/kernel-fsync.m4
+++ b/config/kernel-fsync.m4
@@ -5,7 +5,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FSYNC], [
ZFS_LINUX_TEST_SRC([fsync_without_dentry], [
#include <linux/fs.h>
- int test_fsync(struct file *f, int x) { return 0; }
+ static int test_fsync(struct file *f, int x) { return 0; }
static const struct file_operations
fops __attribute__ ((unused)) = {
@@ -16,7 +16,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FSYNC], [
ZFS_LINUX_TEST_SRC([fsync_range], [
#include <linux/fs.h>
- int test_fsync(struct file *f, loff_t a, loff_t b, int c)
+ static int test_fsync(struct file *f, loff_t a, loff_t b, int c)
{ return 0; }
static const struct file_operations
diff --git a/config/kernel-generic_fadvise.m4 b/config/kernel-generic_fadvise.m4
new file mode 100644
index 000000000000..8d122064b229
--- /dev/null
+++ b/config/kernel-generic_fadvise.m4
@@ -0,0 +1,27 @@
+dnl #
+dnl # 5.3 API change
+dnl # The generic_fadvise() function is present since 4.19 kernel
+dnl # but it was not exported until Linux 5.3.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FADVISE], [
+ ZFS_LINUX_TEST_SRC([generic_fadvise], [
+ #include <linux/fs.h>
+ ], [
+ struct file *fp __attribute__ ((unused)) = NULL;
+ loff_t offset __attribute__ ((unused)) = 0;
+ loff_t len __attribute__ ((unused)) = 0;
+ int advise __attribute__ ((unused)) = 0;
+ generic_fadvise(fp, offset, len, advise);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FADVISE], [
+ AC_MSG_CHECKING([whether generic_fadvise() is available])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([generic_fadvise],
+ [generic_fadvise], [mm/fadvise.c], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GENERIC_FADVISE, 1, [yes])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel-generic_fillattr.m4 b/config/kernel-generic_fillattr.m4
index 0acd5d53103f..f5323f0dcb9f 100644
--- a/config/kernel-generic_fillattr.m4
+++ b/config/kernel-generic_fillattr.m4
@@ -4,7 +4,14 @@ dnl #
dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace*
dnl # as the first arg, to support idmapped mounts.
dnl #
-AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [
+dnl # 6.3 API
+dnl # generic_fillattr() now takes struct mnt_idmap* as the first argument
+dnl #
+dnl # 6.6 API
+dnl # generic_fillattr() now takes u32 as second argument, representing a
+dnl # request_mask for statx
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR], [
ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [
#include <linux/fs.h>
],[
@@ -13,16 +20,49 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [
struct kstat *k = NULL;
generic_fillattr(userns, in, k);
])
+
+ ZFS_LINUX_TEST_SRC([generic_fillattr_mnt_idmap], [
+ #include <linux/fs.h>
+ ],[
+ struct mnt_idmap *idmap = NULL;
+ struct inode *in = NULL;
+ struct kstat *k = NULL;
+ generic_fillattr(idmap, in, k);
+ ])
+
+ ZFS_LINUX_TEST_SRC([generic_fillattr_mnt_idmap_reqmask], [
+ #include <linux/fs.h>
+ ],[
+ struct mnt_idmap *idmap = NULL;
+ struct inode *in = NULL;
+ struct kstat *k = NULL;
+ generic_fillattr(idmap, 0, in, k);
+ ])
])
-AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [
- AC_MSG_CHECKING([whether generic_fillattr requires struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [
+AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR], [
+ AC_MSG_CHECKING(
+ [whether generic_fillattr requires struct mnt_idmap* and request_mask])
+ ZFS_LINUX_TEST_RESULT([generic_fillattr_mnt_idmap_reqmask], [
AC_MSG_RESULT([yes])
- AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1,
- [generic_fillattr requires struct user_namespace*])
+ AC_DEFINE(HAVE_GENERIC_FILLATTR_IDMAP_REQMASK, 1,
+ [generic_fillattr requires struct mnt_idmap* and u32 request_mask])
],[
- AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([whether generic_fillattr requires struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([generic_fillattr_mnt_idmap], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_GENERIC_FILLATTR_IDMAP, 1,
+ [generic_fillattr requires struct mnt_idmap*])
+ ],[
+ AC_MSG_CHECKING([whether generic_fillattr requires struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1,
+ [generic_fillattr requires struct user_namespace*])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+ ])
])
])
diff --git a/config/kernel-generic_io_acct.m4 b/config/kernel-generic_io_acct.m4
index a8a448c6fe96..a6a109004294 100644
--- a/config/kernel-generic_io_acct.m4
+++ b/config/kernel-generic_io_acct.m4
@@ -2,7 +2,20 @@ dnl #
dnl # Check for generic io accounting interface.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
- ZFS_LINUX_TEST_SRC([bdev_io_acct], [
+ ZFS_LINUX_TEST_SRC([bdev_io_acct_63], [
+ #include <linux/blkdev.h>
+ ], [
+ struct block_device *bdev = NULL;
+ struct bio *bio = NULL;
+ unsigned long passed_time = 0;
+ unsigned long start_time;
+
+ start_time = bdev_start_io_acct(bdev, bio_op(bio),
+ passed_time);
+ bdev_end_io_acct(bdev, bio_op(bio), bio_sectors(bio), start_time);
+ ])
+
+ ZFS_LINUX_TEST_SRC([bdev_io_acct_old], [
#include <linux/blkdev.h>
], [
struct block_device *bdev = NULL;
@@ -63,74 +76,85 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT], [
AC_DEFUN([ZFS_AC_KERNEL_GENERIC_IO_ACCT], [
dnl #
- dnl # 5.19 API,
+ dnl # Linux 6.3, and then backports thereof, changed
+ dnl # the signatures on bdev_start_io_acct/bdev_end_io_acct
dnl #
- dnl # disk_start_io_acct() and disk_end_io_acct() have been replaced by
- dnl # bdev_start_io_acct() and bdev_end_io_acct().
- dnl #
- AC_MSG_CHECKING([whether generic bdev_*_io_acct() are available])
- ZFS_LINUX_TEST_RESULT([bdev_io_acct], [
+ AC_MSG_CHECKING([whether 6.3+ bdev_*_io_acct() are available])
+ ZFS_LINUX_TEST_RESULT([bdev_io_acct_63], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_BDEV_IO_ACCT, 1, [bdev_*_io_acct() available])
+ AC_DEFINE(HAVE_BDEV_IO_ACCT_63, 1, [bdev_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
- dnl # 5.12 API,
+ dnl # 5.19 API,
dnl #
- dnl # bio_start_io_acct() and bio_end_io_acct() became GPL-exported
- dnl # so use disk_start_io_acct() and disk_end_io_acct() instead
+ dnl # disk_start_io_acct() and disk_end_io_acct() have been replaced by
+ dnl # bdev_start_io_acct() and bdev_end_io_acct().
dnl #
- AC_MSG_CHECKING([whether generic disk_*_io_acct() are available])
- ZFS_LINUX_TEST_RESULT([disk_io_acct], [
+ AC_MSG_CHECKING([whether pre-6.3 bdev_*_io_acct() are available])
+ ZFS_LINUX_TEST_RESULT([bdev_io_acct_old], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_DISK_IO_ACCT, 1, [disk_*_io_acct() available])
+ AC_DEFINE(HAVE_BDEV_IO_ACCT_OLD, 1, [bdev_*_io_acct() available])
], [
AC_MSG_RESULT(no)
-
dnl #
- dnl # 5.7 API,
+ dnl # 5.12 API,
dnl #
- dnl # Added bio_start_io_acct() and bio_end_io_acct() helpers.
+ dnl # bio_start_io_acct() and bio_end_io_acct() became GPL-exported
+ dnl # so use disk_start_io_acct() and disk_end_io_acct() instead
dnl #
- AC_MSG_CHECKING([whether generic bio_*_io_acct() are available])
- ZFS_LINUX_TEST_RESULT([bio_io_acct], [
+ AC_MSG_CHECKING([whether generic disk_*_io_acct() are available])
+ ZFS_LINUX_TEST_RESULT([disk_io_acct], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_BIO_IO_ACCT, 1, [bio_*_io_acct() available])
+ AC_DEFINE(HAVE_DISK_IO_ACCT, 1, [disk_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
- dnl # 4.14 API,
+ dnl # 5.7 API,
dnl #
- dnl # generic_start_io_acct/generic_end_io_acct now require
- dnl # request_queue to be provided. No functional changes,
- dnl # but preparation for inflight accounting.
+ dnl # Added bio_start_io_acct() and bio_end_io_acct() helpers.
dnl #
- AC_MSG_CHECKING([whether generic_*_io_acct wants 4 args])
- ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
- [generic_start_io_acct], [block/bio.c], [
+ AC_MSG_CHECKING([whether generic bio_*_io_acct() are available])
+ ZFS_LINUX_TEST_RESULT([bio_io_acct], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
- [generic_*_io_acct() 4 arg available])
+ AC_DEFINE(HAVE_BIO_IO_ACCT, 1, [bio_*_io_acct() available])
], [
AC_MSG_RESULT(no)
dnl #
- dnl # 3.19 API addition
+ dnl # 4.14 API,
dnl #
- dnl # torvalds/linux@394ffa50 allows us to increment
- dnl # iostat counters without generic_make_request().
+ dnl # generic_start_io_acct/generic_end_io_acct now require
+ dnl # request_queue to be provided. No functional changes,
+ dnl # but preparation for inflight accounting.
dnl #
- AC_MSG_CHECKING(
- [whether generic_*_io_acct wants 3 args])
- ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
+ AC_MSG_CHECKING([whether generic_*_io_acct wants 4 args])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_4args],
[generic_start_io_acct], [block/bio.c], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
- [generic_*_io_acct() 3 arg available])
+ AC_DEFINE(HAVE_GENERIC_IO_ACCT_4ARG, 1,
+ [generic_*_io_acct() 4 arg available])
], [
AC_MSG_RESULT(no)
+
+ dnl #
+ dnl # 3.19 API addition
+ dnl #
+ dnl # torvalds/linux@394ffa50 allows us to increment
+ dnl # iostat counters without generic_make_request().
+ dnl #
+ AC_MSG_CHECKING(
+ [whether generic_*_io_acct wants 3 args])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([generic_acct_3args],
+ [generic_start_io_acct], [block/bio.c], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GENERIC_IO_ACCT_3ARG, 1,
+ [generic_*_io_acct() 3 arg available])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
])
])
])
diff --git a/config/kernel-get-link.m4 b/config/kernel-get-link.m4
index e4f478e37c18..1f8f5b0c8b72 100644
--- a/config/kernel-get-link.m4
+++ b/config/kernel-get-link.m4
@@ -5,7 +5,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
ZFS_LINUX_TEST_SRC([inode_operations_get_link], [
#include <linux/fs.h>
- const char *get_link(struct dentry *de, struct inode *ip,
+ static const char *get_link(struct dentry *de, struct inode *ip,
struct delayed_call *done) { return "symlink"; }
static struct inode_operations
iops __attribute__ ((unused)) = {
@@ -15,7 +15,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
ZFS_LINUX_TEST_SRC([inode_operations_get_link_cookie], [
#include <linux/fs.h>
- const char *get_link(struct dentry *de, struct
+ static const char *get_link(struct dentry *de, struct
inode *ip, void **cookie) { return "symlink"; }
static struct inode_operations
iops __attribute__ ((unused)) = {
@@ -25,7 +25,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
ZFS_LINUX_TEST_SRC([inode_operations_follow_link], [
#include <linux/fs.h>
- const char *follow_link(struct dentry *de,
+ static const char *follow_link(struct dentry *de,
void **cookie) { return "symlink"; }
static struct inode_operations
iops __attribute__ ((unused)) = {
@@ -35,7 +35,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_LINK], [
ZFS_LINUX_TEST_SRC([inode_operations_follow_link_nameidata], [
#include <linux/fs.h>
- void *follow_link(struct dentry *de, struct
+ static void *follow_link(struct dentry *de, struct
nameidata *nd) { return (void *)NULL; }
static struct inode_operations
iops __attribute__ ((unused)) = {
diff --git a/config/kernel-iattr-vfsid.m4 b/config/kernel-iattr-vfsid.m4
new file mode 100644
index 000000000000..75bc4613b838
--- /dev/null
+++ b/config/kernel-iattr-vfsid.m4
@@ -0,0 +1,24 @@
+dnl #
+dnl # 6.0 API change
+dnl # struct iattr has two unions for the uid and gid
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_IATTR_VFSID], [
+ ZFS_LINUX_TEST_SRC([iattr_vfsid], [
+ #include <linux/fs.h>
+ ], [
+ struct iattr ia;
+ ia.ia_vfsuid = (vfsuid_t){0};
+ ia.ia_vfsgid = (vfsgid_t){0};
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_IATTR_VFSID], [
+ AC_MSG_CHECKING([whether iattr->ia_vfsuid and iattr->ia_vfsgid exist])
+ ZFS_LINUX_TEST_RESULT([iattr_vfsid], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IATTR_VFSID, 1,
+ [iattr->ia_vfsuid and iattr->ia_vfsgid exist])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel-idmap_mnt_api.m4 b/config/kernel-idmap_mnt_api.m4
new file mode 100644
index 000000000000..d1bdd053203e
--- /dev/null
+++ b/config/kernel-idmap_mnt_api.m4
@@ -0,0 +1,50 @@
+dnl #
+dnl # 5.12 API
+dnl #
+dnl # Check if APIs for idmapped mount are available
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_MNT_API], [
+ ZFS_LINUX_TEST_SRC([idmap_mnt_api], [
+ #include <linux/fs.h>
+ ],[
+ int fs_flags = 0;
+ fs_flags |= FS_ALLOW_IDMAP;
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_IDMAP_MNT_API], [
+ AC_MSG_CHECKING([whether APIs for idmapped mount are present])
+ ZFS_LINUX_TEST_RESULT([idmap_mnt_api], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_IDMAP_MNT_API, 1,
+ [APIs for idmapped mount are present])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
+
+dnl #
+dnl # 6.8 decouples mnt_idmap from user_namespace. This is all internal
+dnl # to mnt_idmap so we can't detect it directly, but we detect a related
+dnl # change as use that as a signal.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS], [
+ ZFS_LINUX_TEST_SRC([idmap_no_userns], [
+ #include <linux/uidgid.h>
+ ], [
+ struct uid_gid_map *map = NULL;
+ map_id_down(map, 0);
+ ])
+])
+
+
+AC_DEFUN([ZFS_AC_KERNEL_IDMAP_NO_USERNS], [
+ AC_MSG_CHECKING([whether idmapped mounts have a user namespace])
+ ZFS_LINUX_TEST_RESULT([idmap_no_userns], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_IDMAP_NO_USERNS, 1,
+ [mnt_idmap does not have user_namespace])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/config/kernel-inode-create.m4 b/config/kernel-inode-create.m4
index a6ea11fb61b2..95f8aa2d5220 100644
--- a/config/kernel-inode-create.m4
+++ b/config/kernel-inode-create.m4
@@ -1,5 +1,23 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
dnl #
+ dnl # 6.3 API change
+ dnl # The first arg is changed to struct mnt_idmap *
+ dnl #
+ ZFS_LINUX_TEST_SRC([create_mnt_idmap], [
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+
+ static int inode_create(struct mnt_idmap *idmap,
+ struct inode *inode ,struct dentry *dentry,
+ umode_t umode, bool flag) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .create = inode_create,
+ };
+ ],[])
+
+ dnl #
dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list.
dnl #
@@ -7,7 +25,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
#include <linux/fs.h>
#include <linux/sched.h>
- int inode_create(struct user_namespace *userns,
+ static int inode_create(struct user_namespace *userns,
struct inode *inode ,struct dentry *dentry,
umode_t umode, bool flag) { return 0; }
@@ -24,7 +42,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
#include <linux/fs.h>
#include <linux/sched.h>
- int inode_create(struct inode *inode ,struct dentry *dentry,
+ static int inode_create(struct inode *inode ,struct dentry *dentry,
umode_t umode, bool flag) { return 0; }
static const struct inode_operations
@@ -35,19 +53,28 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
])
AC_DEFUN([ZFS_AC_KERNEL_CREATE], [
- AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([create_userns], [
+ AC_MSG_CHECKING([whether iops->create() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([create_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1,
- [iops->create() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_CREATE_IDMAP, 1,
+ [iops->create() takes struct mnt_idmap*])
],[
AC_MSG_RESULT(no)
- AC_MSG_CHECKING([whether iops->create() passes flags])
- ZFS_LINUX_TEST_RESULT([create_flags], [
+ AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([create_userns], [
AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1,
+ [iops->create() takes struct user_namespace*])
],[
- ZFS_LINUX_TEST_ERROR([iops->create()])
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether iops->create() passes flags])
+ ZFS_LINUX_TEST_RESULT([create_flags], [
+ AC_MSG_RESULT(yes)
+ ],[
+ ZFS_LINUX_TEST_ERROR([iops->create()])
+ ])
])
])
])
diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4
index f62e82f5230a..5f7ce1ad9a5d 100644
--- a/config/kernel-inode-getattr.m4
+++ b/config/kernel-inode-getattr.m4
@@ -1,5 +1,25 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
dnl #
+ dnl # Linux 6.3 API
+ dnl # The first arg of getattr I/O operations handler type
+ dnl # is changed to struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_getattr_mnt_idmap], [
+ #include <linux/fs.h>
+
+ static int test_getattr(
+ struct mnt_idmap *idmap,
+ const struct path *p, struct kstat *k,
+ u32 request_mask, unsigned int query_flags)
+ { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .getattr = test_getattr,
+ };
+ ],[])
+
+ dnl #
dnl # Linux 5.12 API
dnl # The getattr I/O operations handler type was extended to require
dnl # a struct user_namespace* as its first arg, to support idmapped
@@ -8,7 +28,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
ZFS_LINUX_TEST_SRC([inode_operations_getattr_userns], [
#include <linux/fs.h>
- int test_getattr(
+ static int test_getattr(
struct user_namespace *userns,
const struct path *p, struct kstat *k,
u32 request_mask, unsigned int query_flags)
@@ -27,7 +47,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [
#include <linux/fs.h>
- int test_getattr(
+ static int test_getattr(
const struct path *p, struct kstat *k,
u32 request_mask, unsigned int query_flags)
{ return 0; }
@@ -41,7 +61,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
ZFS_LINUX_TEST_SRC([inode_operations_getattr_vfsmount], [
#include <linux/fs.h>
- int test_getattr(
+ static int test_getattr(
struct vfsmount *mnt, struct dentry *d,
struct kstat *k)
{ return 0; }
@@ -55,37 +75,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [
dnl #
- dnl # Kernel 5.12 test
+ dnl # Kernel 6.3 test
dnl #
- AC_MSG_CHECKING([whether iops->getattr() takes user_namespace])
- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [
+ AC_MSG_CHECKING([whether iops->getattr() takes mnt_idmap])
+ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1,
- [iops->getattr() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IDMAP_IOPS_GETATTR, 1,
+ [iops->getattr() takes struct mnt_idmap*])
],[
AC_MSG_RESULT(no)
-
dnl #
- dnl # Kernel 4.11 test
+ dnl # Kernel 5.12 test
dnl #
- AC_MSG_CHECKING([whether iops->getattr() takes a path])
- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
+ AC_MSG_CHECKING([whether iops->getattr() takes user_namespace])
+ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
- [iops->getattr() takes a path])
+ AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1,
+ [iops->getattr() takes struct user_namespace*])
],[
AC_MSG_RESULT(no)
dnl #
- dnl # Kernel < 4.11 test
+ dnl # Kernel 4.11 test
dnl #
- AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
- ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
+ AC_MSG_CHECKING([whether iops->getattr() takes a path])
+ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
- [iops->getattr() takes a vfsmount])
+ AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
+ [iops->getattr() takes a path])
],[
AC_MSG_RESULT(no)
+
+ dnl #
+ dnl # Kernel < 4.11 test
+ dnl #
+ AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
+ ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
+ [iops->getattr() takes a vfsmount])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
])
])
diff --git a/config/kernel-inode-lookup.m4 b/config/kernel-inode-lookup.m4
index 1a56e69b04aa..c7373056422c 100644
--- a/config/kernel-inode-lookup.m4
+++ b/config/kernel-inode-lookup.m4
@@ -6,7 +6,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS], [
#include <linux/fs.h>
#include <linux/sched.h>
- struct dentry *inode_lookup(struct inode *inode,
+ static struct dentry *inode_lookup(struct inode *inode,
struct dentry *dentry, unsigned int flags) { return NULL; }
static const struct inode_operations iops
diff --git a/config/kernel-inode-permission.m4 b/config/kernel-inode-permission.m4
index ba9ff5d43d4d..f7fc16439093 100644
--- a/config/kernel-inode-permission.m4
+++ b/config/kernel-inode-permission.m4
@@ -1,5 +1,23 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [
dnl #
+ dnl # 6.3 API change
+ dnl # iops->permission() now takes struct mnt_idmap*
+ dnl # as its first arg
+ dnl #
+ ZFS_LINUX_TEST_SRC([permission_mnt_idmap], [
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+
+ static int test_permission(struct mnt_idmap *idmap,
+ struct inode *inode, int mask) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .permission = test_permission,
+ };
+ ],[])
+
+ dnl #
dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list.
dnl #
@@ -7,23 +25,30 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [
#include <linux/fs.h>
#include <linux/sched.h>
- int inode_permission(struct user_namespace *userns,
+ static int test_permission(struct user_namespace *userns,
struct inode *inode, int mask) { return 0; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
- .permission = inode_permission,
+ .permission = test_permission,
};
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_PERMISSION], [
- AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([permission_userns], [
+ AC_MSG_CHECKING([whether iops->permission() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([permission_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1,
- [iops->permission() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_PERMISSION_IDMAP, 1,
+ [iops->permission() takes struct mnt_idmap*])
],[
- AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether iops->permission() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([permission_userns], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IOPS_PERMISSION_USERNS, 1,
+ [iops->permission() takes struct user_namespace*])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
])
diff --git a/config/kernel-inode-setattr.m4 b/config/kernel-inode-setattr.m4
new file mode 100644
index 000000000000..69289e897be6
--- /dev/null
+++ b/config/kernel-inode-setattr.m4
@@ -0,0 +1,87 @@
+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SETATTR], [
+ dnl #
+ dnl # Linux 6.3 API
+ dnl # The first arg of setattr I/O operations handler type
+ dnl # is changed to struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_setattr_mnt_idmap], [
+ #include <linux/fs.h>
+
+ static int test_setattr(
+ struct mnt_idmap *idmap,
+ struct dentry *de, struct iattr *ia)
+ { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .setattr = test_setattr,
+ };
+ ],[])
+
+ dnl #
+ dnl # Linux 5.12 API
+ dnl # The setattr I/O operations handler type was extended to require
+ dnl # a struct user_namespace* as its first arg, to support idmapped
+ dnl # mounts.
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_setattr_userns], [
+ #include <linux/fs.h>
+
+ static int test_setattr(
+ struct user_namespace *userns,
+ struct dentry *de, struct iattr *ia)
+ { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .setattr = test_setattr,
+ };
+ ],[])
+
+ ZFS_LINUX_TEST_SRC([inode_operations_setattr], [
+ #include <linux/fs.h>
+
+ static int test_setattr(
+ struct dentry *de, struct iattr *ia)
+ { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .setattr = test_setattr,
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_INODE_SETATTR], [
+ dnl #
+ dnl # Kernel 6.3 test
+ dnl #
+ AC_MSG_CHECKING([whether iops->setattr() takes mnt_idmap])
+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr_mnt_idmap], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IDMAP_IOPS_SETATTR, 1,
+ [iops->setattr() takes struct mnt_idmap*])
+ ],[
+ AC_MSG_RESULT(no)
+ dnl #
+ dnl # Kernel 5.12 test
+ dnl #
+ AC_MSG_CHECKING([whether iops->setattr() takes user_namespace])
+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr_userns], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_USERNS_IOPS_SETATTR, 1,
+ [iops->setattr() takes struct user_namespace*])
+ ],[
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether iops->setattr() exists])
+ ZFS_LINUX_TEST_RESULT([inode_operations_setattr], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IOPS_SETATTR, 1,
+ [iops->setattr() exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+ ])
+ ])
+])
diff --git a/config/kernel-inode-times.m4 b/config/kernel-inode-times.m4
index 9c016c790081..4d861596ed0b 100644
--- a/config/kernel-inode-times.m4
+++ b/config/kernel-inode-times.m4
@@ -27,6 +27,73 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_TIMES], [
memset(&ip, 0, sizeof(ip));
ts = ip.i_mtime;
])
+
+ dnl #
+ dnl # 6.6 API change
+ dnl # i_ctime no longer directly accessible, must use
+ dnl # inode_get_ctime(ip), inode_set_ctime*(ip) to
+ dnl # read/write.
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_get_ctime], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+
+ memset(&ip, 0, sizeof(ip));
+ inode_get_ctime(&ip);
+ ])
+
+ ZFS_LINUX_TEST_SRC([inode_set_ctime_to_ts], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+ struct timespec64 ts = {0};
+
+ memset(&ip, 0, sizeof(ip));
+ inode_set_ctime_to_ts(&ip, ts);
+ ])
+
+ dnl #
+ dnl # 6.7 API change
+ dnl # i_atime/i_mtime no longer directly accessible, must use
+ dnl # inode_get_mtime(ip), inode_set_mtime*(ip) to
+ dnl # read/write.
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_get_atime], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+
+ memset(&ip, 0, sizeof(ip));
+ inode_get_atime(&ip);
+ ])
+ ZFS_LINUX_TEST_SRC([inode_get_mtime], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+
+ memset(&ip, 0, sizeof(ip));
+ inode_get_mtime(&ip);
+ ])
+
+ ZFS_LINUX_TEST_SRC([inode_set_atime_to_ts], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+ struct timespec64 ts = {0};
+
+ memset(&ip, 0, sizeof(ip));
+ inode_set_atime_to_ts(&ip, ts);
+ ])
+ ZFS_LINUX_TEST_SRC([inode_set_mtime_to_ts], [
+ #include <linux/fs.h>
+ ],[
+ struct inode ip;
+ struct timespec64 ts = {0};
+
+ memset(&ip, 0, sizeof(ip));
+ inode_set_mtime_to_ts(&ip, ts);
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
@@ -47,4 +114,58 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_TIMES], [
AC_DEFINE(HAVE_INODE_TIMESPEC64_TIMES, 1,
[inode->i_*time's are timespec64])
])
+
+ AC_MSG_CHECKING([whether inode_get_ctime() exists])
+ ZFS_LINUX_TEST_RESULT([inode_get_ctime], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_GET_CTIME, 1,
+ [inode_get_ctime() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+
+ AC_MSG_CHECKING([whether inode_set_ctime_to_ts() exists])
+ ZFS_LINUX_TEST_RESULT([inode_set_ctime_to_ts], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_SET_CTIME_TO_TS, 1,
+ [inode_set_ctime_to_ts() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+
+ AC_MSG_CHECKING([whether inode_get_atime() exists])
+ ZFS_LINUX_TEST_RESULT([inode_get_atime], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_GET_ATIME, 1,
+ [inode_get_atime() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+
+ AC_MSG_CHECKING([whether inode_set_atime_to_ts() exists])
+ ZFS_LINUX_TEST_RESULT([inode_set_atime_to_ts], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_SET_ATIME_TO_TS, 1,
+ [inode_set_atime_to_ts() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+
+ AC_MSG_CHECKING([whether inode_get_mtime() exists])
+ ZFS_LINUX_TEST_RESULT([inode_get_mtime], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_GET_MTIME, 1,
+ [inode_get_mtime() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+
+ AC_MSG_CHECKING([whether inode_set_mtime_to_ts() exists])
+ ZFS_LINUX_TEST_RESULT([inode_set_mtime_to_ts], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_SET_MTIME_TO_TS, 1,
+ [inode_set_mtime_to_ts() exists in linux/fs.h])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4
index a90cf3da641d..4e9c002b77f2 100644
--- a/config/kernel-is_owner_or_cap.m4
+++ b/config/kernel-is_owner_or_cap.m4
@@ -16,12 +16,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [
(void) inode_owner_or_capable(ip);
])
- ZFS_LINUX_TEST_SRC([inode_owner_or_capable_idmapped], [
+ ZFS_LINUX_TEST_SRC([inode_owner_or_capable_userns], [
#include <linux/fs.h>
],[
struct inode *ip = NULL;
(void) inode_owner_or_capable(&init_user_ns, ip);
])
+
+ ZFS_LINUX_TEST_SRC([inode_owner_or_capable_mnt_idmap], [
+ #include <linux/fs.h>
+ #include <linux/mnt_idmapping.h>
+ ],[
+ struct inode *ip = NULL;
+ (void) inode_owner_or_capable(&nop_mnt_idmap, ip);
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
@@ -35,12 +43,21 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [
AC_MSG_CHECKING(
[whether inode_owner_or_capable() takes user_ns])
- ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_idmapped], [
+ ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_userns], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED, 1,
+ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_USERNS, 1,
[inode_owner_or_capable() takes user_ns])
],[
- ZFS_LINUX_TEST_ERROR([capability])
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(
+ [whether inode_owner_or_capable() takes mnt_idmap])
+ ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_mnt_idmap], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAP, 1,
+ [inode_owner_or_capable() takes mnt_idmap])
+ ], [
+ ZFS_LINUX_TEST_ERROR([capability])
+ ])
])
])
])
diff --git a/config/kernel-make-request-fn.m4 b/config/kernel-make-request-fn.m4
index 86b202a7a272..9813ad2fb3f3 100644
--- a/config/kernel-make-request-fn.m4
+++ b/config/kernel-make-request-fn.m4
@@ -4,7 +4,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
ZFS_LINUX_TEST_SRC([make_request_fn_void], [
#include <linux/blkdev.h>
- void make_request(struct request_queue *q,
+ static void make_request(struct request_queue *q,
struct bio *bio) { return; }
],[
blk_queue_make_request(NULL, &make_request);
@@ -12,7 +12,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
ZFS_LINUX_TEST_SRC([make_request_fn_blk_qc_t], [
#include <linux/blkdev.h>
- blk_qc_t make_request(struct request_queue *q,
+ static blk_qc_t make_request(struct request_queue *q,
struct bio *bio) { return (BLK_QC_T_NONE); }
],[
blk_queue_make_request(NULL, &make_request);
@@ -20,7 +20,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
ZFS_LINUX_TEST_SRC([blk_alloc_queue_request_fn], [
#include <linux/blkdev.h>
- blk_qc_t make_request(struct request_queue *q,
+ static blk_qc_t make_request(struct request_queue *q,
struct bio *bio) { return (BLK_QC_T_NONE); }
],[
struct request_queue *q __attribute__ ((unused));
@@ -29,7 +29,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
ZFS_LINUX_TEST_SRC([blk_alloc_queue_request_fn_rh], [
#include <linux/blkdev.h>
- blk_qc_t make_request(struct request_queue *q,
+ static blk_qc_t make_request(struct request_queue *q,
struct bio *bio) { return (BLK_QC_T_NONE); }
],[
struct request_queue *q __attribute__ ((unused));
@@ -49,6 +49,21 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN], [
struct gendisk *disk __attribute__ ((unused));
disk = blk_alloc_disk(NUMA_NO_NODE);
])
+
+ ZFS_LINUX_TEST_SRC([blk_alloc_disk_2arg], [
+ #include <linux/blkdev.h>
+ ],[
+ struct queue_limits *lim = NULL;
+ struct gendisk *disk __attribute__ ((unused));
+ disk = blk_alloc_disk(lim, NUMA_NO_NODE);
+ ])
+
+ ZFS_LINUX_TEST_SRC([blk_cleanup_disk], [
+ #include <linux/blkdev.h>
+ ],[
+ struct gendisk *disk __attribute__ ((unused));
+ blk_cleanup_disk(disk);
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
@@ -73,6 +88,44 @@ AC_DEFUN([ZFS_AC_KERNEL_MAKE_REQUEST_FN], [
ZFS_LINUX_TEST_RESULT([blk_alloc_disk], [
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_BLK_ALLOC_DISK], 1, [blk_alloc_disk() exists])
+
+ dnl #
+ dnl # 5.20 API change,
+ dnl # Removed blk_cleanup_disk(), put_disk() should be used.
+ dnl #
+ AC_MSG_CHECKING([whether blk_cleanup_disk() exists])
+ ZFS_LINUX_TEST_RESULT([blk_cleanup_disk], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_BLK_CLEANUP_DISK], 1,
+ [blk_cleanup_disk() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+
+ dnl #
+ dnl # Linux 6.9 API Change:
+ dnl # blk_alloc_queue() takes a nullable queue_limits arg.
+ dnl #
+ AC_MSG_CHECKING([whether blk_alloc_disk() exists and takes 2 args])
+ ZFS_LINUX_TEST_RESULT([blk_alloc_disk_2arg], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_BLK_ALLOC_DISK_2ARG], 1, [blk_alloc_disk() exists and takes 2 args])
+
+ dnl #
+ dnl # 5.20 API change,
+ dnl # Removed blk_cleanup_disk(), put_disk() should be used.
+ dnl #
+ AC_MSG_CHECKING([whether blk_cleanup_disk() exists])
+ ZFS_LINUX_TEST_RESULT([blk_cleanup_disk], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_BLK_CLEANUP_DISK], 1,
+ [blk_cleanup_disk() exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
], [
AC_MSG_RESULT(no)
])
diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4
index 6667ed04fa4c..367f100094d3 100644
--- a/config/kernel-mkdir.m4
+++ b/config/kernel-mkdir.m4
@@ -3,6 +3,22 @@ dnl # Supported mkdir() interfaces checked newest to oldest.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [
dnl #
+ dnl # 6.3 API change
+ dnl # mkdir() takes struct mnt_idmap * as the first arg
+ dnl #
+ ZFS_LINUX_TEST_SRC([mkdir_mnt_idmap], [
+ #include <linux/fs.h>
+
+ static int mkdir(struct mnt_idmap *idmap,
+ struct inode *inode, struct dentry *dentry,
+ umode_t umode) { return 0; }
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .mkdir = mkdir,
+ };
+ ],[])
+
+ dnl #
dnl # 5.12 API change
dnl # The struct user_namespace arg was added as the first argument to
dnl # mkdir()
@@ -10,7 +26,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [
ZFS_LINUX_TEST_SRC([mkdir_user_namespace], [
#include <linux/fs.h>
- int mkdir(struct user_namespace *userns,
+ static int mkdir(struct user_namespace *userns,
struct inode *inode, struct dentry *dentry,
umode_t umode) { return 0; }
@@ -31,7 +47,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [
ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [
#include <linux/fs.h>
- int mkdir(struct inode *inode, struct dentry *dentry,
+ static int mkdir(struct inode *inode, struct dentry *dentry,
umode_t umode) { return 0; }
static const struct inode_operations
@@ -43,25 +59,36 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [
AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [
dnl #
- dnl # 5.12 API change
- dnl # The struct user_namespace arg was added as the first argument to
- dnl # mkdir() of the iops structure.
+ dnl # 6.3 API change
+ dnl # mkdir() takes struct mnt_idmap * as the first arg
dnl #
- AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [
+ AC_MSG_CHECKING([whether iops->mkdir() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([mkdir_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
- [iops->mkdir() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_MKDIR_IDMAP, 1,
+ [iops->mkdir() takes struct mnt_idmap*])
],[
- AC_MSG_RESULT(no)
-
- AC_MSG_CHECKING([whether iops->mkdir() takes umode_t])
- ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
+ dnl #
+ dnl # 5.12 API change
+ dnl # The struct user_namespace arg was added as the first argument to
+ dnl # mkdir() of the iops structure.
+ dnl #
+ AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
- [iops->mkdir() takes umode_t])
+ AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
+ [iops->mkdir() takes struct user_namespace*])
],[
- ZFS_LINUX_TEST_ERROR([mkdir()])
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether iops->mkdir() takes umode_t])
+ ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_MKDIR_UMODE_T, 1,
+ [iops->mkdir() takes umode_t])
+ ],[
+ ZFS_LINUX_TEST_ERROR([mkdir()])
+ ])
])
])
])
diff --git a/config/kernel-mknod.m4 b/config/kernel-mknod.m4
index ffe45106003a..6ad3453aaf0a 100644
--- a/config/kernel-mknod.m4
+++ b/config/kernel-mknod.m4
@@ -1,5 +1,23 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [
dnl #
+ dnl # 6.3 API change
+ dnl # The first arg is now struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([mknod_mnt_idmap], [
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+
+ static int tmp_mknod(struct mnt_idmap *idmap,
+ struct inode *inode ,struct dentry *dentry,
+ umode_t u, dev_t d) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .mknod = tmp_mknod,
+ };
+ ],[])
+
+ dnl #
dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list.
dnl #
@@ -7,7 +25,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [
#include <linux/fs.h>
#include <linux/sched.h>
- int tmp_mknod(struct user_namespace *userns,
+ static int tmp_mknod(struct user_namespace *userns,
struct inode *inode ,struct dentry *dentry,
umode_t u, dev_t d) { return 0; }
@@ -19,12 +37,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [
])
AC_DEFUN([ZFS_AC_KERNEL_MKNOD], [
- AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([mknod_userns], [
+ AC_MSG_CHECKING([whether iops->mknod() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([mknod_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1,
- [iops->mknod() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_MKNOD_IDMAP, 1,
+ [iops->mknod() takes struct mnt_idmap*])
],[
AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([mknod_userns], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1,
+ [iops->mknod() takes struct user_namespace*])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
])
diff --git a/config/kernel-mm-page-size.m4 b/config/kernel-mm-page-size.m4
new file mode 100644
index 000000000000..d5ebd926986a
--- /dev/null
+++ b/config/kernel-mm-page-size.m4
@@ -0,0 +1,17 @@
+AC_DEFUN([ZFS_AC_KERNEL_SRC_MM_PAGE_SIZE], [
+ ZFS_LINUX_TEST_SRC([page_size], [
+ #include <linux/mm.h>
+ ],[
+ unsigned long s;
+ s = page_size(NULL);
+ ])
+])
+AC_DEFUN([ZFS_AC_KERNEL_MM_PAGE_SIZE], [
+ AC_MSG_CHECKING([whether page_size() is available])
+ ZFS_LINUX_TEST_RESULT([page_size], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_MM_PAGE_SIZE, 1, [page_size() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
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 <linux/module.h>
- #include <linux/moduleparam.h>
-
- 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-proc-operations.m4 b/config/kernel-proc-operations.m4
index df216222ecc2..3ae8ce2b6d0d 100644
--- a/config/kernel-proc-operations.m4
+++ b/config/kernel-proc-operations.m4
@@ -7,14 +7,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PROC_OPERATIONS], [
ZFS_LINUX_TEST_SRC([proc_ops_struct], [
#include <linux/proc_fs.h>
- int test_open(struct inode *ip, struct file *fp) { return 0; }
- ssize_t test_read(struct file *fp, char __user *ptr,
+ static int test_open(struct inode *ip, struct file *fp) { return 0; }
+ static ssize_t test_read(struct file *fp, char __user *ptr,
size_t size, loff_t *offp) { return 0; }
- ssize_t test_write(struct file *fp, const char __user *ptr,
+ static ssize_t test_write(struct file *fp, const char __user *ptr,
size_t size, loff_t *offp) { return 0; }
- loff_t test_lseek(struct file *fp, loff_t off, int flag)
+ static loff_t test_lseek(struct file *fp, loff_t off, int flag)
{ return 0; }
- int test_release(struct inode *ip, struct file *fp)
+ static int test_release(struct inode *ip, struct file *fp)
{ return 0; }
const struct proc_ops test_ops __attribute__ ((unused)) = {
diff --git a/config/kernel-put-link.m4 b/config/kernel-put-link.m4
index 4234861f3347..8ab318cbff8c 100644
--- a/config/kernel-put-link.m4
+++ b/config/kernel-put-link.m4
@@ -4,7 +4,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_PUT_LINK], [
ZFS_LINUX_TEST_SRC([put_link_cookie], [
#include <linux/fs.h>
- void put_link(struct inode *ip, void *cookie)
+ static void put_link(struct inode *ip, void *cookie)
{ return; }
static struct inode_operations
iops __attribute__ ((unused)) = {
@@ -14,7 +14,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_PUT_LINK], [
ZFS_LINUX_TEST_SRC([put_link_nameidata], [
#include <linux/fs.h>
- void put_link(struct dentry *de, struct
+ static void put_link(struct dentry *de, struct
nameidata *nd, void *ptr) { return; }
static struct inode_operations
iops __attribute__ ((unused)) = {
diff --git a/config/kernel-reclaim_state.m4 b/config/kernel-reclaim_state.m4
new file mode 100644
index 000000000000..9936b3c1001f
--- /dev/null
+++ b/config/kernel-reclaim_state.m4
@@ -0,0 +1,26 @@
+AC_DEFUN([ZFS_AC_KERNEL_SRC_RECLAIMED], [
+ dnl #
+ dnl # 6.4 API change
+ dnl # The reclaimed_slab of struct reclaim_state
+ dnl # is renamed to reclaimed
+ dnl #
+ ZFS_LINUX_TEST_SRC([reclaim_state_reclaimed], [
+ #include <linux/swap.h>
+ static const struct reclaim_state
+ rs __attribute__ ((unused)) = {
+ .reclaimed = 100,
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_RECLAIMED], [
+ AC_MSG_CHECKING([whether struct reclaim_state has reclaimed field])
+ ZFS_LINUX_TEST_RESULT([reclaim_state_reclaimed], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RECLAIM_STATE_RECLAIMED, 1,
+ [struct reclaim_state has reclaimed])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
diff --git a/config/kernel-register_sysctl_table.m4 b/config/kernel-register_sysctl_table.m4
new file mode 100644
index 000000000000..a5e934f56d29
--- /dev/null
+++ b/config/kernel-register_sysctl_table.m4
@@ -0,0 +1,27 @@
+dnl #
+dnl # Linux 6.5 removes register_sysctl_table
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE], [
+ ZFS_LINUX_TEST_SRC([has_register_sysctl_table], [
+ #include <linux/sysctl.h>
+
+ static struct ctl_table dummy_table[] = {
+ {}
+ };
+
+ ],[
+ struct ctl_table_header *h
+ __attribute((unused)) = register_sysctl_table(dummy_table);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE], [
+ AC_MSG_CHECKING([whether register_sysctl_table exists])
+ ZFS_LINUX_TEST_RESULT([has_register_sysctl_table], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_REGISTER_SYSCTL_TABLE, 1,
+ [register_sysctl_table exists])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4
index 302db43f5748..ce881502d1b1 100644
--- a/config/kernel-rename.m4
+++ b/config/kernel-rename.m4
@@ -1,12 +1,32 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
dnl #
+ dnl # 3.9 (to 4.9) API change,
+ dnl #
+ dnl # A new version of iops->rename() was added (rename2) that takes a flag
+ dnl # argument (to support renameat2). However this separate function was
+ dnl # merged back into iops->rename() in Linux 4.9.
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_rename2], [
+ #include <linux/fs.h>
+ static int rename2_fn(struct inode *sip, struct dentry *sdp,
+ struct inode *tip, struct dentry *tdp,
+ unsigned int flags) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .rename2 = rename2_fn,
+ };
+ ],[])
+
+ dnl #
dnl # 4.9 API change,
- dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants
- dnl # flags.
+ dnl #
+ dnl # iops->rename2() merged into iops->rename(), and iops->rename() now
+ dnl # wants flags.
dnl #
ZFS_LINUX_TEST_SRC([inode_operations_rename_flags], [
#include <linux/fs.h>
- int rename_fn(struct inode *sip, struct dentry *sdp,
+ static int rename_fn(struct inode *sip, struct dentry *sdp,
struct inode *tip, struct dentry *tdp,
unsigned int flags) { return 0; }
@@ -17,14 +37,47 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
],[])
dnl #
+ dnl # EL7 compatibility
+ dnl #
+ dnl # EL7 has backported renameat2 support, but it's done by defining a
+ dnl # separate iops wrapper structure that takes the .renameat2 function.
+ dnl #
+ ZFS_LINUX_TEST_SRC([dir_inode_operations_wrapper_rename2], [
+ #include <linux/fs.h>
+ static int rename2_fn(struct inode *sip, struct dentry *sdp,
+ struct inode *tip, struct dentry *tdp,
+ unsigned int flags) { return 0; }
+
+ static const struct inode_operations_wrapper
+ iops __attribute__ ((unused)) = {
+ .rename2 = rename2_fn,
+ };
+ ],[])
+
+ dnl #
dnl # 5.12 API change,
dnl #
- dnl # Linux 5.12 introduced passing struct user_namespace* as the first argument
- dnl # of the rename() and other inode_operations members.
+ dnl # Linux 5.12 introduced passing struct user_namespace* as the first
+ dnl # argument of the rename() and other inode_operations members.
dnl #
ZFS_LINUX_TEST_SRC([inode_operations_rename_userns], [
#include <linux/fs.h>
- int rename_fn(struct user_namespace *user_ns, struct inode *sip,
+ static int rename_fn(struct user_namespace *user_ns, struct inode *sip,
+ struct dentry *sdp, struct inode *tip, struct dentry *tdp,
+ unsigned int flags) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .rename = rename_fn,
+ };
+ ],[])
+
+ dnl #
+ dnl # 6.3 API change - the first arg is now struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_rename_mnt_idmap], [
+ #include <linux/fs.h>
+ static int rename_fn(struct mnt_idmap *idmap, struct inode *sip,
struct dentry *sdp, struct inode *tip, struct dentry *tdp,
unsigned int flags) { return 0; }
@@ -36,21 +89,45 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
])
AC_DEFUN([ZFS_AC_KERNEL_RENAME], [
- AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [
+ AC_MSG_CHECKING([whether iops->rename() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([inode_operations_rename_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1,
- [iops->rename() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_RENAME_IDMAP, 1,
+ [iops->rename() takes struct mnt_idmap*])
],[
- AC_MSG_RESULT(no)
-
- AC_MSG_CHECKING([whether iop->rename() wants flags])
- ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [
+ AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
- [iops->rename() wants flags])
+ AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1,
+ [iops->rename() takes struct user_namespace*])
],[
AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether iops->rename2() exists])
+ ZFS_LINUX_TEST_RESULT([inode_operations_rename2], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RENAME2, 1, [iops->rename2() exists])
+ ],[
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether iops->rename() wants flags])
+ ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1,
+ [iops->rename() wants flags])
+ ],[
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether struct inode_operations_wrapper takes .rename2()])
+ ZFS_LINUX_TEST_RESULT([dir_inode_operations_wrapper_rename2], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RENAME2_OPERATIONS_WRAPPER, 1,
+ [struct inode_operations_wrapper takes .rename2()])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+ ])
+ ])
])
])
])
diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4
index 24245aa53448..e02d6263e9c9 100644
--- a/config/kernel-setattr-prepare.m4
+++ b/config/kernel-setattr-prepare.m4
@@ -27,26 +27,48 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
int error __attribute__ ((unused)) =
setattr_prepare(userns, dentry, attr);
])
+
+ dnl #
+ dnl # 6.3 API change
+ dnl # The first arg of setattr_prepare() is changed to struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([setattr_prepare_mnt_idmap], [
+ #include <linux/fs.h>
+ ], [
+ struct dentry *dentry = NULL;
+ struct iattr *attr = NULL;
+ struct mnt_idmap *idmap = NULL;
+ int error __attribute__ ((unused)) =
+ setattr_prepare(idmap, dentry, attr);
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [
- AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*])
- ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns],
+ AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_mnt_idmap],
[setattr_prepare], [fs/attr.c], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1,
- [setattr_prepare() accepts user_namespace])
+ AC_DEFINE(HAVE_SETATTR_PREPARE_IDMAP, 1,
+ [setattr_prepare() accepts mnt_idmap])
], [
- AC_MSG_RESULT(no)
-
- AC_MSG_CHECKING([whether setattr_prepare() is available, doesn't accept user_namespace])
- ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
- [setattr_prepare], [fs/attr.c], [
+ AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns],
+ [setattr_prepare], [fs/attr.c], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1,
- [setattr_prepare() is available, doesn't accept user_namespace])
+ AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1,
+ [setattr_prepare() accepts user_namespace])
], [
AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([whether setattr_prepare() is available, doesn't accept user_namespace])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare],
+ [setattr_prepare], [fs/attr.c], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1,
+ [setattr_prepare() is available, doesn't accept user_namespace])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
])
])
])
diff --git a/config/kernel-show-options.m4 b/config/kernel-show-options.m4
index 93bd5fbfbb24..fd62f30086dc 100644
--- a/config/kernel-show-options.m4
+++ b/config/kernel-show-options.m4
@@ -5,7 +5,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHOW_OPTIONS], [
ZFS_LINUX_TEST_SRC([super_operations_show_options], [
#include <linux/fs.h>
- int show_options(struct seq_file * x, struct dentry * y) {
+ static int show_options(struct seq_file * x, struct dentry * y) {
return 0;
};
diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
index 8cf0f2761bde..6580b08d5ff2 100644
--- a/config/kernel-shrink.m4
+++ b/config/kernel-shrink.m4
@@ -8,9 +8,6 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK], [
ZFS_LINUX_TEST_SRC([super_block_s_shrink], [
#include <linux/fs.h>
- int shrink(struct shrinker *s, struct shrink_control *sc)
- { return 0; }
-
static const struct super_block
sb __attribute__ ((unused)) = {
.s_shrink.seeks = DEFAULT_SEEKS,
@@ -19,12 +16,44 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK], [
],[])
])
+dnl #
+dnl # 6.7 API change
+dnl # s_shrink is now a pointer.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK_PTR], [
+ ZFS_LINUX_TEST_SRC([super_block_s_shrink_ptr], [
+ #include <linux/fs.h>
+ static unsigned long shrinker_cb(struct shrinker *shrink,
+ struct shrink_control *sc) { return 0; }
+ static struct shrinker shrinker = {
+ .count_objects = shrinker_cb,
+ .scan_objects = shrinker_cb,
+ .seeks = DEFAULT_SEEKS,
+ };
+ static const struct super_block
+ sb __attribute__ ((unused)) = {
+ .s_shrink = &shrinker,
+ };
+ ],[])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_SHRINK], [
AC_MSG_CHECKING([whether super_block has s_shrink])
ZFS_LINUX_TEST_RESULT([super_block_s_shrink], [
AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SUPER_BLOCK_S_SHRINK, 1,
+ [have super_block s_shrink])
],[
- ZFS_LINUX_TEST_ERROR([sb->s_shrink()])
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether super_block has s_shrink pointer])
+ ZFS_LINUX_TEST_RESULT([super_block_s_shrink_ptr], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SUPER_BLOCK_S_SHRINK_PTR, 1,
+ [have super_block s_shrink pointer])
+ ],[
+ AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_ERROR([sb->s_shrink()])
+ ])
])
])
@@ -54,10 +83,25 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
])
])
+AC_DEFUN([ZFS_AC_KERNEL_SRC_REGISTER_SHRINKER_VARARG], [
+ ZFS_LINUX_TEST_SRC([register_shrinker_vararg], [
+ #include <linux/mm.h>
+ static unsigned long shrinker_cb(struct shrinker *shrink,
+ struct shrink_control *sc) { return 0; }
+ ],[
+ struct shrinker cache_shrinker = {
+ .count_objects = shrinker_cb,
+ .scan_objects = shrinker_cb,
+ .seeks = DEFAULT_SEEKS,
+ };
+ register_shrinker(&cache_shrinker, "vararg-reg-shrink-test");
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control], [
#include <linux/mm.h>
- int shrinker_cb(struct shrinker *shrink,
+ static int shrinker_cb(struct shrinker *shrink,
struct shrink_control *sc) { return 0; }
],[
struct shrinker cache_shrinker = {
@@ -69,7 +113,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
ZFS_LINUX_TEST_SRC([shrinker_cb_shrink_control_split], [
#include <linux/mm.h>
- unsigned long shrinker_cb(struct shrinker *shrink,
+ static unsigned long shrinker_cb(struct shrinker *shrink,
struct shrink_control *sc) { return 0; }
],[
struct shrinker cache_shrinker = {
@@ -81,31 +125,93 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK], [
])
])
+dnl #
+dnl # 6.7 API change
+dnl # register_shrinker has been replaced by shrinker_register.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER_REGISTER], [
+ ZFS_LINUX_TEST_SRC([shrinker_register], [
+ #include <linux/shrinker.h>
+ static unsigned long shrinker_cb(struct shrinker *shrink,
+ struct shrink_control *sc) { return 0; }
+ ],[
+ struct shrinker cache_shrinker = {
+ .count_objects = shrinker_cb,
+ .scan_objects = shrinker_cb,
+ .seeks = DEFAULT_SEEKS,
+ };
+ shrinker_register(&cache_shrinker);
+ ])
+])
+
AC_DEFUN([ZFS_AC_KERNEL_SHRINKER_CALLBACK],[
dnl #
- dnl # 3.0 - 3.11 API change
- dnl # cs->shrink(struct shrinker *, struct shrink_control *sc)
+ dnl # 6.0 API change
+ dnl # register_shrinker() becomes a var-arg function that takes
+ dnl # a printf-style format string as args > 0
dnl #
- AC_MSG_CHECKING([whether new 2-argument shrinker exists])
- ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control], [
+ AC_MSG_CHECKING([whether new var-arg register_shrinker() exists])
+ ZFS_LINUX_TEST_RESULT([register_shrinker_vararg], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SINGLE_SHRINKER_CALLBACK, 1,
- [new shrinker callback wants 2 args])
+ AC_DEFINE(HAVE_REGISTER_SHRINKER_VARARG, 1,
+ [register_shrinker is vararg])
+
+ dnl # We assume that the split shrinker callback exists if the
+ dnl # vararg register_shrinker() exists, because the latter is
+ dnl # a much more recent addition, and the macro test for the
+ dnl # var-arg version only works if the callback is split
+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
+ [cs->count_objects exists])
],[
AC_MSG_RESULT(no)
-
dnl #
- dnl # 3.12 API change,
- dnl # cs->shrink() is logically split in to
- dnl # cs->count_objects() and cs->scan_objects()
+ dnl # 3.0 - 3.11 API change
+ dnl # cs->shrink(struct shrinker *, struct shrink_control *sc)
dnl #
- AC_MSG_CHECKING([whether cs->count_objects callback exists])
- ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control_split], [
+ AC_MSG_CHECKING([whether new 2-argument shrinker exists])
+ ZFS_LINUX_TEST_RESULT([shrinker_cb_shrink_control], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
- [cs->count_objects exists])
+ AC_DEFINE(HAVE_SINGLE_SHRINKER_CALLBACK, 1,
+ [new shrinker callback wants 2 args])
],[
- ZFS_LINUX_TEST_ERROR([shrinker])
+ AC_MSG_RESULT(no)
+
+ dnl #
+ dnl # 3.12 API change,
+ dnl # cs->shrink() is logically split in to
+ dnl # cs->count_objects() and cs->scan_objects()
+ dnl #
+ AC_MSG_CHECKING(
+ [whether cs->count_objects callback exists])
+ ZFS_LINUX_TEST_RESULT(
+ [shrinker_cb_shrink_control_split],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, 1,
+ [cs->count_objects exists])
+ ],[
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING(
+ [whether shrinker_register exists])
+ ZFS_LINUX_TEST_RESULT([shrinker_register], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SHRINKER_REGISTER, 1,
+ [shrinker_register exists])
+
+ dnl # We assume that the split shrinker
+ dnl # callback exists if
+ dnl # shrinker_register() exists,
+ dnl # because the latter is a much more
+ dnl # recent addition, and the macro
+ dnl # test for shrinker_register() only
+ dnl # works if the callback is split
+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
+ 1, [cs->count_objects exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_ERROR([shrinker])
+ ])
+ ])
])
])
])
@@ -138,9 +244,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_STRUCT], [
AC_DEFUN([ZFS_AC_KERNEL_SRC_SHRINKER], [
ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK
+ ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_SHRINK_PTR
ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_HAS_NID
ZFS_AC_KERNEL_SRC_SHRINKER_CALLBACK
ZFS_AC_KERNEL_SRC_SHRINK_CONTROL_STRUCT
+ ZFS_AC_KERNEL_SRC_REGISTER_SHRINKER_VARARG
+ ZFS_AC_KERNEL_SRC_SHRINKER_REGISTER
])
AC_DEFUN([ZFS_AC_KERNEL_SHRINKER], [
diff --git a/config/kernel-strlcpy.m4 b/config/kernel-strlcpy.m4
new file mode 100644
index 000000000000..c31cf52d78b0
--- /dev/null
+++ b/config/kernel-strlcpy.m4
@@ -0,0 +1,47 @@
+dnl #
+dnl # 6.8.x replaced strlcpy with strscpy. Check for both so we can provide
+dnl # appropriate fallbacks.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_STRLCPY], [
+ ZFS_LINUX_TEST_SRC([kernel_has_strlcpy], [
+ #include <linux/string.h>
+ ], [
+ const char *src = "goodbye";
+ char dst[32];
+ size_t len;
+ len = strlcpy(dst, src, sizeof (dst));
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_STRSCPY], [
+ ZFS_LINUX_TEST_SRC([kernel_has_strscpy], [
+ #include <linux/string.h>
+ ], [
+ const char *src = "goodbye";
+ char dst[32];
+ ssize_t len;
+ len = strscpy(dst, src, sizeof (dst));
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_STRLCPY], [
+ AC_MSG_CHECKING([whether strlcpy() exists])
+ ZFS_LINUX_TEST_RESULT([kernel_has_strlcpy], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_KERNEL_STRLCPY, 1,
+ [strlcpy() exists])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_STRSCPY], [
+ AC_MSG_CHECKING([whether strscpy() exists])
+ ZFS_LINUX_TEST_RESULT([kernel_has_strscpy], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_KERNEL_STRSCPY, 1,
+ [strscpy() exists])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/config/kernel-symlink.m4 b/config/kernel-symlink.m4
index d90366d04b72..804fceab28f0 100644
--- a/config/kernel-symlink.m4
+++ b/config/kernel-symlink.m4
@@ -1,5 +1,21 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [
dnl #
+ dnl # 6.3 API change that changed the first arg
+ dnl # to struct mnt_idmap*
+ dnl #
+ ZFS_LINUX_TEST_SRC([symlink_mnt_idmap], [
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ static int tmp_symlink(struct mnt_idmap *idmap,
+ struct inode *inode ,struct dentry *dentry,
+ const char *path) { return 0; }
+
+ static const struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .symlink = tmp_symlink,
+ };
+ ],[])
+ dnl #
dnl # 5.12 API change that added the struct user_namespace* arg
dnl # to the front of this function type's arg list.
dnl #
@@ -7,7 +23,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [
#include <linux/fs.h>
#include <linux/sched.h>
- int tmp_symlink(struct user_namespace *userns,
+ static int tmp_symlink(struct user_namespace *userns,
struct inode *inode ,struct dentry *dentry,
const char *path) { return 0; }
@@ -19,12 +35,19 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [
])
AC_DEFUN([ZFS_AC_KERNEL_SYMLINK], [
- AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*])
- ZFS_LINUX_TEST_RESULT([symlink_userns], [
+ AC_MSG_CHECKING([whether iops->symlink() takes struct mnt_idmap*])
+ ZFS_LINUX_TEST_RESULT([symlink_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1,
- [iops->symlink() takes struct user_namespace*])
+ AC_DEFINE(HAVE_IOPS_SYMLINK_IDMAP, 1,
+ [iops->symlink() takes struct mnt_idmap*])
],[
- AC_MSG_RESULT(no)
+ AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*])
+ ZFS_LINUX_TEST_RESULT([symlink_userns], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1,
+ [iops->symlink() takes struct user_namespace*])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
])
diff --git a/config/kernel-timer.m4 b/config/kernel-timer.m4
index 403cff3f4189..c710e804be0b 100644
--- a/config/kernel-timer.m4
+++ b/config/kernel-timer.m4
@@ -18,7 +18,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TIMER_SETUP], [
int data;
};
- void task_expire(struct timer_list *tl)
+ static void task_expire(struct timer_list *tl)
{
struct my_task_timer *task_timer =
from_timer(task_timer, tl, timer);
@@ -31,7 +31,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TIMER_SETUP], [
ZFS_LINUX_TEST_SRC([timer_list_function], [
#include <linux/timer.h>
- void task_expire(struct timer_list *tl) {}
+ static void task_expire(struct timer_list *tl) {}
],[
struct timer_list tl;
tl.function = task_expire;
diff --git a/config/kernel-tmpfile.m4 b/config/kernel-tmpfile.m4
index 45c2e6ceea52..7439514186e4 100644
--- a/config/kernel-tmpfile.m4
+++ b/config/kernel-tmpfile.m4
@@ -4,12 +4,39 @@ dnl # Add support for i_op->tmpfile
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
dnl #
+ dnl # 6.3 API change
+ dnl # The first arg is now struct mnt_idmap *
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_mnt_idmap], [
+ #include <linux/fs.h>
+ static int tmpfile(struct mnt_idmap *idmap,
+ struct inode *inode, struct file *file,
+ umode_t mode) { return 0; }
+ static struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .tmpfile = tmpfile,
+ };
+ ],[])
+ dnl # 6.1 API change
+ dnl # use struct file instead of struct dentry
+ dnl #
+ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
+ #include <linux/fs.h>
+ static int tmpfile(struct user_namespace *userns,
+ struct inode *inode, struct file *file,
+ umode_t mode) { return 0; }
+ static struct inode_operations
+ iops __attribute__ ((unused)) = {
+ .tmpfile = tmpfile,
+ };
+ ],[])
+ dnl #
dnl # 5.11 API change
dnl # add support for userns parameter to tmpfile
dnl #
- ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_userns], [
+ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_dentry_userns], [
#include <linux/fs.h>
- int tmpfile(struct user_namespace *userns,
+ static int tmpfile(struct user_namespace *userns,
struct inode *inode, struct dentry *dentry,
umode_t mode) { return 0; }
static struct inode_operations
@@ -17,9 +44,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
.tmpfile = tmpfile,
};
],[])
- ZFS_LINUX_TEST_SRC([inode_operations_tmpfile], [
+ ZFS_LINUX_TEST_SRC([inode_operations_tmpfile_dentry], [
#include <linux/fs.h>
- int tmpfile(struct inode *inode, struct dentry *dentry,
+ static int tmpfile(struct inode *inode, struct dentry *dentry,
umode_t mode) { return 0; }
static struct inode_operations
iops __attribute__ ((unused)) = {
@@ -30,16 +57,30 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_TMPFILE], [
AC_DEFUN([ZFS_AC_KERNEL_TMPFILE], [
AC_MSG_CHECKING([whether i_op->tmpfile() exists])
- ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_userns], [
+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_mnt_idmap], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
- AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns])
- ],[
+ AC_DEFINE(HAVE_TMPFILE_IDMAP, 1, [i_op->tmpfile() has mnt_idmap])
+ ], [
ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
+ AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns])
],[
- AC_MSG_RESULT(no)
+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry_userns], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
+ AC_DEFINE(HAVE_TMPFILE_USERNS, 1, [i_op->tmpfile() has userns])
+ AC_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature])
+ ],[
+ ZFS_LINUX_TEST_RESULT([inode_operations_tmpfile_dentry], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_TMPFILE, 1, [i_op->tmpfile() exists])
+ AC_DEFINE(HAVE_TMPFILE_DENTRY, 1, [i_op->tmpfile() uses old dentry signature])
+ ],[
+ ZFS_LINUX_REQUIRE_API([i_op->tmpfile()], [3.11])
+ ])
+ ])
])
])
])
diff --git a/config/kernel-vfs-direct_IO.m4 b/config/kernel-vfs-direct_IO.m4
index 82583d52fcbc..7b7b91f979f9 100644
--- a/config/kernel-vfs-direct_IO.m4
+++ b/config/kernel-vfs-direct_IO.m4
@@ -5,7 +5,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
ZFS_LINUX_TEST_SRC([direct_io_iter], [
#include <linux/fs.h>
- ssize_t test_direct_IO(struct kiocb *kiocb,
+ static ssize_t test_direct_IO(struct kiocb *kiocb,
struct iov_iter *iter) { return 0; }
static const struct address_space_operations
@@ -17,7 +17,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
ZFS_LINUX_TEST_SRC([direct_io_iter_offset], [
#include <linux/fs.h>
- ssize_t test_direct_IO(struct kiocb *kiocb,
+ static ssize_t test_direct_IO(struct kiocb *kiocb,
struct iov_iter *iter, loff_t offset) { return 0; }
static const struct address_space_operations
@@ -29,7 +29,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
ZFS_LINUX_TEST_SRC([direct_io_iter_rw_offset], [
#include <linux/fs.h>
- ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+ static ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
struct iov_iter *iter, loff_t offset) { return 0; }
static const struct address_space_operations
@@ -41,7 +41,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO], [
ZFS_LINUX_TEST_SRC([direct_io_iovec], [
#include <linux/fs.h>
- ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+ static ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
const struct iovec *iov, loff_t offset,
unsigned long nr_segs) { return 0; }
diff --git a/config/kernel-vfs-extended-file_range.m4 b/config/kernel-vfs-extended-file_range.m4
new file mode 100644
index 000000000000..a2622313129e
--- /dev/null
+++ b/config/kernel-vfs-extended-file_range.m4
@@ -0,0 +1,50 @@
+dnl #
+dnl # EL7 have backported copy_file_range and clone_file_range and
+dnl # added them to an "extended" file_operations struct.
+dnl #
+dnl # We're testing for both functions in one here, because they will only
+dnl # ever appear together and we don't want to match a similar method in
+dnl # some future vendor kernel.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_FILE_OPERATIONS_EXTEND], [
+ ZFS_LINUX_TEST_SRC([vfs_file_operations_extend], [
+ #include <linux/fs.h>
+
+ static ssize_t test_copy_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ size_t len, unsigned int flags) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len; (void) flags;
+ return (0);
+ }
+
+ static int test_clone_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ u64 len) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len;
+ return (0);
+ }
+
+ static const struct file_operations_extend
+ fops __attribute__ ((unused)) = {
+ .kabi_fops = {},
+ .copy_file_range = test_copy_file_range,
+ .clone_file_range = test_clone_file_range,
+ };
+ ],[])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_FILE_OPERATIONS_EXTEND], [
+ AC_MSG_CHECKING([whether file_operations_extend takes \
+.copy_file_range() and .clone_file_range()])
+ ZFS_LINUX_TEST_RESULT([vfs_file_operations_extend], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_VFS_FILE_OPERATIONS_EXTEND, 1,
+ [file_operations_extend takes .copy_file_range()
+ and .clone_file_range()])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/config/kernel-vfs-file_range.m4 b/config/kernel-vfs-file_range.m4
new file mode 100644
index 000000000000..8a5cbe2eeeed
--- /dev/null
+++ b/config/kernel-vfs-file_range.m4
@@ -0,0 +1,191 @@
+dnl #
+dnl # The *_file_range APIs have a long history:
+dnl #
+dnl # 2.6.29: BTRFS_IOC_CLONE and BTRFS_IOC_CLONE_RANGE ioctl introduced
+dnl # 3.12: BTRFS_IOC_FILE_EXTENT_SAME ioctl introduced
+dnl #
+dnl # 4.5: copy_file_range() syscall introduced, added to VFS
+dnl # 4.5: BTRFS_IOC_CLONE and BTRFS_IOC_CLONE_RANGE renamed to FICLONE ands
+dnl # FICLONERANGE, added to VFS as clone_file_range()
+dnl # 4.5: BTRFS_IOC_FILE_EXTENT_SAME renamed to FIDEDUPERANGE, added to VFS
+dnl # as dedupe_file_range()
+dnl #
+dnl # 4.20: VFS clone_file_range() and dedupe_file_range() replaced by
+dnl # remap_file_range()
+dnl #
+dnl # 5.3: VFS copy_file_range() expected to do its own fallback,
+dnl # generic_copy_file_range() added to support it
+dnl #
+dnl # 6.8: generic_copy_file_range() removed, replaced by
+dnl # splice_copy_file_range()
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_COPY_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([vfs_copy_file_range], [
+ #include <linux/fs.h>
+
+ static ssize_t test_copy_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ size_t len, unsigned int flags) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len; (void) flags;
+ return (0);
+ }
+
+ static const struct file_operations
+ fops __attribute__ ((unused)) = {
+ .copy_file_range = test_copy_file_range,
+ };
+ ],[])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_COPY_FILE_RANGE], [
+ AC_MSG_CHECKING([whether fops->copy_file_range() is available])
+ ZFS_LINUX_TEST_RESULT([vfs_copy_file_range], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_VFS_COPY_FILE_RANGE, 1,
+ [fops->copy_file_range() is available])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_GENERIC_COPY_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([generic_copy_file_range], [
+ #include <linux/fs.h>
+ ], [
+ struct file *src_file __attribute__ ((unused)) = NULL;
+ loff_t src_off __attribute__ ((unused)) = 0;
+ struct file *dst_file __attribute__ ((unused)) = NULL;
+ loff_t dst_off __attribute__ ((unused)) = 0;
+ size_t len __attribute__ ((unused)) = 0;
+ unsigned int flags __attribute__ ((unused)) = 0;
+ generic_copy_file_range(src_file, src_off, dst_file, dst_off,
+ len, flags);
+ ])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_GENERIC_COPY_FILE_RANGE], [
+ AC_MSG_CHECKING([whether generic_copy_file_range() is available])
+ ZFS_LINUX_TEST_RESULT_SYMBOL([generic_copy_file_range],
+ [generic_copy_file_range], [fs/read_write.c], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_VFS_GENERIC_COPY_FILE_RANGE, 1,
+ [generic_copy_file_range() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_SPLICE_COPY_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([splice_copy_file_range], [
+ #include <linux/splice.h>
+ ], [
+ struct file *src_file __attribute__ ((unused)) = NULL;
+ loff_t src_off __attribute__ ((unused)) = 0;
+ struct file *dst_file __attribute__ ((unused)) = NULL;
+ loff_t dst_off __attribute__ ((unused)) = 0;
+ size_t len __attribute__ ((unused)) = 0;
+ splice_copy_file_range(src_file, src_off, dst_file, dst_off,
+ len);
+ ])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_SPLICE_COPY_FILE_RANGE], [
+ AC_MSG_CHECKING([whether splice_copy_file_range() is available])
+ ZFS_LINUX_TEST_RESULT([splice_copy_file_range], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_VFS_SPLICE_COPY_FILE_RANGE, 1,
+ [splice_copy_file_range() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_CLONE_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([vfs_clone_file_range], [
+ #include <linux/fs.h>
+
+ static int test_clone_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ u64 len) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len;
+ return (0);
+ }
+
+ static const struct file_operations
+ fops __attribute__ ((unused)) = {
+ .clone_file_range = test_clone_file_range,
+ };
+ ],[])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_CLONE_FILE_RANGE], [
+ AC_MSG_CHECKING([whether fops->clone_file_range() is available])
+ ZFS_LINUX_TEST_RESULT([vfs_clone_file_range], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_VFS_CLONE_FILE_RANGE, 1,
+ [fops->clone_file_range() is available])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_DEDUPE_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([vfs_dedupe_file_range], [
+ #include <linux/fs.h>
+
+ static int test_dedupe_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ u64 len) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len;
+ return (0);
+ }
+
+ static const struct file_operations
+ fops __attribute__ ((unused)) = {
+ .dedupe_file_range = test_dedupe_file_range,
+ };
+ ],[])
+])
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DEDUPE_FILE_RANGE], [
+ AC_MSG_CHECKING([whether fops->dedupe_file_range() is available])
+ ZFS_LINUX_TEST_RESULT([vfs_dedupe_file_range], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_VFS_DEDUPE_FILE_RANGE, 1,
+ [fops->dedupe_file_range() is available])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_REMAP_FILE_RANGE], [
+ ZFS_LINUX_TEST_SRC([vfs_remap_file_range], [
+ #include <linux/fs.h>
+
+ static loff_t test_remap_file_range(struct file *src_file,
+ loff_t src_off, struct file *dst_file, loff_t dst_off,
+ loff_t len, unsigned int flags) {
+ (void) src_file; (void) src_off;
+ (void) dst_file; (void) dst_off;
+ (void) len; (void) flags;
+ return (0);
+ }
+
+ static const struct file_operations
+ fops __attribute__ ((unused)) = {
+ .remap_file_range = test_remap_file_range,
+ };
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_VFS_REMAP_FILE_RANGE], [
+ AC_MSG_CHECKING([whether fops->remap_file_range() is available])
+ ZFS_LINUX_TEST_RESULT([vfs_remap_file_range], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_VFS_REMAP_FILE_RANGE, 1,
+ [fops->remap_file_range() is available])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/config/kernel-vfs-iov_iter.m4 b/config/kernel-vfs-iov_iter.m4
index e0617faab02c..ff560ff3eef0 100644
--- a/config/kernel-vfs-iov_iter.m4
+++ b/config/kernel-vfs-iov_iter.m4
@@ -6,8 +6,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_IOV_ITER], [
#include <linux/fs.h>
#include <linux/uio.h>
],[
- int type __attribute__ ((unused)) =
- ITER_IOVEC | ITER_KVEC | ITER_BVEC | ITER_PIPE;
+ int type __attribute__ ((unused)) = ITER_KVEC;
])
ZFS_LINUX_TEST_SRC([iov_iter_advance], [
@@ -93,6 +92,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_IOV_ITER], [
struct iov_iter iter = { 0 };
__attribute__((unused)) enum iter_type i = iov_iter_type(&iter);
])
+
+ ZFS_LINUX_TEST_SRC([iter_iov], [
+ #include <linux/fs.h>
+ #include <linux/uio.h>
+ ],[
+ struct iov_iter iter = { 0 };
+ __attribute__((unused)) const struct iovec *iov = iter_iov(&iter);
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
@@ -201,4 +208,19 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
AC_DEFINE(HAVE_VFS_IOV_ITER, 1,
[All required iov_iter interfaces are available])
])
+
+ dnl #
+ dnl # Kernel 6.5 introduces the iter_iov() function that returns the
+ dnl # __iov member of an iov_iter*. The iov member was renamed to this
+ dnl # __iov member, and is intended to be accessed via the helper
+ dnl # function now.
+ dnl #
+ AC_MSG_CHECKING([whether iter_iov() is available])
+ ZFS_LINUX_TEST_RESULT([iter_iov], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_ITER_IOV, 1,
+ [iter_iov() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
])
diff --git a/config/kernel-vfs-iterate.m4 b/config/kernel-vfs-iterate.m4
index 172118eac87b..2e396daa1c0f 100644
--- a/config/kernel-vfs-iterate.m4
+++ b/config/kernel-vfs-iterate.m4
@@ -1,7 +1,7 @@
AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_ITERATE], [
ZFS_LINUX_TEST_SRC([file_operations_iterate_shared], [
#include <linux/fs.h>
- int iterate(struct file *filp, struct dir_context * context)
+ static int iterate(struct file *filp, struct dir_context * context)
{ return 0; }
static const struct file_operations fops
@@ -12,7 +12,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_ITERATE], [
ZFS_LINUX_TEST_SRC([file_operations_iterate], [
#include <linux/fs.h>
- int iterate(struct file *filp,
+ static int iterate(struct file *filp,
struct dir_context *context) { return 0; }
static const struct file_operations fops
@@ -27,7 +27,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_ITERATE], [
ZFS_LINUX_TEST_SRC([file_operations_readdir], [
#include <linux/fs.h>
- int readdir(struct file *filp, void *entry,
+ static int readdir(struct file *filp, void *entry,
filldir_t func) { return 0; }
static const struct file_operations fops
diff --git a/config/kernel-vfs-rw-iterate.m4 b/config/kernel-vfs-rw-iterate.m4
index 000353ec15b0..cb20ed03099a 100644
--- a/config/kernel-vfs-rw-iterate.m4
+++ b/config/kernel-vfs-rw-iterate.m4
@@ -5,9 +5,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE], [
ZFS_LINUX_TEST_SRC([file_operations_rw], [
#include <linux/fs.h>
- ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
+ static ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
{ return 0; }
- ssize_t test_write(struct kiocb *kiocb, struct iov_iter *from)
+ static ssize_t test_write(struct kiocb *kiocb, struct iov_iter *from)
{ return 0; }
static const struct file_operations
diff --git a/config/kernel-writepage_t.m4 b/config/kernel-writepage_t.m4
new file mode 100644
index 000000000000..a82cf370c9d4
--- /dev/null
+++ b/config/kernel-writepage_t.m4
@@ -0,0 +1,26 @@
+AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
+ dnl #
+ dnl # 6.3 API change
+ dnl # The writepage_t function type now has its first argument as
+ dnl # struct folio* instead of struct page*
+ dnl #
+ ZFS_LINUX_TEST_SRC([writepage_t_folio], [
+ #include <linux/writeback.h>
+ static int putpage(struct folio *folio,
+ struct writeback_control *wbc, void *data)
+ { return 0; }
+ writepage_t func = putpage;
+ ],[])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [
+ AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*])
+ ZFS_LINUX_TEST_RESULT([writepage_t_folio], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1,
+ [int (*writepage_t)() takes struct folio*])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
index 00b1e74a9ccb..32f58c70a500 100644
--- a/config/kernel-xattr-handler.m4
+++ b/config/kernel-xattr-handler.m4
@@ -68,7 +68,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry_inode], [
#include <linux/xattr.h>
- int get(const struct xattr_handler *handler,
+ static int get(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
const char *name, void *buffer, size_t size) { return 0; }
static const struct xattr_handler
@@ -80,7 +80,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
ZFS_LINUX_TEST_SRC([xattr_handler_get_xattr_handler], [
#include <linux/xattr.h>
- int get(const struct xattr_handler *handler,
+ static int get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size) { return 0; }
static const struct xattr_handler
@@ -92,7 +92,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry], [
#include <linux/xattr.h>
- int get(struct dentry *dentry, const char *name,
+ static int get(struct dentry *dentry, const char *name,
void *buffer, size_t size, int handler_flags)
{ return 0; }
static const struct xattr_handler
@@ -100,6 +100,19 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_GET], [
.get = get,
};
],[])
+
+ ZFS_LINUX_TEST_SRC([xattr_handler_get_dentry_inode_flags], [
+ #include <linux/xattr.h>
+
+ static int get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *buffer,
+ size_t size, int flags) { return 0; }
+ static const struct xattr_handler
+ xops __attribute__ ((unused)) = {
+ .get = get,
+ };
+ ],[])
])
AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
@@ -142,7 +155,21 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
AC_DEFINE(HAVE_XATTR_GET_DENTRY, 1,
[xattr_handler->get() wants dentry])
],[
- ZFS_LINUX_TEST_ERROR([xattr get()])
+ dnl #
+ dnl # Android API change,
+ dnl # The xattr_handler->get() callback was
+ dnl # changed to take dentry, inode and flags.
+ dnl #
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(
+ [whether xattr_handler->get() wants dentry and inode and flags])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_get_dentry_inode_flags], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_XATTR_GET_DENTRY_INODE_FLAGS, 1,
+ [xattr_handler->get() wants dentry and inode and flags])
+ ],[
+ ZFS_LINUX_TEST_ERROR([xattr get()])
+ ])
])
])
])
@@ -152,10 +179,25 @@ dnl #
dnl # Supported xattr handler set() interfaces checked newest to oldest.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
+ ZFS_LINUX_TEST_SRC([xattr_handler_set_mnt_idmap], [
+ #include <linux/xattr.h>
+
+ static int set(const struct xattr_handler *handler,
+ struct mnt_idmap *idmap,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *buffer,
+ size_t size, int flags)
+ { return 0; }
+ static const struct xattr_handler
+ xops __attribute__ ((unused)) = {
+ .set = set,
+ };
+ ],[])
+
ZFS_LINUX_TEST_SRC([xattr_handler_set_userns], [
#include <linux/xattr.h>
- int set(const struct xattr_handler *handler,
+ static int set(const struct xattr_handler *handler,
struct user_namespace *mnt_userns,
struct dentry *dentry, struct inode *inode,
const char *name, const void *buffer,
@@ -170,7 +212,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [
#include <linux/xattr.h>
- int set(const struct xattr_handler *handler,
+ static int set(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
@@ -184,7 +226,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
ZFS_LINUX_TEST_SRC([xattr_handler_set_xattr_handler], [
#include <linux/xattr.h>
- int set(const struct xattr_handler *handler,
+ static int set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
{ return 0; }
@@ -197,7 +239,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [
ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry], [
#include <linux/xattr.h>
- int set(struct dentry *dentry, const char *name,
+ static int set(struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags,
int handler_flags) { return 0; }
static const struct xattr_handler
@@ -213,53 +255,63 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
dnl # The xattr_handler->set() callback was changed to 8 arguments, and
dnl # struct user_namespace* was inserted as arg #2
dnl #
- AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace])
- ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [
+ dnl # 6.3 API change,
+ dnl # The xattr_handler->set() callback 2nd arg is now struct mnt_idmap *
+ dnl #
+ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and mnt_idmap])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_mnt_idmap], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_XATTR_SET_USERNS, 1,
- [xattr_handler->set() takes user_namespace])
- ],[
- dnl #
- dnl # 4.7 API change,
- dnl # The xattr_handler->set() callback was changed to take both
- dnl # dentry and inode.
- dnl #
- AC_MSG_RESULT(no)
- AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
- ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
+ AC_DEFINE(HAVE_XATTR_SET_IDMAP, 1,
+ [xattr_handler->set() takes mnt_idmap])
+ ], [
+ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
- [xattr_handler->set() wants both dentry and inode])
+ AC_DEFINE(HAVE_XATTR_SET_USERNS, 1,
+ [xattr_handler->set() takes user_namespace])
],[
dnl #
- dnl # 4.4 API change,
- dnl # The xattr_handler->set() callback was changed to take a
- dnl # xattr_handler, and handler_flags argument was removed and
- dnl # should be accessed by handler->flags.
+ dnl # 4.7 API change,
+ dnl # The xattr_handler->set() callback was changed to take both
+ dnl # dentry and inode.
dnl #
AC_MSG_RESULT(no)
- AC_MSG_CHECKING(
- [whether xattr_handler->set() wants xattr_handler])
- ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
+ AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
- [xattr_handler->set() wants xattr_handler])
+ AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1,
+ [xattr_handler->set() wants both dentry and inode])
],[
dnl #
- dnl # 2.6.33 API change,
- dnl # The xattr_handler->set() callback was changed
- dnl # to take a dentry instead of an inode, and a
- dnl # handler_flags argument was added.
+ dnl # 4.4 API change,
+ dnl # The xattr_handler->set() callback was changed to take a
+ dnl # xattr_handler, and handler_flags argument was removed and
+ dnl # should be accessed by handler->flags.
dnl #
AC_MSG_RESULT(no)
AC_MSG_CHECKING(
- [whether xattr_handler->set() wants dentry])
- ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
+ [whether xattr_handler->set() wants xattr_handler])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
- [xattr_handler->set() wants dentry])
+ AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1,
+ [xattr_handler->set() wants xattr_handler])
],[
- ZFS_LINUX_TEST_ERROR([xattr set()])
+ dnl #
+ dnl # 2.6.33 API change,
+ dnl # The xattr_handler->set() callback was changed
+ dnl # to take a dentry instead of an inode, and a
+ dnl # handler_flags argument was added.
+ dnl #
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(
+ [whether xattr_handler->set() wants dentry])
+ ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1,
+ [xattr_handler->set() wants dentry])
+ ],[
+ ZFS_LINUX_TEST_ERROR([xattr set()])
+ ])
])
])
])
@@ -273,7 +325,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST], [
ZFS_LINUX_TEST_SRC([xattr_handler_list_simple], [
#include <linux/xattr.h>
- bool list(struct dentry *dentry) { return 0; }
+ static bool list(struct dentry *dentry) { return 0; }
static const struct xattr_handler
xops __attribute__ ((unused)) = {
.list = list,
@@ -283,7 +335,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST], [
ZFS_LINUX_TEST_SRC([xattr_handler_list_xattr_handler], [
#include <linux/xattr.h>
- size_t list(const struct xattr_handler *handler,
+ static size_t list(const struct xattr_handler *handler,
struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t name_len) { return 0; }
static const struct xattr_handler
@@ -295,7 +347,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_LIST], [
ZFS_LINUX_TEST_SRC([xattr_handler_list_dentry], [
#include <linux/xattr.h>
- size_t list(struct dentry *dentry,
+ static size_t list(struct dentry *dentry,
char *list, size_t list_size,
const char *name, size_t name_len,
int handler_flags) { return 0; }
diff --git a/config/kernel.m4 b/config/kernel.m4
index 1f274cbe4f30..548905ccd04d 100644
--- a/config/kernel.m4
+++ b/config/kernel.m4
@@ -42,6 +42,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE
ZFS_AC_KERNEL_SRC_PDE_DATA
ZFS_AC_KERNEL_SRC_FALLOCATE
+ ZFS_AC_KERNEL_SRC_FADVISE
+ ZFS_AC_KERNEL_SRC_GENERIC_FADVISE
ZFS_AC_KERNEL_SRC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
ZFS_AC_KERNEL_SRC_RWSEM
ZFS_AC_KERNEL_SRC_SCHED
@@ -69,6 +71,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE
ZFS_AC_KERNEL_SRC_XATTR
ZFS_AC_KERNEL_SRC_ACL
+ ZFS_AC_KERNEL_SRC_INODE_SETATTR
ZFS_AC_KERNEL_SRC_INODE_GETATTR
ZFS_AC_KERNEL_SRC_INODE_SET_FLAGS
ZFS_AC_KERNEL_SRC_INODE_SET_IVERSION
@@ -94,6 +97,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_SRC_DENTRY
+ ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SRC_SECURITY_INODE
ZFS_AC_KERNEL_SRC_FST_MOUNT
@@ -112,6 +116,13 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_VFS_RW_ITERATE
ZFS_AC_KERNEL_SRC_VFS_GENERIC_WRITE_CHECKS
ZFS_AC_KERNEL_SRC_VFS_IOV_ITER
+ ZFS_AC_KERNEL_SRC_VFS_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_GENERIC_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_SPLICE_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_REMAP_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_CLONE_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_DEDUPE_FILE_RANGE
+ ZFS_AC_KERNEL_SRC_VFS_FILE_OPERATIONS_EXTEND
ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS
ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE
ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN
@@ -120,7 +131,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
@@ -131,7 +141,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_KSTRTOUL
ZFS_AC_KERNEL_SRC_PERCPU
ZFS_AC_KERNEL_SRC_CPU_HOTPLUG
- ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS
+ ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR
ZFS_AC_KERNEL_SRC_MKNOD
ZFS_AC_KERNEL_SRC_SYMLINK
ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
@@ -140,12 +150,33 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_SYSFS
ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE
ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG
+ ZFS_AC_KERNEL_SRC_STRLCPY
+ ZFS_AC_KERNEL_SRC_STRSCPY
ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
ZFS_AC_KERNEL_SRC_ADD_DISK
ZFS_AC_KERNEL_SRC_KTHREAD
ZFS_AC_KERNEL_SRC_ZERO_PAGE
ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM
+ ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
+ ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS
+ ZFS_AC_KERNEL_SRC_IATTR_VFSID
+ ZFS_AC_KERNEL_SRC_FILEMAP
+ ZFS_AC_KERNEL_SRC_WRITEPAGE_T
+ ZFS_AC_KERNEL_SRC_RECLAIMED
+ ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE
+ ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ
+ ZFS_AC_KERNEL_SRC_SYNC_BDEV
+ ZFS_AC_KERNEL_SRC_MM_PAGE_SIZE
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
+ ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
+ ;;
+ riscv*)
+ ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
+ ;;
+ esac
AC_MSG_CHECKING([for available kernel interfaces])
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
@@ -161,6 +192,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_OBJTOOL
ZFS_AC_KERNEL_PDE_DATA
ZFS_AC_KERNEL_FALLOCATE
+ ZFS_AC_KERNEL_FADVISE
+ ZFS_AC_KERNEL_GENERIC_FADVISE
ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
ZFS_AC_KERNEL_RWSEM
ZFS_AC_KERNEL_SCHED
@@ -188,6 +221,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE
ZFS_AC_KERNEL_XATTR
ZFS_AC_KERNEL_ACL
+ ZFS_AC_KERNEL_INODE_SETATTR
ZFS_AC_KERNEL_INODE_GETATTR
ZFS_AC_KERNEL_INODE_SET_FLAGS
ZFS_AC_KERNEL_INODE_SET_IVERSION
@@ -213,6 +247,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SETATTR_PREPARE
ZFS_AC_KERNEL_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_DENTRY
+ ZFS_AC_KERNEL_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SECURITY_INODE
ZFS_AC_KERNEL_FST_MOUNT
@@ -231,6 +266,13 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_VFS_RW_ITERATE
ZFS_AC_KERNEL_VFS_GENERIC_WRITE_CHECKS
ZFS_AC_KERNEL_VFS_IOV_ITER
+ ZFS_AC_KERNEL_VFS_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_GENERIC_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_SPLICE_COPY_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_REMAP_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_CLONE_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_DEDUPE_FILE_RANGE
+ ZFS_AC_KERNEL_VFS_FILE_OPERATIONS_EXTEND
ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS
ZFS_AC_KERNEL_FOLLOW_DOWN_ONE
ZFS_AC_KERNEL_MAKE_REQUEST_FN
@@ -239,7 +281,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
@@ -250,7 +291,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_KSTRTOUL
ZFS_AC_KERNEL_PERCPU
ZFS_AC_KERNEL_CPU_HOTPLUG
- ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS
+ ZFS_AC_KERNEL_GENERIC_FILLATTR
ZFS_AC_KERNEL_MKNOD
ZFS_AC_KERNEL_SYMLINK
ZFS_AC_KERNEL_BIO_MAX_SEGS
@@ -259,12 +300,33 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SYSFS
ZFS_AC_KERNEL_SET_SPECIAL_STATE
ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG
+ ZFS_AC_KERNEL_STRLCPY
+ ZFS_AC_KERNEL_STRSCPY
ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
ZFS_AC_KERNEL_ADD_DISK
ZFS_AC_KERNEL_KTHREAD
ZFS_AC_KERNEL_ZERO_PAGE
ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
ZFS_AC_KERNEL_USER_NS_COMMON_INUM
+ ZFS_AC_KERNEL_IDMAP_MNT_API
+ ZFS_AC_KERNEL_IDMAP_NO_USERNS
+ ZFS_AC_KERNEL_IATTR_VFSID
+ ZFS_AC_KERNEL_FILEMAP
+ ZFS_AC_KERNEL_WRITEPAGE_T
+ ZFS_AC_KERNEL_RECLAIMED
+ ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE
+ ZFS_AC_KERNEL_COPY_SPLICE_READ
+ ZFS_AC_KERNEL_SYNC_BDEV
+ ZFS_AC_KERNEL_MM_PAGE_SIZE
+ case "$host_cpu" in
+ powerpc*)
+ ZFS_AC_KERNEL_CPU_HAS_FEATURE
+ ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
+ ;;
+ riscv*)
+ ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
+ ;;
+ esac
])
dnl #
@@ -938,8 +1000,47 @@ 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])
+ ])
+])
+
+dnl #
+dnl # AS_VERSION_COMPARE_LE
+dnl # like AS_VERSION_COMPARE_LE, but runs $3 if (and only if) $1 <= $2
+dnl # AS_VERSION_COMPARE_LE (version-1, version-2, [action-if-less-or-equal], [action-if-greater])
+dnl #
+AC_DEFUN([AS_VERSION_COMPARE_LE], [
+ AS_VERSION_COMPARE([$1], [$2], [$3], [$3], [$4])
+])
+
+dnl #
+dnl # ZFS_LINUX_REQUIRE_API
+dnl # like ZFS_LINUX_TEST_ERROR, except only fails if the kernel is
+dnl # at least some specified version.
+dnl #
+AC_DEFUN([ZFS_LINUX_REQUIRE_API], [
+ AS_VERSION_COMPARE_LE([$2], [$kernsrcver], [
+ AC_MSG_ERROR([
+ *** None of the expected "$1" interfaces were detected. This
+ *** interface is expected for kernels version "$2" and above.
+ *** This may be because your kernel version is newer than what is
+ *** supported, or you are using a patched custom kernel with
+ *** incompatible modifications. Newer kernels may have incompatible
+ *** APIs.
+ ***
+ *** ZFS Version: $ZFS_META_ALIAS
+ *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
+ ])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
])
diff --git a/config/rpm.am b/config/rpm.am
index 13bd54a625b0..85c56c0b2e3a 100644
--- a/config/rpm.am
+++ b/config/rpm.am
@@ -83,6 +83,11 @@ srpm-common:
rpm-local || exit 1; \
LANG=C $(RPMBUILD) \
--define "_tmppath $$rpmbuild/TMP" \
+ --define "_builddir $$rpmbuild/BUILD" \
+ --define "_rpmdir $$rpmbuild/RPMS" \
+ --define "_srcrpmdir $$rpmbuild/SRPMS" \
+ --define "_specdir $$rpmbuild/SPECS" \
+ --define "_sourcedir $$rpmbuild/SOURCES" \
--define "_topdir $$rpmbuild" \
$(def) -bs $$rpmbuild/SPECS/$$rpmspec || exit 1; \
cp $$rpmbuild/SRPMS/$$rpmpkg . || exit 1; \
@@ -99,6 +104,11 @@ rpm-common:
rpm-local || exit 1; \
LANG=C ${RPMBUILD} \
--define "_tmppath $$rpmbuild/TMP" \
+ --define "_builddir $$rpmbuild/BUILD" \
+ --define "_rpmdir $$rpmbuild/RPMS" \
+ --define "_srcrpmdir $$rpmbuild/SRPMS" \
+ --define "_specdir $$rpmbuild/SPECS" \
+ --define "_sourcedir $$rpmbuild/SOURCES" \
--define "_topdir $$rpmbuild" \
$(def) --rebuild $$rpmpkg || exit 1; \
cp $$rpmbuild/RPMS/*/* . || exit 1; \
diff --git a/config/user-backtrace.m4 b/config/user-backtrace.m4
new file mode 100644
index 000000000000..25706767cdc3
--- /dev/null
+++ b/config/user-backtrace.m4
@@ -0,0 +1,14 @@
+dnl
+dnl backtrace(), for userspace assertions. glibc has this directly in libc.
+dnl FreeBSD and (sometimes) musl have it in a separate -lexecinfo. It's assumed
+dnl that this will also get the companion function backtrace_symbols().
+dnl
+AC_DEFUN([ZFS_AC_CONFIG_USER_BACKTRACE], [
+ AX_SAVE_FLAGS
+ LIBS=""
+ AC_SEARCH_LIBS([backtrace], [execinfo], [
+ AC_DEFINE(HAVE_BACKTRACE, 1, [backtrace() is available])
+ AC_SUBST([BACKTRACE_LIBS], ["$LIBS"])
+ ])
+ AX_RESTORE_FLAGS
+])
diff --git a/config/user-libunwind.m4 b/config/user-libunwind.m4
new file mode 100644
index 000000000000..99ba3dcf452d
--- /dev/null
+++ b/config/user-libunwind.m4
@@ -0,0 +1,44 @@
+dnl
+dnl Checks for libunwind, which usually does a better job than backtrace() when
+dnl resolving symbols in the stack backtrace. Newer versions have support for
+dnl getting info about the object file the function came from, so we look for
+dnl that too and use it if found.
+dnl
+AC_DEFUN([ZFS_AC_CONFIG_USER_LIBUNWIND], [
+ AC_ARG_WITH([libunwind],
+ AS_HELP_STRING([--with-libunwind],
+ [use libunwind for backtraces in userspace assertions]),
+ [],
+ [with_libunwind=auto])
+
+ AS_IF([test "x$with_libunwind" != "xno"], [
+ ZFS_AC_FIND_SYSTEM_LIBRARY(LIBUNWIND, [libunwind], [libunwind.h], [], [unwind], [], [
+ dnl unw_get_elf_filename() is sometimes a macro, other
+ dnl times a proper symbol, so we can't just do a link
+ dnl check; we need to include the header properly.
+ AX_SAVE_FLAGS
+ CFLAGS="$CFLAGS $LIBUNWIND_CFLAGS"
+ LIBS="$LIBS $LIBUNWIND_LIBS"
+ AC_MSG_CHECKING([for unw_get_elf_filename in libunwind])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([
+ #define UNW_LOCAL_ONLY
+ #include <libunwind.h>
+ ], [
+ unw_get_elf_filename(0, 0, 0, 0);
+ ])
+ ], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_LIBUNWIND_ELF, 1,
+ [libunwind has unw_get_elf_filename])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ AX_RESTORE_FLAGS
+ ], [
+ AS_IF([test "x$with_libunwind" = "xyes"], [
+ AC_MSG_FAILURE([--with-libunwind was given, but libunwind is not available, try installing libunwind-devel])
+ ])
+ ])
+ ])
+])
diff --git a/config/user.m4 b/config/user.m4
index a7241f44f1fd..badd920d2b8a 100644
--- a/config/user.m4
+++ b/config/user.m4
@@ -14,11 +14,11 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
AM_COND_IF([BUILD_LINUX], [
ZFS_AC_CONFIG_USER_UDEV
ZFS_AC_CONFIG_USER_SYSTEMD
+ ZFS_AC_CONFIG_USER_LIBUDEV
ZFS_AC_CONFIG_USER_LIBUUID
ZFS_AC_CONFIG_USER_LIBBLKID
])
ZFS_AC_CONFIG_USER_LIBTIRPC
- ZFS_AC_CONFIG_USER_LIBUDEV
ZFS_AC_CONFIG_USER_LIBCRYPTO
ZFS_AC_CONFIG_USER_LIBAIO
ZFS_AC_CONFIG_USER_LIBATOMIC
@@ -26,12 +26,14 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_AIO_H
ZFS_AC_CONFIG_USER_CLOCK_GETTIME
ZFS_AC_CONFIG_USER_PAM
+ ZFS_AC_CONFIG_USER_BACKTRACE
+ ZFS_AC_CONFIG_USER_LIBUNWIND
ZFS_AC_CONFIG_USER_RUNSTATEDIR
ZFS_AC_CONFIG_USER_MAKEDEV_IN_SYSMACROS
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV
ZFS_AC_CONFIG_USER_ZFSEXEC
- AC_CHECK_FUNCS([issetugid mlockall strlcat strlcpy])
+ AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy gettid])
AC_SUBST(RM)
])
diff --git a/config/zfs-build.m4 b/config/zfs-build.m4
index d14a6bb7ac9f..bb5a85d815d1 100644
--- a/config/zfs-build.m4
+++ b/config/zfs-build.m4
@@ -81,7 +81,7 @@ AC_DEFUN([ZFS_AC_DEBUG], [
AC_DEFUN([ZFS_AC_DEBUGINFO_ENABLE], [
DEBUG_CFLAGS="$DEBUG_CFLAGS -g -fno-inline $NO_IPA_SRA"
- KERNEL_DEBUG_CFLAGS="$KERNEL_DEBUG_CFLAGS -fno-inline $NO_IPA_SRA"
+ KERNEL_DEBUG_CFLAGS="$KERNEL_DEBUG_CFLAGS -fno-inline $KERNEL_NO_IPA_SRA"
KERNEL_MAKE="$KERNEL_MAKE CONFIG_DEBUG_INFO=y"
DEBUGINFO_ZFS="_with_debuginfo"
@@ -211,12 +211,15 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
ZFS_AC_CONFIG_ALWAYS_CC_NO_CLOBBERED
ZFS_AC_CONFIG_ALWAYS_CC_INFINITE_RECURSION
+ ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_INFINITE_RECURSION
ZFS_AC_CONFIG_ALWAYS_CC_IMPLICIT_FALLTHROUGH
ZFS_AC_CONFIG_ALWAYS_CC_FRAME_LARGER_THAN
ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_TRUNCATION
ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_ZERO_LENGTH
+ ZFS_AC_CONFIG_ALWAYS_CC_FORMAT_OVERFLOW
ZFS_AC_CONFIG_ALWAYS_CC_NO_OMIT_FRAME_POINTER
ZFS_AC_CONFIG_ALWAYS_CC_NO_IPA_SRA
+ ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_NO_IPA_SRA
ZFS_AC_CONFIG_ALWAYS_CC_ASAN
ZFS_AC_CONFIG_ALWAYS_CC_UBSAN
ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD
@@ -355,6 +358,9 @@ AC_DEFUN([ZFS_AC_RPM], [
AS_IF([test -n "$udevruledir" ], [
RPM_DEFINE_UTIL=${RPM_DEFINE_UTIL}' --define "_udevruledir $(udevruledir)"'
])
+ AS_IF([test -n "$bashcompletiondir" ], [
+ RPM_DEFINE_UTIL=${RPM_DEFINE_UTIL}' --define "_bashcompletiondir $(bashcompletiondir)"'
+ ])
RPM_DEFINE_UTIL=${RPM_DEFINE_UTIL}' $(DEFINE_SYSTEMD)'
RPM_DEFINE_UTIL=${RPM_DEFINE_UTIL}' $(DEFINE_PYZFS)'
RPM_DEFINE_UTIL=${RPM_DEFINE_UTIL}' $(DEFINE_PAM)'
@@ -461,6 +467,7 @@ AC_DEFUN([ZFS_AC_DPKG], [
AC_SUBST(HAVE_DPKGBUILD)
AC_SUBST(DPKGBUILD)
AC_SUBST(DPKGBUILD_VERSION)
+ AC_SUBST([CFGOPTS], ["$CFGOPTS"])
])
dnl #
@@ -529,6 +536,8 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
VENDOR=alpine ;
elif test -f /bin/freebsd-version ; then
VENDOR=freebsd ;
+ elif test -f /etc/openEuler-release ; then
+ VENDOR=openeuler ;
else
VENDOR= ;
fi],
@@ -553,6 +562,7 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
ubuntu) DEFAULT_PACKAGE=deb ;;
debian) DEFAULT_PACKAGE=deb ;;
freebsd) DEFAULT_PACKAGE=pkg ;;
+ openeuler) DEFAULT_PACKAGE=rpm ;;
*) DEFAULT_PACKAGE=rpm ;;
esac
AC_MSG_RESULT([$DEFAULT_PACKAGE])
@@ -566,32 +576,17 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_RESULT([$initdir])
AC_SUBST(initdir)
- AC_MSG_CHECKING([default init script type and shell])
- case "$VENDOR" in
- toss) DEFAULT_INIT_SCRIPT=redhat ;;
- redhat) DEFAULT_INIT_SCRIPT=redhat ;;
- fedora) DEFAULT_INIT_SCRIPT=fedora ;;
- gentoo) DEFAULT_INIT_SCRIPT=openrc ;;
- alpine) DEFAULT_INIT_SCRIPT=openrc ;;
- arch) DEFAULT_INIT_SCRIPT=lsb ;;
- sles) DEFAULT_INIT_SCRIPT=lsb ;;
- slackware) DEFAULT_INIT_SCRIPT=lsb ;;
- lunar) DEFAULT_INIT_SCRIPT=lunar ;;
- ubuntu) DEFAULT_INIT_SCRIPT=lsb ;;
- debian) DEFAULT_INIT_SCRIPT=lsb ;;
- freebsd) DEFAULT_INIT_SCRIPT=freebsd;;
- *) DEFAULT_INIT_SCRIPT=lsb ;;
- esac
-
+ AC_MSG_CHECKING([default shell])
case "$VENDOR" in
- gentoo) DEFAULT_INIT_SHELL="/sbin/openrc-run";;
- alpine) DEFAULT_INIT_SHELL="/sbin/openrc-run";;
- *) DEFAULT_INIT_SHELL="/bin/sh" ;;
+ gentoo|alpine) DEFAULT_INIT_SHELL=/sbin/openrc-run
+ IS_SYSV_RC=false ;;
+ *) DEFAULT_INIT_SHELL=/bin/sh
+ IS_SYSV_RC=true ;;
esac
- AC_MSG_RESULT([$DEFAULT_INIT_SCRIPT:$DEFAULT_INIT_SHELL])
- AC_SUBST(DEFAULT_INIT_SCRIPT)
+ AC_MSG_RESULT([$DEFAULT_INIT_SHELL])
AC_SUBST(DEFAULT_INIT_SHELL)
+ AC_SUBST(IS_SYSV_RC)
AC_MSG_CHECKING([default nfs server init script])
AS_IF([test "$VENDOR" = "debian"],
@@ -609,6 +604,7 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
redhat) initconfdir=/etc/sysconfig ;;
fedora) initconfdir=/etc/sysconfig ;;
sles) initconfdir=/etc/sysconfig ;;
+ openeuler) initconfdir=/etc/sysconfig ;;
ubuntu) initconfdir=/etc/default ;;
debian) initconfdir=/etc/default ;;
freebsd) initconfdir=$sysconfdir/rc.conf.d;;
@@ -626,6 +622,18 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_RESULT([no])
fi
AC_SUBST(RPM_DEFINE_INITRAMFS)
+
+ AC_MSG_CHECKING([default bash completion directory])
+ case "$VENDOR" in
+ ubuntu) bashcompletiondir=/usr/share/bash-completion/completions ;;
+ debian) bashcompletiondir=/usr/share/bash-completion/completions ;;
+ freebsd) bashcompletiondir=$sysconfdir/bash_completion.d;;
+ gentoo) bashcompletiondir=/usr/share/bash-completion/completions ;;
+ *) bashcompletiondir=/etc/bash_completion.d ;;
+ esac
+ AC_MSG_RESULT([$bashcompletiondir])
+ AC_SUBST(bashcompletiondir)
+
])
dnl #
diff --git a/configure.ac b/configure.ac
index 64974aa32925..2ce049c58219 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -32,6 +32,7 @@
AC_INIT(m4_esyscmd(awk '/^Name:/ {printf $2}' META),
m4_esyscmd(awk '/^Version:/ {printf $2}' META))
+CFGOPTS="$*"
AC_LANG(C)
ZFS_AC_META
AC_CONFIG_AUX_DIR([config])
@@ -43,7 +44,7 @@ AM_INIT_AUTOMAKE([subdir-objects foreign])
# Remove default macros from config.h:
# PACKAGE, PACKAGE_{BUGREPORT,NAME,STRING,TARNAME,VERSION}, STDC_HEADERS, VERSION
AC_CONFIG_HEADERS([zfs_config.h], [
- sed -nri~ -e '/^$/be' -e 'N;N;/#define (PACKAGE|VERSION|STDC_HEADERS)/d' -e ':e' -e 'p' zfs_config.h && rm zfs_config.h~ || exit])
+ $SED -nri~ -e '/^$/be' -e 'N;N;/#define (PACKAGE|VERSION|STDC_HEADERS)/d' -e ':e' -e 'p' zfs_config.h && rm zfs_config.h~ || exit])
LT_INIT
AC_PROG_INSTALL
@@ -65,6 +66,8 @@ ZFS_AC_DEBUG_KMEM_TRACKING
ZFS_AC_DEBUG_INVARIANTS
AC_CONFIG_FILES([
+ contrib/debian/rules
+ contrib/debian/changelog
Makefile
include/Makefile
lib/libzfs/libzfs.pc
diff --git a/contrib/bash_completion.d/Makefile.am b/contrib/bash_completion.d/Makefile.am
index dc4b610c42b8..1ec05ed73d2d 100644
--- a/contrib/bash_completion.d/Makefile.am
+++ b/contrib/bash_completion.d/Makefile.am
@@ -1,5 +1,3 @@
-bashcompletiondir = $(sysconfdir)/bash_completion.d
-
nodist_bashcompletion_DATA = %D%/zfs
SUBSTFILES += $(nodist_bashcompletion_DATA)
diff --git a/contrib/bash_completion.d/zfs.in b/contrib/bash_completion.d/zfs.in
index 72e1092a039b..c5cfd8e8efb2 100644
--- a/contrib/bash_completion.d/zfs.in
+++ b/contrib/bash_completion.d/zfs.in
@@ -63,11 +63,11 @@ __zfs_list_filesystems()
__zfs_match_snapshot()
{
local base_dataset="${cur%@*}"
- if [ "$base_dataset" != "$cur" ]
+ if [[ "$base_dataset" != "$cur" ]]
then
$__ZFS_CMD list -H -o name -s name -t snapshot -d 1 "$base_dataset"
else
- if [ "$cur" != "" ] && __zfs_list_datasets "$cur" &> /dev/null
+ if [[ "$cur" != "" ]] && __zfs_list_datasets "$cur" &> /dev/null
then
$__ZFS_CMD list -H -o name -s name -t filesystem,volume -r "$cur" | tail -n +2
# We output the base dataset name even though we might be
@@ -104,7 +104,7 @@ __zfs_match_snapshot()
__zfs_match_snapshot_or_bookmark()
{
local base_dataset="${cur%[#@]*}"
- if [ "$base_dataset" != "$cur" ]
+ if [[ "$base_dataset" != "$cur" ]]
then
if [[ $cur == *@* ]]
then
@@ -114,7 +114,7 @@ __zfs_match_snapshot_or_bookmark()
fi
else
$__ZFS_CMD list -H -o name -s name -t filesystem,volume
- if [ -e "$cur" ] && $__ZFS_CMD list -H -o name -s name -t filesystem,volume "$cur" &> /dev/null
+ if [[ -e "$cur" ]] && $__ZFS_CMD list -H -o name -s name -t filesystem,volume "$cur" &> /dev/null
then
echo "$cur@"
echo "$cur#"
@@ -126,10 +126,10 @@ __zfs_match_multiple_snapshots()
{
local existing_opts
existing_opts="$(expr "$cur" : '\(.*\)[%,]')"
- if [ -e "$existing_opts" ]
+ if [[ -e "$existing_opts" ]]
then
local base_dataset="${cur%@*}"
- if [ "$base_dataset" != "$cur" ]
+ if [[ "$base_dataset" != "$cur" ]]
then
local cur="${cur##*,}"
if [[ $cur =~ ^%|%.*% ]]
@@ -199,7 +199,7 @@ __zfs_complete_multiple_options()
mapfile -t COMPREPLY < <(compgen -W "$options" -- "${cur##*,}")
existing_opts=$(expr "$cur" : '\(.*,\)')
- if [ -n "$existing_opts" ]
+ if [[ -n "$existing_opts" ]]
then
COMPREPLY=( "${COMPREPLY[@]/#/${existing_opts}}" )
fi
diff --git a/contrib/coverity/model.c b/contrib/coverity/model.c
new file mode 100644
index 000000000000..8b4d14ee22a2
--- /dev/null
+++ b/contrib/coverity/model.c
@@ -0,0 +1,654 @@
+/*
+ * Coverity Scan model
+ * https://scan.coverity.com/models
+ *
+ * This is a modeling file for Coverity Scan.
+ * Modeling helps to avoid false positives.
+ *
+ * - Modeling doesn't need full structs and typedefs. Rudimentary structs
+ * and similar types are sufficient.
+ * - An uninitialized local pointer is not an error. It signifies that the
+ * variable could be either NULL or have some data.
+ *
+ * Coverity Scan doesn't pick up modifications automatically. The model file
+ * must be uploaded by an admin in the analysis settings.
+ *
+ * Some of this initially cribbed from:
+ *
+ * https://github.com/kees/coverity-linux/blob/trunk/model.c
+ *
+ * The below model was based on the original model by Brian Behlendorf for the
+ * original zfsonlinux/zfs repository. Some inspiration was taken from
+ * kees/coverity-linux, specifically involving memory copies.
+ */
+
+#include <stdarg.h>
+
+#define KM_NOSLEEP 0x0001 /* cannot block for memory; may fail */
+
+#define UMEM_DEFAULT 0x0000 /* normal -- may fail */
+#define UMEM_NOFAIL 0x0100 /* Never fails */
+
+#define NULL (0)
+
+typedef enum {
+ B_FALSE = 0,
+ B_TRUE = 1
+} boolean_t;
+
+typedef unsigned int uint_t;
+
+int condition0, condition1;
+
+int
+ddi_copyin(const void *from, void *to, size_t len, int flags)
+{
+ (void) flags;
+ __coverity_negative_sink__(len);
+ __coverity_tainted_data_argument__(from);
+ __coverity_tainted_data_argument__(to);
+ __coverity_writeall__(to);
+}
+
+void *
+memset(void *dst, int c, size_t len)
+{
+ __coverity_negative_sink__(len);
+ if (c == 0)
+ __coverity_writeall0__(dst);
+ else
+ __coverity_writeall__(dst);
+ return (dst);
+}
+
+void *
+memmove(void *dst, void *src, size_t len)
+{
+ int first = ((char *)src)[0];
+ int last = ((char *)src)[len-1];
+
+ __coverity_negative_sink__(len);
+ __coverity_writeall__(dst);
+ return (dst);
+}
+
+void *
+memcpy(void *dst, void *src, size_t len)
+{
+ int first = ((char *)src)[0];
+ int last = ((char *)src)[len-1];
+
+ __coverity_negative_sink__(len);
+ __coverity_writeall__(dst);
+ return (dst);
+}
+
+void *
+umem_alloc_aligned(size_t size, size_t align, int kmflags)
+{
+ __coverity_negative_sink__(size);
+ __coverity_negative_sink__(align);
+
+ if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) {
+ void *buf = __coverity_alloc__(size);
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "umem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void *
+umem_alloc(size_t size, int kmflags)
+{
+ __coverity_negative_sink__(size);
+
+ if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) {
+ void *buf = __coverity_alloc__(size);
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "umem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void *
+umem_zalloc(size_t size, int kmflags)
+{
+ __coverity_negative_sink__(size);
+
+ if (((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) || condition0) {
+ void *buf = __coverity_alloc__(size);
+ __coverity_writeall0__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "umem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void
+umem_free(void *buf, size_t size)
+{
+ __coverity_negative_sink__(size);
+ __coverity_free__(buf);
+}
+
+typedef struct {} umem_cache_t;
+
+void *
+umem_cache_alloc(umem_cache_t *skc, int flags)
+{
+ (void) skc;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (((UMEM_NOFAIL & flags) == UMEM_NOFAIL) || condition0) {
+ void *buf = __coverity_alloc_nosize__();
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "umem_cache_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void
+umem_cache_free(umem_cache_t *skc, void *obj)
+{
+ (void) skc;
+
+ __coverity_free__(obj);
+}
+
+void *
+spl_kmem_alloc(size_t sz, int fl, const char *func, int line)
+{
+ (void) func;
+ (void) line;
+
+ __coverity_negative_sink__(sz);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) {
+ void *buf = __coverity_alloc__(sz);
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "spl_kmem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void *
+spl_kmem_zalloc(size_t sz, int fl, const char *func, int line)
+{
+ (void) func;
+ (void) line;
+
+ __coverity_negative_sink__(sz);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) {
+ void *buf = __coverity_alloc__(sz);
+ __coverity_writeall0__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "spl_kmem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void
+spl_kmem_free(const void *ptr, size_t sz)
+{
+ __coverity_negative_sink__(sz);
+ __coverity_free__(ptr);
+}
+
+char *
+kmem_vasprintf(const char *fmt, va_list ap)
+{
+ char *buf = __coverity_alloc_nosize__();
+ (void) ap;
+
+ __coverity_string_null_sink__(fmt);
+ __coverity_string_size_sink__(fmt);
+
+ __coverity_writeall__(buf);
+
+ __coverity_mark_as_afm_allocated__(buf, "kmem_strfree");
+
+ return (buf);
+}
+
+char *
+kmem_asprintf(const char *fmt, ...)
+{
+ char *buf = __coverity_alloc_nosize__();
+
+ __coverity_string_null_sink__(fmt);
+ __coverity_string_size_sink__(fmt);
+
+ __coverity_writeall__(buf);
+
+ __coverity_mark_as_afm_allocated__(buf, "kmem_strfree");
+
+ return (buf);
+}
+
+char *
+kmem_strdup(const char *str)
+{
+ char *buf = __coverity_alloc_nosize__();
+
+ __coverity_string_null_sink__(str);
+ __coverity_string_size_sink__(str);
+
+ __coverity_writeall__(buf);
+
+ __coverity_mark_as_afm_allocated__(buf, "kmem_strfree");
+
+ return (buf);
+
+
+}
+
+void
+kmem_strfree(char *str)
+{
+ __coverity_free__(str);
+}
+
+void *
+spl_vmem_alloc(size_t sz, int fl, const char *func, int line)
+{
+ (void) func;
+ (void) line;
+
+ __coverity_negative_sink__(sz);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) {
+ void *buf = __coverity_alloc__(sz);
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "spl_vmem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void *
+spl_vmem_zalloc(size_t sz, int fl, const char *func, int line)
+{
+ (void) func;
+ (void) line;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (((fl & KM_NOSLEEP) != KM_NOSLEEP) || condition0) {
+ void *buf = __coverity_alloc__(sz);
+ __coverity_writeall0__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "spl_vmem_free");
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+void
+spl_vmem_free(const void *ptr, size_t sz)
+{
+ __coverity_negative_sink__(sz);
+ __coverity_free__(ptr);
+}
+
+typedef struct {} spl_kmem_cache_t;
+
+void *
+spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags)
+{
+ (void) skc;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if ((flags == 0) || condition0) {
+ void *buf = __coverity_alloc_nosize__();
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "spl_kmem_cache_free");
+ return (buf);
+ }
+}
+
+void
+spl_kmem_cache_free(spl_kmem_cache_t *skc, void *obj)
+{
+ (void) skc;
+
+ __coverity_free__(obj);
+}
+
+typedef struct {} zfsvfs_t;
+
+int
+zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp)
+{
+ (void) osname;
+ (void) readonly;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if (condition0) {
+ *zfvp = __coverity_alloc_nosize__();
+ __coverity_writeall__(*zfvp);
+ return (0);
+ }
+
+ return (1);
+}
+
+void
+zfsvfs_free(zfsvfs_t *zfsvfs)
+{
+ __coverity_free__(zfsvfs);
+}
+
+typedef struct {} nvlist_t;
+
+int
+nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
+{
+ (void) nvflag;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if ((kmflag == 0) || condition0) {
+ *nvlp = __coverity_alloc_nosize__();
+ __coverity_mark_as_afm_allocated__(*nvlp, "nvlist_free");
+ __coverity_writeall__(*nvlp);
+ return (0);
+ }
+
+ return (-1);
+
+}
+
+int
+nvlist_dup(const nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
+{
+ nvlist_t read = *nvl;
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if ((kmflag == 0) || condition0) {
+ nvlist_t *nvl = __coverity_alloc_nosize__();
+ __coverity_mark_as_afm_allocated__(nvl, "nvlist_free");
+ __coverity_writeall__(nvl);
+ *nvlp = nvl;
+ return (0);
+ }
+
+ return (-1);
+}
+
+void
+nvlist_free(nvlist_t *nvl)
+{
+ __coverity_free__(nvl);
+}
+
+int
+nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
+ int kmflag)
+{
+ (void) nvl;
+ (void) encoding;
+
+ if (*bufp == NULL) {
+ if (condition1)
+ __coverity_sleep__();
+
+ if ((kmflag == 0) || condition0) {
+ char *buf = __coverity_alloc_nosize__();
+ __coverity_writeall__(buf);
+ /*
+ * We cannot use __coverity_mark_as_afm_allocated__()
+ * because the free function varies between the kernel
+ * and userspace.
+ */
+ *bufp = buf;
+ return (0);
+ }
+
+ return (-1);
+ }
+
+ /*
+ * Unfortunately, errors from the buffer being too small are not
+ * possible to model, so we assume success.
+ */
+ __coverity_negative_sink__(*buflen);
+ __coverity_writeall__(*bufp);
+ return (0);
+}
+
+
+int
+nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
+{
+ __coverity_negative_sink__(buflen);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ if ((kmflag == 0) || condition0) {
+ nvlist_t *nvl = __coverity_alloc_nosize__();
+ __coverity_mark_as_afm_allocated__(nvl, "nvlist_free");
+ __coverity_writeall__(nvl);
+ *nvlp = nvl;
+ int first = buf[0];
+ int last = buf[buflen-1];
+ return (0);
+ }
+
+ return (-1);
+
+}
+
+void *
+malloc(size_t size)
+{
+ void *buf = __coverity_alloc__(size);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ __coverity_negative_sink__(size);
+ __coverity_mark_as_uninitialized_buffer__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "free");
+
+ return (buf);
+}
+
+void *
+calloc(size_t nmemb, size_t size)
+{
+ void *buf = __coverity_alloc__(size * nmemb);
+
+ if (condition1)
+ __coverity_sleep__();
+
+ __coverity_negative_sink__(size);
+ __coverity_writeall0__(buf);
+ __coverity_mark_as_afm_allocated__(buf, "free");
+ return (buf);
+}
+void
+free(void *buf)
+{
+ __coverity_free__(buf);
+}
+
+int
+sched_yield(void)
+{
+ __coverity_sleep__();
+}
+
+typedef struct {} kmutex_t;
+typedef struct {} krwlock_t;
+typedef int krw_t;
+
+/*
+ * Coverty reportedly does not support macros, so this only works for
+ * userspace.
+ */
+
+void
+mutex_enter(kmutex_t *mp)
+{
+ if (condition0)
+ __coverity_sleep__();
+
+ __coverity_exclusive_lock_acquire__(mp);
+}
+
+int
+mutex_tryenter(kmutex_t *mp)
+{
+ if (condition0) {
+ __coverity_exclusive_lock_acquire__(mp);
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+mutex_exit(kmutex_t *mp)
+{
+ __coverity_exclusive_lock_release__(mp);
+}
+
+void
+rw_enter(krwlock_t *rwlp, krw_t rw)
+{
+ (void) rw;
+
+ if (condition0)
+ __coverity_sleep__();
+
+ __coverity_recursive_lock_acquire__(rwlp);
+}
+
+void
+rw_exit(krwlock_t *rwlp)
+{
+ __coverity_recursive_lock_release__(rwlp);
+
+}
+
+int
+rw_tryenter(krwlock_t *rwlp, krw_t rw)
+{
+ if (condition0) {
+ __coverity_recursive_lock_acquire__(rwlp);
+ return (1);
+ }
+
+ return (0);
+}
+
+/* Thus, we fallback to the Linux kernel locks */
+struct {} mutex;
+struct {} rw_semaphore;
+
+void
+mutex_lock(struct mutex *lock)
+{
+ if (condition0) {
+ __coverity_sleep__();
+ }
+ __coverity_exclusive_lock_acquire__(lock);
+}
+
+void
+mutex_unlock(struct mutex *lock)
+{
+ __coverity_exclusive_lock_release__(lock);
+}
+
+void
+down_read(struct rw_semaphore *sem)
+{
+ if (condition0) {
+ __coverity_sleep__();
+ }
+ __coverity_recursive_lock_acquire__(sem);
+}
+
+void
+down_write(struct rw_semaphore *sem)
+{
+ if (condition0) {
+ __coverity_sleep__();
+ }
+ __coverity_recursive_lock_acquire__(sem);
+}
+
+int
+down_read_trylock(struct rw_semaphore *sem)
+{
+ if (condition0) {
+ __coverity_recursive_lock_acquire__(sem);
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+down_write_trylock(struct rw_semaphore *sem)
+{
+ if (condition0) {
+ __coverity_recursive_lock_acquire__(sem);
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+up_read(struct rw_semaphore *sem)
+{
+ __coverity_recursive_lock_release__(sem);
+}
+
+void
+up_write(struct rw_semaphore *sem)
+{
+ __coverity_recursive_lock_release__(sem);
+}
+
+int
+__cond_resched(void)
+{
+ if (condition0) {
+ __coverity_sleep__();
+ }
+}
diff --git a/contrib/debian/.gitignore b/contrib/debian/.gitignore
new file mode 100644
index 000000000000..de7475d8888c
--- /dev/null
+++ b/contrib/debian/.gitignore
@@ -0,0 +1 @@
+rules
diff --git a/contrib/debian/changelog.in b/contrib/debian/changelog.in
new file mode 100644
index 000000000000..9ced39b1f7b5
--- /dev/null
+++ b/contrib/debian/changelog.in
@@ -0,0 +1,19 @@
+openzfs-linux (@VERSION@-1) unstable; urgency=low
+
+ * OpenZFS @VERSION@ is tagged.
+
+ -- Umer Saleem <usaleem@ixsystems.com> Wed, 15 Nov 2023 15:00:00 +0500
+
+openzfs-linux (2.2.99-1) unstable; urgency=low
+
+ * OpenZFS 2.2 is tagged.
+
+ -- Umer Saleem <usaleem@ixsystems.com> Wed, 12 Jul 2022 15:00:00 -0400
+
+openzfs-linux (2.1.99-1) unstable; urgency=low
+
+ * Integrate minimally modified Debian packaging from ZFS on Linux
+ (source: https://salsa.debian.org/zfsonlinux-team/zfs)
+ * This packaging is a fork of Debian zfs-linux 2.1.6-2 release.
+
+ -- Umer Saleem <usaleem@ixsystems.com> Fri, 11 Oct 2022 15:00:00 -0400
diff --git a/contrib/debian/clean b/contrib/debian/clean
new file mode 100644
index 000000000000..3100d693aeba
--- /dev/null
+++ b/contrib/debian/clean
@@ -0,0 +1,11 @@
+bin/
+cmd/zed/zed.d/history_event-zfs-list-cacher.sh
+contrib/pyzfs/build/
+contrib/pyzfs/libzfs_core/__pycache__/
+contrib/pyzfs/libzfs_core/bindings/__pycache__/
+contrib/pyzfs/pyzfs.egg-info/
+debian/openzfs-libnvpair3.install
+debian/openzfs-libuutil3.install
+debian/openzfs-libzfs4.install
+debian/openzfs-libzfs-dev.install
+debian/openzfs-libzpool5.install
diff --git a/contrib/debian/control b/contrib/debian/control
new file mode 100644
index 000000000000..e56fbf0f1c93
--- /dev/null
+++ b/contrib/debian/control
@@ -0,0 +1,326 @@
+Source: openzfs-linux
+Section: contrib/kernel
+Priority: optional
+Maintainer: ZFS on Linux specific mailing list <zfs-discuss@list.zfsonlinux.org>
+Build-Depends: debhelper-compat (= 12),
+ dh-python,
+ dh-sequence-dkms | dkms (>> 2.1.1.2-5),
+ libaio-dev,
+ libblkid-dev,
+ libcurl4-openssl-dev,
+ libelf-dev,
+ libpam0g-dev,
+ libssl-dev | libssl1.0-dev,
+ libtool,
+ libudev-dev,
+ lsb-release,
+ po-debconf,
+ python3-all-dev,
+ python3-cffi,
+ python3-setuptools,
+ python3-sphinx,
+ uuid-dev,
+ zlib1g-dev
+Standards-Version: 4.5.1
+Homepage: https://openzfs.org/
+Vcs-Git: https://github.com/openzfs/zfs.git
+Vcs-Browser: https://github.com/openzfs/zfs
+Rules-Requires-Root: no
+XS-Autobuild: yes
+
+Package: openzfs-libnvpair3
+Section: contrib/libs
+Architecture: linux-any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Breaks: libnvpair1, libnvpair3
+Replaces: libnvpair1, libnvpair3, libnvpair3linux
+Conflicts: libnvpair3linux
+Description: Solaris name-value library for Linux
+ This library provides routines for packing and unpacking nv pairs for
+ transporting data across process boundaries, transporting between
+ kernel and userland, and possibly saving onto disk files.
+
+Package: openzfs-libpam-zfs
+Section: contrib/admin
+Architecture: linux-any
+Depends: libpam-runtime, ${misc:Depends}, ${shlibs:Depends}
+Replaces: libpam-zfs
+Conflicts: libpam-zfs
+Description: PAM module for managing encryption keys for ZFS
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This provides a Pluggable Authentication Module (PAM) that automatically
+ unlocks encrypted ZFS datasets upon login.
+
+Package: openzfs-libuutil3
+Section: contrib/libs
+Architecture: linux-any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Breaks: libuutil1, libuutil3
+Replaces: libuutil1, libuutil3, libuutil3linux
+Conflicts: libuutil3linux
+Description: Solaris userland utility library for Linux
+ This library provides a variety of glue functions for ZFS on Linux:
+ * libspl: The Solaris Porting Layer userland library, which provides APIs
+ that make it possible to run Solaris user code in a Linux environment
+ with relatively minimal modification.
+ * libavl: The Adelson-Velskii Landis balanced binary tree manipulation
+ library.
+ * libefi: The Extensible Firmware Interface library for GUID disk
+ partitioning.
+ * libshare: NFS, SMB, and iSCSI service integration for ZFS.
+
+Package: openzfs-libzfs-dev
+Section: contrib/libdevel
+Architecture: linux-any
+Depends: libssl-dev | libssl1.0-dev,
+ openzfs-libnvpair3 (= ${binary:Version}),
+ openzfs-libuutil3 (= ${binary:Version}),
+ openzfs-libzfs4 (= ${binary:Version}),
+ openzfs-libzfsbootenv1 (= ${binary:Version}),
+ openzfs-libzpool5 (= ${binary:Version}),
+ ${misc:Depends}
+Replaces: libzfslinux-dev
+Conflicts: libzfslinux-dev
+Provides: libnvpair-dev, libuutil-dev
+Description: OpenZFS filesystem development files for Linux
+ Header files and static libraries for compiling software against
+ libraries of OpenZFS filesystem.
+ .
+ This package includes the development files of libnvpair3, libuutil3,
+ libzpool5 and libzfs4.
+
+Package: openzfs-libzfs4
+Section: contrib/libs
+Architecture: linux-any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+# The libcurl4 is loaded through dlopen("libcurl.so.4").
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988521
+Recommends: libcurl4
+Breaks: libzfs2, libzfs4
+Replaces: libzfs2, libzfs4, libzfs4linux
+Conflicts: libzfs4linux
+Description: OpenZFS filesystem library for Linux - general support
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ The OpenZFS library provides support for managing OpenZFS filesystems.
+
+Package: openzfs-libzfsbootenv1
+Section: contrib/libs
+Architecture: linux-any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Breaks: libzfs2, libzfs4
+Replaces: libzfs2, libzfs4, libzfsbootenv1linux
+Conflicts: libzfsbootenv1linux
+Description: OpenZFS filesystem library for Linux - label info support
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ The zfsbootenv library provides support for modifying ZFS label information.
+
+Package: openzfs-libzpool5
+Section: contrib/libs
+Architecture: linux-any
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Breaks: libzpool2, libzpool5
+Replaces: libzpool2, libzpool5, libzpool5linux
+Conflicts: libzpool5linux
+Description: OpenZFS pool library for Linux
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This zpool library provides support for managing zpools.
+
+Package: openzfs-python3-pyzfs
+Section: contrib/python
+Architecture: linux-any
+Depends: python3-cffi,
+ openzfs-zfsutils (= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends}
+Replaces: python3-pyzfs
+Conflicts: python3-pyzfs
+Description: wrapper for libzfs_core C library
+ libzfs_core is intended to be a stable interface for programmatic
+ administration of ZFS. This wrapper provides one-to-one wrappers for
+ libzfs_core API functions, but the signatures and types are more natural to
+ Python.
+ .
+ nvlists are wrapped as dictionaries or lists depending on their usage.
+ Some parameters have default values depending on typical use for
+ increased convenience. Enumerations and bit flags become strings and lists
+ of strings in Python. Errors are reported as exceptions rather than integer
+ errno-style error codes. The wrapper takes care to provide one-to-many
+ mapping of the error codes to the exceptions by interpreting a context
+ in which the error code is produced.
+
+Package: openzfs-pyzfs-doc
+Section: contrib/doc
+Architecture: all
+Depends: ${misc:Depends}, ${sphinxdoc:Depends}
+Recommends: openzfs-python3-pyzfs
+Replaces: pyzfs-doc
+Conflicts: pyzfs-doc
+Description: wrapper for libzfs_core C library (documentation)
+ libzfs_core is intended to be a stable interface for programmatic
+ administration of ZFS. This wrapper provides one-to-one wrappers for
+ libzfs_core API functions, but the signatures and types are more natural to
+ Python.
+ .
+ nvlists are wrapped as dictionaries or lists depending on their usage.
+ Some parameters have default values depending on typical use for
+ increased convenience. Enumerations and bit flags become strings and lists
+ of strings in Python. Errors are reported as exceptions rather than integer
+ errno-style error codes. The wrapper takes care to provide one-to-many
+ mapping of the error codes to the exceptions by interpreting a context
+ in which the error code is produced.
+ .
+ This package contains the documentation.
+
+Package: openzfs-zfs-dkms
+Architecture: all
+Depends: dkms (>> 2.1.1.2-5),
+ file,
+ libc6-dev | libc-dev,
+ lsb-release,
+ python3 (>> 3.12) | python3-distutils | libpython3-stdlib (<< 3.6.4),
+ ${misc:Depends},
+ ${perl:Depends}
+Recommends: openzfs-zfs-zed, openzfs-zfsutils (>= ${source:Version}), ${linux:Recommends}
+# suggests debhelper because e.g. `dkms mkdeb -m zfs -v 0.8.2` needs dh_testdir (#909183)
+Suggests: debhelper
+Breaks: spl-dkms (<< 0.8.0~rc1)
+Replaces: spl-dkms, zfs-dkms
+Provides: openzfs-zfs-modules
+Description: OpenZFS filesystem kernel modules for Linux
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This DKMS package includes the SPA, DMU, ZVOL, and ZPL components of
+ OpenZFS.
+
+Package: openzfs-zfs-initramfs
+Architecture: all
+Depends: busybox-initramfs | busybox-static | busybox,
+ initramfs-tools,
+ openzfs-zfs-modules | openzfs-zfs-dkms,
+ openzfs-zfsutils (>= ${source:Version}),
+ ${misc:Depends}
+Breaks: zfsutils-linux (<= 0.7.11-2)
+Replaces: zfsutils-linux (<= 0.7.11-2), zfs-initramfs
+Conflicts: zfs-initramfs
+Description: OpenZFS root filesystem capabilities for Linux - initramfs
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This package adds OpenZFS to the system initramfs with a hook
+ for the initramfs-tools infrastructure.
+
+Package: openzfs-zfs-dracut
+Architecture: all
+Depends: dracut,
+ openzfs-zfs-modules | openzfs-zfs-dkms,
+ openzfs-zfsutils (>= ${source:Version}),
+ ${misc:Depends}
+Conflicts: zfs-dracut
+Replaces: zfs-dracut
+Description: OpenZFS root filesystem capabilities for Linux - dracut
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This package adds OpenZFS to the system initramfs with a hook
+ for the dracut infrastructure.
+
+Package: openzfs-zfsutils
+Section: contrib/admin
+Architecture: linux-any
+Pre-Depends: ${misc:Pre-Depends}
+Depends: openzfs-libnvpair3 (= ${binary:Version}),
+ openzfs-libuutil3 (= ${binary:Version}),
+ openzfs-libzfs4 (= ${binary:Version}),
+ openzfs-libzpool5 (= ${binary:Version}),
+ python3,
+ ${misc:Depends},
+ ${shlibs:Depends}
+Recommends: lsb-base, openzfs-zfs-modules | openzfs-zfs-dkms, openzfs-zfs-zed
+Breaks: openrc,
+ spl (<< 0.7.9-2),
+ spl-dkms (<< 0.8.0~rc1),
+ openzfs-zfs-dkms (<< ${source:Version}),
+ openzfs-zfs-dkms (>> ${source:Version}...)
+Replaces: spl (<< 0.7.9-2), spl-dkms, zfsutils-linux
+Conflicts: zfs, zfs-fuse, zfsutils-linux
+Suggests: nfs-kernel-server,
+ samba-common-bin (>= 3.0.23),
+ openzfs-zfs-initramfs | openzfs-zfs-dracut
+Provides: openzfsutils
+Description: command-line tools to manage OpenZFS filesystems
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This package provides the zfs and zpool commands to create and administer
+ OpenZFS filesystems.
+
+Package: openzfs-zfs-zed
+Section: contrib/admin
+Architecture: linux-any
+Pre-Depends: ${misc:Pre-Depends}
+Depends: openzfs-zfs-modules | openzfs-zfs-dkms,
+ openzfs-zfsutils (>= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends}
+Conflicts: zfs, zfs-zed
+Replaces: zfs-zed
+Description: OpenZFS Event Daemon
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ ZED (ZFS Event Daemon) monitors events generated by the ZFS kernel
+ module. When a zevent (ZFS Event) is posted, ZED will run any ZEDLETs
+ (ZFS Event Daemon Linkage for Executable Tasks) that have been enabled
+ for the corresponding zevent class.
+ .
+ This package provides the OpenZFS Event Daemon (zed).
+
+Package: openzfs-zfs-test
+Section: contrib/admin
+Architecture: linux-any
+Depends: acl,
+ attr,
+ bc,
+ fio,
+ ksh,
+ lsscsi,
+ mdadm,
+ parted,
+ python3,
+ openzfs-python3-pyzfs,
+ sudo,
+ sysstat,
+ openzfs-zfs-modules | openzfs-zfs-dkms,
+ openzfs-zfsutils (>=${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends}
+Recommends: nfs-kernel-server
+Breaks: zfsutils-linux (<= 0.7.9-2)
+Replaces: zfsutils-linux (<= 0.7.9-2), zfs-test
+Conflicts: zutils, zfs-test
+Description: OpenZFS test infrastructure and support scripts
+ OpenZFS is a storage platform that encompasses the functionality of
+ traditional filesystems and volume managers. It supports data checksums,
+ compression, encryption, snapshots, and more.
+ .
+ This package provides the OpenZFS test infrastructure for destructively
+ testing and validating a system using OpenZFS. It is entirely optional
+ and should only be installed and used in test environments.
diff --git a/contrib/debian/control.modules.in b/contrib/debian/control.modules.in
new file mode 100644
index 000000000000..34eb7fafba7c
--- /dev/null
+++ b/contrib/debian/control.modules.in
@@ -0,0 +1,33 @@
+Source: openzfs-linux
+Section: contrib/kernel
+Priority: optional
+Maintainer: ZFS on Linux specific mailing list <zfs-discuss@list.zfsonlinux.org>
+Build-Depends: debhelper-compat (= 10),
+ dkms (>> 2.1.1.2-5),
+ libtool,
+ linux-headers-_KVERS_ | raspberrypi-kernel-headers
+Standards-Version: 4.3.0
+Homepage: http://www.openzfs.org/
+Vcs-Git: https://github.com/openzfs/zfs.git
+Vcs-Browser: https://github.com/openzfs/zfs
+
+Package: openzfs-zfs-modules-_KVERS_
+Architecture: _ARCH_
+Provides: openzfs-zfs-modules
+Depends: linux-image-_KVERS_ | raspberrypi-kernel
+Recommends: openzfsutils
+Replaces: zfs-modules-_KVERS_
+Conflicts: zfs-modules-_KVERS_
+Description: OpenZFS filesystem kernel modules for Linux (kernel _KVERS_)
+ An advanced integrated volume manager and filesystem that is designed for
+ performance and data integrity. Snapshots, clones, checksums, deduplication,
+ compression, and RAID redundancy are built-in features.
+ .
+ This package contains the compiled kernel module for _KVERS_
+ .
+ Includes the SPA, DMU, ZVOL, and ZPL components of OpenZFS.
+ .
+ If you have compiled your own kernel, you will most likely need to build
+ your own zfs-modules. The zfs-source package has been
+ provided for use with the Debian kernel-package utility to produce a
+ version of zfs-module for your kernel.
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
new file mode 100644
index 000000000000..65c7d209d8eb
--- /dev/null
+++ b/contrib/debian/copyright
@@ -0,0 +1,19 @@
+This Debian packaging is a derived work of Debian's zfs-linux package [1].
+The original copy of the Debian-styled copyright file can be found at [2].
+The detailed contributor information can be found in [2][3].
+
+Files: contrib/debian/*
+Copyright:
+ 2013-2016, Aron Xu <aron@debian.org>
+ 2016, Petter Reinholdtsen <pere@hungry.com>
+ 2013, Carlos Alberto Lopez Perez <clopez@igalia.com>
+ 2013, Turbo Fredriksson <turbo@bayour.com>
+ 2012-2013, Richard Laager <rlaager@wiktel.com>
+ 2011-2013, Darik Horn <dajhorn@vanadac.com>
+ 2018-2019, Mo Zhou <cdluminate@gmail.com>
+ 2018-2020, Mo Zhou <lumin@debian.org>
+License: GPL-2+
+
+[1] https://tracker.debian.org/pkg/zfs-linux
+[2] https://salsa.debian.org/zfsonlinux-team/zfs/-/blob/master/debian/copyright
+[3] https://salsa.debian.org/zfsonlinux-team/zfs/-/blob/master/debian/changelog
diff --git a/contrib/debian/not-installed b/contrib/debian/not-installed
new file mode 100644
index 000000000000..ad14776f3b7e
--- /dev/null
+++ b/contrib/debian/not-installed
@@ -0,0 +1,13 @@
+usr/bin/arc_summary.py
+usr/share/zfs/enum-extract.pl
+usr/share/zfs/zfs-helpers.sh
+etc/default/zfs
+etc/init.d
+etc/sudoers.d
+etc/zfs/vdev_id.conf.alias.example
+etc/zfs/vdev_id.conf.multipath.example
+etc/zfs/vdev_id.conf.sas_direct.example
+etc/zfs/vdev_id.conf.sas_switch.example
+etc/zfs/vdev_id.conf.scsi.example
+etc/zfs/zfs-functions
+lib/systemd/system/zfs-import.service
diff --git a/contrib/debian/openzfs-libnvpair3.docs b/contrib/debian/openzfs-libnvpair3.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libnvpair3.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libnvpair3.install.in b/contrib/debian/openzfs-libnvpair3.install.in
new file mode 100644
index 000000000000..ed7b541e3607
--- /dev/null
+++ b/contrib/debian/openzfs-libnvpair3.install.in
@@ -0,0 +1 @@
+lib/@DEB_HOST_MULTIARCH@/libnvpair.so.*
diff --git a/contrib/debian/openzfs-libpam-zfs.install b/contrib/debian/openzfs-libpam-zfs.install
new file mode 100644
index 000000000000..c33123f69a8d
--- /dev/null
+++ b/contrib/debian/openzfs-libpam-zfs.install
@@ -0,0 +1,2 @@
+lib/*/security/pam_zfs_key.so
+usr/share/pam-configs/zfs_key
diff --git a/contrib/debian/openzfs-libpam-zfs.postinst b/contrib/debian/openzfs-libpam-zfs.postinst
new file mode 100644
index 000000000000..03893454eee9
--- /dev/null
+++ b/contrib/debian/openzfs-libpam-zfs.postinst
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if ! $(ldd "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security/pam_zfs_key.so" | grep -q "libasan") ; then
+ pam-auth-update --package
+fi
+
+#DEBHELPER#
diff --git a/contrib/debian/openzfs-libpam-zfs.prerm b/contrib/debian/openzfs-libpam-zfs.prerm
new file mode 100644
index 000000000000..21e827001c23
--- /dev/null
+++ b/contrib/debian/openzfs-libpam-zfs.prerm
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = remove ] ; then
+ pam-auth-update --package --remove zfs_key
+fi
+
+#DEBHELPER#
diff --git a/contrib/debian/openzfs-libuutil3.docs b/contrib/debian/openzfs-libuutil3.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libuutil3.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libuutil3.install.in b/contrib/debian/openzfs-libuutil3.install.in
new file mode 100644
index 000000000000..a197d030d743
--- /dev/null
+++ b/contrib/debian/openzfs-libuutil3.install.in
@@ -0,0 +1 @@
+lib/@DEB_HOST_MULTIARCH@/libuutil.so.*
diff --git a/contrib/debian/openzfs-libzfs-dev.docs b/contrib/debian/openzfs-libzfs-dev.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libzfs-dev.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libzfs-dev.install.in b/contrib/debian/openzfs-libzfs-dev.install.in
new file mode 100644
index 000000000000..eaa8c3925e24
--- /dev/null
+++ b/contrib/debian/openzfs-libzfs-dev.install.in
@@ -0,0 +1,3 @@
+lib/@DEB_HOST_MULTIARCH@/*.a usr/lib/@DEB_HOST_MULTIARCH@
+usr/include
+usr/lib/@DEB_HOST_MULTIARCH@
diff --git a/contrib/debian/openzfs-libzfs4.docs b/contrib/debian/openzfs-libzfs4.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libzfs4.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libzfs4.install.in b/contrib/debian/openzfs-libzfs4.install.in
new file mode 100644
index 000000000000..6765aaee59cc
--- /dev/null
+++ b/contrib/debian/openzfs-libzfs4.install.in
@@ -0,0 +1,2 @@
+lib/@DEB_HOST_MULTIARCH@/libzfs.so.*
+lib/@DEB_HOST_MULTIARCH@/libzfs_core.so.*
diff --git a/contrib/debian/openzfs-libzfsbootenv1.docs b/contrib/debian/openzfs-libzfsbootenv1.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libzfsbootenv1.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libzfsbootenv1.install.in b/contrib/debian/openzfs-libzfsbootenv1.install.in
new file mode 100644
index 000000000000..49216742433f
--- /dev/null
+++ b/contrib/debian/openzfs-libzfsbootenv1.install.in
@@ -0,0 +1 @@
+lib/@DEB_HOST_MULTIARCH@/libzfsbootenv.so.*
diff --git a/contrib/debian/openzfs-libzpool5.docs b/contrib/debian/openzfs-libzpool5.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-libzpool5.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-libzpool5.install.in b/contrib/debian/openzfs-libzpool5.install.in
new file mode 100644
index 000000000000..b9e872df9ba8
--- /dev/null
+++ b/contrib/debian/openzfs-libzpool5.install.in
@@ -0,0 +1 @@
+lib/@DEB_HOST_MULTIARCH@/libzpool.so.*
diff --git a/contrib/debian/openzfs-python3-pyzfs.install b/contrib/debian/openzfs-python3-pyzfs.install
new file mode 100644
index 000000000000..4606faae20a7
--- /dev/null
+++ b/contrib/debian/openzfs-python3-pyzfs.install
@@ -0,0 +1 @@
+usr/lib/python3*
diff --git a/contrib/debian/openzfs-zfs-dkms.config b/contrib/debian/openzfs-zfs-dkms.config
new file mode 100644
index 000000000000..ad7e160a2b11
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.config
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+set -e
+
+# Source debconf library
+. /usr/share/debconf/confmodule
+
+db_input critical zfs-dkms/note-incompatible-licenses || true
+db_go
+
+kernelbits=unknown
+if [ -r /proc/kallsyms ]; then
+ addrlen=$(head -1 /proc/kallsyms|awk '{print $1}'|wc -c)
+ if [ $addrlen = 17 ]; then
+ kernelbits=64
+ elif [ $addrlen = 9 ]; then
+ kernelbits=32
+ fi
+fi
+
+if [ $kernelbits != 64 ]; then
+ if [ $kernelbits = 32 ]; then
+ db_input critical zfs-dkms/stop-build-for-32bit-kernel || true
+ db_go || true
+ else
+ db_input critical zfs-dkms/stop-build-for-unknown-kernel || true
+ db_go || true
+ fi
+fi
+
+#DEBHELPER#
diff --git a/contrib/debian/openzfs-zfs-dkms.dkms b/contrib/debian/openzfs-zfs-dkms.dkms
new file mode 100644
index 000000000000..3ac8677b7cde
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.dkms
@@ -0,0 +1 @@
+scripts/zfs-dkms.dkms
diff --git a/contrib/debian/openzfs-zfs-dkms.docs b/contrib/debian/openzfs-zfs-dkms.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-zfs-dkms.install b/contrib/debian/openzfs-zfs-dkms.install
new file mode 100644
index 000000000000..b601f22c481a
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.install
@@ -0,0 +1 @@
+usr/src
diff --git a/contrib/debian/openzfs-zfs-dkms.postinst b/contrib/debian/openzfs-zfs-dkms.postinst
new file mode 100644
index 000000000000..0ecb9674d559
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.postinst
@@ -0,0 +1,51 @@
+#!/bin/sh
+set -e
+
+# Source debconf library (see dh_installdebconf(1) and #106070 #626312)
+. /usr/share/debconf/confmodule
+
+kernelbits=unknown
+if [ -r /proc/kallsyms ]; then
+ addrlen=$(head -1 /proc/kallsyms| grep -o '^ *[^ ]*' |wc -c)
+ if [ $addrlen = 17 ]; then
+ kernelbits=64
+ elif [ $addrlen = 9 ]; then
+ kernelbits=32
+ fi
+fi
+
+if [ $kernelbits != 64 ]; then
+ if [ $kernelbits = 32 ]; then
+ db_get zfs-dkms/stop-build-for-32bit-kernel
+ if [ "$RET" = "true" ]; then
+ echo "Ok, aborting, since ZFS is not designed for 32-bit kernels." 1>&2
+ # Exit 0: Tell dpkg that we finished OK but stop here.
+ # (don't build the module)
+ exit 0
+ else
+ echo "WARNING: Building ZFS module on a 32-bit kernel." 1>&2
+ fi
+ else
+ db_get zfs-dkms/stop-build-for-unknown-kernel
+ if [ "$RET" = "true" ]; then
+ echo "Ok, aborting, since ZFS is not designed for 32-bit kernels." 1>&2
+ # Exit 0: (same that above)
+ exit 0
+ else
+ echo "WARNING: Building ZFS module on an unknown kernel." 1>&2
+ fi
+ fi
+fi
+
+# Here the module gets built (automatically handled by dh_dkms)
+
+#DEBHELPER#
+
+
+case $1 in
+ (configure)
+ if [ -x /usr/share/update-notifier/notify-reboot-required ]; then
+ /usr/share/update-notifier/notify-reboot-required
+ fi
+ ;;
+esac
diff --git a/contrib/debian/openzfs-zfs-dkms.prerm b/contrib/debian/openzfs-zfs-dkms.prerm
new file mode 100644
index 000000000000..fea2aee8b902
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.prerm
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+#DEBHELPER#
+
+if [ "$1" = "remove" ]; then
+ rm -f /etc/zfs/zpool.cache
+fi
diff --git a/contrib/debian/openzfs-zfs-dkms.templates b/contrib/debian/openzfs-zfs-dkms.templates
new file mode 100644
index 000000000000..3db643464e7f
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.templates
@@ -0,0 +1,40 @@
+Template: zfs-dkms/stop-build-for-32bit-kernel
+Type: boolean
+Default: true
+_Description: Abort building OpenZFS on a 32-bit kernel?
+ You are attempting to build OpenZFS against a 32-bit running kernel.
+ .
+ Although possible, building in a 32-bit environment is unsupported and
+ likely to cause instability leading to possible data corruption. You
+ are strongly advised to use a 64-bit kernel; if you do decide to
+ proceed with using OpenZFS on this kernel then keep in mind that it is at
+ your own risk.
+
+Template: zfs-dkms/stop-build-for-unknown-kernel
+Type: boolean
+Default: true
+_Description: Abort building OpenZFS on an unknown kernel?
+ You are attempting to build OpenZFS against a running kernel that could not
+ be identified as 32-bit or 64-bit. If you are not completely sure that
+ the running kernel is a 64-bit one, you should probably stop the build.
+ .
+ Although possible, building in a 32-bit environment is unsupported and
+ likely to cause instability leading to possible data corruption. You
+ are strongly advised to use a 64-bit kernel; if you do decide to
+ proceed with using OpenZFS on this kernel then keep in mind that it is at
+ your own risk.
+
+Template: zfs-dkms/note-incompatible-licenses
+Type: note
+_Description: Licenses of OpenZFS and Linux are incompatible
+ OpenZFS is licensed under the Common Development and Distribution License (CDDL),
+ and the Linux kernel is licensed under the GNU General Public License Version 2
+ (GPL-2). While both are free open source licenses they are restrictive
+ licenses. The combination of them causes problems because it prevents using
+ pieces of code exclusively available under one license with pieces of code
+ exclusively available under the other in the same binary.
+ .
+ You are going to build OpenZFS using DKMS in such a way that they are not going to
+ be built into one monolithic binary. Please be aware that distributing both of
+ the binaries in the same media (disk images, virtual appliances, etc) may
+ lead to infringing.
diff --git a/contrib/debian/openzfs-zfs-dkms.triggers b/contrib/debian/openzfs-zfs-dkms.triggers
new file mode 100644
index 000000000000..865f50a5d99d
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dkms.triggers
@@ -0,0 +1 @@
+activate-await update-initramfs
diff --git a/contrib/debian/openzfs-zfs-dracut.install b/contrib/debian/openzfs-zfs-dracut.install
new file mode 100644
index 000000000000..8c2bf1b5c58b
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-dracut.install
@@ -0,0 +1,2 @@
+usr/lib/dracut
+usr/share/man/man7/dracut.zfs.7
diff --git a/contrib/debian/openzfs-zfs-initramfs.install b/contrib/debian/openzfs-zfs-initramfs.install
new file mode 100644
index 000000000000..222620947f10
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-initramfs.install
@@ -0,0 +1,2 @@
+../tree/zfs-initramfs/* /
+usr/share/initramfs-tools/*
diff --git a/contrib/debian/openzfs-zfs-modules-_KVERS_-di.install.in b/contrib/debian/openzfs-zfs-modules-_KVERS_-di.install.in
new file mode 100644
index 000000000000..fc1828ee9639
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-modules-_KVERS_-di.install.in
@@ -0,0 +1,2 @@
+module/spl.ko lib/modules/_KVERS_/extra/zcommon/
+module/zfs.ko lib/modules/_KVERS_/extra/zcommon/
diff --git a/contrib/debian/openzfs-zfs-modules-_KVERS_.install.in b/contrib/debian/openzfs-zfs-modules-_KVERS_.install.in
new file mode 100644
index 000000000000..fc1828ee9639
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-modules-_KVERS_.install.in
@@ -0,0 +1,2 @@
+module/spl.ko lib/modules/_KVERS_/extra/zcommon/
+module/zfs.ko lib/modules/_KVERS_/extra/zcommon/
diff --git a/contrib/debian/openzfs-zfs-modules-_KVERS_.postinst.in b/contrib/debian/openzfs-zfs-modules-_KVERS_.postinst.in
new file mode 100644
index 000000000000..4eb2314508a6
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-modules-_KVERS_.postinst.in
@@ -0,0 +1,16 @@
+#!/bin/sh
+set -e
+
+# Run depmod first
+depmod -a _KVERS_
+
+#DEBHELPER#
+
+
+case $1 in
+ (configure)
+ if [ -x /usr/share/update-notifier/notify-reboot-required ]; then
+ /usr/share/update-notifier/notify-reboot-required
+ fi
+ ;;
+esac
diff --git a/contrib/debian/openzfs-zfs-modules-_KVERS_.postrm.in b/contrib/debian/openzfs-zfs-modules-_KVERS_.postrm.in
new file mode 100644
index 000000000000..2a2fc4b5cb95
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-modules-_KVERS_.postrm.in
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+
+# Run depmod after module uninstallation.
+depmod
+
+#DEBHELPER#
diff --git a/contrib/debian/openzfs-zfs-test.install b/contrib/debian/openzfs-zfs-test.install
new file mode 100644
index 000000000000..b3afef50dbd4
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-test.install
@@ -0,0 +1,13 @@
+sbin/ztest
+usr/bin/raidz_test
+usr/share/man/man1/raidz_test.1
+usr/share/man/man1/test-runner.1
+usr/share/man/man1/ztest.1
+usr/share/zfs/common.sh
+usr/share/zfs/runfiles/
+usr/share/zfs/test-runner
+usr/share/zfs/zfs-tests.sh
+usr/share/zfs/zfs-tests/
+usr/share/zfs/zfs.sh
+usr/share/zfs/zimport.sh
+usr/share/zfs/zloop.sh
diff --git a/contrib/debian/openzfs-zfs-zed.install b/contrib/debian/openzfs-zfs-zed.install
new file mode 100644
index 000000000000..a348ba828ee5
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-zed.install
@@ -0,0 +1,5 @@
+etc/zfs/zed.d/*
+lib/systemd/system/zfs-zed.service
+usr/lib/zfs-linux/zed.d/*
+usr/sbin/zed
+usr/share/man/man8/zed.8
diff --git a/contrib/debian/openzfs-zfs-zed.postinst b/contrib/debian/openzfs-zfs-zed.postinst
new file mode 100644
index 000000000000..ac14957a3fe1
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-zed.postinst
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -e
+
+zedd="/usr/lib/zfs-linux/zed.d"
+etcd="/etc/zfs/zed.d"
+
+# remove the overrides created in prerm
+find "${etcd}" -maxdepth 1 -lname '/dev/null' -delete
+# remove any dangling symlinks to old zedlets
+find "${etcd}" -maxdepth 1 -lname "${zedd}/*" -xtype l -delete
+
+#DEBHELPER#
+
diff --git a/contrib/debian/openzfs-zfs-zed.postrm b/contrib/debian/openzfs-zfs-zed.postrm
new file mode 100644
index 000000000000..e9aed3f4ce2b
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-zed.postrm
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -e
+
+zedd="/usr/lib/zfs-linux/zed.d"
+etcd="/etc/zfs/zed.d"
+
+if [ "$1" = "purge" ] && [ -d "$etcd" ] ; then
+ # remove the overrides created in prerm
+ find "${etcd}" -maxdepth 1 -lname '/dev/null' -delete
+ # remove any dangling symlinks to old zedlets
+ find "${etcd}" -maxdepth 1 -lname "${zedd}/*" -xtype l -delete
+ # clean up any empty directories
+ ( rmdir "$etcd" && rmdir "/etc/zfs" ) || true
+fi
+
+#DEBHELPER#
+
diff --git a/contrib/debian/openzfs-zfs-zed.zfs-zed.init b/contrib/debian/openzfs-zfs-zed.zfs-zed.init
new file mode 120000
index 000000000000..3f41f6813577
--- /dev/null
+++ b/contrib/debian/openzfs-zfs-zed.zfs-zed.init
@@ -0,0 +1 @@
+../etc/init.d/zfs-zed \ No newline at end of file
diff --git a/contrib/debian/openzfs-zfsutils.docs b/contrib/debian/openzfs-zfsutils.docs
new file mode 100644
index 000000000000..4302f1b2ab6a
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.docs
@@ -0,0 +1,2 @@
+COPYRIGHT
+LICENSE
diff --git a/contrib/debian/openzfs-zfsutils.examples b/contrib/debian/openzfs-zfsutils.examples
new file mode 100644
index 000000000000..9f10d3fc0a7a
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.examples
@@ -0,0 +1,5 @@
+etc/zfs/vdev_id.conf.alias.example
+etc/zfs/vdev_id.conf.multipath.example
+etc/zfs/vdev_id.conf.sas_direct.example
+etc/zfs/vdev_id.conf.sas_switch.example
+etc/zfs/vdev_id.conf.scsi.example
diff --git a/contrib/debian/openzfs-zfsutils.install b/contrib/debian/openzfs-zfsutils.install
new file mode 100644
index 000000000000..741014398ade
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.install
@@ -0,0 +1,136 @@
+etc/default/zfs
+etc/zfs/zfs-functions
+etc/zfs/zpool.d/
+lib/systemd/system-generators/
+lib/systemd/system-preset/
+lib/systemd/system/zfs-import-cache.service
+lib/systemd/system/zfs-import-scan.service
+lib/systemd/system/zfs-import.target
+lib/systemd/system/zfs-load-key.service
+lib/systemd/system/zfs-mount.service
+lib/systemd/system/zfs-scrub-monthly@.timer
+lib/systemd/system/zfs-scrub-weekly@.timer
+lib/systemd/system/zfs-scrub@.service
+lib/systemd/system/zfs-trim-monthly@.timer
+lib/systemd/system/zfs-trim-weekly@.timer
+lib/systemd/system/zfs-trim@.service
+lib/systemd/system/zfs-share.service
+lib/systemd/system/zfs-volume-wait.service
+lib/systemd/system/zfs-volumes.target
+lib/systemd/system/zfs.target
+lib/udev/
+sbin/fsck.zfs
+sbin/mount.zfs
+sbin/zdb
+sbin/zfs
+sbin/zfs_ids_to_path
+sbin/zgenhostid
+sbin/zhack
+sbin/zinject
+sbin/zpool
+sbin/zstream
+sbin/zstreamdump
+usr/bin/zvol_wait
+usr/lib/modules-load.d/ lib/
+usr/lib/zfs-linux/zpool.d/
+usr/lib/zfs-linux/zpool_influxdb
+usr/lib/zfs-linux/zfs_prepare_disk
+usr/sbin/arc_summary
+usr/sbin/arcstat
+usr/sbin/dbufstat
+usr/sbin/zilstat
+usr/share/zfs/compatibility.d/
+usr/share/bash-completion/completions
+usr/share/man/man1/arcstat.1
+usr/share/man/man1/zhack.1
+usr/share/man/man1/zvol_wait.1
+usr/share/man/man5/
+usr/share/man/man8/fsck.zfs.8
+usr/share/man/man8/mount.zfs.8
+usr/share/man/man8/vdev_id.8
+usr/share/man/man8/zdb.8
+usr/share/man/man8/zfs-allow.8
+usr/share/man/man8/zfs-bookmark.8
+usr/share/man/man8/zfs-change-key.8
+usr/share/man/man8/zfs-clone.8
+usr/share/man/man8/zfs-create.8
+usr/share/man/man8/zfs-destroy.8
+usr/share/man/man8/zfs-diff.8
+usr/share/man/man8/zfs-get.8
+usr/share/man/man8/zfs-groupspace.8
+usr/share/man/man8/zfs-hold.8
+usr/share/man/man8/zfs-inherit.8
+usr/share/man/man8/zfs-list.8
+usr/share/man/man8/zfs-load-key.8
+usr/share/man/man8/zfs-mount-generator.8
+usr/share/man/man8/zfs-mount.8
+usr/share/man/man8/zfs-program.8
+usr/share/man/man8/zfs-project.8
+usr/share/man/man8/zfs-projectspace.8
+usr/share/man/man8/zfs-promote.8
+usr/share/man/man8/zfs-receive.8
+usr/share/man/man8/zfs-recv.8
+usr/share/man/man8/zfs-redact.8
+usr/share/man/man8/zfs-release.8
+usr/share/man/man8/zfs-rename.8
+usr/share/man/man8/zfs-rollback.8
+usr/share/man/man8/zfs-send.8
+usr/share/man/man8/zfs-set.8
+usr/share/man/man8/zfs-share.8
+usr/share/man/man8/zfs-snapshot.8
+usr/share/man/man8/zfs-unallow.8
+usr/share/man/man8/zfs-unload-key.8
+usr/share/man/man8/zfs-unmount.8
+usr/share/man/man8/zfs-unzone.8
+usr/share/man/man8/zfs-upgrade.8
+usr/share/man/man8/zfs-userspace.8
+usr/share/man/man8/zfs-wait.8
+usr/share/man/man8/zfs-zone.8
+usr/share/man/man8/zfs.8
+usr/share/man/man8/zfs_ids_to_path.8
+usr/share/man/man8/zfs_prepare_disk.8
+usr/share/man/man7/zfsconcepts.7
+usr/share/man/man7/zfsprops.7
+usr/share/man/man8/zgenhostid.8
+usr/share/man/man8/zinject.8
+usr/share/man/man8/zpool-add.8
+usr/share/man/man8/zpool-attach.8
+usr/share/man/man8/zpool-checkpoint.8
+usr/share/man/man8/zpool-clear.8
+usr/share/man/man8/zpool-create.8
+usr/share/man/man8/zpool-destroy.8
+usr/share/man/man8/zpool-detach.8
+usr/share/man/man8/zpool-events.8
+usr/share/man/man8/zpool-export.8
+usr/share/man/man8/zpool-get.8
+usr/share/man/man8/zpool-history.8
+usr/share/man/man8/zpool-import.8
+usr/share/man/man8/zpool-initialize.8
+usr/share/man/man8/zpool-iostat.8
+usr/share/man/man8/zpool-labelclear.8
+usr/share/man/man8/zpool-list.8
+usr/share/man/man8/zpool-offline.8
+usr/share/man/man8/zpool-online.8
+usr/share/man/man8/zpool-reguid.8
+usr/share/man/man8/zpool-remove.8
+usr/share/man/man8/zpool-reopen.8
+usr/share/man/man8/zpool-replace.8
+usr/share/man/man8/zpool-resilver.8
+usr/share/man/man8/zpool-scrub.8
+usr/share/man/man8/zpool-set.8
+usr/share/man/man8/zpool-split.8
+usr/share/man/man8/zpool-status.8
+usr/share/man/man8/zpool-sync.8
+usr/share/man/man8/zpool-trim.8
+usr/share/man/man8/zpool-upgrade.8
+usr/share/man/man8/zpool-wait.8
+usr/share/man/man8/zpool.8
+usr/share/man/man7/vdevprops.7
+usr/share/man/man7/zpoolconcepts.7
+usr/share/man/man7/zpoolprops.7
+usr/share/man/man8/zstream.8
+usr/share/man/man8/zstreamdump.8
+usr/share/man/man4/spl.4
+usr/share/man/man4/zfs.4
+usr/share/man/man7/zpool-features.7
+usr/share/man/man8/zpool_influxdb.8
diff --git a/contrib/debian/openzfs-zfsutils.postinst b/contrib/debian/openzfs-zfsutils.postinst
new file mode 100644
index 000000000000..7dc208d0dd7b
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.postinst
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -e
+
+# When processed to here but zfs kernel module is not loaded, the subsequent
+# services would fail to start. In this case the installation process just
+# fails at the postinst stage. The user could do
+# $ sudo modprobe zfs; sudo dpkg --configure -a
+# to complete the installation.
+#
+modprobe -v zfs || true # modprobe zfs does nothing if zfs.ko was already loaded.
+
+#DEBHELPER#
+
diff --git a/contrib/debian/openzfs-zfsutils.zfs-import.init b/contrib/debian/openzfs-zfsutils.zfs-import.init
new file mode 120000
index 000000000000..bfc368fd3426
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.zfs-import.init
@@ -0,0 +1 @@
+../etc/init.d/zfs-import \ No newline at end of file
diff --git a/contrib/debian/openzfs-zfsutils.zfs-load-key.init b/contrib/debian/openzfs-zfsutils.zfs-load-key.init
new file mode 120000
index 000000000000..3f3e97f811bb
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.zfs-load-key.init
@@ -0,0 +1 @@
+../etc/init.d/zfs-load-key \ No newline at end of file
diff --git a/contrib/debian/openzfs-zfsutils.zfs-mount.init b/contrib/debian/openzfs-zfsutils.zfs-mount.init
new file mode 120000
index 000000000000..62a544332422
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.zfs-mount.init
@@ -0,0 +1 @@
+../etc/init.d/zfs-mount \ No newline at end of file
diff --git a/contrib/debian/openzfs-zfsutils.zfs-share.init b/contrib/debian/openzfs-zfsutils.zfs-share.init
new file mode 120000
index 000000000000..3f069f9baaaf
--- /dev/null
+++ b/contrib/debian/openzfs-zfsutils.zfs-share.init
@@ -0,0 +1 @@
+../etc/init.d/zfs-share \ No newline at end of file
diff --git a/contrib/debian/rules.in b/contrib/debian/rules.in
new file mode 100755
index 000000000000..a3a05efacb50
--- /dev/null
+++ b/contrib/debian/rules.in
@@ -0,0 +1,218 @@
+#!/usr/bin/make -f
+
+include /usr/share/dpkg/default.mk
+
+LSB_DISTRIBUTOR := $(shell lsb_release -is)
+NAME := $(shell awk '$$1 == "Name:" { print $$2; }' META)
+LINUX_MIN := $(shell awk '/Linux-Minimum:/{print $$2}' META)
+LINUX_NEXT := $(shell awk -F'[ .]' '/Linux-Maximum:/{print $$2 "." $$3+1}' META)
+
+DKMSFILES := module include config zfs.release.in autogen.sh copy-builtin META AUTHORS \
+ COPYRIGHT LICENSE README.md CODE_OF_CONDUCT.md NEWS NOTICE RELEASES.md
+
+ifndef KVERS
+KVERS=$(shell uname -r)
+endif
+
+non_epoch_version=$(shell echo $(KVERS) | perl -pe 's/^\d+://')
+PACKAGE=openzfs-zfs
+pmodules = $(PACKAGE)-modules-$(non_epoch_version)
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+NUM_CPUS = $(shell nproc 2>/dev/null)
+PARALLEL = $(subst parallel=,,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+NJOBS = -j$(or $(PARALLEL),$(NUM_CPUS),1)
+
+%:
+ dh $@ --with autoreconf,dkms,python3,sphinxdoc
+
+override_dh_autoreconf:
+ @# Embed the downstream version in the module.
+ @sed -e 's/^Version:.*/Version: $(DEB_VERSION_UPSTREAM)/' -i.orig META
+
+ dh_autoreconf
+
+override_dh_auto_configure:
+ @# Build the userland, but don't build the kernel modules.
+ dh_auto_configure -- @CFGOPTS@ \
+ --bindir=/usr/bin \
+ --sbindir=/sbin \
+ --libdir=/lib/"$(DEB_HOST_MULTIARCH)" \
+ --with-udevdir=/lib/udev \
+ --with-zfsexecdir=/usr/lib/zfs-linux \
+ --enable-systemd \
+ --enable-pyzfs \
+ --with-python=python3 \
+ --with-pammoduledir='/lib/$(DEB_HOST_MULTIARCH)/security' \
+ --with-pkgconfigdir='/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig' \
+ --with-systemdunitdir=/lib/systemd/system \
+ --with-systemdpresetdir=/lib/systemd/system-preset \
+ --with-systemdgeneratordir=/lib/systemd/system-generators \
+ --with-config=user
+
+ for i in $(wildcard $(CURDIR)/debian/*.install.in) ; do \
+ basename "$$i" | grep _KVERS_ && continue ; \
+ sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' "$$i" > "$${i%%.in}" ; \
+ done
+
+override_dh_gencontrol:
+ dh_gencontrol -- -Vlinux:Recommends="linux-libc-dev (<< $(LINUX_NEXT)~), linux-libc-dev (>= $(LINUX_MIN)~),"
+
+override_dh_auto_build:
+ @# Get a bare copy of the source code for DKMS.
+ @# This creates the $(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/ tree, which does not
+ @# contain the userland sources. NB: Remove-userland-dist-rules.patch
+ $(MAKE) distdir
+
+ dh_auto_build
+
+override_dh_auto_install:
+ @# Install the utilities.
+ $(MAKE) install DESTDIR='$(CURDIR)/debian/tmp'
+
+ # Move from bin_dir to /usr/sbin
+ # Remove suffix (.py) as per policy 10.4 - Scripts
+ # https://www.debian.org/doc/debian-policy/ch-files.html#s-scripts
+ mkdir -p '$(CURDIR)/debian/tmp/usr/sbin/'
+ mv '$(CURDIR)/debian/tmp/usr/bin/arc_summary' '$(CURDIR)/debian/tmp/usr/sbin/arc_summary'
+ mv '$(CURDIR)/debian/tmp/usr/bin/arcstat' '$(CURDIR)/debian/tmp/usr/sbin/arcstat'
+ mv '$(CURDIR)/debian/tmp/usr/bin/dbufstat' '$(CURDIR)/debian/tmp/usr/sbin/dbufstat'
+ mv '$(CURDIR)/debian/tmp/usr/bin/zilstat' '$(CURDIR)/debian/tmp/usr/sbin/zilstat'
+
+ @# Zed has dependencies outside of the system root.
+ mv '$(CURDIR)/debian/tmp/sbin/zed' '$(CURDIR)/debian/tmp/usr/sbin/zed'
+
+ @# Install the DKMS source.
+ @# We only want the files needed to build the modules
+ install -D -t '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/scripts' \
+ '$(CURDIR)/scripts/enum-extract.pl' \
+ '$(CURDIR)/scripts/dkms.postbuild'
+ $(foreach file,$(DKMSFILES),mv '$(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/$(file)' '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)' || exit 1;)
+
+ @# Only ever build Linux modules
+ echo 'SUBDIRS = linux' > '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/include/os/Makefile.am'
+
+ @# Hellish awk line:
+ @# * Deletes from configure.ac the parts not needed for building the kernel module
+ @# * It deletes from inside AC_CONFIG_FILES([]) everything except:
+ @# - Makefile$
+ @# - include/(Makefile|sys|os/(Makefile|linux))
+ @# - module/
+ @# - zfs.release$
+ @# * Takes care of spaces and tabs
+ @# * Remove reference to ZFS_AC_PACKAGE
+ awk '/^AC_CONFIG_FILES\(\[/,/^\]\)/ {\
+ if ($$0 !~ /^(AC_CONFIG_FILES\(\[([ \t]+)?$$|\]\)([ \t]+)?$$|([ \t]+)?(include\/(Makefile|sys|os\/(Makefile|linux))|module\/|Makefile([ \t]+)?$$|zfs\.release([ \t]+)?$$))/) \
+ {next} } {print}' \
+ '$(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/configure.ac' | sed '/ZFS_AC_PACKAGE/d' > '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/configure.ac'
+ @# Set "SUBDIRS = module include" for CONFIG_KERNEL and remove SUBDIRS for all other configs.
+ @# Do not regenerate zfs_gitrev.h during dkms build
+ sed '1,/CONFIG_KERNEL/s/SUBDIRS.*=.*//g;s/SUBDIRS.*=.*/SUBDIRS = module include/g;/make_gitrev.sh/d' \
+ '$(CURDIR)/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am' > '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am'
+ @# Sanity test
+ grep -q 'SUBDIRS = module include' '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am'
+ sed -i '/rpm.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/cmd.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/contrib.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/etc.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/lib.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/man.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/scripts.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/tests.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ sed -i '/udev.Makefile/d' $(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/Makefile.am
+ @# Run autogen on the stripped source tree
+ cd '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)'; ./autogen.sh
+ rm -fr '$(CURDIR)/debian/tmp/usr/src/$(NAME)-$(DEB_VERSION_UPSTREAM)/autom4te.cache'
+
+ for i in `ls $(CURDIR)/debian/tmp/lib/$(DEB_HOST_MULTIARCH)/*.so`; do \
+ ln -s '/lib/$(DEB_HOST_MULTIARCH)/'`readlink $${i}` '$(CURDIR)/debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/'`basename $${i}`; \
+ rm $${i}; \
+ done
+
+ chmod a-x '$(CURDIR)/debian/tmp/etc/zfs/zfs-functions'
+ chmod a-x '$(CURDIR)/debian/tmp/etc/default/zfs'
+
+override_dh_python3:
+ dh_python3 -p openzfs-python3-pyzfs
+
+override_dh_dkms:
+ '$(CURDIR)/scripts/dkms.mkconf' -n $(NAME) -v $(DEB_VERSION_UPSTREAM) -f '$(CURDIR)/scripts/zfs-dkms.dkms'
+ dh_dkms
+ rm -f '$(CURDIR)/scripts/zfs-dkms.dkms'
+
+override_dh_makeshlibs:
+ dh_makeshlibs -a -V
+
+override_dh_strip:
+ dh_strip
+
+override_dh_auto_clean:
+ rm -rf zfs-$(DEB_VERSION_UPSTREAM)
+ dh_auto_clean
+ @if test -e META.orig; then mv META.orig META; fi
+
+override_dh_install:
+ find debian/tmp/lib -name '*.la' -delete
+ dh_install
+
+override_dh_missing:
+ dh_missing --fail-missing
+
+override_dh_installinit:
+ dh_installinit -r --no-restart-after-upgrade --name zfs-import
+ dh_installinit -r --no-restart-after-upgrade --name zfs-mount
+ dh_installinit -r --no-restart-after-upgrade --name zfs-load-key
+ dh_installinit -R --name zfs-share
+ dh_installinit -R --name zfs-zed
+
+override_dh_installsystemd:
+ mkdir -p debian/openzfs-zfsutils/lib/systemd/system
+ ln -sr /dev/null debian/openzfs-zfsutils/lib/systemd/system/zfs-import.service
+ dh_installsystemd --no-stop-on-upgrade -X zfs-zed.service
+ dh_installsystemd --name zfs-zed
+
+override_dh_installdocs:
+ dh_installdocs -A
+ifeq (,$(findstring nodoc, $(DEB_BUILD_OPTIONS)))
+ http_proxy='127.0.0.1:9' sphinx-build -N -bhtml "$(CURDIR)/contrib/pyzfs/docs/source/" debian/openzfs-pyzfs-doc/usr/share/doc/openzfs-pyzfs-doc/html/
+endif
+
+# ------------
+
+override_dh_prep-deb-files:
+ for templ in $(wildcard $(CURDIR)/debian/*_KVERS_*.in); do \
+ sed -e 's/##KVERS##/$(KVERS)/g ; s/#KVERS#/$(KVERS)/g ; s/_KVERS_/$(KVERS)/g ; s/##KDREV##/$(KDREV)/g ; s/#KDREV#/$(KDREV)/g ; s/_KDREV_/$(KDREV)/g ; s/_ARCH_/$(DEB_HOST_ARCH)/' \
+ < $$templ > `echo $$templ | sed -e 's/_KVERS_/$(KVERS)/g ; s/_ARCH_/$(DEB_HOST_ARCH)/g ; s/\.in$$//'` ; \
+ done
+ sed -e 's/##KVERS##/$(KVERS)/g ; s/#KVERS#/$(KVERS)/g ; s/_KVERS_/$(KVERS)/g ; s/##KDREV##/$(KDREV)/g ; s/#KDREV#/$(KDREV)/g ; s/_KDREV_/$(KDREV)/g ; s/_ARCH_/$(DEB_HOST_ARCH)/g' \
+ < debian/control.modules.in > debian/control
+
+override_dh_configure_modules: override_dh_configure_modules_stamp
+override_dh_configure_modules_stamp:
+ ./configure @CFGOPTS@ \
+ --with-config=kernel \
+ --with-linux=$(KSRC) \
+ --with-linux-obj=$(KOBJ)
+ touch override_dh_configure_modules_stamp
+
+override_dh_binary-modules: override_dh_prep-deb-files override_dh_configure_modules
+ dh_testdir
+ dh_testroot
+ dh_prep
+
+ $(MAKE) $(NJOBS) -C $(CURDIR)/module modules
+
+ dh_install -p${pmodules}
+ dh_installdocs -p${pmodules}
+ dh_installchangelogs -p${pmodules}
+ dh_compress -p${pmodules}
+ dh_strip -p${pmodules}
+ dh_fixperms -p${pmodules}
+ dh_installdeb -p${pmodules}
+ dh_gencontrol -p${pmodules}
+ dh_md5sums -p${pmodules}
+ dh_builddeb -p${pmodules}
+
+debian-copyright:
+ cme update dpkg-copyright -file debian/copyright.cme
diff --git a/contrib/debian/source/format b/contrib/debian/source/format
new file mode 100644
index 000000000000..163aaf8d82b6
--- /dev/null
+++ b/contrib/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/conf.d/zfs b/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/conf.d/zfs
new file mode 100644
index 000000000000..5103cc450858
--- /dev/null
+++ b/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/conf.d/zfs
@@ -0,0 +1,8 @@
+for x in $(cat /proc/cmdline)
+do
+ case $x in
+ root=ZFS=*)
+ BOOT=zfs
+ ;;
+ esac
+done
diff --git a/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/hooks/zdev b/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/hooks/zdev
new file mode 100755
index 000000000000..0cf21a4211a8
--- /dev/null
+++ b/contrib/debian/tree/zfs-initramfs/usr/share/initramfs-tools/hooks/zdev
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# Add udev rules for ZoL to the initrd.
+#
+
+PREREQ="udev"
+PREREQ_UDEV_RULES="60-zvol.rules 69-vdev.rules"
+COPY_EXEC_LIST="/lib/udev/zvol_id /lib/udev/vdev_id"
+
+# Generic result code.
+RC=0
+
+case $1 in
+prereqs)
+ echo "$PREREQ"
+ exit 0
+ ;;
+esac
+
+for ii in $COPY_EXEC_LIST
+do
+ if [ ! -x "$ii" ]
+ then
+ echo "Error: $ii is not executable."
+ RC=2
+ fi
+done
+
+if [ "$RC" -ne 0 ]
+then
+ exit "$RC"
+fi
+
+. /usr/share/initramfs-tools/hook-functions
+
+mkdir -p "$DESTDIR/lib/udev/rules.d/"
+for ii in $PREREQ_UDEV_RULES
+do
+ if [ -e "/etc/udev/rules.d/$ii" ]
+ then
+ cp -p "/etc/udev/rules.d/$ii" "$DESTDIR/lib/udev/rules.d/"
+ elif [ -e "/lib/udev/rules.d/$ii" ]
+ then
+ cp -p "/lib/udev/rules.d/$ii" "$DESTDIR/lib/udev/rules.d/"
+ else
+ echo "Error: Missing udev rule: $ii"
+ echo " This file must be in the /etc/udev/rules.d or /lib/udev/rules.d directory."
+ exit 1
+ fi
+done
+
+for ii in $COPY_EXEC_LIST
+do
+ copy_exec "$ii"
+done
+
+if [ -f '/etc/default/zfs' -a -r '/etc/default/zfs' ]
+then
+ mkdir -p "$DESTDIR/etc/default"
+ cp -a '/etc/default/zfs' "$DESTDIR/etc/default/"
+fi
+
+if [ -d '/etc/zfs' -a -r '/etc/zfs' ]
+then
+ mkdir -p "$DESTDIR/etc"
+ cp -a '/etc/zfs' "$DESTDIR/etc/"
+fi
diff --git a/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
index df8df3181fce..b1f2d8f4c7b3 100755
--- a/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
+++ b/contrib/dracut/02zfsexpandknowledge/module-setup.sh.in
@@ -3,7 +3,7 @@
get_devtype() {
local typ
typ=$(udevadm info --query=property --name="$1" | sed -n 's|^ID_FS_TYPE=||p')
- if [ -z "$typ" ] ; then
+ if [[ -z "$typ" ]] ; then
typ=$(blkid -c /dev/null "$1" -o value -s TYPE)
fi
echo "$typ"
@@ -22,7 +22,7 @@ get_pool_devices() {
else
awk -F '\t' '/\t\/dev/ { print $2 }' "$poolconfigtemp" | \
while read -r pooldev ; do
- if [ -e "$pooldev" ] ; then
+ if [[ -e "$pooldev" ]] ; then
resolved="$(readlink -f "$pooldev")"
dinfo "zfsexpandknowledge: pool $1 has device $pooldev (which resolves to $resolved)"
echo "$resolved"
@@ -38,15 +38,15 @@ find_zfs_block_devices() {
local fstype
local _
numfields="$(awk '{print NF; exit}' /proc/self/mountinfo)"
- if [ "$numfields" = "10" ] ; then
+ if [[ "$numfields" = "10" ]] ; then
fields="_ _ _ _ mp _ _ fstype dev _"
else
fields="_ _ _ _ mp _ _ _ fstype dev _"
fi
# shellcheck disable=SC2086
while read -r ${fields?} ; do
- [ "$fstype" = "zfs" ] || continue
- [ "$mp" = "$1" ] && get_pool_devices "${dev%%/*}"
+ [[ "$fstype" = "zfs" ]] || continue
+ [[ "$mp" = "$1" ]] && get_pool_devices "${dev%%/*}"
done < /proc/self/mountinfo
}
@@ -73,7 +73,7 @@ check() {
local _depdevtype
# shellcheck disable=SC2154
-if [ -n "$hostonly" ]; then
+if [[ -n "$hostonly" ]]; then
for mp in \
"/" \
@@ -92,7 +92,7 @@ if [ -n "$hostonly" ]; then
mp=$(readlink -f "$mp")
mountpoint "$mp" >/dev/null 2>&1 || continue
blockdevs=$(find_zfs_block_devices "$mp")
- if [ -z "$blockdevs" ] ; then continue ; fi
+ if [[ -z "$blockdevs" ]] ; then continue ; fi
dinfo "zfsexpandknowledge: block devices backing ZFS dataset $mp: ${blockdevs//$'\n'/ }"
for dev in $blockdevs
do
@@ -100,9 +100,9 @@ if [ -n "$hostonly" ]; then
fstype=$(get_devtype "$dev")
host_fs_types["$dev"]="$fstype"
majmin=$(get_maj_min "$dev")
- if [ -d "/sys/dev/block/$majmin/slaves" ] ; then
+ if [[ -d "/sys/dev/block/$majmin/slaves" ]] ; then
for _depdev in "/sys/dev/block/$majmin/slaves"/*; do
- [ -f "$_depdev/dev" ] || continue
+ [[ -f "$_depdev/dev" ]] || continue
_depdev="/dev/${_depdev##*/}"
_depdevname=$(udevadm info --query=property --name="$_depdev" | sed -n 's|^DEVNAME=||p')
_depdevtype=$(get_devtype "$_depdevname")
diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in
index 81d7d2abe496..acad468edfd1 100755
--- a/contrib/dracut/90zfs/module-setup.sh.in
+++ b/contrib/dracut/90zfs/module-setup.sh.in
@@ -3,7 +3,7 @@
check() {
# We depend on udev-rules being loaded
- [ "${1}" = "-d" ] && return 0
+ [[ "${1}" = "-d" ]] && return 0
# Verify the zfs tool chain
for tool in "zgenhostid" "zpool" "zfs" "mount.zfs"; do
@@ -36,7 +36,7 @@ install() {
{ dfatal "Failed to install essential binaries"; exit 1; }
# Adapted from https://github.com/zbm-dev/zfsbootmenu
- if ! ldd "$(command -v zpool)" | grep -qF 'libgcc_s.so'; then
+ if ! ldd "$(command -v zpool)" | grep -qF 'libgcc_s.so' && ldconfig -p 2> /dev/null | grep -qF 'libc.so.6' ; then
# On systems with gcc-config (Gentoo, Funtoo, etc.), use it to find libgcc_s
if command -v gcc-config >/dev/null; then
inst_simple "/usr/lib/gcc/$(s=$(gcc-config -c); echo "${s%-*}/${s##*-}")/libgcc_s.so.1" ||
@@ -50,7 +50,7 @@ install() {
fi
inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
- if [ -n "${systemdutildir}" ]; then
+ if [[ -n "${systemdutildir}" ]]; then
inst_script "${moddir}/zfs-generator.sh" "${systemdutildir}/system-generators/dracut-zfs-generator"
fi
inst_hook pre-mount 90 "${moddir}/zfs-load-key.sh"
@@ -68,7 +68,7 @@ install() {
# Synchronize initramfs and system hostid
if ! inst_simple -H @sysconfdir@/hostid; then
- if HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then
+ if HOSTID="$(hostid 2>/dev/null)" && [[ "${HOSTID}" != "00000000" ]]; then
zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}"
mark_hostonly @sysconfdir@/hostid
fi
@@ -81,11 +81,33 @@ install() {
inst_simple "${moddir}/zfs-env-bootfs.service" "${systemdsystemunitdir}/zfs-env-bootfs.service"
systemctl -q --root "${initdir}" add-wants zfs-import.target zfs-env-bootfs.service
+ inst_simple "${moddir}/zfs-nonroot-necessities.service" "${systemdsystemunitdir}/zfs-nonroot-necessities.service"
+ systemctl -q --root "${initdir}" add-requires initrd-root-fs.target zfs-nonroot-necessities.service
+
+ # Add user-provided unit overrides:
+ # - /etc/systemd/system/${_service}
+ # - /etc/systemd/system/${_service}.d/overrides.conf
+ # -H ensures they are marked host-only
+ # -o ensures there is no error upon absence of these files
+ inst_multiple -o -H \
+ "${systemdsystemconfdir}/zfs-import.target" \
+ "${systemdsystemconfdir}/zfs-import.target.d/"*.conf
+
for _service in \
"zfs-import-scan.service" \
"zfs-import-cache.service"; do
inst_simple "${systemdsystemunitdir}/${_service}"
systemctl -q --root "${initdir}" add-wants zfs-import.target "${_service}"
+
+ # Add user-provided unit overrides:
+ # - /etc/systemd/system/${_service}
+ # - /etc/systemd/system/${_service}.d/overrides.conf
+ # -H ensures they are marked host-only
+ # -o ensures there is no error upon absence of these files
+ inst_multiple -o -H \
+ "${systemdsystemconfdir}/${_service}" \
+ "${systemdsystemconfdir}/${_service}.d/"*.conf
+
done
for _service in \
@@ -93,6 +115,15 @@ install() {
"zfs-rollback-bootfs.service"; do
inst_simple "${moddir}/${_service}" "${systemdsystemunitdir}/${_service}"
systemctl -q --root "${initdir}" add-wants initrd.target "${_service}"
+
+ # Add user-provided unit overrides:
+ # - /etc/systemd/system/${_service}
+ # - /etc/systemd/system/${_service}.d/overrides.conf
+ # -H ensures they are marked host-only
+ # -o ensures there is no error upon absence of these files
+ inst_multiple -o -H \
+ "${systemdsystemconfdir}/${_service}" \
+ "${systemdsystemconfdir}/${_service}.d/"*.conf
done
inst_simple "${moddir}/import-opts-generator.sh" "${systemdutildir}/system-environment-generators/zfs-import-opts.sh"
diff --git a/contrib/dracut/90zfs/zfs-env-bootfs.service.in b/contrib/dracut/90zfs/zfs-env-bootfs.service.in
index 34c88037cac2..fe362b930bf5 100644
--- a/contrib/dracut/90zfs/zfs-env-bootfs.service.in
+++ b/contrib/dracut/90zfs/zfs-env-bootfs.service.in
@@ -1,6 +1,5 @@
[Unit]
-Description=Set BOOTFS environment for dracut
-Documentation=man:zpool(8)
+Description=Set BOOTFS and BOOTFSFLAGS environment variables for dracut
DefaultDependencies=no
After=zfs-import-cache.service
After=zfs-import-scan.service
@@ -8,7 +7,18 @@ Before=zfs-import.target
[Service]
Type=oneshot
-ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"
+ExecStart=/bin/sh -c ' \
+ . /lib/dracut-zfs-lib.sh; \
+ decode_root_args || exit 0; \
+ [ "$root" = "zfs:AUTO" ] && root="$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"; \
+ rootflags="$(getarg rootflags=)"; \
+ [ "$(@sbindir@/zfs get -H -o value mountpoint "$root")" = legacy ] || \
+ case ",$rootflags," in \
+ *,zfsutil,*) ;; \
+ ,,) rootflags=zfsutil ;; \
+ *) rootflags="zfsutil,$rootflags" ;; \
+ esac; \
+ exec systemctl set-environment BOOTFS="$root" BOOTFSFLAGS="$rootflags"'
[Install]
WantedBy=zfs-import.target
diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in
index 56f7ca9785ba..4e1eb7490e0d 100755
--- a/contrib/dracut/90zfs/zfs-generator.sh.in
+++ b/contrib/dracut/90zfs/zfs-generator.sh.in
@@ -14,81 +14,24 @@ GENERATOR_DIR="$1"
. /lib/dracut-zfs-lib.sh
decode_root_args || exit 0
-[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=)
-case ",${rootflags}," in
- *,zfsutil,*) ;;
- ,,) rootflags=zfsutil ;;
- *) rootflags="zfsutil,${rootflags}" ;;
-esac
-
[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
-mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/initrd-root-fs.target.requires "$GENERATOR_DIR"/dracut-pre-mount.service.d
+mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/dracut-pre-mount.service.d
+
{
echo "[Unit]"
echo "Before=initrd-root-fs.target"
echo "After=zfs-import.target"
echo
echo "[Mount]"
- if [ "${root}" = "zfs:AUTO" ]; then
- echo "PassEnvironment=BOOTFS"
- echo 'What=${BOOTFS}'
- else
- echo "What=${root}"
- fi
+ echo "PassEnvironment=BOOTFS BOOTFSFLAGS"
+ echo 'What=${BOOTFS}'
echo "Type=zfs"
- echo "Options=${rootflags}"
+ echo 'Options=${BOOTFSFLAGS}'
} > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf
ln -fs ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
-
-if [ "${root}" = "zfs:AUTO" ]; then
- {
- echo "[Unit]"
- echo "Before=initrd-root-fs.target"
- echo "After=sysroot.mount"
- echo "DefaultDependencies=no"
- echo
- echo "[Service]"
- echo "Type=oneshot"
- echo "PassEnvironment=BOOTFS"
- echo "ExecStart=/bin/sh -c '" ' \
- . /lib/dracut-zfs-lib.sh; \
- _zfs_nonroot_necessities_cb() { \
- zfs mount | grep -m1 -q "^$1 " && return 0; \
- echo "Mounting $1 on /sysroot$2"; \
- mount -o zfsutil -t zfs "$1" "/sysroot$2"; \
- }; \
- for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb;' \
- "'"
- } > "$GENERATOR_DIR"/zfs-nonroot-necessities.service
- ln -fs ../zfs-nonroot-necessities.service "$GENERATOR_DIR"/initrd-root-fs.target.requires/zfs-nonroot-necessities.service
-else
- # We can solve this statically at generation time, so do!
- _zfs_generator_cb() {
- dset="${1}"
- mpnt="${2}"
- unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")"
-
- {
- echo "[Unit]"
- echo "Before=initrd-root-fs.target"
- echo "After=sysroot.mount"
- echo
- echo "[Mount]"
- echo "Where=/sysroot${mpnt}"
- echo "What=${dset}"
- echo "Type=zfs"
- echo "Options=zfsutil"
- } > "$GENERATOR_DIR/${unit}"
- ln -fs ../"${unit}" "$GENERATOR_DIR"/initrd-root-fs.target.requires/"${unit}"
- }
-
- for_relevant_root_children "${root}" _zfs_generator_cb
-fi
-
-
{
echo "[Unit]"
echo "After=zfs-import.target"
diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in
index 3a43e514d6f9..7139e2e6fe4b 100755
--- a/contrib/dracut/90zfs/zfs-lib.sh.in
+++ b/contrib/dracut/90zfs/zfs-lib.sh.in
@@ -39,7 +39,7 @@ mount_dataset() {
# for_relevant_root_children DATASET EXEC
# Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup
-# Used by zfs-generator.sh and friends, too!
+# Used by zfs-nonroot-necessities.service and friends, too!
for_relevant_root_children() {
dataset="${1}"
exec="${2}"
diff --git a/contrib/dracut/90zfs/zfs-load-key.sh.in b/contrib/dracut/90zfs/zfs-load-key.sh.in
index d916f43b4e95..8e6846831e6f 100755
--- a/contrib/dracut/90zfs/zfs-load-key.sh.in
+++ b/contrib/dracut/90zfs/zfs-load-key.sh.in
@@ -34,7 +34,7 @@ _load_key_cb() {
case "${KEYLOCATION%%://*}" in
prompt)
for _ in 1 2 3; do
- systemd-ask-password --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break
+ systemd-ask-password --timeout=0 --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break
done
;;
http*)
diff --git a/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in b/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in
new file mode 100644
index 000000000000..8f420c737c72
--- /dev/null
+++ b/contrib/dracut/90zfs/zfs-nonroot-necessities.service.in
@@ -0,0 +1,20 @@
+[Unit]
+Before=initrd-root-fs.target
+After=sysroot.mount
+DefaultDependencies=no
+ConditionEnvironment=BOOTFS
+
+[Service]
+Type=oneshot
+PassEnvironment=BOOTFS
+ExecStart=/bin/sh -c ' \
+ . /lib/dracut-zfs-lib.sh; \
+ _zfs_nonroot_necessities_cb() { \
+ @sbindir@/zfs mount | grep -m1 -q "^$1 " && return 0; \
+ echo "Mounting $1 on /sysroot$2"; \
+ mount -o zfsutil -t zfs "$1" "/sysroot$2"; \
+ }; \
+ for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb'
+
+[Install]
+RequiredBy=initrd-root-fs.target
diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
index a29cf3a3dd81..12d8ac703e37 100644
--- a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
+++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
@@ -2,11 +2,12 @@
Description=Rollback bootfs just before it is mounted
Requisite=zfs-import.target
After=zfs-import.target dracut-pre-mount.service zfs-snapshot-bootfs.service
-Before=dracut-mount.service
+Before=dracut-mount.service sysroot.mount
DefaultDependencies=no
ConditionKernelCommandLine=bootfs.rollback
+ConditionEnvironment=BOOTFS
[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-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$BOOTFS@${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 befd163b6536..a675b5b2ea98 100644
--- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in
+++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in
@@ -5,8 +5,9 @@ After=zfs-import.target dracut-pre-mount.service
Before=dracut-mount.service
DefaultDependencies=no
ConditionKernelCommandLine=bootfs.snapshot
+ConditionEnvironment=BOOTFS
[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-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$BOOTFS@${SNAPNAME:-%v}"'
RemainAfterExit=yes
diff --git a/contrib/dracut/Makefile.am b/contrib/dracut/Makefile.am
index 73ca52b66316..b432ab76a6d8 100644
--- a/contrib/dracut/Makefile.am
+++ b/contrib/dracut/Makefile.am
@@ -16,6 +16,7 @@ pkgdracut_90_SCRIPTS = \
pkgdracut_90_DATA = \
%D%/90zfs/zfs-env-bootfs.service \
+ %D%/90zfs/zfs-nonroot-necessities.service \
%D%/90zfs/zfs-rollback-bootfs.service \
%D%/90zfs/zfs-snapshot-bootfs.service
diff --git a/contrib/initramfs/README.md b/contrib/initramfs/README.md
index 34e9bab3c756..68647fa9fc3d 100644
--- a/contrib/initramfs/README.md
+++ b/contrib/initramfs/README.md
@@ -78,7 +78,30 @@ To use this feature:
1. Install the `dropbear-initramfs` package. You may wish to uninstall the
`cryptsetup-initramfs` package to avoid warnings.
2. Add your SSH key(s) to `/etc/dropbear-initramfs/authorized_keys`. Note
- that Dropbear does not support ed25519 keys before version 2020.79;
+ that Dropbear does not support ed25519 keys before version 2020.79;
in that case, use RSA (2048-bit or more) instead.
3. Rebuild the initramfs with your keys: `update-initramfs -u`
4. During the system boot, login via SSH and run: `zfsunlock`
+
+### Unlocking a ZFS encrypted root via alternate means
+
+If present, a shell program at `/etc/zfs/initramfs-tools-load-key`
+and files matching `/etc/zfs/initramfs-tools-load-key.d/*`
+will be copied to the initramfs during generation
+and sourced to load the key, if required.
+
+The `$ENCRYPTIONROOT` to load the key for and `$KEYLOCATION` variables are set,
+and all initramfs-tools functions are available;
+use unquoted `$ZPOOL` and `$ZFS` to run `zpool` and `zfs`.
+
+A successful return (and loaded key) stops the search.
+A failure return is non-fatal,
+and loading keys proceeds as normal if no hook succeeds.
+
+A trivial example of a key-loading drop-in that uses the BLAKE2 checksum
+of the file at the `keylocation` as the key follows.
+
+```sh
+key="$(b2sum "${KEYLOCATION#file://}")" || return
+printf '%s\n' "${key%% *}" | $ZFS load-key -L prompt "$ENCRYPTIONROOT"
+```
diff --git a/contrib/initramfs/hooks/zfs.in b/contrib/initramfs/hooks/zfs.in
index 28dd252eea52..6cd7e6f1ea3b 100755
--- a/contrib/initramfs/hooks/zfs.in
+++ b/contrib/initramfs/hooks/zfs.in
@@ -41,6 +41,9 @@ copy_file cache "@sysconfdir@/zfs/zpool.cache"
copy_file config "@initconfdir@/zfs"
copy_file config "@sysconfdir@/zfs/zfs-functions"
copy_file config "@sysconfdir@/zfs/vdev_id.conf"
+for f in "@sysconfdir@/zfs/initramfs-tools-load-key" "@sysconfdir@/zfs/initramfs-tools-load-key.d/"*; do
+ copy_file config "$f"
+done
copy_file rule "@udevruledir@/60-zvol.rules"
copy_file rule "@udevruledir@/69-vdev.rules"
diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs
index 1c8c496a7ff4..0a2bd2efda7a 100644
--- a/contrib/initramfs/scripts/zfs
+++ b/contrib/initramfs/scripts/zfs
@@ -194,7 +194,7 @@ import_pool()
# Verify that the pool isn't already imported
# Make as sure as we can to not require '-f' to import.
- "${ZPOOL}" get name,guid -o value -H 2>/dev/null | grep -Fxq "$pool" && return 0
+ "${ZPOOL}" get -H -o value name,guid 2>/dev/null | grep -Fxq "$pool" && return 0
# For backwards compatibility, make sure that ZPOOL_IMPORT_PATH is set
# to something we can use later with the real import(s). We want to
@@ -272,30 +272,46 @@ import_pool()
# with more logging etc.
load_module_initrd()
{
- [ -n "$ROOTDELAY" ] && ZFS_INITRD_PRE_MOUNTROOT_SLEEP="$ROOTDELAY"
+ ZFS_INITRD_PRE_MOUNTROOT_SLEEP=${ROOTDELAY:-0}
- if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ] 2>/dev/null
- then
- if [ "$quiet" != "y" ]; then
- zfs_log_begin_msg "Sleeping for" \
- "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP seconds..."
- fi
- sleep "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP"
- [ "$quiet" != "y" ] && zfs_log_end_msg
+ if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ]; then
+ [ "$quiet" != "y" ] && zfs_log_begin_msg "Delaying for up to '${ZFS_INITRD_PRE_MOUNTROOT_SLEEP}' seconds."
fi
- # Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
- if command -v wait_for_udev > /dev/null 2>&1 ; then
- wait_for_udev 10
- elif command -v wait_for_dev > /dev/null 2>&1 ; then
- wait_for_dev
- fi
+ START=$(/bin/date -u +%s)
+ END=$((START+ZFS_INITRD_PRE_MOUNTROOT_SLEEP))
+ while true; do
- # zpool import refuse to import without a valid /proc/self/mounts
- [ ! -f /proc/self/mounts ] && mount proc /proc
+ # Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
+ if command -v wait_for_udev > /dev/null 2>&1 ; then
+ wait_for_udev 10
+ elif command -v wait_for_dev > /dev/null 2>&1 ; then
+ wait_for_dev
+ fi
+
+ #
+ # zpool import refuse to import without a valid
+ # /proc/self/mounts
+ #
+ [ ! -f /proc/self/mounts ] && mount proc /proc
+
+ # Load the module
+ if load_module "zfs"; then
+ ret=0
+ break
+ else
+ ret=1
+ fi
- # Load the module
- load_module "zfs" || return 1
+ [ "$(/bin/date -u +%s)" -gt "$END" ] && break
+ sleep 1
+
+ done
+ if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ]; then
+ [ "$quiet" != "y" ] && zfs_log_end_msg
+ fi
+
+ [ "$ret" -ne 0 ] && return 1
if [ "$ZFS_INITRD_POST_MODPROBE_SLEEP" -gt 0 ] 2>/dev/null
then
@@ -328,30 +344,29 @@ mount_fs()
# Need the _original_ datasets mountpoint!
mountpoint=$(get_fs_value "$fs" mountpoint)
- ZFS_CMD="mount.zfs -o zfsutil"
+ ZFS_CMD="mount -o zfsutil -t zfs"
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
# clone_snap() if that's usable.
- mountpoint=$(get_fs_value "$fs" org.zol:mountpoint)
- if [ "$mountpoint" = "legacy" ] ||
- [ "$mountpoint" = "none" ] ||
- [ "$mountpoint" = "-" ]
+ mountpoint1=$(get_fs_value "$fs" org.zol:mountpoint)
+ if [ "$mountpoint1" = "legacy" ] ||
+ [ "$mountpoint1" = "none" ] ||
+ [ "$mountpoint1" = "-" ]
then
if [ "$fs" != "${ZFS_BOOTFS}" ]; then
# We don't have a proper mountpoint and this
# isn't the root fs.
return 0
- else
- # Last hail-mary: Hope 'rootmnt' is set!
- mountpoint=""
fi
- fi
-
- # If it's not a legacy filesystem, it can only be a
- # native one...
- if [ "$mountpoint" = "legacy" ]; then
- ZFS_CMD="mount.zfs"
+ # Don't use mount.zfs -o zfsutils for legacy mountpoint
+ if [ "$mountpoint" = "legacy" ]; then
+ ZFS_CMD="mount -t zfs"
+ fi
+ # Last hail-mary: Hope 'rootmnt' is set!
+ mountpoint=""
+ else
+ mountpoint="$mountpoint1"
fi
fi
@@ -405,6 +420,16 @@ decrypt_fs()
# Continue only if the key needs to be loaded
[ "$KEYSTATUS" = "unavailable" ] || return 0
+ # Try extensions first
+ for f in "/etc/zfs/initramfs-tools-load-key" "/etc/zfs/initramfs-tools-load-key.d/"*; do
+ [ -r "$f" ] || continue
+ (. "$f") && {
+ # Successful return and actually-loaded key: we're done
+ KEYSTATUS="$(get_fs_value "${ENCRYPTIONROOT}" keystatus)"
+ [ "$KEYSTATUS" = "unavailable" ] || return 0
+ }
+ done
+
# Do not prompt if key is stored noninteractively,
if ! [ "${KEYLOCATION}" = "prompt" ]; then
$ZFS load-key "${ENCRYPTIONROOT}"
@@ -505,7 +530,7 @@ clone_snap()
echo "Error: $ZFS_ERROR"
echo ""
echo "Failed to clone snapshot."
- echo "Make sure that the any problems are corrected and then make sure"
+ echo "Make sure that any problems are corrected and then make sure"
echo "that the dataset '$destfs' exists and is bootable."
shell
else
@@ -640,8 +665,8 @@ setup_snapshot_booting()
# rpool/ROOT/debian/boot@snap2 => rpool/ROOT/debian_snap2/boot
# rpool/ROOT/debian/usr@snap2 => rpool/ROOT/debian_snap2/usr
# rpool/ROOT/debian/var@snap2 => rpool/ROOT/debian_snap2/var
- subfs="${s##$rootfs}"
- subfs="${subfs%%@$snapname}"
+ subfs="${s##"$rootfs"}"
+ subfs="${subfs%%@"$snapname"}"
destfs="${rootfs}_${snapname}" # base fs.
[ -n "$subfs" ] && destfs="${destfs}$subfs" # + sub fs.
@@ -888,12 +913,12 @@ mountroot()
fi
# In case the pool was specified as guid, resolve guid to name
- pool="$("${ZPOOL}" get name,guid -o name,value -H | \
+ pool="$("${ZPOOL}" get -H -o name,value name,guid | \
awk -v pool="${ZFS_RPOOL}" '$2 == pool { print $1 }')"
if [ -n "$pool" ]; then
# If $ZFS_BOOTFS contains guid, replace the guid portion with $pool
ZFS_BOOTFS=$(echo "$ZFS_BOOTFS" | \
- sed -e "s/$("${ZPOOL}" get guid -o value "$pool" -H)/$pool/g")
+ sed -e "s/$("${ZPOOL}" get -H -o value guid "$pool")/$pool/g")
ZFS_RPOOL="${pool}"
fi
@@ -919,7 +944,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.zfs -o zfsutil ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt"
+ echo "Hint: Try: mount -o zfsutil -t zfs ${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 6f95d468074f..08a8640669b3 100644
--- a/contrib/pam_zfs_key/pam_zfs_key.c
+++ b/contrib/pam_zfs_key/pam_zfs_key.c
@@ -67,6 +67,7 @@ pam_syslog(pam_handle_t *pamh, int loglevel, const char *fmt, ...)
#include <sys/mman.h>
static const char PASSWORD_VAR_NAME[] = "pam_zfs_key_authtok";
+static const char OLD_PASSWORD_VAR_NAME[] = "pam_zfs_key_oldauthtok";
static libzfs_handle_t *g_zfs;
@@ -160,10 +161,10 @@ pw_free(pw_password_t *pw)
}
static pw_password_t *
-pw_fetch(pam_handle_t *pamh)
+pw_fetch(pam_handle_t *pamh, int tok)
{
const char *token;
- if (pam_get_authtok(pamh, PAM_AUTHTOK, &token, NULL) != PAM_SUCCESS) {
+ if (pam_get_authtok(pamh, tok, &token, NULL) != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR,
"couldn't get password from PAM stack");
return (NULL);
@@ -177,13 +178,13 @@ pw_fetch(pam_handle_t *pamh)
}
static const pw_password_t *
-pw_fetch_lazy(pam_handle_t *pamh)
+pw_fetch_lazy(pam_handle_t *pamh, int tok, const char *var_name)
{
- pw_password_t *pw = pw_fetch(pamh);
+ pw_password_t *pw = pw_fetch(pamh, tok);
if (pw == NULL) {
return (NULL);
}
- int ret = pam_set_data(pamh, PASSWORD_VAR_NAME, pw, destroy_pw);
+ int ret = pam_set_data(pamh, var_name, pw, destroy_pw);
if (ret != PAM_SUCCESS) {
pw_free(pw);
pam_syslog(pamh, LOG_ERR, "pam_set_data failed");
@@ -193,23 +194,23 @@ pw_fetch_lazy(pam_handle_t *pamh)
}
static const pw_password_t *
-pw_get(pam_handle_t *pamh)
+pw_get(pam_handle_t *pamh, int tok, const char *var_name)
{
const pw_password_t *authtok = NULL;
- int ret = pam_get_data(pamh, PASSWORD_VAR_NAME,
+ int ret = pam_get_data(pamh, var_name,
(const void**)(&authtok));
if (ret == PAM_SUCCESS)
return (authtok);
if (ret == PAM_NO_MODULE_DATA)
- return (pw_fetch_lazy(pamh));
+ return (pw_fetch_lazy(pamh, tok, var_name));
pam_syslog(pamh, LOG_ERR, "password not available");
return (NULL);
}
static int
-pw_clear(pam_handle_t *pamh)
+pw_clear(pam_handle_t *pamh, const char *var_name)
{
- int ret = pam_set_data(pamh, PASSWORD_VAR_NAME, NULL, NULL);
+ int ret = pam_set_data(pamh, var_name, NULL, NULL);
if (ret != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR, "clearing password failed");
return (-1);
@@ -371,7 +372,7 @@ change_key(pam_handle_t *pamh, const char *ds_name,
static int
decrypt_mount(pam_handle_t *pamh, const char *ds_name,
- const char *passphrase)
+ const char *passphrase, boolean_t noop)
{
zfs_handle_t *ds = zfs_open(g_zfs, ds_name, ZFS_TYPE_FILESYSTEM);
if (ds == NULL) {
@@ -383,33 +384,37 @@ decrypt_mount(pam_handle_t *pamh, const char *ds_name,
zfs_close(ds);
return (-1);
}
- int ret = lzc_load_key(ds_name, B_FALSE, (uint8_t *)key->value,
+ int ret = lzc_load_key(ds_name, noop, (uint8_t *)key->value,
WRAPPING_KEY_LEN);
pw_free(key);
- if (ret) {
+ if (ret && ret != EEXIST) {
pam_syslog(pamh, LOG_ERR, "load_key failed: %d", ret);
zfs_close(ds);
return (-1);
}
+ if (noop) {
+ goto out;
+ }
ret = zfs_mount(ds, NULL, 0);
if (ret) {
pam_syslog(pamh, LOG_ERR, "mount failed: %d", ret);
zfs_close(ds);
return (-1);
}
+out:
zfs_close(ds);
return (0);
}
static int
-unmount_unload(pam_handle_t *pamh, const char *ds_name)
+unmount_unload(pam_handle_t *pamh, const char *ds_name, boolean_t force)
{
zfs_handle_t *ds = zfs_open(g_zfs, ds_name, ZFS_TYPE_FILESYSTEM);
if (ds == NULL) {
pam_syslog(pamh, LOG_ERR, "dataset %s not found", ds_name);
return (-1);
}
- int ret = zfs_unmount(ds, NULL, 0);
+ int ret = zfs_unmount(ds, NULL, force ? MS_FORCE : 0);
if (ret) {
pam_syslog(pamh, LOG_ERR, "zfs_unmount failed with: %d", ret);
zfs_close(ds);
@@ -431,9 +436,13 @@ typedef struct {
char *runstatedir;
char *homedir;
char *dsname;
+ uid_t uid_min;
+ uid_t uid_max;
uid_t uid;
const char *username;
- int unmount_and_unload;
+ boolean_t unmount_and_unload;
+ boolean_t force_unmount;
+ boolean_t recursive_homes;
} zfs_key_config_t;
static int
@@ -443,13 +452,13 @@ zfs_key_config_load(pam_handle_t *pamh, zfs_key_config_t *config,
config->homes_prefix = strdup("rpool/home");
if (config->homes_prefix == NULL) {
pam_syslog(pamh, LOG_ERR, "strdup failure");
- return (-1);
+ return (PAM_SERVICE_ERR);
}
config->runstatedir = strdup(RUNSTATEDIR "/pam_zfs_key");
if (config->runstatedir == NULL) {
pam_syslog(pamh, LOG_ERR, "strdup failure");
free(config->homes_prefix);
- return (-1);
+ return (PAM_SERVICE_ERR);
}
const char *name;
if (pam_get_user(pamh, &name, NULL) != PAM_SUCCESS) {
@@ -457,17 +466,21 @@ zfs_key_config_load(pam_handle_t *pamh, zfs_key_config_t *config,
"couldn't get username from PAM stack");
free(config->runstatedir);
free(config->homes_prefix);
- return (-1);
+ return (PAM_SERVICE_ERR);
}
struct passwd *entry = getpwnam(name);
if (!entry) {
free(config->runstatedir);
free(config->homes_prefix);
- return (-1);
+ return (PAM_USER_UNKNOWN);
}
+ config->uid_min = 1000;
+ config->uid_max = MAXUID;
config->uid = entry->pw_uid;
config->username = name;
- config->unmount_and_unload = 1;
+ config->unmount_and_unload = B_TRUE;
+ config->force_unmount = B_FALSE;
+ config->recursive_homes = B_FALSE;
config->dsname = NULL;
config->homedir = NULL;
for (int c = 0; c < argc; c++) {
@@ -477,13 +490,22 @@ zfs_key_config_load(pam_handle_t *pamh, zfs_key_config_t *config,
} else if (strncmp(argv[c], "runstatedir=", 12) == 0) {
free(config->runstatedir);
config->runstatedir = strdup(argv[c] + 12);
+ } else if (strncmp(argv[c], "uid_min=", 8) == 0) {
+ sscanf(argv[c] + 8, "%u", &config->uid_min);
+ } else if (strncmp(argv[c], "uid_max=", 8) == 0) {
+ sscanf(argv[c] + 8, "%u", &config->uid_max);
} else if (strcmp(argv[c], "nounmount") == 0) {
- config->unmount_and_unload = 0;
+ config->unmount_and_unload = B_FALSE;
+ } else if (strcmp(argv[c], "forceunmount") == 0) {
+ config->force_unmount = B_TRUE;
+ } else if (strcmp(argv[c], "recursive_homes") == 0) {
+ config->recursive_homes = B_TRUE;
} else if (strcmp(argv[c], "prop_mountpoint") == 0) {
- config->homedir = strdup(entry->pw_dir);
+ if (config->homedir == NULL)
+ config->homedir = strdup(entry->pw_dir);
}
}
- return (0);
+ return (PAM_SUCCESS);
}
static void
@@ -512,8 +534,12 @@ find_dsname_by_prop_value(zfs_handle_t *zhp, void *data)
(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
if (strcmp(target->homedir, mountpoint) != 0) {
+ if (target->recursive_homes) {
+ (void) zfs_iter_filesystems_v2(zhp, 0,
+ find_dsname_by_prop_value, target);
+ }
zfs_close(zhp);
- return (0);
+ return (target->dsname != NULL);
}
target->dsname = strdup(zfs_get_name(zhp));
@@ -526,23 +552,32 @@ zfs_key_config_get_dataset(zfs_key_config_t *config)
{
if (config->homedir != NULL &&
config->homes_prefix != NULL) {
- zfs_handle_t *zhp = zfs_open(g_zfs, config->homes_prefix,
- ZFS_TYPE_FILESYSTEM);
- if (zhp == NULL) {
- pam_syslog(NULL, LOG_ERR, "dataset %s not found",
- config->homes_prefix);
+ if (strcmp(config->homes_prefix, "*") == 0) {
+ (void) zfs_iter_root(g_zfs,
+ find_dsname_by_prop_value, config);
+ } else {
+ zfs_handle_t *zhp = zfs_open(g_zfs,
+ config->homes_prefix, ZFS_TYPE_FILESYSTEM);
+ if (zhp == NULL) {
+ pam_syslog(NULL, LOG_ERR,
+ "dataset %s not found",
+ config->homes_prefix);
+ return (NULL);
+ }
+
+ (void) zfs_iter_filesystems_v2(zhp, 0,
+ find_dsname_by_prop_value, config);
zfs_close(zhp);
- return (NULL);
}
-
- (void) zfs_iter_filesystems(zhp, find_dsname_by_prop_value,
- config);
- zfs_close(zhp);
char *dsname = config->dsname;
config->dsname = NULL;
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);
@@ -554,9 +589,8 @@ zfs_key_config_get_dataset(zfs_key_config_t *config)
return (NULL);
}
ret[0] = 0;
- strcat(ret, config->homes_prefix);
- strcat(ret, "/");
- strcat(ret, config->username);
+ (void) snprintf(ret, len + 1, "%s/%s", config->homes_prefix,
+ config->username);
return (ret);
}
@@ -580,16 +614,11 @@ zfs_key_config_modify_session_counter(pam_handle_t *pamh,
errno);
return (-1);
}
- size_t runtime_path_len = strlen(runtime_path);
- size_t counter_path_len = runtime_path_len + 1 + 10;
- char *counter_path = malloc(counter_path_len + 1);
- if (!counter_path) {
+
+ char *counter_path;
+ if (asprintf(&counter_path, "%s/%u", runtime_path, config->uid) == -1)
return (-1);
- }
- counter_path[0] = 0;
- strcat(counter_path, runtime_path);
- snprintf(counter_path + runtime_path_len, counter_path_len, "/%d",
- config->uid);
+
const int fd = open(counter_path,
O_RDWR | O_CLOEXEC | O_CREAT | O_NOFOLLOW,
S_IRUSR | S_IWUSR);
@@ -641,12 +670,48 @@ PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- (void) flags, (void) argc, (void) argv;
+ (void) flags;
- if (pw_fetch_lazy(pamh) == NULL) {
- return (PAM_AUTH_ERR);
+ if (geteuid() != 0) {
+ pam_syslog(pamh, LOG_ERR,
+ "Cannot zfs_mount when not being root.");
+ return (PAM_SERVICE_ERR);
+ }
+ zfs_key_config_t config;
+ int config_err = zfs_key_config_load(pamh, &config, argc, argv);
+ if (config_err != PAM_SUCCESS) {
+ return (config_err);
+ }
+ if (config.uid < config.uid_min || config.uid > config.uid_max) {
+ zfs_key_config_free(&config);
+ return (PAM_SERVICE_ERR);
}
+ const pw_password_t *token = pw_fetch_lazy(pamh,
+ PAM_AUTHTOK, PASSWORD_VAR_NAME);
+ if (token == NULL) {
+ zfs_key_config_free(&config);
+ return (PAM_AUTH_ERR);
+ }
+ if (pam_zfs_init(pamh) != 0) {
+ zfs_key_config_free(&config);
+ return (PAM_SERVICE_ERR);
+ }
+ char *dataset = zfs_key_config_get_dataset(&config);
+ if (!dataset) {
+ pam_zfs_free();
+ zfs_key_config_free(&config);
+ return (PAM_SERVICE_ERR);
+ }
+ if (decrypt_mount(pamh, dataset, token->value, B_TRUE) == -1) {
+ free(dataset);
+ pam_zfs_free();
+ zfs_key_config_free(&config);
+ return (PAM_AUTH_ERR);
+ }
+ free(dataset);
+ pam_zfs_free();
+ zfs_key_config_free(&config);
return (PAM_SUCCESS);
}
@@ -670,13 +735,15 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
return (PAM_PERM_DENIED);
}
zfs_key_config_t config;
- if (zfs_key_config_load(pamh, &config, argc, argv) == -1) {
+ if (zfs_key_config_load(pamh, &config, argc, argv) != PAM_SUCCESS) {
return (PAM_SERVICE_ERR);
}
- if (config.uid < 1000) {
+ if (config.uid < config.uid_min || config.uid > config.uid_max) {
zfs_key_config_free(&config);
- return (PAM_SUCCESS);
+ return (PAM_SERVICE_ERR);
}
+ const pw_password_t *old_token = pw_get(pamh,
+ PAM_OLDAUTHTOK, OLD_PASSWORD_VAR_NAME);
{
if (pam_zfs_init(pamh) != 0) {
zfs_key_config_free(&config);
@@ -688,49 +755,62 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
zfs_key_config_free(&config);
return (PAM_SERVICE_ERR);
}
- int key_loaded = is_key_loaded(pamh, dataset);
- if (key_loaded == -1) {
+ if (!old_token) {
+ pam_syslog(pamh, LOG_ERR,
+ "old password from PAM stack is null");
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
return (PAM_SERVICE_ERR);
}
- free(dataset);
- pam_zfs_free();
- if (! key_loaded) {
+ if (decrypt_mount(pamh, dataset,
+ old_token->value, B_TRUE) == -1) {
pam_syslog(pamh, LOG_ERR,
- "key not loaded, returning try_again");
+ "old token mismatch");
+ free(dataset);
+ pam_zfs_free();
zfs_key_config_free(&config);
return (PAM_PERM_DENIED);
}
}
if ((flags & PAM_UPDATE_AUTHTOK) != 0) {
- const pw_password_t *token = pw_get(pamh);
+ const pw_password_t *token = pw_get(pamh, PAM_AUTHTOK,
+ PASSWORD_VAR_NAME);
if (token == NULL) {
+ pam_syslog(pamh, LOG_ERR, "new password unavailable");
+ pam_zfs_free();
zfs_key_config_free(&config);
- return (PAM_SERVICE_ERR);
- }
- if (pam_zfs_init(pamh) != 0) {
- zfs_key_config_free(&config);
+ pw_clear(pamh, OLD_PASSWORD_VAR_NAME);
return (PAM_SERVICE_ERR);
}
char *dataset = zfs_key_config_get_dataset(&config);
if (!dataset) {
pam_zfs_free();
zfs_key_config_free(&config);
+ pw_clear(pamh, OLD_PASSWORD_VAR_NAME);
+ pw_clear(pamh, PASSWORD_VAR_NAME);
return (PAM_SERVICE_ERR);
}
- if (change_key(pamh, dataset, token->value) == -1) {
+ int was_loaded = is_key_loaded(pamh, dataset);
+ if (!was_loaded && decrypt_mount(pamh, dataset,
+ old_token->value, B_FALSE) == -1) {
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
+ pw_clear(pamh, OLD_PASSWORD_VAR_NAME);
+ pw_clear(pamh, PASSWORD_VAR_NAME);
return (PAM_SERVICE_ERR);
}
+ int changed = change_key(pamh, dataset, token->value);
+ if (!was_loaded) {
+ unmount_unload(pamh, dataset, config.force_unmount);
+ }
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
- if (pw_clear(pamh) == -1) {
+ if (pw_clear(pamh, OLD_PASSWORD_VAR_NAME) == -1 ||
+ pw_clear(pamh, PASSWORD_VAR_NAME) == -1 || changed == -1) {
return (PAM_SERVICE_ERR);
}
} else {
@@ -751,8 +831,11 @@ 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 (config.uid < 1000) {
+ if (zfs_key_config_load(pamh, &config, argc, argv) != PAM_SUCCESS) {
+ return (PAM_SESSION_ERR);
+ }
+
+ if (config.uid < config.uid_min || config.uid > config.uid_max) {
zfs_key_config_free(&config);
return (PAM_SUCCESS);
}
@@ -763,7 +846,8 @@ pam_sm_open_session(pam_handle_t *pamh, int flags,
return (PAM_SUCCESS);
}
- const pw_password_t *token = pw_get(pamh);
+ const pw_password_t *token = pw_get(pamh,
+ PAM_AUTHTOK, PASSWORD_VAR_NAME);
if (token == NULL) {
zfs_key_config_free(&config);
return (PAM_SESSION_ERR);
@@ -778,7 +862,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags,
zfs_key_config_free(&config);
return (PAM_SERVICE_ERR);
}
- if (decrypt_mount(pamh, dataset, token->value) == -1) {
+ if (decrypt_mount(pamh, dataset, token->value, B_FALSE) == -1) {
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
@@ -787,7 +871,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags,
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
- if (pw_clear(pamh) == -1) {
+ if (pw_clear(pamh, PASSWORD_VAR_NAME) == -1) {
return (PAM_SERVICE_ERR);
}
return (PAM_SUCCESS);
@@ -807,8 +891,10 @@ 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 (config.uid < 1000) {
+ if (zfs_key_config_load(pamh, &config, argc, argv) != PAM_SUCCESS) {
+ return (PAM_SESSION_ERR);
+ }
+ if (config.uid < config.uid_min || config.uid > config.uid_max) {
zfs_key_config_free(&config);
return (PAM_SUCCESS);
}
@@ -830,7 +916,7 @@ pam_sm_close_session(pam_handle_t *pamh, int flags,
zfs_key_config_free(&config);
return (PAM_SESSION_ERR);
}
- if (unmount_unload(pamh, dataset) == -1) {
+ if (unmount_unload(pamh, dataset, config.force_unmount) == -1) {
free(dataset);
pam_zfs_free();
zfs_key_config_free(&config);
diff --git a/contrib/pyzfs/libzfs_core/__init__.py b/contrib/pyzfs/libzfs_core/__init__.py
index 25ea3e495b02..a80f94b524ec 100644
--- a/contrib/pyzfs/libzfs_core/__init__.py
+++ b/contrib/pyzfs/libzfs_core/__init__.py
@@ -72,6 +72,7 @@ from ._libzfs_core import (
lzc_receive_resumable,
lzc_receive_with_cmdprops,
lzc_receive_with_header,
+ lzc_receive_with_heal,
lzc_release,
lzc_reopen,
lzc_rollback,
@@ -127,6 +128,7 @@ __all__ = [
'lzc_receive_resumable',
'lzc_receive_with_cmdprops',
'lzc_receive_with_header',
+ 'lzc_receive_with_heal',
'lzc_release',
'lzc_reopen',
'lzc_rollback',
diff --git a/contrib/pyzfs/libzfs_core/_constants.py b/contrib/pyzfs/libzfs_core/_constants.py
index 7ee2ef87df3e..9c40ece1a7df 100644
--- a/contrib/pyzfs/libzfs_core/_constants.py
+++ b/contrib/pyzfs/libzfs_core/_constants.py
@@ -101,17 +101,21 @@ zfs_errno = enum_with_offset(1024, [
'ZFS_ERR_BADPROP',
'ZFS_ERR_VDEV_NOTSUP',
'ZFS_ERR_NOT_USER_NAMESPACE',
+ 'ZFS_ERR_RESUME_EXISTS',
+ 'ZFS_ERR_CRYPTO_NOTSUP',
+ 'ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS',
],
{}
)
# compat before we used the enum helper for these values
ZFS_ERR_CHECKPOINT_EXISTS = zfs_errno.ZFS_ERR_CHECKPOINT_EXISTS
-assert(ZFS_ERR_CHECKPOINT_EXISTS == 1024)
+assert (ZFS_ERR_CHECKPOINT_EXISTS == 1024)
ZFS_ERR_DISCARDING_CHECKPOINT = zfs_errno.ZFS_ERR_DISCARDING_CHECKPOINT
ZFS_ERR_NO_CHECKPOINT = zfs_errno.ZFS_ERR_NO_CHECKPOINT
ZFS_ERR_DEVRM_IN_PROGRESS = zfs_errno.ZFS_ERR_DEVRM_IN_PROGRESS
ZFS_ERR_VDEV_TOO_BIG = zfs_errno.ZFS_ERR_VDEV_TOO_BIG
ZFS_ERR_WRONG_PARENT = zfs_errno.ZFS_ERR_WRONG_PARENT
ZFS_ERR_VDEV_NOTSUP = zfs_errno.ZFS_ERR_VDEV_NOTSUP
+ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS = zfs_errno.ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
# vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4
diff --git a/contrib/pyzfs/libzfs_core/_error_translation.py b/contrib/pyzfs/libzfs_core/_error_translation.py
index f494461f63b2..3d1a2d573e39 100644
--- a/contrib/pyzfs/libzfs_core/_error_translation.py
+++ b/contrib/pyzfs/libzfs_core/_error_translation.py
@@ -43,6 +43,7 @@ from ._constants import (
ZFS_ERR_DEVRM_IN_PROGRESS,
ZFS_ERR_VDEV_TOO_BIG,
ZFS_ERR_WRONG_PARENT,
+ ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS,
zfs_errno
)
@@ -469,6 +470,8 @@ def lzc_receive_translate_errors(
raise lzc_exc.ReadOnlyPool(_pool_name(snapname))
if ret == errno.EAGAIN:
raise lzc_exc.SuspendedPool(_pool_name(snapname))
+ if ret == errno.EACCES:
+ raise lzc_exc.EncryptionKeyNotLoaded()
if ret == ECKSUM:
raise lzc_exc.BadStream()
if ret == ZFS_ERR_WRONG_PARENT:
@@ -594,6 +597,8 @@ def lzc_pool_checkpoint_translate_error(ret, name, discard=False):
raise lzc_exc.DeviceRemovalRunning()
if ret == ZFS_ERR_VDEV_TOO_BIG:
raise lzc_exc.DeviceTooBig()
+ if ret == ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS:
+ raise lzc_exc.RaidzExpansionRunning()
if discard:
raise _generic_exception(
ret, name, "Failed to discard pool checkpoint")
diff --git a/contrib/pyzfs/libzfs_core/_libzfs_core.py b/contrib/pyzfs/libzfs_core/_libzfs_core.py
index fcfa5be31b1f..fa74ad9a760c 100644
--- a/contrib/pyzfs/libzfs_core/_libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/_libzfs_core.py
@@ -1427,6 +1427,135 @@ def lzc_receive_with_cmdprops(
@_uncommitted()
+def lzc_receive_with_heal(
+ snapname, fd, begin_record, force=False, corrective=True, resumable=False,
+ raw=False, origin=None, props=None, cmdprops=None, key=None, cleanup_fd=-1,
+ action_handle=0
+):
+ '''
+ Like :func:`lzc_receive_cmdprops`, but allows the caller to pass an
+ additional 'corrective' argument. The 'corrective' boolean set to true
+ indicates that a corruption healing receive should be performed.
+
+ :param bytes snapname: the name of the snapshot to create.
+ :param int fd: the file descriptor from which to read the stream.
+ :param begin_record: the stream's begin record.
+ :type begin_record: ``cffi`` `CData` representing the dmu_replay_record_t
+ structure.
+ :param bool force: whether to roll back or destroy the target filesystem
+ if that is required to receive the stream.
+ :param bool corrective: whether this stream should be used to heal data.
+ :param bool resumable: whether this stream should be treated as resumable.
+ If the receive fails due to premature stream termination, the
+ intermediate state will be preserved on disk and may subsequently be
+ resumed with :func:`lzc_send_resume`.
+ :param bool raw: whether this is a "raw" stream.
+ :param origin: the optional origin snapshot name if the stream is for a
+ clone.
+ :type origin: bytes or None
+ :param props: the properties to set on the snapshot as *received*
+ properties.
+ :type props: dict of bytes : Any
+ :param cmdprops: the properties to set on the snapshot as local overrides
+ to *received* properties. `bool` values are forcefully inherited while
+ every other value is set locally as if the command "zfs set" was
+ invoked immediately before the receive.
+ :type cmdprops: dict of bytes : Any
+ :param key: raw bytes representing user's wrapping key
+ :type key: bytes
+ :param int cleanup_fd: file descriptor used to set a cleanup-on-exit file
+ descriptor.
+ :param int action_handle: variable used to pass the handle for guid/ds
+ mapping: this should be set to zero on first call and will contain an
+ updated handle on success, it should be passed in subsequent calls.
+
+ :return: a tuple with two elements where the first one is the number of
+ bytes read from the file descriptor and the second one is the
+ action_handle return value.
+
+ :raises IOError: if an input / output error occurs while reading from the
+ ``fd``.
+ :raises DatasetExists: if the snapshot named ``snapname`` already exists.
+ :raises DatasetExists: if the stream is a full stream and the destination
+ filesystem already exists.
+ :raises DatasetExists: if ``force`` is `True` but the destination
+ filesystem could not be rolled back to a matching snapshot because a
+ newer snapshot exists and it is an origin of a cloned filesystem.
+ :raises StreamMismatch: if an incremental stream is received and the latest
+ snapshot of the destination filesystem does not match the source
+ snapshot of the stream.
+ :raises StreamMismatch: if a full stream is received and the destination
+ filesystem already exists and it has at least one snapshot, and
+ ``force`` is `False`.
+ :raises StreamMismatch: if an incremental clone stream is received but the
+ specified ``origin`` is not the actual received origin.
+ :raises DestinationModified: if an incremental stream is received and the
+ destination filesystem has been modified since the last snapshot and
+ ``force`` is `False`.
+ :raises DestinationModified: if a full stream is received and the
+ destination filesystem already exists and it does not have any
+ snapshots, and ``force`` is `False`.
+ :raises DatasetNotFound: if the destination filesystem and its parent do
+ not exist.
+ :raises DatasetNotFound: if the ``origin`` is not `None` and does not
+ exist.
+ :raises DatasetBusy: if ``force`` is `True` but the destination filesystem
+ could not be rolled back to a matching snapshot because a newer
+ snapshot is held and could not be destroyed.
+ :raises DatasetBusy: if another receive operation is being performed on the
+ destination filesystem.
+ :raises EncryptionKeyNotLoaded: if corrective is set to true indicates the
+ key must be loaded to do a non-raw corrective recv on an encrypted
+ dataset.
+ :raises BadStream: if corrective is set to true indicates that
+ corrective recv was not able to reconstruct a corrupted block.
+ :raises BadStream: if the stream is corrupt or it is not recognized or it
+ is a compound stream or it is a clone stream, but ``origin`` is `None`.
+ :raises BadStream: if a clone stream is received and the destination
+ filesystem already exists.
+ :raises StreamFeatureNotSupported: if corrective is set to true indicates
+ stream is not compatible with the data in the pool.
+ :raises StreamFeatureNotSupported: if the stream has a feature that is not
+ supported on this side.
+ :raises ReceivePropertyFailure: if one or more of the specified properties
+ is invalid or has an invalid type or value.
+ :raises NameInvalid: if the name of either snapshot is invalid.
+ :raises NameTooLong: if the name of either snapshot is too long.
+ '''
+
+ if origin is not None:
+ c_origin = origin
+ else:
+ c_origin = _ffi.NULL
+ if action_handle is not None:
+ c_action_handle = _ffi.new("uint64_t *")
+ else:
+ c_action_handle = _ffi.NULL
+ c_read_bytes = _ffi.new("uint64_t *")
+ c_errflags = _ffi.new("uint64_t *")
+ if props is None:
+ props = {}
+ if cmdprops is None:
+ cmdprops = {}
+ if key is None:
+ key = b""
+ else:
+ key = bytes(key)
+
+ nvlist = nvlist_in(props)
+ cmdnvlist = nvlist_in(cmdprops)
+ properrs = {}
+ with nvlist_out(properrs) as c_errors:
+ ret = _lib.lzc_receive_with_heal(
+ snapname, nvlist, cmdnvlist, key, len(key), c_origin,
+ force, corrective, resumable, raw, fd, begin_record, cleanup_fd,
+ c_read_bytes, c_errflags, c_action_handle, c_errors)
+ errors.lzc_receive_translate_errors(
+ ret, snapname, fd, force, raw, False, False, origin, properrs)
+ return (int(c_read_bytes[0]), action_handle)
+
+
+@_uncommitted()
def lzc_reopen(poolname, restart=True):
'''
Reopen a pool
diff --git a/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py b/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
index 1b46a0891944..bcb9ed379e21 100644
--- a/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
@@ -112,6 +112,10 @@ CDEF = """
uint8_t *, uint_t, const char *, boolean_t, boolean_t,
boolean_t, int, const dmu_replay_record_t *, int, uint64_t *,
uint64_t *, uint64_t *, nvlist_t **);
+ int lzc_receive_with_heal(const char *, nvlist_t *, nvlist_t *,
+ uint8_t *, uint_t, const char *, boolean_t, boolean_t, boolean_t,
+ boolean_t, int, const dmu_replay_record_t *, int, uint64_t *,
+ uint64_t *, uint64_t *, nvlist_t **);
int lzc_receive_with_header(const char *, nvlist_t *, const char *,
boolean_t, boolean_t, boolean_t, int, const dmu_replay_record_t *);
int lzc_release(nvlist_t *, nvlist_t **);
diff --git a/contrib/pyzfs/libzfs_core/exceptions.py b/contrib/pyzfs/libzfs_core/exceptions.py
index e484b07b6450..ba8f7e49093c 100644
--- a/contrib/pyzfs/libzfs_core/exceptions.py
+++ b/contrib/pyzfs/libzfs_core/exceptions.py
@@ -30,6 +30,7 @@ from ._constants import (
ZFS_ERR_DEVRM_IN_PROGRESS,
ZFS_ERR_VDEV_TOO_BIG,
ZFS_ERR_WRONG_PARENT,
+ ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS,
zfs_errno
)
@@ -598,4 +599,9 @@ class DeviceTooBig(ZFSError):
message = "One or more top-level vdevs exceed the maximum vdev size"
+class RaidzExpansionRunning(ZFSError):
+ errno = ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
+ message = "A raidz device is currently expanding"
+
+
# vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4
diff --git a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
index 9b1aea193f44..c94ae6de6bbf 100644
--- a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
@@ -2911,6 +2911,27 @@ class ZFSTest(unittest.TestCase):
self.assertEqual(fs.getProperty("compression"), b"on")
self.assertEqual(fs.getProperty("ns:prop"), b"val")
+ def test_recv_with_heal(self):
+ snap = ZFSTest.pool.makeName(b"fs1@snap1")
+ fs = ZFSTest.pool.getFilesystem(b"fs1")
+ props = {}
+ cmdprops = {
+ b"compression": 0x01,
+ b"ns:prop": b"val"
+ }
+
+ lzc.lzc_snapshot([snap])
+ with tempfile.TemporaryFile(suffix='.zstream') as stream:
+ lzc.lzc_send(snap, None, stream.fileno())
+ stream.seek(0)
+ (header, c_header) = lzc.receive_header(stream.fileno())
+ lzc.lzc_receive_with_heal(
+ snap, stream.fileno(), c_header, props=props,
+ cmdprops=cmdprops)
+ self.assertExists(snap)
+ self.assertEqual(fs.getProperty("compression"), b"on")
+ self.assertEqual(fs.getProperty("ns:prop"), b"val")
+
def test_recv_with_cmdprops_and_recvprops(self):
fromsnap = ZFSTest.pool.makeName(b"fs1@snap1")
fs = ZFSTest.pool.getFilesystem(b"recv")
diff --git a/etc/Makefile.am b/etc/Makefile.am
index b4b3ae1f5798..7187762d3802 100644
--- a/etc/Makefile.am
+++ b/etc/Makefile.am
@@ -74,6 +74,7 @@ INSTALL_DATA_HOOKS += systemd-install-data-hook
systemd-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"
systemdgenerator_PROGRAMS = \
diff --git a/etc/init.d/README.md b/etc/init.d/README.md
index f417b24c5923..da780fdc1222 100644
--- a/etc/init.d/README.md
+++ b/etc/init.d/README.md
@@ -7,11 +7,7 @@ DESCRIPTION
They have been tested successfully on:
- * Debian GNU/Linux Wheezy
- * Debian GNU/Linux Jessie
- * Ubuntu Trusty
- * CentOS 6.0
- * CentOS 6.6
+ * Debian GNU/Linux Bookworm
* Gentoo
SUPPORT
@@ -44,7 +40,7 @@ INSTALLING INIT SCRIPT LINKS
update-rc.d zfs-import start 07 S . stop 07 0 1 6 .
update-rc.d zfs-load-key start 02 2 3 4 5 . stop 06 0 1 6 .
- update-rc.d zfs-mount start 02 2 3 4 5 . stop 06 0 1 6 .
+ update-rc.d zfs-mount start 02 S . stop 06 0 1 6 .
update-rc.d zfs-zed start 07 2 3 4 5 . stop 08 0 1 6 .
update-rc.d zfs-share start 27 2 3 4 5 . stop 05 0 1 6 .
diff --git a/etc/init.d/zfs-import.in b/etc/init.d/zfs-import.in
index a9a0604f81ac..ff169eb96d86 100755
--- a/etc/init.d/zfs-import.in
+++ b/etc/init.d/zfs-import.in
@@ -307,7 +307,7 @@ do_start()
# ----------------------------------------------------
-if [ ! -e /sbin/openrc-run ]
+if @IS_SYSV_RC@
then
case "$1" in
start)
diff --git a/etc/init.d/zfs-load-key.in b/etc/init.d/zfs-load-key.in
index 53c7766b793a..27dfeeb0bcc5 100755
--- a/etc/init.d/zfs-load-key.in
+++ b/etc/init.d/zfs-load-key.in
@@ -104,7 +104,7 @@ do_stop()
# ----------------------------------------------------
-if [ ! -e /sbin/openrc-run ]
+if @IS_SYSV_RC@
then
case "$1" in
start)
diff --git a/etc/init.d/zfs-mount.in b/etc/init.d/zfs-mount.in
index df28c6c951c5..6a3ca5f86908 100755
--- a/etc/init.d/zfs-mount.in
+++ b/etc/init.d/zfs-mount.in
@@ -13,10 +13,11 @@
#
### BEGIN INIT INFO
# Provides: zfs-mount
-# Required-Start: $local_fs zfs-import
+# Required-Start: zfs-import
# Required-Stop: $local_fs zfs-import
-# Default-Start: 2 3 4 5
+# Default-Start: S
# Default-Stop: 0 1 6
+# X-Start-Before: mountall
# X-Stop-After: zfs-zed
# Short-Description: Mount ZFS filesystems and volumes
# Description: Run the `zfs mount -a` or `zfs umount -a` commands.
@@ -113,7 +114,7 @@ do_stop()
# ----------------------------------------------------
-if [ ! -e /sbin/openrc-run ]
+if @IS_SYSV_RC@
then
case "$1" in
start)
diff --git a/etc/init.d/zfs-share.in b/etc/init.d/zfs-share.in
index 88978071cbf6..06c59c620b75 100755
--- a/etc/init.d/zfs-share.in
+++ b/etc/init.d/zfs-share.in
@@ -57,7 +57,8 @@ do_stop()
# ----------------------------------------------------
-if [ ! -e /sbin/openrc-run ]; then
+if @IS_SYSV_RC@
+then
case "$1" in
start)
do_start
diff --git a/etc/init.d/zfs-zed.in b/etc/init.d/zfs-zed.in
index e9cf8867403c..3d40600cea5d 100755
--- a/etc/init.d/zfs-zed.in
+++ b/etc/init.d/zfs-zed.in
@@ -93,7 +93,8 @@ do_reload()
# ----------------------------------------------------
-if [ ! -e /sbin/openrc-run ]; then
+if @IS_SYSV_RC@
+then
case "$1" in
start)
do_start
diff --git a/etc/systemd/system-generators/zfs-mount-generator.c b/etc/systemd/system-generators/zfs-mount-generator.c
index b07574e72afe..ab5dc4d78d60 100644
--- a/etc/systemd/system-generators/zfs-mount-generator.c
+++ b/etc/systemd/system-generators/zfs-mount-generator.c
@@ -224,9 +224,10 @@ line_worker(char *line, const char *cachefile)
const char *p_systemd_ignore = strtok_r(NULL, "\t", &toktmp) ?: "-";
/* END CSTYLED */
- const char *pool = dataset;
- if ((toktmp = strchr(pool, '/')) != NULL)
- pool = strndupa(pool, toktmp - pool);
+ size_t pool_len = strlen(dataset);
+ if ((toktmp = strchr(dataset, '/')) != NULL)
+ pool_len = toktmp - dataset;
+ const char *pool = *(tofree++) = strndup(dataset, pool_len);
if (p_nbmand == NULL) {
fprintf(stderr, PROGNAME "[%d]: %s: not enough tokens!\n",
@@ -734,7 +735,7 @@ end:
if (tofree >= tofree_all + nitems(tofree_all)) {
/*
* This won't happen as-is:
- * we've got 8 slots and allocate 4 things at most.
+ * we've got 8 slots and allocate 5 things at most.
*/
fprintf(stderr,
PROGNAME "[%d]: %s: need to free %zu > %zu!\n",
diff --git a/etc/systemd/system/zfs-import-cache.service.in b/etc/systemd/system/zfs-import-cache.service.in
index 08c11698bcce..fd822989da93 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 c37f70f13b71..c5dd45d87e68 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/etc/systemd/system/zfs-share.service.in b/etc/systemd/system/zfs-share.service.in
index 263055e5281f..1a6342a06fec 100644
--- a/etc/systemd/system/zfs-share.service.in
+++ b/etc/systemd/system/zfs-share.service.in
@@ -1,7 +1,7 @@
[Unit]
Description=ZFS file system shares
Documentation=man:zfs(8)
-After=nfs-server.service nfs-kernel-server.service
+Before=nfs-server.service nfs-kernel-server.service
After=smb.service
Before=rpc-statd-notify.service
Wants=zfs-mount.service
diff --git a/etc/systemd/system/zfs-zed.service.in b/etc/systemd/system/zfs-zed.service.in
index 73a83e59e510..be2fc67348f9 100644
--- a/etc/systemd/system/zfs-zed.service.in
+++ b/etc/systemd/system/zfs-zed.service.in
@@ -6,7 +6,7 @@ ConditionPathIsDirectory=/sys/module/zfs
[Service]
EnvironmentFile=-@initconfdir@/zfs
ExecStart=@sbindir@/zed -F
-Restart=on-abort
+Restart=always
[Install]
Alias=zed.service
diff --git a/include/Makefile.am b/include/Makefile.am
index 1a7f67e9c440..fa725c2e7a5f 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -20,8 +20,10 @@ COMMON_H = \
sys/aggsum.h \
sys/arc.h \
sys/arc_impl.h \
+ sys/asm_linkage.h \
sys/avl.h \
sys/avl_impl.h \
+ sys/bitmap.h \
sys/bitops.h \
sys/blake3.h \
sys/blkptr.h \
@@ -30,9 +32,12 @@ COMMON_H = \
sys/bptree.h \
sys/bqueue.h \
sys/btree.h \
+ sys/brt.h \
+ sys/brt_impl.h \
sys/dataset_kstats.h \
sys/dbuf.h \
sys/ddt.h \
+ sys/ddt_impl.h \
sys/dmu.h \
sys/dmu_impl.h \
sys/dmu_objset.h \
@@ -74,9 +79,9 @@ COMMON_H = \
sys/rrwlock.h \
sys/sa.h \
sys/sa_impl.h \
+ sys/sha2.h \
sys/skein.h \
sys/spa.h \
- sys/spa_boot.h \
sys/spa_checkpoint.h \
sys/spa_checksum.h \
sys/spa_impl.h \
@@ -124,6 +129,7 @@ COMMON_H = \
sys/zfs_delay.h \
sys/zfs_file.h \
sys/zfs_fuid.h \
+ sys/zfs_impl.h \
sys/zfs_project.h \
sys/zfs_quota.h \
sys/zfs_racct.h \
@@ -181,6 +187,7 @@ USER_H = \
libuutil.h \
libuutil_common.h \
libuutil_impl.h \
+ libzdb.h \
libzfs.h \
libzfs_core.h \
libzfsbootenv.h \
diff --git a/include/libnvpair.h b/include/libnvpair.h
index bc50c3b7e1f8..09b224b4de5a 100644
--- a/include/libnvpair.h
+++ b/include/libnvpair.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -42,9 +42,10 @@ extern "C" {
* are all imported from <sys/nvpair.h> included above.
*/
-_LIBNVPAIR_H int nvpair_value_match(nvpair_t *, int, char *, char **);
-_LIBNVPAIR_H int nvpair_value_match_regex(nvpair_t *, int, char *, regex_t *,
- char **);
+_LIBNVPAIR_H int nvpair_value_match(nvpair_t *, int, const char *,
+ const char **);
+_LIBNVPAIR_H int nvpair_value_match_regex(nvpair_t *, int, const char *,
+ regex_t *, const char **);
_LIBNVPAIR_H void nvlist_print(FILE *, nvlist_t *);
_LIBNVPAIR_H int nvlist_print_json(FILE *, nvlist_t *);
@@ -156,7 +157,7 @@ NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_uint32, uint32_t);
NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_int64, int64_t);
NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_uint64, uint64_t);
NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_double, double);
-NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_string, char *);
+NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_string, const char *);
NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_hrtime, hrtime_t);
NVLIST_PRINTCTL_SVDECL(nvlist_prtctlop_nvlist, nvlist_t *);
@@ -185,7 +186,7 @@ NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_int32_array, int32_t *);
NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_uint32_array, uint32_t *);
NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_int64_array, int64_t *);
NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_uint64_array, uint64_t *);
-NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_string_array, char **);
+NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_string_array, const char **);
NVLIST_PRINTCTL_AVDECL(nvlist_prtctlop_nvlist_array, nvlist_t **);
#undef NVLIST_PRINTCTL_AVDECL /* was just for "clarity" above */
diff --git a/include/libuutil.h b/include/libuutil.h
index 05a7f503cca1..906b49ea5ca9 100644
--- a/include/libuutil.h
+++ b/include/libuutil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -57,13 +57,6 @@ extern "C" {
#define UU_ERROR_UNKNOWN 100 /* error status not known */
/*
- * Standard program exit codes.
- */
-#define UU_EXIT_OK (*(uu_exit_ok()))
-#define UU_EXIT_FATAL (*(uu_exit_fatal()))
-#define UU_EXIT_USAGE (*(uu_exit_usage()))
-
-/*
* Exit status profiles.
*/
#define UU_PROFILE_DEFAULT 0
@@ -76,32 +69,6 @@ uint32_t uu_error(void);
const char *uu_strerror(uint32_t);
/*
- * Program notification functions.
- */
-extern void uu_alt_exit(int);
-extern const char *uu_setpname(char *);
-extern const char *uu_getpname(void);
-extern void uu_warn(const char *, ...)
- __attribute__((format(printf, 1, 2)));
-extern void uu_vwarn(const char *, va_list)
- __attribute__((format(printf, 1, 0)));
-extern __attribute__((noreturn)) void uu_die(const char *, ...)
- __attribute__((format(printf, 1, 2)));
-extern __attribute__((noreturn)) void uu_vdie(const char *, va_list)
- __attribute__((format(printf, 1, 0)));
-extern __attribute__((noreturn)) void uu_xdie(int, const char *, ...)
- __attribute__((format(printf, 2, 3)));
-extern __attribute__((noreturn)) void uu_vxdie(int, const char *, va_list)
- __attribute__((format(printf, 2, 0)));
-
-/*
- * Exit status functions (not to be used directly)
- */
-extern int *uu_exit_ok(void);
-extern int *uu_exit_fatal(void);
-extern int *uu_exit_usage(void);
-
-/*
* Identifier test flags and function.
*/
#define UU_NAME_DOMAIN 0x1 /* allow SUNW, or com.sun, prefix */
diff --git a/include/libuutil_common.h b/include/libuutil_common.h
index 52ac4887f75c..cdfa0c2f556f 100644
--- a/include/libuutil_common.h
+++ b/include/libuutil_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/libuutil_impl.h b/include/libuutil_impl.h
index 753bbff2461d..58b6df579d72 100644
--- a/include/libuutil_impl.h
+++ b/include/libuutil_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -42,25 +42,11 @@ extern "C" {
void uu_set_error(uint_t);
-void uu_panic(const char *format, ...) __attribute__((format(printf, 1, 2)));
+__attribute__((format(printf, 1, 2), __noreturn__))
+void uu_panic(const char *format, ...);
/*
- * For debugging purposes, libuutil keeps around linked lists of all uu_lists
- * and uu_avls, along with pointers to their parents. These can cause false
- * negatives when looking for memory leaks, so we encode the pointers by
- * storing them with swapped endianness; this is not perfect, but it's about
- * the best we can do without wasting a lot of space.
- */
-#ifdef _LP64
-#define UU_PTR_ENCODE(ptr) BSWAP_64((uintptr_t)(void *)(ptr))
-#else
-#define UU_PTR_ENCODE(ptr) BSWAP_32((uintptr_t)(void *)(ptr))
-#endif
-
-#define UU_PTR_DECODE(ptr) ((void *)UU_PTR_ENCODE(ptr))
-
-/*
* uu_list structures
*/
typedef struct uu_list_node_impl {
@@ -79,11 +65,11 @@ struct uu_list_walk {
};
struct uu_list {
- uintptr_t ul_next_enc;
- uintptr_t ul_prev_enc;
+ uu_list_t *ul_next;
+ uu_list_t *ul_prev;
uu_list_pool_t *ul_pool;
- uintptr_t ul_parent_enc; /* encoded parent pointer */
+ void *ul_parent;
size_t ul_offset;
size_t ul_numnodes;
uint8_t ul_debug;
@@ -94,8 +80,6 @@ struct uu_list {
uu_list_walk_t ul_null_walk; /* for robust walkers */
};
-#define UU_LIST_PTR(ptr) ((uu_list_t *)UU_PTR_DECODE(ptr))
-
#define UU_LIST_POOL_MAXNAME 64
struct uu_list_pool {
@@ -128,11 +112,11 @@ struct uu_avl_walk {
};
struct uu_avl {
- uintptr_t ua_next_enc;
- uintptr_t ua_prev_enc;
+ uu_avl_t *ua_next;
+ uu_avl_t *ua_prev;
uu_avl_pool_t *ua_pool;
- uintptr_t ua_parent_enc;
+ void *ua_parent;
uint8_t ua_debug;
uint8_t ua_index; /* mark for uu_avl_index_ts */
@@ -140,8 +124,6 @@ struct uu_avl {
uu_avl_walk_t ua_null_walk;
};
-#define UU_AVL_PTR(x) ((uu_avl_t *)UU_PTR_DECODE(x))
-
#define UU_AVL_POOL_MAXNAME 64
struct uu_avl_pool {
diff --git a/include/libzdb.h b/include/libzdb.h
new file mode 100644
index 000000000000..ef910d0a2c5a
--- /dev/null
+++ b/include/libzdb.h
@@ -0,0 +1,68 @@
+#define ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
+ zio_compress_table[(idx)].ci_name : "UNKNOWN")
+#define ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
+ zio_checksum_table[(idx)].ci_name : "UNKNOWN")
+#define ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : \
+ (idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA ? \
+ DMU_OT_ZAP_OTHER : \
+ (idx) == DMU_OTN_UINT64_DATA || (idx) == DMU_OTN_UINT64_METADATA ? \
+ DMU_OT_UINT64_OTHER : DMU_OT_NUMTYPES)
+
+/* Some platforms require part of inode IDs to be remapped */
+#ifdef __APPLE__
+#define ZDB_MAP_OBJECT_ID(obj) INO_XNUTOZFS(obj, 2)
+#else
+#define ZDB_MAP_OBJECT_ID(obj) (obj)
+#endif
+
+#define ZOR_FLAG_PLAIN_FILE 0x0001
+#define ZOR_FLAG_DIRECTORY 0x0002
+#define ZOR_FLAG_SPACE_MAP 0x0004
+#define ZOR_FLAG_ZAP 0x0008
+#define ZOR_FLAG_ALL_TYPES -1
+#define ZOR_SUPPORTED_FLAGS (ZOR_FLAG_PLAIN_FILE | \
+ ZOR_FLAG_DIRECTORY | \
+ ZOR_FLAG_SPACE_MAP | \
+ ZOR_FLAG_ZAP)
+
+#define ZDB_FLAG_CHECKSUM 0x0001
+#define ZDB_FLAG_DECOMPRESS 0x0002
+#define ZDB_FLAG_BSWAP 0x0004
+#define ZDB_FLAG_GBH 0x0008
+#define ZDB_FLAG_INDIRECT 0x0010
+#define ZDB_FLAG_RAW 0x0020
+#define ZDB_FLAG_PRINT_BLKPTR 0x0040
+#define ZDB_FLAG_VERBOSE 0x0080
+
+
+typedef struct zdb_ctx {
+} zdb_ctx_t;
+
+typedef struct zopt_object_range {
+ uint64_t zor_obj_start;
+ uint64_t zor_obj_end;
+ uint64_t zor_flags;
+} zopt_object_range_t;
+
+
+typedef struct sublivelist_verify {
+ /* FREE's that haven't yet matched to an ALLOC, in one sub-livelist */
+ zfs_btree_t sv_pair;
+
+ /* ALLOC's without a matching FREE, accumulates across sub-livelists */
+ zfs_btree_t sv_leftover;
+} sublivelist_verify_t;
+
+typedef struct sublivelist_verify_block {
+ dva_t svb_dva;
+
+ /*
+ * We need this to check if the block marked as allocated
+ * in the livelist was freed (and potentially reallocated)
+ * in the metaslab spacemaps at a later TXG.
+ */
+ uint64_t svb_allocated_txg;
+} sublivelist_verify_block_t;
+
+const char *zdb_ot_name(dmu_object_type_t type);
+int livelist_compare(const void *larg, const void *rarg);
diff --git a/include/libzfs.h b/include/libzfs.h
index 6b4ead8182d6..2823b8845827 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright Joyent, Inc.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2016, Intel Corporation.
@@ -125,11 +125,14 @@ typedef enum zfs_error {
EZFS_THREADCREATEFAILED, /* thread create failed */
EZFS_POSTSPLIT_ONLINE, /* onlining a disk after splitting it */
EZFS_SCRUBBING, /* currently scrubbing */
+ EZFS_ERRORSCRUBBING, /* currently error scrubbing */
+ EZFS_ERRORSCRUB_PAUSED, /* error scrub currently paused */
EZFS_NO_SCRUB, /* no active scrub */
EZFS_DIFF, /* general failure of zfs diff */
EZFS_DIFFDATA, /* bad zfs diff data */
EZFS_POOLREADONLY, /* pool is in read-only mode */
EZFS_SCRUB_PAUSED, /* scrub currently paused */
+ EZFS_SCRUB_PAUSED_TO_CANCEL, /* scrub currently paused */
EZFS_ACTIVE_POOL, /* pool is imported on a different system */
EZFS_CRYPTOFAILED, /* failed to setup encryption */
EZFS_NO_PENDING, /* cannot cancel, no operation is pending */
@@ -151,6 +154,11 @@ typedef enum zfs_error {
EZFS_REBUILDING, /* resilvering (sequential reconstrution) */
EZFS_VDEV_NOTSUP, /* ops not supported for this type of vdev */
EZFS_NOT_USER_NAMESPACE, /* a file is not a user namespace */
+ EZFS_CKSUM, /* insufficient replicas */
+ EZFS_RESUME_EXISTS, /* Resume on existing dataset without force */
+ EZFS_SHAREFAILED, /* filesystem share failed */
+ EZFS_RAIDZ_EXPAND_IN_PROGRESS, /* a raidz is currently expanding */
+ EZFS_ASHIFT_MISMATCH, /* can't add vdevs with different ashifts */
EZFS_UNKNOWN
} zfs_error_t;
@@ -254,14 +262,14 @@ _LIBZFS_H boolean_t zpool_skip_pool(const char *);
_LIBZFS_H int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
nvlist_t *, nvlist_t *);
_LIBZFS_H int zpool_destroy(zpool_handle_t *, const char *);
-_LIBZFS_H int zpool_add(zpool_handle_t *, nvlist_t *);
+_LIBZFS_H int zpool_add(zpool_handle_t *, nvlist_t *, boolean_t check_ashift);
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;
@@ -308,9 +316,13 @@ _LIBZFS_H int zpool_vdev_indirect_size(zpool_handle_t *, const char *,
uint64_t *);
_LIBZFS_H int zpool_vdev_split(zpool_handle_t *, char *, nvlist_t **,
nvlist_t *, splitflags_t);
+_LIBZFS_H int zpool_vdev_remove_wanted(zpool_handle_t *, const char *);
_LIBZFS_H int zpool_vdev_fault(zpool_handle_t *, uint64_t, vdev_aux_t);
_LIBZFS_H int zpool_vdev_degrade(zpool_handle_t *, uint64_t, vdev_aux_t);
+_LIBZFS_H int zpool_vdev_set_removed_state(zpool_handle_t *, uint64_t,
+ vdev_aux_t);
+
_LIBZFS_H int zpool_vdev_clear(zpool_handle_t *, uint64_t);
_LIBZFS_H nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
@@ -319,6 +331,15 @@ _LIBZFS_H nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
boolean_t *, boolean_t *, boolean_t *);
_LIBZFS_H int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *,
const char *);
+_LIBZFS_H int zpool_prepare_disk(zpool_handle_t *zhp, nvlist_t *vdev_nv,
+ const char *prepare_str, char **lines[], int *lines_cnt);
+_LIBZFS_H int zpool_prepare_and_label_disk(libzfs_handle_t *hdl,
+ zpool_handle_t *, const char *, nvlist_t *vdev_nv, const char *prepare_str,
+ char **lines[], int *lines_cnt);
+_LIBZFS_H char ** zpool_vdev_script_alloc_env(const char *pool_name,
+ const char *vdev_path, const char *vdev_upath,
+ const char *vdev_enc_sysfs_path, const char *opt_key, const char *opt_val);
+_LIBZFS_H void zpool_vdev_script_free_env(char **env);
_LIBZFS_H uint64_t zpool_vdev_path_to_guid(zpool_handle_t *zhp,
const char *path);
@@ -330,6 +351,8 @@ _LIBZFS_H const char *zpool_get_state_str(zpool_handle_t *);
_LIBZFS_H int zpool_set_prop(zpool_handle_t *, const char *, const char *);
_LIBZFS_H int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
size_t proplen, zprop_source_t *, boolean_t literal);
+_LIBZFS_H int zpool_get_userprop(zpool_handle_t *, const char *, char *,
+ size_t proplen, zprop_source_t *);
_LIBZFS_H uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
zprop_source_t *);
_LIBZFS_H int zpool_props_refresh(zpool_handle_t *);
@@ -475,7 +498,6 @@ _LIBZFS_H void zpool_obj_to_path_ds(zpool_handle_t *, uint64_t, uint64_t,
_LIBZFS_H void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
size_t);
_LIBZFS_H int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
-_LIBZFS_H int zpool_get_physpath(zpool_handle_t *, char *, size_t);
_LIBZFS_H void zpool_explain_recover(libzfs_handle_t *, const char *, int,
nvlist_t *);
_LIBZFS_H int zpool_checkpoint(zpool_handle_t *);
@@ -515,6 +537,7 @@ _LIBZFS_H nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
_LIBZFS_H const char *zfs_prop_to_name(zfs_prop_t);
_LIBZFS_H int zfs_prop_set(zfs_handle_t *, const char *, const char *);
_LIBZFS_H int zfs_prop_set_list(zfs_handle_t *, nvlist_t *);
+_LIBZFS_H int zfs_prop_set_list_flags(zfs_handle_t *, nvlist_t *, int);
_LIBZFS_H int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
zprop_source_t *, char *, size_t, boolean_t);
_LIBZFS_H int zfs_prop_get_recvd(zfs_handle_t *, const char *, char *, size_t,
@@ -531,7 +554,7 @@ _LIBZFS_H int zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal);
_LIBZFS_H int zfs_prop_get_feature(zfs_handle_t *zhp, const char *propname,
char *buf, size_t len);
-_LIBZFS_H uint64_t getprop_uint64(zfs_handle_t *, zfs_prop_t, char **);
+_LIBZFS_H uint64_t getprop_uint64(zfs_handle_t *, zfs_prop_t, const char **);
_LIBZFS_H uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
_LIBZFS_H int zfs_prop_inherit(zfs_handle_t *, const char *, boolean_t);
_LIBZFS_H const char *zfs_prop_values(zfs_prop_t);
@@ -637,6 +660,13 @@ typedef struct zprop_get_cbdata {
vdev_cbdata_t cb_vdevs;
} zprop_get_cbdata_t;
+#define ZFS_SET_NOMOUNT 1
+
+typedef struct zprop_set_cbdata {
+ int cb_flags;
+ nvlist_t *cb_proplist;
+} zprop_set_cbdata_t;
+
_LIBZFS_H void zprop_print_one_property(const char *, zprop_get_cbdata_t *,
const char *, const char *, zprop_source_t, const char *,
const char *);
@@ -644,6 +674,14 @@ _LIBZFS_H void zprop_print_one_property(const char *, zprop_get_cbdata_t *,
/*
* Iterator functions.
*/
+#define ZFS_ITER_RECURSE (1 << 0)
+#define ZFS_ITER_ARGS_CAN_BE_PATHS (1 << 1)
+#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
+#define ZFS_ITER_DEPTH_LIMIT (1 << 3)
+#define ZFS_ITER_RECVD_PROPS (1 << 4)
+#define ZFS_ITER_LITERAL_PROPS (1 << 5)
+#define ZFS_ITER_SIMPLE (1 << 6)
+
typedef int (*zfs_iter_f)(zfs_handle_t *, void *);
_LIBZFS_H int zfs_iter_root(libzfs_handle_t *, zfs_iter_f, void *);
_LIBZFS_H int zfs_iter_children(zfs_handle_t *, zfs_iter_f, void *);
@@ -657,6 +695,18 @@ _LIBZFS_H int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *,
_LIBZFS_H int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f,
void *);
_LIBZFS_H int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);
+
+_LIBZFS_H int zfs_iter_children_v2(zfs_handle_t *, int, zfs_iter_f, void *);
+_LIBZFS_H int zfs_iter_dependents_v2(zfs_handle_t *, int, boolean_t, zfs_iter_f,
+ void *);
+_LIBZFS_H int zfs_iter_filesystems_v2(zfs_handle_t *, int, zfs_iter_f, void *);
+_LIBZFS_H int zfs_iter_snapshots_v2(zfs_handle_t *, int, zfs_iter_f, void *,
+ uint64_t, uint64_t);
+_LIBZFS_H int zfs_iter_snapshots_sorted_v2(zfs_handle_t *, int, zfs_iter_f,
+ void *, uint64_t, uint64_t);
+_LIBZFS_H int zfs_iter_snapspec_v2(zfs_handle_t *, int, const char *,
+ zfs_iter_f, void *);
+_LIBZFS_H int zfs_iter_bookmarks_v2(zfs_handle_t *, int, zfs_iter_f, void *);
_LIBZFS_H int zfs_iter_mounted(zfs_handle_t *, zfs_iter_f, void *);
typedef struct get_all_cb {
@@ -688,13 +738,13 @@ _LIBZFS_H 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;
_LIBZFS_H int zfs_rename(zfs_handle_t *, const char *, renameflags_t);
@@ -730,6 +780,9 @@ typedef struct sendflags {
/* show progress (ie. -v) */
boolean_t progress;
+ /* show progress as process title (ie. -V) */
+ boolean_t progressastitle;
+
/* large blocks (>128K) are permitted */
boolean_t largeblock;
@@ -829,6 +882,9 @@ typedef struct recvflags {
/* force unmount while recv snapshot (private) */
boolean_t forceunmount;
+
+ /* use this recv to check (and heal if needed) an existing snapshot */
+ boolean_t heal;
} recvflags_t;
_LIBZFS_H int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *,
@@ -893,6 +949,7 @@ _LIBZFS_H int zfs_unshare(zfs_handle_t *zhp, const char *mountpoint,
_LIBZFS_H int zfs_unshareall(zfs_handle_t *zhp,
const enum sa_protocol *proto);
_LIBZFS_H void zfs_commit_shares(const enum sa_protocol *proto);
+_LIBZFS_H void zfs_truncate_shares(const enum sa_protocol *proto);
_LIBZFS_H int zfs_nicestrtonum(libzfs_handle_t *, const char *, uint64_t *);
diff --git a/include/libzfs_core.h b/include/libzfs_core.h
index b826e94c4c18..867c18b9c226 100644
--- a/include/libzfs_core.h
+++ b/include/libzfs_core.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,9 +21,9 @@
/*
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
- * Copyright (c) 2017 Datto Inc.
* Copyright 2017 RackTop Systems.
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+ * Copyright (c) 2019 Datto Inc.
*/
#ifndef _LIBZFS_CORE_H
@@ -114,6 +114,10 @@ _LIBZFS_CORE_H int lzc_receive_with_cmdprops(const char *, nvlist_t *,
nvlist_t *, uint8_t *, uint_t, const char *, boolean_t, boolean_t,
boolean_t, int, const struct dmu_replay_record *, int, uint64_t *,
uint64_t *, uint64_t *, nvlist_t **);
+_LIBZFS_CORE_H int lzc_receive_with_heal(const char *, nvlist_t *, nvlist_t *,
+ uint8_t *, uint_t, const char *, boolean_t, boolean_t, boolean_t, boolean_t,
+ int, const struct dmu_replay_record *, int, uint64_t *, uint64_t *,
+ uint64_t *, nvlist_t **);
_LIBZFS_CORE_H int lzc_send_space(const char *, const char *,
enum lzc_send_flags, uint64_t *);
_LIBZFS_CORE_H int lzc_send_space_resume_redacted(const char *, const char *,
@@ -151,6 +155,8 @@ _LIBZFS_CORE_H int lzc_get_bootenv(const char *, nvlist_t **);
_LIBZFS_CORE_H int lzc_get_vdev_prop(const char *, nvlist_t *, nvlist_t **);
_LIBZFS_CORE_H int lzc_set_vdev_prop(const char *, nvlist_t *, nvlist_t **);
+_LIBZFS_CORE_H int lzc_scrub(zfs_ioc_t, const char *, nvlist_t *, nvlist_t **);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/libzutil.h b/include/libzutil.h
index a46059b128f9..e2108ceeaa44 100644
--- a/include/libzutil.h
+++ b/include/libzutil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,12 +20,14 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2018, 2024 by Delphix. All rights reserved.
*/
#ifndef _LIBZUTIL_H
#define _LIBZUTIL_H extern __attribute__((visibility("default")))
+#include <string.h>
+#include <locale.h>
#include <sys/nvpair.h>
#include <sys/fs/zfs.h>
@@ -34,7 +36,7 @@ extern "C" {
#endif
/*
- * Default wait time for a device name to be created.
+ * Default wait time in milliseconds for a device name to be created.
*/
#define DISK_LABEL_WAIT (30 * 1000) /* 30 seconds */
@@ -56,8 +58,17 @@ typedef const struct pool_config_ops {
/*
* An instance of pool_config_ops_t is expected in the caller's binary.
*/
-_LIBZUTIL_H const pool_config_ops_t libzfs_config_ops;
-_LIBZUTIL_H const pool_config_ops_t libzpool_config_ops;
+_LIBZUTIL_H pool_config_ops_t libzfs_config_ops;
+_LIBZUTIL_H pool_config_ops_t libzpool_config_ops;
+
+typedef enum lpc_error {
+ LPC_SUCCESS = 0, /* no error -- success */
+ LPC_BADCACHE = 2000, /* out of memory */
+ LPC_BADPATH, /* must be an absolute path */
+ LPC_NOMEM, /* out of memory */
+ LPC_EACCESS, /* some devices require root privileges */
+ LPC_UNKNOWN
+} lpc_error_t;
typedef struct importargs {
char **path; /* a list of paths to search */
@@ -68,16 +79,29 @@ typedef struct importargs {
boolean_t can_be_active; /* can the pool be active? */
boolean_t scan; /* prefer scanning to libblkid cache */
nvlist_t *policy; /* load policy (max txg, rewind, etc.) */
+ boolean_t do_destroyed;
+ boolean_t do_all;
} importargs_t;
-_LIBZUTIL_H nvlist_t *zpool_search_import(void *, importargs_t *,
- const pool_config_ops_t *);
-_LIBZUTIL_H int zpool_find_config(void *, const char *, nvlist_t **,
- importargs_t *, const pool_config_ops_t *);
+typedef struct libpc_handle {
+ int lpc_error;
+ boolean_t lpc_printerr;
+ boolean_t lpc_open_access_error;
+ boolean_t lpc_desc_active;
+ char lpc_desc[1024];
+ pool_config_ops_t *lpc_ops;
+ void *lpc_lib_handle;
+} libpc_handle_t;
+
+_LIBZUTIL_H const char *libpc_error_description(libpc_handle_t *);
+_LIBZUTIL_H nvlist_t *zpool_search_import(libpc_handle_t *, importargs_t *);
+_LIBZUTIL_H int zpool_find_config(libpc_handle_t *, const char *, nvlist_t **,
+ importargs_t *);
_LIBZUTIL_H const char * const * zpool_default_search_paths(size_t *count);
_LIBZUTIL_H int zpool_read_label(int, nvlist_t **, int *);
_LIBZUTIL_H int zpool_label_disk_wait(const char *, int);
+_LIBZUTIL_H int zpool_disk_wait(const char *);
struct udev_device;
@@ -144,23 +168,42 @@ _LIBZUTIL_H void zfs_niceraw(uint64_t, char *, size_t);
_LIBZUTIL_H void zpool_dump_ddt(const ddt_stat_t *, const ddt_histogram_t *);
_LIBZUTIL_H int zpool_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***,
uint_t *);
+_LIBZUTIL_H void fsleep(float sec);
+_LIBZUTIL_H int zpool_getenv_int(const char *env, int default_val);
struct zfs_cmd;
/*
* List of colors to use
*/
+#define ANSI_BLACK "\033[0;30m"
#define ANSI_RED "\033[0;31m"
+#define ANSI_GREEN "\033[0;32m"
#define ANSI_YELLOW "\033[0;33m"
+#define ANSI_BLUE "\033[0;34m"
+#define ANSI_BOLD_BLUE "\033[1;34m" /* light blue */
+#define ANSI_MAGENTA "\033[0;35m"
+#define ANSI_CYAN "\033[0;36m"
+#define ANSI_GRAY "\033[0;37m"
+
#define ANSI_RESET "\033[0m"
#define ANSI_BOLD "\033[1m"
+_LIBZUTIL_H int use_color(void);
_LIBZUTIL_H void color_start(const char *color);
_LIBZUTIL_H void color_end(void);
_LIBZUTIL_H int printf_color(const char *color, const char *format, ...);
_LIBZUTIL_H const char *zfs_basename(const char *path);
_LIBZUTIL_H ssize_t zfs_dirnamelen(const char *path);
+#ifdef __linux__
+extern char **environ;
+_LIBZUTIL_H void zfs_setproctitle_init(int argc, char *argv[], char *envp[]);
+_LIBZUTIL_H void zfs_setproctitle(const char *fmt, ...);
+#else
+#define zfs_setproctitle(fmt, ...) setproctitle(fmt, ##__VA_ARGS__)
+#define zfs_setproctitle_init(x, y, z) ((void)0)
+#endif
/*
* These functions are used by the ZFS libraries and cmd/zpool code, but are
@@ -169,9 +212,73 @@ _LIBZUTIL_H ssize_t zfs_dirnamelen(const char *path);
typedef int (*pool_vdev_iter_f)(void *, nvlist_t *, void *);
int for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func,
void *data);
+int for_each_vdev_macro_helper_func(void *zhp_data, nvlist_t *nv, void *data);
+int for_each_real_leaf_vdev_macro_helper_func(void *zhp_data, nvlist_t *nv,
+ void *data);
+/*
+ * Often you'll want to iterate over all the vdevs in the pool, but don't want
+ * to use for_each_vdev() since it requires a callback function.
+ *
+ * Instead you can use FOR_EACH_VDEV():
+ *
+ * zpool_handle_t *zhp // Assume this is initialized
+ * nvlist_t *nv
+ * ...
+ * FOR_EACH_VDEV(zhp, nv) {
+ * const char *path = NULL;
+ * nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path);
+ * printf("Looking at vdev %s\n", path);
+ * }
+ *
+ * Note: FOR_EACH_VDEV runs in O(n^2) time where n = number of vdevs. However,
+ * there's an upper limit of 256 vdevs per dRAID top-level vdevs (TLDs), 255 for
+ * raidz2 TLDs, a real world limit of ~500 vdevs for mirrors, so this shouldn't
+ * really be an issue.
+ *
+ * Here are some micro-benchmarks of a complete FOR_EACH_VDEV loop on a RAID0
+ * pool:
+ *
+ * 100 vdevs = 0.7ms
+ * 500 vdevs = 17ms
+ * 750 vdevs = 40ms
+ * 1000 vdevs = 82ms
+ *
+ * The '__nv += 0' at the end of the for() loop gets around a "comma or
+ * semicolon followed by non-blank" checkstyle error. Note on most compliers
+ * the '__nv += 0' can just be replaced with 'NULL', but gcc on Centos 7
+ * will give a 'warning: statement with no effect' error if you do that.
+ */
+#define __FOR_EACH_VDEV(__zhp, __nv, __func) { \
+ __nv = zpool_get_config(__zhp, NULL); \
+ VERIFY0(nvlist_lookup_nvlist(__nv, ZPOOL_CONFIG_VDEV_TREE, &__nv)); \
+ } \
+ for (nvlist_t *__root_nv = __nv, *__state = (nvlist_t *)0; \
+ for_each_vdev_cb(&__state, __root_nv, __func, &__nv) == 1; \
+ __nv += 0)
+
+#define FOR_EACH_VDEV(__zhp, __nv) \
+ __FOR_EACH_VDEV(__zhp, __nv, for_each_vdev_macro_helper_func)
+
+/*
+ * "real leaf" vdevs are leaf vdevs that are real devices (disks or files).
+ * This excludes leaf vdevs like like draid spares.
+ */
+#define FOR_EACH_REAL_LEAF_VDEV(__zhp, __nv) \
+ __FOR_EACH_VDEV(__zhp, __nv, for_each_real_leaf_vdev_macro_helper_func)
+
int for_each_vdev_in_nvlist(nvlist_t *nvroot, pool_vdev_iter_f func,
void *data);
void update_vdevs_config_dev_sysfs_path(nvlist_t *config);
+_LIBZUTIL_H void update_vdev_config_dev_sysfs_path(nvlist_t *nv,
+ const char *path, const char *key);
+
+/*
+ * Thread-safe strerror() for use in ZFS libraries
+ */
+static inline char *zfs_strerror(int errnum) {
+ return (strerror_l(errnum, uselocale(0)));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/include/os/freebsd/Makefile.am b/include/os/freebsd/Makefile.am
index 5ddb7cd710b8..292f79b8ce72 100644
--- a/include/os/freebsd/Makefile.am
+++ b/include/os/freebsd/Makefile.am
@@ -4,7 +4,7 @@ noinst_HEADERS = \
\
%D%/spl/acl/acl_common.h \
\
- %D%/spl/rpc/xdr.h \
+ %D%/spl/sys/ia32/asm_linkage.h \
\
%D%/spl/sys/acl.h \
%D%/spl/sys/acl_impl.h \
@@ -20,8 +20,6 @@ noinst_HEADERS = \
%D%/spl/sys/debug.h \
%D%/spl/sys/dirent.h \
%D%/spl/sys/disp.h \
- %D%/spl/sys/dkio.h \
- %D%/spl/sys/extdirent.h \
%D%/spl/sys/fcntl.h \
%D%/spl/sys/file.h \
%D%/spl/sys/freebsd_rwlock.h \
@@ -50,6 +48,9 @@ noinst_HEADERS = \
%D%/spl/sys/sid.h \
%D%/spl/sys/sig.h \
%D%/spl/sys/simd.h \
+ %D%/spl/sys/simd_aarch64.h \
+ %D%/spl/sys/simd_arm.h \
+ %D%/spl/sys/simd_powerpc.h \
%D%/spl/sys/simd_x86.h \
%D%/spl/sys/spl_condvar.h \
%D%/spl/sys/string.h \
@@ -76,8 +77,9 @@ noinst_HEADERS = \
%D%/spl/sys/zmod.h \
%D%/spl/sys/zone.h \
\
+ %D%/zfs/sys/arc_os.h \
%D%/zfs/sys/freebsd_crypto.h \
- %D%/zfs/sys/sha2.h \
+ %D%/zfs/sys/freebsd_event.h \
%D%/zfs/sys/vdev_os.h \
%D%/zfs/sys/zfs_bootenv_os.h \
%D%/zfs/sys/zfs_context_os.h \
@@ -88,3 +90,4 @@ noinst_HEADERS = \
%D%/zfs/sys/zfs_vnops_os.h \
%D%/zfs/sys/zfs_znode_impl.h \
%D%/zfs/sys/zpl.h
+
diff --git a/include/os/freebsd/linux/compiler.h b/include/os/freebsd/linux/compiler.h
index 3a66da195891..b408b77c746d 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/acl/acl_common.h b/include/os/freebsd/spl/acl/acl_common.h
index 44f5bed592f6..53b69154d671 100644
--- a/include/os/freebsd/spl/acl/acl_common.h
+++ b/include/os/freebsd/spl/acl/acl_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -47,7 +47,7 @@ extern int acltrivial(const char *);
extern void adjust_ace_pair(ace_t *pair, mode_t mode);
extern void adjust_ace_pair_common(void *, size_t, size_t, mode_t);
extern int ace_trivial_common(void *, int,
- uint64_t (*walk)(void *, uint64_t, int aclcnt, uint16_t *, uint16_t *,
+ uintptr_t (*walk)(void *, uintptr_t, int aclcnt, uint16_t *, uint16_t *,
uint32_t *mask));
#if !defined(_KERNEL)
extern acl_t *acl_alloc(acl_type_t);
diff --git a/include/os/freebsd/spl/rpc/xdr.h b/include/os/freebsd/spl/rpc/xdr.h
deleted file mode 100644
index c98466e9d16a..000000000000
--- a/include/os/freebsd/spl/rpc/xdr.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-#ifndef _OPENSOLARIS_RPC_XDR_H_
-#define _OPENSOLARIS_RPC_XDR_H_
-
-#include <rpc/types.h>
-#include_next <rpc/xdr.h>
-
-#if !defined(_KERNEL) && !defined(_STANDALONE)
-
-#include <assert.h>
-
-/*
- * Taken from sys/xdr/xdr_mem.c.
- *
- * FreeBSD's userland XDR doesn't implement control method (only the kernel),
- * but OpenSolaris nvpair still depend on it, so we have to implement it here.
- */
-static __inline bool_t
-xdrmem_control(XDR *xdrs, int request, void *info)
-{
- xdr_bytesrec *xptr;
-
- switch (request) {
- case XDR_GET_BYTES_AVAIL:
- xptr = (xdr_bytesrec *)info;
- xptr->xc_is_last_record = TRUE;
- xptr->xc_num_avail = xdrs->x_handy;
- return (TRUE);
- default:
- assert(!"unexpected request");
- }
- return (FALSE);
-}
-
-#undef XDR_CONTROL
-#define XDR_CONTROL(xdrs, req, op) \
- (((xdrs)->x_ops->x_control == NULL) ? \
- xdrmem_control((xdrs), (req), (op)) : \
- (*(xdrs)->x_ops->x_control)(xdrs, req, op))
-
-#endif /* !_KERNEL && !_STANDALONE */
-
-#endif /* !_OPENSOLARIS_RPC_XDR_H_ */
diff --git a/include/os/freebsd/spl/sys/acl.h b/include/os/freebsd/spl/sys/acl.h
index ee50b0a18368..e757a601a842 100644
--- a/include/os/freebsd/spl/sys/acl.h
+++ b/include/os/freebsd/spl/sys/acl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/acl_impl.h b/include/os/freebsd/spl/sys/acl_impl.h
index 1efbd6d73bd0..de5961ef7740 100644
--- a/include/os/freebsd/spl/sys/acl_impl.h
+++ b/include/os/freebsd/spl/sys/acl_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/atomic.h b/include/os/freebsd/spl/sys/atomic.h
index 1a68bfc4de23..40a67704fde0 100644
--- a/include/os/freebsd/spl/sys/atomic.h
+++ b/include/os/freebsd/spl/sys/atomic.h
@@ -57,7 +57,9 @@ 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()
+#define membar_sync() atomic_thread_fence_seq_cst()
static __inline uint32_t
atomic_add_32_nv(volatile uint32_t *target, int32_t delta)
@@ -165,7 +167,7 @@ atomic_dec_64_nv(volatile uint64_t *target)
return (atomic_add_64_nv(target, -1));
}
-#if !defined(COMPAT_32BIT) && defined(__LP64__)
+#ifdef __LP64__
static __inline void *
atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
{
@@ -179,7 +181,7 @@ atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
return ((void *)atomic_cas_32((volatile uint32_t *)target,
(uint32_t)cmp, (uint32_t)newval));
}
-#endif /* !defined(COMPAT_32BIT) && defined(__LP64__) */
+#endif /* __LP64__ */
#else /* _STANDALONE */
/*
@@ -188,6 +190,8 @@ atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
*/
#undef atomic_add_64
#define atomic_add_64(ptr, val) *(ptr) += val
+#undef atomic_sub_64
+#define atomic_sub_64(ptr, val) *(ptr) -= val
#endif /* !_STANDALONE */
#endif /* !_OPENSOLARIS_SYS_ATOMIC_H_ */
diff --git a/include/os/freebsd/spl/sys/byteorder.h b/include/os/freebsd/spl/sys/byteorder.h
index 0b3d01eb3759..0c09757c8e15 100644
--- a/include/os/freebsd/spl/sys/byteorder.h
+++ b/include/os/freebsd/spl/sys/byteorder.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -44,6 +44,18 @@
#include <sys/endian.h>
+#ifdef __COVERITY__
+/*
+ * Coverity's taint warnings from byteswapping are false positives for us.
+ * Suppress them by hiding byteswapping from Coverity.
+ */
+#define BSWAP_8(x) ((x) & 0xff)
+#define BSWAP_16(x) ((x) & 0xffff)
+#define BSWAP_32(x) ((x) & 0xffffffff)
+#define BSWAP_64(x) (x)
+
+#else /* __COVERITY__ */
+
/*
* Macros to reverse byte order
*/
@@ -52,6 +64,8 @@
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
+#endif /* __COVERITY__ */
+
#define BMASK_8(x) ((x) & 0xff)
#define BMASK_16(x) ((x) & 0xffff)
#define BMASK_32(x) ((x) & 0xffffffff)
diff --git a/include/os/freebsd/spl/sys/callb.h b/include/os/freebsd/spl/sys/callb.h
index d51132d4e612..006a90cae8c0 100644
--- a/include/os/freebsd/spl/sys/callb.h
+++ b/include/os/freebsd/spl/sys/callb.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/ccompat.h b/include/os/freebsd/spl/sys/ccompat.h
index eaee9159eabd..e34bab7e896d 100644
--- a/include/os/freebsd/spl/sys/ccompat.h
+++ b/include/os/freebsd/spl/sys/ccompat.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/include/os/freebsd/spl/sys/ccompile.h b/include/os/freebsd/spl/sys/ccompile.h
index 90b077a7be4e..26cf4db87aea 100644
--- a/include/os/freebsd/spl/sys/ccompile.h
+++ b/include/os/freebsd/spl/sys/ccompile.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/cmn_err.h b/include/os/freebsd/spl/sys/cmn_err.h
index ddc2f0049e59..87fce4955bc1 100644
--- a/include/os/freebsd/spl/sys/cmn_err.h
+++ b/include/os/freebsd/spl/sys/cmn_err.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,6 +33,7 @@
#if !defined(_ASM)
#include <sys/_stdarg.h>
+#include <sys/atomic.h>
#endif
#ifdef __cplusplus
@@ -71,7 +72,39 @@ extern void vuprintf(const char *, __va_list)
__attribute__((format(printf, 1, 0)));
extern void panic(const char *, ...)
- __attribute__((format(printf, 1, 2)));
+ __attribute__((format(printf, 1, 2), __noreturn__));
+
+#define cmn_err_once(ce, ...) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ cmn_err(ce, __VA_ARGS__); \
+ } \
+} while (0)
+
+#define vcmn_err_once(ce, fmt, ap) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ vcmn_err(ce, fmt, ap); \
+ } \
+} while (0)
+
+#define zcmn_err_once(zone, ce, ...) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ zcmn_err(zone, ce, __VA_ARGS__); \
+ } \
+} while (0)
+
+#define vzcmn_err_once(zone, ce, fmt, ap) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ vzcmn_err(zone, ce, fmt, ap); \
+ } \
+} while (0)
#endif /* !_ASM */
diff --git a/include/os/freebsd/spl/sys/cred.h b/include/os/freebsd/spl/sys/cred.h
index db986af57bf5..06d537126285 100644
--- a/include/os/freebsd/spl/sys/cred.h
+++ b/include/os/freebsd/spl/sys/cred.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/ctype.h b/include/os/freebsd/spl/sys/ctype.h
index 53afd8b8bd42..b9ca0f8ef2c4 100644
--- a/include/os/freebsd/spl/sys/ctype.h
+++ b/include/os/freebsd/spl/sys/ctype.h
@@ -39,5 +39,6 @@
((C) >= 0x3A && (C) <= 0x40) || \
((C) >= 0x5B && (C) <= 0x60) || \
((C) >= 0x7B && (C) <= 0x7E))
+#define isspace(C) ((C) == 0x20 || ((C) >= 0x9 && (C) <= 0xD))
#endif
diff --git a/include/os/freebsd/spl/sys/debug.h b/include/os/freebsd/spl/sys/debug.h
index 86fad18e17d2..f041dde34fc8 100644
--- a/include/os/freebsd/spl/sys/debug.h
+++ b/include/os/freebsd/spl/sys/debug.h
@@ -39,12 +39,14 @@
* ASSERT3U() - Assert unsigned X OP Y is true, if not panic.
* ASSERT3P() - Assert pointer X OP Y is true, if not panic.
* ASSERT0() - Assert value is zero, if not panic.
+ * ASSERT0P() - Assert pointer is null, if not panic.
* VERIFY() - Verify X is true, if not panic.
* VERIFY3B() - Verify boolean X OP Y is true, if not panic.
* VERIFY3S() - Verify signed X OP Y is true, if not panic.
* VERIFY3U() - Verify unsigned X OP Y is true, if not panic.
* VERIFY3P() - Verify pointer X OP Y is true, if not panic.
* VERIFY0() - Verify value is zero, if not panic.
+ * VERIFY0P() - Verify pointer is null, if not panic.
*/
#ifndef _SPL_DEBUG_H
@@ -54,23 +56,63 @@
/*
* Common DEBUG functionality.
*/
-int spl_panic(const char *file, const char *func, int line,
+#ifdef __FreeBSD__
+#include <linux/compiler.h>
+#endif
+
+#ifndef __printflike
+#define __printflike(a, b) __printf(a, b)
+#endif
+
+#ifndef __maybe_unused
+#define __maybe_unused __attribute__((unused))
+#endif
+
+/*
+ * Without this, we see warnings from objtool during normal Linux builds when
+ * the kernel is built with CONFIG_STACK_VALIDATION=y:
+ *
+ * warning: objtool: tsd_create() falls through to next function __list_add()
+ * warning: objtool: .text: unexpected end of section
+ *
+ * Until the toolchain stops doing this, we must only define this attribute on
+ * spl_panic() when doing static analysis.
+ */
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+__attribute__((__noreturn__))
+#endif
+extern void spl_panic(const char *file, const char *func, int line,
const char *fmt, ...);
-void spl_dumpstack(void);
+extern void spl_dumpstack(void);
+
+static inline int
+spl_assert(const char *buf, const char *file, const char *func, int line)
+{
+ spl_panic(file, func, line, "%s", buf);
+ return (0);
+}
#ifndef expect
#define expect(expr, value) (__builtin_expect((expr), (value)))
#endif
+#ifndef __linux__
#define likely(expr) expect((expr) != 0, 1)
#define unlikely(expr) expect((expr) != 0, 0)
+#endif
#define PANIC(fmt, a...) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "%s", "VERIFY(" #cond ") failed\n"))
+ spl_assert("VERIFY(" #cond ") failed\n", \
+ __FILE__, __FUNCTION__, __LINE__))
+
+#define VERIFYF(cond, str, ...) do { \
+ if (unlikely(!cond)) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY(" #cond ") failed " str "\n", __VA_ARGS__);\
+ } while (0)
#define VERIFY3B(LEFT, OP, RIGHT) do { \
const boolean_t _verify3_left = (boolean_t)(LEFT); \
@@ -79,8 +121,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%d " #OP " %d)\n", \
- (boolean_t)(_verify3_left), \
- (boolean_t)(_verify3_right)); \
+ (boolean_t)_verify3_left, \
+ (boolean_t)_verify3_right); \
} while (0)
#define VERIFY3S(LEFT, OP, RIGHT) do { \
@@ -90,8 +132,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%lld " #OP " %lld)\n", \
- (long long) (_verify3_left), \
- (long long) (_verify3_right)); \
+ (long long)_verify3_left, \
+ (long long)_verify3_right); \
} while (0)
#define VERIFY3U(LEFT, OP, RIGHT) do { \
@@ -101,8 +143,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%llu " #OP " %llu)\n", \
- (unsigned long long) (_verify3_left), \
- (unsigned long long) (_verify3_right)); \
+ (unsigned long long)_verify3_left, \
+ (unsigned long long)_verify3_right); \
} while (0)
#define VERIFY3P(LEFT, OP, RIGHT) do { \
@@ -112,20 +154,116 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%px " #OP " %px)\n", \
- (void *) (_verify3_left), \
- (void *) (_verify3_right)); \
+ (void *)_verify3_left, \
+ (void *)_verify3_right); \
} while (0)
#define VERIFY0(RIGHT) do { \
+ const int64_t _verify0_right = (int64_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(" #RIGHT ") " \
+ "failed (0 == %lld)\n", \
+ (long long)_verify0_right); \
+ } while (0)
+
+#define VERIFY0P(RIGHT) do { \
+ const uintptr_t _verify0_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0P(" #RIGHT ") " \
+ "failed (NULL == %px)\n", \
+ (void *)_verify0_right); \
+ } while (0)
+
+/*
+ * Note that you should not put any operations you want to always happen
+ * in the print section for ASSERTs unless you only want them to run on
+ * debug builds!
+ * e.g. ASSERT3UF(2, <, 3, "%s", foo(x)), foo(x) won't run on non-debug
+ * builds.
+ */
+
+#define VERIFY3BF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (boolean_t)(_verify3_left), \
+ (boolean_t)(_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY3SF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (long long)(_verify3_left), \
+ (long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3UF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (unsigned long long)(_verify3_left), \
+ (unsigned long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3PF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (void *) (_verify3_left), \
+ (void *) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0PF(RIGHT, STR, ...) do { \
+ const uintptr_t _verify3_left = (uintptr_t)(0); \
+ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(_verify3_left == _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %px) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0F(RIGHT, STR, ...) 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)); \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %lld) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
} while (0)
+#define VERIFY_IMPLY(A, B) \
+ ((void)(likely((!(A)) || (B)) || \
+ spl_assert("(" #A ") implies (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
+#define VERIFY_EQUIV(A, B) \
+ ((void)(likely(!!(A) == !!(B)) || \
+ spl_assert("(" #A ") is equivalent to (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
/*
* Debugging disabled (--disable-debug)
*/
@@ -141,6 +279,14 @@ void spl_dumpstack(void);
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT3BF(x, y, z, str, ...) ASSERT3B(x, y, z)
+#define ASSERT3SF(x, y, z, str, ...) ASSERT3S(x, y, z)
+#define ASSERT3UF(x, y, z, str, ...) ASSERT3U(x, y, z)
+#define ASSERT3PF(x, y, z, str, ...) ASSERT3P(x, y, z)
+#define ASSERT0PF(x, str, ...) ASSERT0P(x)
+#define ASSERT0F(x, str, ...) ASSERT0(x)
+#define ASSERTF(x, str, ...) ASSERT(x)
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
#define EQUIV(A, B) \
@@ -156,15 +302,17 @@ void spl_dumpstack(void);
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
+#define ASSERT0P VERIFY0P
+#define ASSERT3BF VERIFY3BF
+#define ASSERT3SF VERIFY3SF
+#define ASSERT3UF VERIFY3UF
+#define ASSERT3PF VERIFY3PF
+#define ASSERT0PF VERIFY0PF
+#define ASSERT0F VERIFY0F
+#define ASSERTF VERIFYF
#define ASSERT VERIFY
-#define IMPLY(A, B) \
- ((void)(likely((!(A)) || (B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") implies (" #B ")")))
-#define EQUIV(A, B) \
- ((void)(likely(!!(A) == !!(B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") is equivalent to (" #B ")")))
+#define IMPLY VERIFY_IMPLY
+#define EQUIV VERIFY_EQUIV
#endif /* NDEBUG */
diff --git a/include/os/freebsd/spl/sys/disp.h b/include/os/freebsd/spl/sys/disp.h
index 2be1b76e4334..d46a7d2c0143 100644
--- a/include/os/freebsd/spl/sys/disp.h
+++ b/include/os/freebsd/spl/sys/disp.h
@@ -31,6 +31,8 @@
#include <sys/proc.h>
+#define KPREEMPT_SYNC (-1)
+
#define kpreempt(x) kern_yield(PRI_USER)
#endif /* _OPENSOLARIS_SYS_DISP_H_ */
diff --git a/include/os/freebsd/spl/sys/dkio.h b/include/os/freebsd/spl/sys/dkio.h
deleted file mode 100644
index aed54ba50893..000000000000
--- a/include/os/freebsd/spl/sys/dkio.h
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * $FreeBSD$
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _OPENSOLARIS_SYS_DKIO_H_
-#define _OPENSOLARIS_SYS_DKIO_H_
-
-#include <sys/types.h> /* Needed for NDKMAP define */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(_SUNOS_VTOC_16)
-#define NDKMAP 16 /* # of logical partitions */
-#define DK_LABEL_LOC 1 /* location of disk label */
-#elif defined(_SUNOS_VTOC_8)
-#define NDKMAP 8 /* # of logical partitions */
-#define DK_LABEL_LOC 0 /* location of disk label */
-#else
-#error "No VTOC format defined."
-#endif
-
-/*
- * Structures and definitions for disk io control commands
- */
-
-/*
- * Structures used as data by ioctl calls.
- */
-
-#define DK_DEVLEN 16 /* device name max length, including */
- /* unit # & NULL (ie - "xyc1") */
-
-/*
- * Used for controller info
- */
-struct dk_cinfo {
- char dki_cname[DK_DEVLEN]; /* controller name (no unit #) */
- ushort_t dki_ctype; /* controller type */
- ushort_t dki_flags; /* flags */
- ushort_t dki_cnum; /* controller number */
- uint_t dki_addr; /* controller address */
- uint_t dki_space; /* controller bus type */
- uint_t dki_prio; /* interrupt priority */
- uint_t dki_vec; /* interrupt vector */
- char dki_dname[DK_DEVLEN]; /* drive name (no unit #) */
- uint_t dki_unit; /* unit number */
- ushort_t dki_partition; /* partition number */
- ushort_t dki_maxtransfer; /* max. transfer size in DEV_BSIZE */
-};
-
-/*
- * Controller types
- */
-#define DKC_UNKNOWN 0
-#define DKC_CDROM 1 /* CD-ROM, SCSI or otherwise */
-#define DKC_WDC2880 2
-#define DKC_XXX_0 3 /* unassigned */
-#define DKC_XXX_1 4 /* unassigned */
-#define DKC_DSD5215 5
-#define DKC_ACB4000 7
-#define DKC_MD21 8
-#define DKC_XXX_2 9 /* unassigned */
-#define DKC_NCRFLOPPY 10
-#define DKC_SMSFLOPPY 12
-#define DKC_SCSI_CCS 13 /* SCSI CCS compatible */
-#define DKC_INTEL82072 14 /* native floppy chip */
-#define DKC_MD 16 /* meta-disk (virtual-disk) driver */
-#define DKC_INTEL82077 19 /* 82077 floppy disk controller */
-#define DKC_DIRECT 20 /* Intel direct attached device i.e. IDE */
-#define DKC_PCMCIA_MEM 21 /* PCMCIA memory disk-like type */
-#define DKC_PCMCIA_ATA 22 /* PCMCIA AT Attached type */
-#define DKC_VBD 23 /* virtual block device */
-
-/*
- * Sun reserves up through 1023
- */
-
-#define DKC_CUSTOMER_BASE 1024
-
-/*
- * Flags
- */
-#define DKI_BAD144 0x01 /* use DEC std 144 bad sector fwding */
-#define DKI_MAPTRK 0x02 /* controller does track mapping */
-#define DKI_FMTTRK 0x04 /* formats only full track at a time */
-#define DKI_FMTVOL 0x08 /* formats only full volume at a time */
-#define DKI_FMTCYL 0x10 /* formats only full cylinders at a time */
-#define DKI_HEXUNIT 0x20 /* unit number is printed as 3 hex digits */
-#define DKI_PCMCIA_PFD 0x40 /* PCMCIA pseudo-floppy memory card */
-
-/*
- * partition headers: section 1
- * Returned in struct dk_allmap by ioctl DKIOC[SG]APART (dkio(7I))
- */
-struct dk_map {
- uint64_t dkl_cylno; /* starting cylinder */
- uint64_t dkl_nblk; /* number of blocks; if == 0, */
- /* partition is undefined */
-};
-
-/*
- * Used for all partitions
- */
-struct dk_allmap {
- struct dk_map dka_map[NDKMAP];
-};
-
-#if defined(_SYSCALL32)
-struct dk_allmap32 {
- struct dk_map32 dka_map[NDKMAP];
-};
-#endif /* _SYSCALL32 */
-
-/*
- * Definition of a disk's geometry
- */
-struct dk_geom {
- unsigned short dkg_ncyl; /* # of data cylinders */
- unsigned short dkg_acyl; /* # of alternate cylinders */
- unsigned short dkg_bcyl; /* cyl offset (for fixed head area) */
- unsigned short dkg_nhead; /* # of heads */
- unsigned short dkg_obs1; /* obsolete */
- unsigned short dkg_nsect; /* # of data sectors per track */
- unsigned short dkg_intrlv; /* interleave factor */
- unsigned short dkg_obs2; /* obsolete */
- unsigned short dkg_obs3; /* obsolete */
- unsigned short dkg_apc; /* alternates per cyl (SCSI only) */
- unsigned short dkg_rpm; /* revolutions per minute */
- unsigned short dkg_pcyl; /* # of physical cylinders */
- unsigned short dkg_write_reinstruct; /* # sectors to skip, writes */
- unsigned short dkg_read_reinstruct; /* # sectors to skip, reads */
- unsigned short dkg_extra[7]; /* for compatible expansion */
-};
-
-/*
- * These defines are for historic compatibility with old drivers.
- */
-#define dkg_bhead dkg_obs1 /* used to be head offset */
-#define dkg_gap1 dkg_obs2 /* used to be gap1 */
-#define dkg_gap2 dkg_obs3 /* used to be gap2 */
-
-/*
- * Disk io control commands
- * Warning: some other ioctls with the DIOC prefix exist elsewhere.
- * The Generic DKIOC numbers are from 0 - 50.
- * The Floppy Driver uses 51 - 100.
- * The Hard Disk (except SCSI) 101 - 106. (these are obsolete)
- * The CDROM Driver 151 - 200.
- * The USCSI ioctl 201 - 250.
- */
-#define DKIOC (0x04 << 8)
-
-/*
- * The following ioctls are generic in nature and need to be
- * supported as appropriate by all disk drivers
- */
-#define DKIOCGGEOM (DKIOC|1) /* Get geometry */
-#define DKIOCINFO (DKIOC|3) /* Get info */
-#define DKIOCEJECT (DKIOC|6) /* Generic 'eject' */
-#define DKIOCGVTOC (DKIOC|11) /* Get VTOC */
-#define DKIOCSVTOC (DKIOC|12) /* Set VTOC & Write to Disk */
-
-/*
- * Disk Cache Controls. These ioctls should be supported by
- * all disk drivers.
- *
- * DKIOCFLUSHWRITECACHE when used from user-mode ignores the ioctl
- * argument, but it should be passed as NULL to allow for future
- * reinterpretation. From user-mode, this ioctl request is synchronous.
- *
- * When invoked from within the kernel, the arg can be NULL to indicate
- * a synchronous request or can be the address of a struct dk_callback
- * to request an asynchronous callback when the flush request is complete.
- * In this case, the flag to the ioctl must include FKIOCTL and the
- * dkc_callback field of the pointed to struct must be non-null or the
- * request is made synchronously.
- *
- * In the callback case: if the ioctl returns 0, a callback WILL be performed.
- * If the ioctl returns non-zero, a callback will NOT be performed.
- * NOTE: In some cases, the callback may be done BEFORE the ioctl call
- * returns. The caller's locking strategy should be prepared for this case.
- */
-#define DKIOCFLUSHWRITECACHE (DKIOC|34) /* flush cache to phys medium */
-
-struct dk_callback {
- void (*dkc_callback)(void *dkc_cookie, int error);
- void *dkc_cookie;
- int dkc_flag;
-};
-
-/* bit flag definitions for dkc_flag */
-#define FLUSH_VOLATILE 0x1 /* Bit 0: if set, only flush */
- /* volatile cache; otherwise, flush */
- /* volatile and non-volatile cache */
-
-#define DKIOCGETWCE (DKIOC|36) /* Get current write cache */
- /* enablement status */
-#define DKIOCSETWCE (DKIOC|37) /* Enable/Disable write cache */
-
-/*
- * The following ioctls are used by Sun drivers to communicate
- * with their associated format routines. Support of these ioctls
- * is not required of foreign drivers
- */
-#define DKIOCSGEOM (DKIOC|2) /* Set geometry */
-#define DKIOCSAPART (DKIOC|4) /* Set all partitions */
-#define DKIOCGAPART (DKIOC|5) /* Get all partitions */
-#define DKIOCG_PHYGEOM (DKIOC|32) /* get physical geometry */
-#define DKIOCG_VIRTGEOM (DKIOC|33) /* get virtual geometry */
-
-/*
- * The following ioctl's are removable media support
- */
-#define DKIOCLOCK (DKIOC|7) /* Generic 'lock' */
-#define DKIOCUNLOCK (DKIOC|8) /* Generic 'unlock' */
-#define DKIOCSTATE (DKIOC|13) /* Inquire insert/eject state */
-#define DKIOCREMOVABLE (DKIOC|16) /* is media removable */
-
-
-/*
- * ioctl for hotpluggable devices
- */
-#define DKIOCHOTPLUGGABLE (DKIOC|35) /* is hotpluggable */
-
-/*
- * Ioctl to force driver to re-read the alternate partition and rebuild
- * the internal defect map.
- */
-#define DKIOCADDBAD (DKIOC|20) /* Re-read the alternate map (IDE) */
-#define DKIOCGETDEF (DKIOC|21) /* read defect list (IDE) */
-
-/*
- * Used by applications to get disk defect information from IDE
- * drives.
- */
-#ifdef _SYSCALL32
-struct defect_header32 {
- int head;
- caddr32_t buffer;
-};
-#endif /* _SYSCALL32 */
-
-struct defect_header {
- int head;
- caddr_t buffer;
-};
-
-#define DKIOCPARTINFO (DKIOC|22) /* Get partition or slice parameters */
-
-/*
- * Used by applications to get partition or slice information
- */
-#ifdef _SYSCALL32
-struct part_info32 {
- uint32_t p_start;
- int p_length;
-};
-#endif /* _SYSCALL32 */
-
-struct part_info {
- uint64_t p_start;
- int p_length;
-};
-
-/* The following ioctls are for Optical Memory Device */
-#define DKIOC_EBP_ENABLE (DKIOC|40) /* enable by pass erase on write */
-#define DKIOC_EBP_DISABLE (DKIOC|41) /* disable by pass erase on write */
-
-/*
- * This state enum is the argument passed to the DKIOCSTATE ioctl.
- */
-enum dkio_state { DKIO_NONE, DKIO_EJECTED, DKIO_INSERTED, DKIO_DEV_GONE };
-
-#define DKIOCGMEDIAINFO (DKIOC|42) /* get information about the media */
-
-/*
- * ioctls to read/write mboot info.
- */
-#define DKIOCGMBOOT (DKIOC|43) /* get mboot info */
-#define DKIOCSMBOOT (DKIOC|44) /* set mboot info */
-
-/*
- * ioctl to get the device temperature.
- */
-#define DKIOCGTEMPERATURE (DKIOC|45) /* get temperature */
-
-/*
- * Used for providing the temperature.
- */
-
-struct dk_temperature {
- uint_t dkt_flags; /* Flags */
- short dkt_cur_temp; /* Current disk temperature */
- short dkt_ref_temp; /* reference disk temperature */
-};
-
-#define DKT_BYPASS_PM 0x1
-#define DKT_INVALID_TEMP 0xFFFF
-
-
-/*
- * Media types or profiles known
- */
-#define DK_UNKNOWN 0x00 /* Media inserted - type unknown */
-
-
-/*
- * SFF 8090 Specification Version 3, media types 0x01 - 0xfffe are retained to
- * maintain compatibility with SFF8090. The following define the
- * optical media type.
- */
-#define DK_REMOVABLE_DISK 0x02 /* Removable Disk */
-#define DK_MO_ERASABLE 0x03 /* MO Erasable */
-#define DK_MO_WRITEONCE 0x04 /* MO Write once */
-#define DK_AS_MO 0x05 /* AS MO */
-#define DK_CDROM 0x08 /* CDROM */
-#define DK_CDR 0x09 /* CD-R */
-#define DK_CDRW 0x0A /* CD-RW */
-#define DK_DVDROM 0x10 /* DVD-ROM */
-#define DK_DVDR 0x11 /* DVD-R */
-#define DK_DVDRAM 0x12 /* DVD_RAM or DVD-RW */
-
-/*
- * Media types for other rewritable magnetic media
- */
-#define DK_FIXED_DISK 0x10001 /* Fixed disk SCSI or otherwise */
-#define DK_FLOPPY 0x10002 /* Floppy media */
-#define DK_ZIP 0x10003 /* IOMEGA ZIP media */
-#define DK_JAZ 0x10004 /* IOMEGA JAZ media */
-
-#define DKIOCSETEFI (DKIOC|17) /* Set EFI info */
-#define DKIOCGETEFI (DKIOC|18) /* Get EFI info */
-
-#define DKIOCPARTITION (DKIOC|9) /* Get partition info */
-
-/*
- * Ioctls to get/set volume capabilities related to Logical Volume Managers.
- * They include the ability to get/set capabilities and to issue a read to a
- * specific underlying device of a replicated device.
- */
-
-#define DKIOCGETVOLCAP (DKIOC | 25) /* Get volume capabilities */
-#define DKIOCSETVOLCAP (DKIOC | 26) /* Set volume capabilities */
-#define DKIOCDMR (DKIOC | 27) /* Issue a directed read */
-
-typedef uint_t volcapinfo_t;
-
-typedef uint_t volcapset_t;
-
-#define DKV_ABR_CAP 0x00000001 /* Support Appl.Based Recovery */
-#define DKV_DMR_CAP 0x00000002 /* Support Directed Mirror Read */
-
-typedef struct volcap {
- volcapinfo_t vc_info; /* Capabilities available */
- volcapset_t vc_set; /* Capabilities set */
-} volcap_t;
-
-#define VOL_SIDENAME 256
-
-typedef struct vol_directed_rd {
- int vdr_flags;
- offset_t vdr_offset;
- size_t vdr_nbytes;
- size_t vdr_bytesread;
- void *vdr_data;
- int vdr_side;
- char vdr_side_name[VOL_SIDENAME];
-} vol_directed_rd_t;
-
-#define DKV_SIDE_INIT (-1)
-#define DKV_DMR_NEXT_SIDE 0x00000001
-#define DKV_DMR_DONE 0x00000002
-#define DKV_DMR_ERROR 0x00000004
-#define DKV_DMR_SUCCESS 0x00000008
-#define DKV_DMR_SHORT 0x00000010
-
-#ifdef _MULTI_DATAMODEL
-#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
-#pragma pack(4)
-#endif
-typedef struct vol_directed_rd32 {
- int32_t vdr_flags;
- offset_t vdr_offset; /* 64-bit element on 32-bit alignment */
- size32_t vdr_nbytes;
- size32_t vdr_bytesread;
- caddr32_t vdr_data;
- int32_t vdr_side;
- char vdr_side_name[VOL_SIDENAME];
-} vol_directed_rd32_t;
-#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
-#pragma pack()
-#endif
-#endif /* _MULTI_DATAMODEL */
-
-/*
- * The ioctl is used to fetch disk's device type, vendor ID,
- * model number/product ID, firmware revision and serial number together.
- *
- * Currently there are two device types - DKD_ATA_TYPE which means the
- * disk is driven by cmdk/ata or dad/uata driver, and DKD_SCSI_TYPE
- * which means the disk is driven by sd/scsi hba driver.
- */
-#define DKIOC_GETDISKID (DKIOC|46)
-
-/* These two labels are for dkd_dtype of dk_disk_id_t */
-#define DKD_ATA_TYPE 0x01 /* ATA disk or legacy mode SATA disk */
-#define DKD_SCSI_TYPE 0x02 /* SCSI disk or native mode SATA disk */
-
-#define DKD_ATA_MODEL 40 /* model number length */
-#define DKD_ATA_FWVER 8 /* firmware revision length */
-#define DKD_ATA_SERIAL 20 /* serial number length */
-
-#define DKD_SCSI_VENDOR 8 /* vendor ID length */
-#define DKD_SCSI_PRODUCT 16 /* product ID length */
-#define DKD_SCSI_REVLEVEL 4 /* revision level length */
-#define DKD_SCSI_SERIAL 12 /* serial number length */
-
-/*
- * The argument type for DKIOC_GETDISKID ioctl.
- */
-typedef struct dk_disk_id {
- uint_t dkd_dtype;
- union {
- struct {
- char dkd_amodel[DKD_ATA_MODEL]; /* 40 bytes */
- char dkd_afwver[DKD_ATA_FWVER]; /* 8 bytes */
- char dkd_aserial[DKD_ATA_SERIAL]; /* 20 bytes */
- } ata_disk_id;
- struct {
- char dkd_svendor[DKD_SCSI_VENDOR]; /* 8 bytes */
- char dkd_sproduct[DKD_SCSI_PRODUCT]; /* 16 bytes */
- char dkd_sfwver[DKD_SCSI_REVLEVEL]; /* 4 bytes */
- char dkd_sserial[DKD_SCSI_SERIAL]; /* 12 bytes */
- } scsi_disk_id;
- } disk_id;
-} dk_disk_id_t;
-
-/*
- * The ioctl is used to update the firmware of device.
- */
-#define DKIOC_UPDATEFW (DKIOC|47)
-
-/* The argument type for DKIOC_UPDATEFW ioctl */
-typedef struct dk_updatefw {
- caddr_t dku_ptrbuf; /* pointer to firmware buf */
- uint_t dku_size; /* firmware buf length */
- uint8_t dku_type; /* firmware update type */
-} dk_updatefw_t;
-
-#ifdef _SYSCALL32
-typedef struct dk_updatefw_32 {
- caddr32_t dku_ptrbuf; /* pointer to firmware buf */
- uint_t dku_size; /* firmware buf length */
- uint8_t dku_type; /* firmware update type */
-} dk_updatefw_32_t;
-#endif /* _SYSCALL32 */
-
-/*
- * firmware update type - temporary or permanent use
- */
-#define FW_TYPE_TEMP 0x0 /* temporary use */
-#define FW_TYPE_PERM 0x1 /* permanent use */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _OPENSOLARIS_SYS_DKIO_H_ */
diff --git a/include/os/freebsd/spl/sys/extdirent.h b/include/os/freebsd/spl/sys/extdirent.h
deleted file mode 100644
index b22e8e8563a2..000000000000
--- a/include/os/freebsd/spl/sys/extdirent.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_EXTDIRENT_H
-#define _SYS_EXTDIRENT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <sys/dirent.h>
-
-/*
- * Extended file-system independent directory entry. This style of
- * dirent provides additional informational flag bits for each
- * directory entry. This dirent will be returned instead of the
- * standard dirent if a VOP_READDIR() requests dirent flags via
- * V_RDDIR_ENTFLAGS, and if the file system supports the flags.
- */
-typedef struct edirent {
- ino64_t ed_ino; /* "inode number" of entry */
- off64_t ed_off; /* offset of disk directory entry */
- uint32_t ed_eflags; /* per-entry flags */
- unsigned short ed_reclen; /* length of this record */
- char ed_name[1]; /* name of file */
-} edirent_t;
-
-#define EDIRENT_RECLEN(namelen) \
- ((offsetof(edirent_t, ed_name[0]) + 1 + (namelen) + 7) & ~ 7)
-#define EDIRENT_NAMELEN(reclen) \
- ((reclen) - (offsetof(edirent_t, ed_name[0])))
-
-/*
- * Extended entry flags
- * Extended entries include a bitfield of extra information
- * regarding that entry.
- */
-#define ED_CASE_CONFLICT 0x10 /* Disconsidering case, entry is not unique */
-
-/*
- * Extended flags accessor function
- */
-#define ED_CASE_CONFLICTS(x) ((x)->ed_eflags & ED_CASE_CONFLICT)
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_EXTDIRENT_H */
diff --git a/module/icp/include/sys/ia32/asm_linkage.h b/include/os/freebsd/spl/sys/ia32/asm_linkage.h
index 71157caeee2a..d1f53cf22f41 100644
--- a/module/icp/include/sys/ia32/asm_linkage.h
+++ b/include/os/freebsd/spl/sys/ia32/asm_linkage.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,14 +27,16 @@
#ifndef _IA32_SYS_ASM_LINKAGE_H
#define _IA32_SYS_ASM_LINKAGE_H
-#include <sys/stack.h>
-#include <sys/trap.h>
-
-#if defined(__linux__) && defined(CONFIG_SLS)
-#define RET ret; int3
-#else
#define RET ret
-#endif
+
+/* Tell compiler to call assembler like Unix */
+#undef ASMABI
+#define ASMABI __attribute__((sysv_abi))
+
+#define ENDBR
+
+#define SECTION_TEXT .text
+#define SECTION_STATIC .section .rodata
#ifdef __cplusplus
extern "C" {
@@ -42,6 +44,7 @@ extern "C" {
#ifdef _ASM /* The remainder of this file is only for assembly files */
+
/*
* make annoying differences in assembler syntax go away
*/
@@ -124,16 +127,20 @@ extern "C" {
*/
#define ENTRY(x) \
.text; \
- .align ASM_ENTRY_ALIGN; \
+ .balign ASM_ENTRY_ALIGN; \
.globl x; \
- .type x, @function; \
x: MCOUNT(x)
#define ENTRY_NP(x) \
.text; \
- .align ASM_ENTRY_ALIGN; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+x:
+
+#define ENTRY_ALIGN(x, a) \
+ .text; \
+ .balign a; \
.globl x; \
- .type x, @function; \
x:
/*
@@ -141,19 +148,15 @@ x:
*/
#define ENTRY2(x, y) \
.text; \
- .align ASM_ENTRY_ALIGN; \
+ .balign ASM_ENTRY_ALIGN; \
.globl x, y; \
- .type x, @function; \
- .type y, @function; \
x:; \
y: MCOUNT(x)
#define ENTRY_NP2(x, y) \
.text; \
- .align ASM_ENTRY_ALIGN; \
+ .balign ASM_ENTRY_ALIGN; \
.globl x, y; \
- .type x, @function; \
- .type y, @function; \
x:; \
y:
@@ -161,8 +164,10 @@ y:
/*
* SET_SIZE trails a function and set the size for the ELF symbol table.
*/
-#define SET_SIZE(x) \
- .size x, [.-x]
+#define SET_SIZE(x)
+
+#define SET_OBJ(x)
+
#endif /* _ASM */
diff --git a/include/os/freebsd/spl/sys/idmap.h b/include/os/freebsd/spl/sys/idmap.h
index 39eeb905c72b..bd2383794f18 100644
--- a/include/os/freebsd/spl/sys/idmap.h
+++ b/include/os/freebsd/spl/sys/idmap.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/isa_defs.h b/include/os/freebsd/spl/sys/isa_defs.h
index 399d510b5f9b..9eba593fa797 100644
--- a/include/os/freebsd/spl/sys/isa_defs.h
+++ b/include/os/freebsd/spl/sys/isa_defs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,59 +41,6 @@
* The natural byte order of the processor. A pointer to an int points
* to the least/most significant byte of that int.
*
- * _STACK_GROWS_UPWARD / _STACK_GROWS_DOWNWARD:
- * The processor specific direction of stack growth. A push onto the
- * stack increases/decreases the stack pointer, so it stores data at
- * successively higher/lower addresses. (Stackless machines ignored
- * without regrets).
- *
- * _LONG_LONG_HTOL / _LONG_LONG_LTOH:
- * A pointer to a long long points to the most/least significant long
- * within that long long.
- *
- * _BIT_FIELDS_HTOL / _BIT_FIELDS_LTOH:
- * The C compiler assigns bit fields from the high/low to the low/high end
- * of an int (most to least significant vs. least to most significant).
- *
- * _IEEE_754:
- * The processor (or supported implementations of the processor)
- * supports the ieee-754 floating point standard. No other floating
- * point standards are supported (or significant). Any other supported
- * floating point formats are expected to be cased on the ISA processor
- * symbol.
- *
- * _CHAR_IS_UNSIGNED / _CHAR_IS_SIGNED:
- * The C Compiler implements objects of type `char' as `unsigned' or
- * `signed' respectively. This is really an implementation choice of
- * the compiler writer, but it is specified in the ABI and tends to
- * be uniform across compilers for an instruction set architecture.
- * Hence, it has the properties of a processor characteristic.
- *
- * _CHAR_ALIGNMENT / _SHORT_ALIGNMENT / _INT_ALIGNMENT / _LONG_ALIGNMENT /
- * _LONG_LONG_ALIGNMENT / _DOUBLE_ALIGNMENT / _LONG_DOUBLE_ALIGNMENT /
- * _POINTER_ALIGNMENT / _FLOAT_ALIGNMENT:
- * The ABI defines alignment requirements of each of the primitive
- * object types. Some, if not all, may be hardware requirements as
- * well. The values are expressed in "byte-alignment" units.
- *
- * _MAX_ALIGNMENT:
- * The most stringent alignment requirement as specified by the ABI.
- * Equal to the maximum of all the above _XXX_ALIGNMENT values.
- *
- * _ALIGNMENT_REQUIRED:
- * True or false (1 or 0) whether or not the hardware requires the ABI
- * alignment.
- *
- * _LONG_LONG_ALIGNMENT_32
- * The 32-bit ABI supported by a 64-bit kernel may have different
- * alignment requirements for primitive object types. The value of this
- * identifier is expressed in "byte-alignment" units.
- *
- * _HAVE_CPUID_INSN
- * This indicates that the architecture supports the 'cpuid'
- * instruction as defined by Intel. (Intel allows other vendors
- * to extend the instruction for their own purposes.)
- *
*
* Implementation Choices:
*
@@ -112,10 +59,6 @@
* Long/Pointer are 64 bits, Int is 32 bits. This is the chosen
* implementation for 64-bit ABIs such as SPARC V9.
*
- * _I32LPx:
- * A compilation environment where 'int' is 32-bit, and
- * longs and pointers are simply the same size.
- *
* In all cases, Char is 8 bits and Short is 16 bits.
*
* _SUNOS_VTOC_8 / _SUNOS_VTOC_16 / _SVR4_VTOC_16:
@@ -141,78 +84,10 @@
* 16 partitions per disk.
*
*
- * _DMA_USES_PHYSADDR / _DMA_USES_VIRTADDR
- * This describes the type of addresses used by system DMA:
- *
- * _DMA_USES_PHYSADDR:
- * This type of DMA, used in the x86 implementation,
- * requires physical addresses for DMA buffers. The 24-bit
- * addresses used by some legacy boards is the source of the
- * "low-memory" (<16MB) requirement for some devices using DMA.
- *
- * _DMA_USES_VIRTADDR:
- * This method of DMA allows the use of virtual addresses for
- * DMA transfers.
- *
- * _FIRMWARE_NEEDS_FDISK / _NO_FDISK_PRESENT
- * This indicates the presence/absence of an fdisk table.
- *
- * _FIRMWARE_NEEDS_FDISK
- * The fdisk table is required by system firmware. If present,
- * it allows a disk to be subdivided into multiple fdisk
- * partitions, each of which is equivalent to a separate,
- * virtual disk. This enables the co-existence of multiple
- * operating systems on a shared hard disk.
- *
- * _NO_FDISK_PRESENT
- * If the fdisk table is absent, it is assumed that the entire
- * media is allocated for a single operating system.
- *
- * _HAVE_TEM_FIRMWARE
- * Defined if this architecture has the (fallback) option of
- * using prom_* calls for doing I/O if a suitable kernel driver
- * is not available to do it.
- *
- * _DONT_USE_1275_GENERIC_NAMES
- * Controls whether or not device tree node names should
- * comply with the IEEE 1275 "Generic Names" Recommended
- * Practice. With _DONT_USE_GENERIC_NAMES, device-specific
- * names identifying the particular device will be used.
- *
- * __i386_COMPAT
- * This indicates whether the i386 ABI is supported as a *non-native*
- * mode for the platform. When this symbol is defined:
- * - 32-bit xstat-style system calls are enabled
- * - 32-bit xmknod-style system calls are enabled
- * - 32-bit system calls use i386 sizes -and- alignments
- *
- * Note that this is NOT defined for the i386 native environment!
- *
* __x86
* This is ONLY a synonym for defined(__i386) || defined(__amd64)
* which is useful only insofar as these two architectures share
* common attributes. Analogous to __sparc.
- *
- * _PSM_MODULES
- * This indicates whether or not the implementation uses PSM
- * modules for processor support, reading /etc/mach from inside
- * the kernel to extract a list.
- *
- * _RTC_CONFIG
- * This indicates whether or not the implementation uses /etc/rtc_config
- * to configure the real-time clock in the kernel.
- *
- * _UNIX_KRTLD
- * This indicates that the implementation uses a dynamically
- * linked unix + krtld to form the core kernel image at boot
- * time, or (in the absence of this symbol) a prelinked kernel image.
- *
- * _OBP
- * This indicates the firmware interface is OBP.
- *
- * _SOFT_HOSTID
- * This indicates that the implementation obtains the hostid
- * from the file /etc/hostid, rather than from hardware.
*/
#ifdef __cplusplus
@@ -234,53 +109,12 @@ extern "C" {
#endif
/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_SIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_ALIGNMENT 8
-#define _LONG_LONG_ALIGNMENT 8
-#define _DOUBLE_ALIGNMENT 8
-#define _DOUBLE_COMPLEX_ALIGNMENT 8
-#define _LONG_DOUBLE_ALIGNMENT 16
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
-#define _POINTER_ALIGNMENT 8
-#define _MAX_ALIGNMENT 16
-#define _ALIGNMENT_REQUIRED 1
-
-/*
- * Different alignment constraints for the i386 ABI in compatibility mode
- */
-#define _LONG_LONG_ALIGNMENT_32 4
-
-/*
* Define the appropriate "implementation choices".
*/
#if !defined(_LP64)
#error "_LP64 not defined"
#endif
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
-#define _MULTI_DATAMODEL
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define __i386_COMPAT
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _SOFT_HOSTID
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
/*
* The feature test macro __i386 is generic for all processors implementing
@@ -298,206 +132,46 @@ extern "C" {
#endif
/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_SIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_ALIGNMENT 4
-#define _LONG_LONG_ALIGNMENT 4
-#define _DOUBLE_ALIGNMENT 4
-#define _DOUBLE_COMPLEX_ALIGNMENT 4
-#define _LONG_DOUBLE_ALIGNMENT 4
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 4
-#define _POINTER_ALIGNMENT 4
-#define _MAX_ALIGNMENT 4
-#define _ALIGNMENT_REQUIRED 0
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices".
*/
#if !defined(_ILP32)
#define _ILP32
#endif
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _SOFT_HOSTID
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
#elif defined(__aarch64__)
/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_UNSIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_ALIGNMENT 8
-#define _LONG_LONG_ALIGNMENT 8
-#define _DOUBLE_ALIGNMENT 8
-#define _DOUBLE_COMPLEX_ALIGNMENT 8
-#define _LONG_DOUBLE_ALIGNMENT 16
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
-#define _POINTER_ALIGNMENT 8
-#define _MAX_ALIGNMENT 16
-#define _ALIGNMENT_REQUIRED 1
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices"
*/
#if !defined(_LP64)
#error "_LP64 not defined"
#endif
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
#elif defined(__riscv)
/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_UNSIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_ALIGNMENT 8
-#define _LONG_LONG_ALIGNMENT 8
-#define _DOUBLE_ALIGNMENT 8
-#define _DOUBLE_COMPLEX_ALIGNMENT 8
-#define _LONG_DOUBLE_ALIGNMENT 16
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
-#define _POINTER_ALIGNMENT 8
-#define _MAX_ALIGNMENT 16
-#define _ALIGNMENT_REQUIRED 1
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices"
*/
#if !defined(_LP64)
#define _LP64
#endif
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
#elif defined(__arm__)
/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_SIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_ALIGNMENT 4
-#define _LONG_LONG_ALIGNMENT 4
-#define _DOUBLE_ALIGNMENT 4
-#define _DOUBLE_COMPLEX_ALIGNMENT 4
-#define _LONG_DOUBLE_ALIGNMENT 4
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 4
-#define _POINTER_ALIGNMENT 4
-#define _MAX_ALIGNMENT 4
-#define _ALIGNMENT_REQUIRED 0
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices".
*/
#if !defined(_ILP32)
#define _ILP32
#endif
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
#elif defined(__mips__)
-/*
- * Define the appropriate "processor characteristics"
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_LTOH
-#define _BIT_FIELDS_LTOH
-#define _IEEE_754
-#define _CHAR_IS_SIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
#if defined(__mips_n64)
-#define _LONG_ALIGNMENT 8
-#define _LONG_LONG_ALIGNMENT 8
-#define _DOUBLE_ALIGNMENT 8
-#define _DOUBLE_COMPLEX_ALIGNMENT 8
-#define _LONG_DOUBLE_ALIGNMENT 8
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 8
-#define _POINTER_ALIGNMENT 8
-#define _MAX_ALIGNMENT 8
-#define _ALIGNMENT_REQUIRED 0
-
-#define _LONG_LONG_ALIGNMENT_32 _INT_ALIGNMENT
/*
* Define the appropriate "implementation choices".
*/
@@ -505,57 +179,21 @@ extern "C" {
#error "_LP64 not defined"
#endif
#else
-#define _LONG_ALIGNMENT 4
-#define _LONG_LONG_ALIGNMENT 4
-#define _DOUBLE_ALIGNMENT 4
-#define _DOUBLE_COMPLEX_ALIGNMENT 4
-#define _LONG_DOUBLE_ALIGNMENT 4
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 4
-#define _POINTER_ALIGNMENT 4
-#define _MAX_ALIGNMENT 4
-#define _ALIGNMENT_REQUIRED 0
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
/*
* Define the appropriate "implementation choices".
*/
#if !defined(_ILP32)
#define _ILP32
#endif
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
#endif
#define _SUNOS_VTOC_16
-#define _DMA_USES_PHYSADDR
-#define _FIRMWARE_NEEDS_FDISK
-#define _PSM_MODULES
-#define _RTC_CONFIG
-#define _DONT_USE_1275_GENERIC_NAMES
-#define _HAVE_CPUID_INSN
#elif defined(__powerpc__)
-#if defined(__BIG_ENDIAN__)
-#define _BIT_FIELDS_HTOL
-#else
-#define _BIT_FIELDS_LTOH
-#endif
-
#if !defined(__powerpc)
#define __powerpc
#endif
-#if defined(__powerpc64__)
-#define _LONG_LONG_ALIGNMENT 8
-#define _MULTI_DATAMODEL
-#else
-#define _LONG_LONG_ALIGNMENT 4
-#endif
-#define _LONG_LONG_ALIGNMENT_32 4
-#define _ALIGNMENT_REQUIRED 1
-
#define _SUNOS_VTOC_16 1
/*
@@ -601,33 +239,9 @@ extern "C" {
#endif
/*
- * Define the appropriate "processor characteristics" shared between
- * all Solaris on SPARC systems.
- */
-#define _STACK_GROWS_DOWNWARD
-#define _LONG_LONG_HTOL
-#define _BIT_FIELDS_HTOL
-#define _IEEE_754
-#define _CHAR_IS_SIGNED
-#define _BOOL_ALIGNMENT 1
-#define _CHAR_ALIGNMENT 1
-#define _SHORT_ALIGNMENT 2
-#define _INT_ALIGNMENT 4
-#define _FLOAT_ALIGNMENT 4
-#define _FLOAT_COMPLEX_ALIGNMENT 4
-#define _LONG_LONG_ALIGNMENT 8
-#define _DOUBLE_ALIGNMENT 8
-#define _DOUBLE_COMPLEX_ALIGNMENT 8
-#define _ALIGNMENT_REQUIRED 1
-
-/*
* Define the appropriate "implementation choices" shared between versions.
*/
#define _SUNOS_VTOC_8
-#define _DMA_USES_VIRTADDR
-#define _NO_FDISK_PRESENT
-#define _HAVE_TEM_FIRMWARE
-#define _OBP
/*
* The following set of definitions characterize the implementation of
@@ -636,23 +250,9 @@ extern "C" {
#if defined(__sparcv8)
/*
- * Define the appropriate "processor characteristics"
- */
-#define _LONG_ALIGNMENT 4
-#define _LONG_DOUBLE_ALIGNMENT 8
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 8
-#define _POINTER_ALIGNMENT 4
-#define _MAX_ALIGNMENT 8
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices"
*/
#define _ILP32
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
/*
* The following set of definitions characterize the implementation of
@@ -661,26 +261,11 @@ extern "C" {
#elif defined(__sparcv9)
/*
- * Define the appropriate "processor characteristics"
- */
-#define _LONG_ALIGNMENT 8
-#define _LONG_DOUBLE_ALIGNMENT 16
-#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
-#define _POINTER_ALIGNMENT 8
-#define _MAX_ALIGNMENT 16
-
-#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
-
-/*
* Define the appropriate "implementation choices"
*/
#if !defined(_LP64)
#error "_LP64 not defined"
#endif
-#if !defined(_I32LPx)
-#define _I32LPx
-#endif
-#define _MULTI_DATAMODEL
#else
#error "unknown SPARC version"
diff --git a/include/os/freebsd/spl/sys/kmem.h b/include/os/freebsd/spl/sys/kmem.h
index a81cb1fb521d..c633799318d5 100644
--- a/include/os/freebsd/spl/sys/kmem.h
+++ b/include/os/freebsd/spl/sys/kmem.h
@@ -52,8 +52,13 @@ MALLOC_DECLARE(M_SOLARIS);
typedef struct vmem vmem_t;
-extern char *kmem_asprintf(const char *, ...);
-extern char *kmem_vasprintf(const char *fmt, va_list ap);
+extern char *kmem_asprintf(const char *, ...)
+ __attribute__((format(printf, 1, 2)));
+extern char *kmem_vasprintf(const char *fmt, va_list ap)
+ __attribute__((format(printf, 1, 0)));
+
+extern int kmem_scnprintf(char *restrict str, size_t size,
+ const char *restrict fmt, ...);
typedef struct kmem_cache {
char kc_name[32];
@@ -70,6 +75,7 @@ typedef struct kmem_cache {
extern uint64_t spl_kmem_cache_inuse(kmem_cache_t *cache);
extern uint64_t spl_kmem_cache_entry_size(kmem_cache_t *cache);
+__attribute__((malloc, alloc_size(1)))
void *zfs_kmem_alloc(size_t size, int kmflags);
void zfs_kmem_free(void *buf, size_t size);
uint64_t kmem_size(void);
@@ -77,6 +83,7 @@ kmem_cache_t *kmem_cache_create(const char *name, size_t bufsize, size_t align,
int (*constructor)(void *, void *, int), void (*destructor)(void *, void *),
void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int cflags);
void kmem_cache_destroy(kmem_cache_t *cache);
+__attribute__((malloc))
void *kmem_cache_alloc(kmem_cache_t *cache, int flags);
void kmem_cache_free(kmem_cache_t *cache, void *buf);
boolean_t kmem_cache_reap_active(void);
diff --git a/include/os/freebsd/spl/sys/kstat.h b/include/os/freebsd/spl/sys/kstat.h
index 947dfee62393..7dc2c4753b02 100644
--- a/include/os/freebsd/spl/sys/kstat.h
+++ b/include/os/freebsd/spl/sys/kstat.h
@@ -94,7 +94,7 @@ void seq_printf(struct seq_file *m, const char *fmt, ...);
typedef struct kstat_module {
- char ksm_name[KSTAT_STRLEN+1]; /* module name */
+ char ksm_name[KSTAT_STRLEN]; /* module name */
struct list_head ksm_module_list; /* module linkage */
struct list_head ksm_kstat_list; /* list of kstat entries */
struct proc_dir_entry *ksm_proc; /* proc entry */
@@ -112,10 +112,10 @@ struct kstat_s {
kid_t ks_kid; /* unique kstat ID */
hrtime_t ks_crtime; /* creation time */
hrtime_t ks_snaptime; /* last access time */
- char ks_module[KSTAT_STRLEN+1]; /* provider module name */
+ char ks_module[KSTAT_STRLEN]; /* provider module name */
int ks_instance; /* provider module instance */
- char ks_name[KSTAT_STRLEN+1]; /* kstat name */
- char ks_class[KSTAT_STRLEN+1]; /* kstat class */
+ char ks_name[KSTAT_STRLEN]; /* kstat name */
+ char ks_class[KSTAT_STRLEN]; /* kstat class */
uchar_t ks_type; /* kstat data type */
uchar_t ks_flags; /* kstat flags */
void *ks_data; /* kstat type-specific data */
@@ -181,7 +181,7 @@ typedef struct kstat_io {
} kstat_io_t;
typedef struct kstat_timer {
- char name[KSTAT_STRLEN+1]; /* event name */
+ char name[KSTAT_STRLEN]; /* event name */
u_longlong_t num_events; /* number of events */
hrtime_t elapsed_time; /* cumulative elapsed time */
hrtime_t min_time; /* shortest event duration */
diff --git a/include/os/freebsd/spl/sys/list.h b/include/os/freebsd/spl/sys/list.h
index 6db92ed42955..6c32402a7bd1 100644
--- a/include/os/freebsd/spl/sys/list.h
+++ b/include/os/freebsd/spl/sys/list.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/list_impl.h b/include/os/freebsd/spl/sys/list_impl.h
index a6614f9a38c2..06a5c6d1dbc6 100644
--- a/include/os/freebsd/spl/sys/list_impl.h
+++ b/include/os/freebsd/spl/sys/list_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -39,7 +39,6 @@ struct list_node {
};
struct list {
- size_t list_size;
size_t list_offset;
struct list_node list_head;
};
diff --git a/include/os/freebsd/spl/sys/mod_os.h b/include/os/freebsd/spl/sys/mod_os.h
index 3a9ebbfc3bc4..df7be6fc13f6 100644
--- a/include/os/freebsd/spl/sys/mod_os.h
+++ b/include/os/freebsd/spl/sys/mod_os.h
@@ -31,10 +31,6 @@
#include <sys/sysctl.h>
-#define EXPORT_SYMBOL(x)
-#define module_param(a, b, c)
-#define MODULE_PARM_DESC(a, b)
-
#define ZMOD_RW CTLFLAG_RWTUN
#define ZMOD_RD CTLFLAG_RDTUN
@@ -47,7 +43,7 @@
#define ZFS_MODULE_PARAM_CALL_IMPL(parent, name, perm, args, desc) \
SYSCTL_DECL(parent); \
- SYSCTL_PROC(parent, OID_AUTO, name, perm | args, desc)
+ SYSCTL_PROC(parent, OID_AUTO, name, CTLFLAG_MPSAFE | perm | args, desc)
#define ZFS_MODULE_PARAM_CALL( \
scope_prefix, name_prefix, name, func, _, perm, desc) \
@@ -56,42 +52,66 @@
#define ZFS_MODULE_VIRTUAL_PARAM_CALL ZFS_MODULE_PARAM_CALL
-#define param_set_arc_long_args(var) \
- CTLTYPE_ULONG, &var, 0, param_set_arc_long, "LU"
+#define param_set_arc_u64_args(var) \
+ CTLTYPE_U64, &var, 0, param_set_arc_u64, "QU"
+
+#define param_set_arc_int_args(var) \
+ CTLTYPE_INT, &var, 0, param_set_arc_int, "I"
#define param_set_arc_min_args(var) \
- CTLTYPE_ULONG, &var, 0, param_set_arc_min, "LU"
+ CTLTYPE_U64, NULL, 0, param_set_arc_min, "QU"
#define param_set_arc_max_args(var) \
- CTLTYPE_ULONG, &var, 0, param_set_arc_max, "LU"
+ CTLTYPE_U64, NULL, 0, param_set_arc_max, "QU"
-#define param_set_arc_int_args(var) \
- CTLTYPE_INT, &var, 0, param_set_arc_int, "I"
+#define param_set_arc_free_target_args(var) \
+ CTLTYPE_UINT, NULL, 0, param_set_arc_free_target, "IU"
+
+#define param_set_arc_no_grow_shift_args(var) \
+ CTLTYPE_INT, NULL, 0, param_set_arc_no_grow_shift, "I"
#define param_set_deadman_failmode_args(var) \
CTLTYPE_STRING, NULL, 0, param_set_deadman_failmode, "A"
+#define param_set_active_allocator_args(var) \
+ CTLTYPE_STRING, NULL, 0, param_set_active_allocator, "A"
+
#define param_set_deadman_synctime_args(var) \
- CTLTYPE_ULONG, NULL, 0, param_set_deadman_synctime, "LU"
+ CTLTYPE_U64, NULL, 0, param_set_deadman_synctime, "QU"
#define param_set_deadman_ziotime_args(var) \
- CTLTYPE_ULONG, NULL, 0, param_set_deadman_ziotime, "LU"
+ CTLTYPE_U64, NULL, 0, param_set_deadman_ziotime, "QU"
#define param_set_multihost_interval_args(var) \
- CTLTYPE_ULONG, &var, 0, param_set_multihost_interval, "LU"
+ CTLTYPE_U64, NULL, 0, param_set_multihost_interval, "QU"
#define param_set_slop_shift_args(var) \
- CTLTYPE_INT, &var, 0, param_set_slop_shift, "I"
+ CTLTYPE_INT, NULL, 0, param_set_slop_shift, "I"
#define param_set_min_auto_ashift_args(var) \
- CTLTYPE_U64, &var, 0, param_set_min_auto_ashift, "QU"
+ CTLTYPE_UINT, NULL, 0, param_set_min_auto_ashift, "IU"
#define param_set_max_auto_ashift_args(var) \
- CTLTYPE_U64, &var, 0, param_set_max_auto_ashift, "QU"
+ CTLTYPE_UINT, NULL, 0, param_set_max_auto_ashift, "IU"
+
+#define spa_taskq_read_param_set_args(var) \
+ CTLTYPE_STRING, NULL, 0, spa_taskq_read_param, "A"
+
+#define spa_taskq_write_param_set_args(var) \
+ CTLTYPE_STRING, NULL, 0, spa_taskq_write_param, "A"
#define fletcher_4_param_set_args(var) \
CTLTYPE_STRING, NULL, 0, fletcher_4_param, "A"
+#define blake3_param_set_args(var) \
+ CTLTYPE_STRING, NULL, 0, blake3_param, "A"
+
+#define sha256_param_set_args(var) \
+ CTLTYPE_STRING, NULL, 0, sha256_param, "A"
+
+#define sha512_param_set_args(var) \
+ CTLTYPE_STRING, NULL, 0, sha512_param, "A"
+
#include <sys/kernel.h>
#define module_init(fn) \
static void \
diff --git a/include/os/freebsd/spl/sys/mutex.h b/include/os/freebsd/spl/sys/mutex.h
index e757d12c1502..8cfe56c75309 100644
--- a/include/os/freebsd/spl/sys/mutex.h
+++ b/include/os/freebsd/spl/sys/mutex.h
@@ -64,6 +64,7 @@ typedef enum {
} while (0)
#define mutex_destroy(lock) sx_destroy(lock)
#define mutex_enter(lock) sx_xlock(lock)
+#define mutex_enter_interruptible(lock) sx_xlock_sig(lock)
#define mutex_enter_nested(lock, type) sx_xlock(lock)
#define mutex_tryenter(lock) sx_try_xlock(lock)
#define mutex_exit(lock) sx_xunlock(lock)
diff --git a/include/os/freebsd/spl/sys/processor.h b/include/os/freebsd/spl/sys/processor.h
index 53149840f21f..40464e53d5c4 100644
--- a/include/os/freebsd/spl/sys/processor.h
+++ b/include/os/freebsd/spl/sys/processor.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/procfs_list.h b/include/os/freebsd/spl/sys/procfs_list.h
index 4bc603756ea4..4e98675053d2 100644
--- a/include/os/freebsd/spl/sys/procfs_list.h
+++ b/include/os/freebsd/spl/sys/procfs_list.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/simd.h b/include/os/freebsd/spl/sys/simd.h
index 53503e838912..4560bb05e978 100644
--- a/include/os/freebsd/spl/sys/simd.h
+++ b/include/os/freebsd/spl/sys/simd.h
@@ -26,13 +26,22 @@
* $FreeBSD$
*/
-
#ifndef _FREEBSD_SIMD_H
#define _FREEBSD_SIMD_H
+
#if defined(__amd64__) || defined(__i386__)
#include <sys/simd_x86.h>
-#else
+#elif defined(__arm__)
+#include <sys/simd_arm.h>
+
+#elif defined(__aarch64__)
+#include <sys/simd_aarch64.h>
+
+#elif defined(__powerpc__)
+#include <sys/simd_powerpc.h>
+
+#else
#define kfpu_allowed() 0
#define kfpu_initialize(tsk) do {} while (0)
#define kfpu_begin() do {} while (0)
@@ -40,4 +49,5 @@
#define kfpu_init() (0)
#define kfpu_fini() do {} while (0)
#endif
+
#endif
diff --git a/include/os/freebsd/spl/sys/simd_aarch64.h b/include/os/freebsd/spl/sys/simd_aarch64.h
new file mode 100644
index 000000000000..234f401db791
--- /dev/null
+++ b/include/os/freebsd/spl/sys/simd_aarch64.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_neon_available()
+ * zfs_sha256_available()
+ * zfs_sha512_available()
+ */
+
+#ifndef _FREEBSD_SIMD_AARCH64_H
+#define _FREEBSD_SIMD_AARCH64_H
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <machine/elf.h>
+#include <machine/fpu.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+#define kfpu_allowed() 1
+#define kfpu_initialize(tsk) do {} while (0)
+#define kfpu_begin() do { \
+ if (__predict_false(!is_fpu_kern_thread(0))) \
+ fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); \
+} while (0)
+
+#define kfpu_end() do { \
+ if (__predict_false(curthread->td_pcb->pcb_fpflags & PCB_FP_NOSAVE)) \
+ fpu_kern_leave(curthread, NULL); \
+} while (0)
+#define kfpu_init() (0)
+#define kfpu_fini() do {} while (0)
+
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+ return (elf_hwcap & HWCAP_FP);
+}
+
+/*
+ * Check if SHA256 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+ return (elf_hwcap & HWCAP_SHA2);
+}
+
+/*
+ * Check if SHA512 is available
+ */
+static inline boolean_t
+zfs_sha512_available(void)
+{
+ return (elf_hwcap & HWCAP_SHA512);
+}
+
+#endif /* _FREEBSD_SIMD_AARCH64_H */
diff --git a/include/os/freebsd/spl/sys/simd_arm.h b/include/os/freebsd/spl/sys/simd_arm.h
new file mode 100644
index 000000000000..178fbc3b3c6e
--- /dev/null
+++ b/include/os/freebsd/spl/sys/simd_arm.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_neon_available()
+ * zfs_sha256_available()
+ */
+
+#ifndef _FREEBSD_SIMD_ARM_H
+#define _FREEBSD_SIMD_ARM_H
+
+#include <sys/types.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+#define kfpu_allowed() 1
+#define kfpu_initialize(tsk) do {} while (0)
+#define kfpu_begin() do {} while (0)
+#define kfpu_end() do {} while (0)
+#define kfpu_init() (0)
+#define kfpu_fini() do {} while (0)
+
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+ return (elf_hwcap & HWCAP_NEON);
+}
+
+/*
+ * Check if SHA256 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+ return (elf_hwcap2 & HWCAP2_SHA2);
+}
+
+#endif /* _FREEBSD_SIMD_ARM_H */
diff --git a/include/os/freebsd/spl/sys/simd_powerpc.h b/include/os/freebsd/spl/sys/simd_powerpc.h
new file mode 100644
index 000000000000..cf3c712c6af2
--- /dev/null
+++ b/include/os/freebsd/spl/sys/simd_powerpc.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_altivec_available()
+ * zfs_vsx_available()
+ * zfs_isa207_available()
+ */
+
+#ifndef _FREEBSD_SIMD_POWERPC_H
+#define _FREEBSD_SIMD_POWERPC_H
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <machine/pcb.h>
+#include <machine/cpu.h>
+
+#define kfpu_allowed() 0
+#define kfpu_initialize(tsk) do {} while (0)
+#define kfpu_begin() do {} while (0)
+#define kfpu_end() do {} while (0)
+#define kfpu_init() (0)
+#define kfpu_fini() do {} while (0)
+
+/*
+ * Check if Altivec is available
+ */
+static inline boolean_t
+zfs_altivec_available(void)
+{
+ return ((cpu_features & PPC_FEATURE_HAS_ALTIVEC) != 0);
+}
+
+/*
+ * Check if VSX is available
+ */
+static inline boolean_t
+zfs_vsx_available(void)
+{
+ return ((cpu_features & PPC_FEATURE_HAS_VSX) != 0);
+}
+
+/*
+ * Check if POWER ISA 2.07 is available (SHA2)
+ */
+static inline boolean_t
+zfs_isa207_available(void)
+{
+ return ((cpu_features2 & PPC_FEATURE2_ARCH_2_07) != 0);
+}
+
+#endif
diff --git a/include/os/freebsd/spl/sys/simd_x86.h b/include/os/freebsd/spl/sys/simd_x86.h
index 480bfd28973b..8e93b558dfe8 100644
--- a/include/os/freebsd/spl/sys/simd_x86.h
+++ b/include/os/freebsd/spl/sys/simd_x86.h
@@ -45,6 +45,10 @@
fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);\
}
+#ifndef PCB_FPUNOSAVE
+#define PCB_FPUNOSAVE PCB_NPXNOSAVE
+#endif
+
#define kfpu_end() { \
if (__predict_false(curpcb->pcb_flags & PCB_FPUNOSAVE)) \
fpu_kern_leave(curthread, NULL); \
@@ -77,7 +81,7 @@ __simd_state_enabled(const uint64_t state)
boolean_t has_osxsave;
uint64_t xcr0;
- has_osxsave = !!(cpu_feature2 & CPUID2_OSXSAVE);
+ has_osxsave = (cpu_feature2 & CPUID2_OSXSAVE) != 0;
if (!has_osxsave)
return (B_FALSE);
@@ -99,7 +103,7 @@ __simd_state_enabled(const uint64_t state)
static inline boolean_t
zfs_sse_available(void)
{
- return (!!(cpu_feature & CPUID_SSE));
+ return ((cpu_feature & CPUID_SSE) != 0);
}
/*
@@ -108,7 +112,7 @@ zfs_sse_available(void)
static inline boolean_t
zfs_sse2_available(void)
{
- return (!!(cpu_feature & CPUID_SSE2));
+ return ((cpu_feature & CPUID_SSE2) != 0);
}
/*
@@ -117,7 +121,7 @@ zfs_sse2_available(void)
static inline boolean_t
zfs_sse3_available(void)
{
- return (!!(cpu_feature2 & CPUID2_SSE3));
+ return ((cpu_feature2 & CPUID2_SSE3) != 0);
}
/*
@@ -126,7 +130,7 @@ zfs_sse3_available(void)
static inline boolean_t
zfs_ssse3_available(void)
{
- return (!!(cpu_feature2 & CPUID2_SSSE3));
+ return ((cpu_feature2 & CPUID2_SSSE3) != 0);
}
/*
@@ -135,7 +139,7 @@ zfs_ssse3_available(void)
static inline boolean_t
zfs_sse4_1_available(void)
{
- return (!!(cpu_feature2 & CPUID2_SSE41));
+ return ((cpu_feature2 & CPUID2_SSE41) != 0);
}
/*
@@ -144,7 +148,7 @@ zfs_sse4_1_available(void)
static inline boolean_t
zfs_sse4_2_available(void)
{
- return (!!(cpu_feature2 & CPUID2_SSE42));
+ return ((cpu_feature2 & CPUID2_SSE42) != 0);
}
/*
@@ -155,7 +159,7 @@ zfs_avx_available(void)
{
boolean_t has_avx;
- has_avx = !!(cpu_feature2 & CPUID2_AVX);
+ has_avx = (cpu_feature2 & CPUID2_AVX) != 0;
return (has_avx && __ymm_enabled());
}
@@ -168,12 +172,25 @@ zfs_avx2_available(void)
{
boolean_t has_avx2;
- has_avx2 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX2);
+ has_avx2 = (cpu_stdext_feature & CPUID_STDEXT_AVX2) != 0;
return (has_avx2 && __ymm_enabled());
}
/*
+ * Check if SHA_NI instruction set is available
+ */
+static inline boolean_t
+zfs_shani_available(void)
+{
+ boolean_t has_shani;
+
+ has_shani = (cpu_stdext_feature & CPUID_STDEXT_SHA) != 0;
+
+ return (has_shani && __ymm_enabled());
+}
+
+/*
* AVX-512 family of instruction sets:
*
* AVX512F Foundation
@@ -196,7 +213,7 @@ zfs_avx512f_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -207,8 +224,8 @@ zfs_avx512cd_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512CD);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512CD) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -219,8 +236,8 @@ zfs_avx512er_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512CD);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512CD) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -231,8 +248,8 @@ zfs_avx512pf_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512PF);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512PF) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -243,7 +260,7 @@ zfs_avx512bw_available(void)
{
boolean_t has_avx512 = B_FALSE;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512BW);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512BW) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -254,8 +271,8 @@ zfs_avx512dq_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512DQ);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512DQ) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -266,8 +283,8 @@ zfs_avx512vl_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512VL);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512VL) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -278,8 +295,8 @@ zfs_avx512ifma_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_AVX512IFMA);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_AVX512IFMA) != 0;
return (has_avx512 && __zmm_enabled());
}
@@ -290,8 +307,8 @@ zfs_avx512vbmi_available(void)
{
boolean_t has_avx512;
- has_avx512 = !!(cpu_stdext_feature & CPUID_STDEXT_AVX512F) &&
- !!(cpu_stdext_feature & CPUID_STDEXT_BMI1);
+ has_avx512 = (cpu_stdext_feature & CPUID_STDEXT_AVX512F) != 0 &&
+ (cpu_stdext_feature & CPUID_STDEXT_BMI1) != 0;
return (has_avx512 && __zmm_enabled());
}
diff --git a/include/os/freebsd/spl/sys/spl_condvar.h b/include/os/freebsd/spl/sys/spl_condvar.h
index 7405f647d59a..2835adafd416 100644
--- a/include/os/freebsd/spl/sys/spl_condvar.h
+++ b/include/os/freebsd/spl/sys/spl_condvar.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2000 Jake Burkholder <jake@freebsd.org>.
* All rights reserved.
diff --git a/include/os/freebsd/spl/sys/sysmacros.h b/include/os/freebsd/spl/sys/sysmacros.h
index 7e3ab8915542..3e8841ae66bd 100644
--- a/include/os/freebsd/spl/sys/sysmacros.h
+++ b/include/os/freebsd/spl/sys/sysmacros.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -281,46 +281,6 @@ extern unsigned char bcd_to_byte[256];
#define INCR_COUNT(var, mutex) mutex_enter(mutex), (*(var))++, mutex_exit(mutex)
#define DECR_COUNT(var, mutex) mutex_enter(mutex), (*(var))--, mutex_exit(mutex)
-/*
- * Macros to declare bitfields - the order in the parameter list is
- * Low to High - that is, declare bit 0 first. We only support 8-bit bitfields
- * because if a field crosses a byte boundary it's not likely to be meaningful
- * without reassembly in its nonnative endianness.
- */
-#if defined(_BIT_FIELDS_LTOH)
-#define DECL_BITFIELD2(_a, _b) \
- uint8_t _a, _b
-#define DECL_BITFIELD3(_a, _b, _c) \
- uint8_t _a, _b, _c
-#define DECL_BITFIELD4(_a, _b, _c, _d) \
- uint8_t _a, _b, _c, _d
-#define DECL_BITFIELD5(_a, _b, _c, _d, _e) \
- uint8_t _a, _b, _c, _d, _e
-#define DECL_BITFIELD6(_a, _b, _c, _d, _e, _f) \
- uint8_t _a, _b, _c, _d, _e, _f
-#define DECL_BITFIELD7(_a, _b, _c, _d, _e, _f, _g) \
- uint8_t _a, _b, _c, _d, _e, _f, _g
-#define DECL_BITFIELD8(_a, _b, _c, _d, _e, _f, _g, _h) \
- uint8_t _a, _b, _c, _d, _e, _f, _g, _h
-#elif defined(_BIT_FIELDS_HTOL)
-#define DECL_BITFIELD2(_a, _b) \
- uint8_t _b, _a
-#define DECL_BITFIELD3(_a, _b, _c) \
- uint8_t _c, _b, _a
-#define DECL_BITFIELD4(_a, _b, _c, _d) \
- uint8_t _d, _c, _b, _a
-#define DECL_BITFIELD5(_a, _b, _c, _d, _e) \
- uint8_t _e, _d, _c, _b, _a
-#define DECL_BITFIELD6(_a, _b, _c, _d, _e, _f) \
- uint8_t _f, _e, _d, _c, _b, _a
-#define DECL_BITFIELD7(_a, _b, _c, _d, _e, _f, _g) \
- uint8_t _g, _f, _e, _d, _c, _b, _a
-#define DECL_BITFIELD8(_a, _b, _c, _d, _e, _f, _g, _h) \
- uint8_t _h, _g, _f, _e, _d, _c, _b, _a
-#else
-#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
-#endif /* _BIT_FIELDS_LTOH */
-
#if !defined(_KMEMUSER) && !defined(offsetof)
/* avoid any possibility of clashing with <stddef.h> version */
diff --git a/include/os/freebsd/spl/sys/taskq.h b/include/os/freebsd/spl/sys/taskq.h
index 3040549e043d..fa6ff84a0134 100644
--- a/include/os/freebsd/spl/sys/taskq.h
+++ b/include/os/freebsd/spl/sys/taskq.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,9 +30,9 @@
#include <sys/types.h>
#include <sys/proc.h>
+#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/thread.h>
-#include <sys/ck.h>
#ifdef __cplusplus
extern "C" {
@@ -42,22 +42,23 @@ extern "C" {
typedef struct taskq {
struct taskqueue *tq_queue;
+ int tq_nthreads;
} taskq_t;
typedef uintptr_t taskqid_t;
typedef void (task_func_t)(void *);
typedef struct taskq_ent {
- struct task tqent_task;
- struct timeout_task tqent_timeout_task;
+ union {
+ struct task tqent_task;
+ struct timeout_task tqent_timeout_task;
+ };
task_func_t *tqent_func;
void *tqent_arg;
- taskqid_t tqent_id;
- CK_LIST_ENTRY(taskq_ent) tqent_hash;
- uint8_t tqent_type;
- uint8_t tqent_registered;
- uint8_t tqent_cancelled;
- volatile uint32_t tqent_rc;
+ taskqid_t tqent_id;
+ LIST_ENTRY(taskq_ent) tqent_hash;
+ uint_t tqent_type;
+ volatile uint_t tqent_rc;
} taskq_ent_t;
/*
@@ -81,7 +82,6 @@ typedef struct taskq_ent {
#define TASKQID_INVALID ((taskqid_t)0)
-#define taskq_init_ent(x)
extern taskq_t *system_taskq;
/* Global dynamic task queue for long delay */
extern taskq_t *system_delay_taskq;
@@ -92,7 +92,10 @@ extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *,
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *);
extern int taskq_empty_ent(taskq_ent_t *);
+extern void taskq_init_ent(taskq_ent_t *);
taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
+taskq_t *taskq_create_synced(const char *, int, pri_t, int, int, uint_t,
+ kthread_t ***);
taskq_t *taskq_create_instance(const char *, int, int, pri_t, int, int, uint_t);
taskq_t *taskq_create_proc(const char *, int, pri_t, int, int,
struct proc *, uint_t);
@@ -117,6 +120,7 @@ void taskq_resume(taskq_t *);
#endif /* _KERNEL */
#ifdef _STANDALONE
+typedef void taskq_t;
typedef int taskq_ent_t;
#define taskq_init_ent(x)
#endif /* _STANDALONE */
diff --git a/include/os/freebsd/spl/sys/time.h b/include/os/freebsd/spl/sys/time.h
index fbc679aacf93..47d64c34756a 100644
--- a/include/os/freebsd/spl/sys/time.h
+++ b/include/os/freebsd/spl/sys/time.h
@@ -22,8 +22,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#ifndef _OPENSOLARIS_SYS_TIME_H_
@@ -91,6 +89,6 @@ gethrtime(void)
{
struct timespec ts;
clock_gettime(CLOCK_UPTIME, &ts);
- return (((u_int64_t)ts.tv_sec) * NANOSEC + ts.tv_nsec);
+ return (((uint64_t)ts.tv_sec) * NANOSEC + ts.tv_nsec);
}
#endif /* !_OPENSOLARIS_SYS_TIME_H_ */
diff --git a/include/os/freebsd/spl/sys/timer.h b/include/os/freebsd/spl/sys/timer.h
index d4694bb7c09c..7ff77e9b1b74 100644
--- a/include/os/freebsd/spl/sys/timer.h
+++ b/include/os/freebsd/spl/sys/timer.h
@@ -33,6 +33,4 @@
#define usleep_range(wakeup, wakeupepsilon) \
pause_sbt("usleep_range", ustosbt(wakeup), \
ustosbt(wakeupepsilon - wakeup), 0)
-
-#define schedule() pause("schedule", 1)
#endif
diff --git a/include/os/freebsd/spl/sys/types.h b/include/os/freebsd/spl/sys/types.h
index b1308df29503..ebc93f4f4485 100644
--- a/include/os/freebsd/spl/sys/types.h
+++ b/include/os/freebsd/spl/sys/types.h
@@ -105,5 +105,7 @@ typedef u_longlong_t len_t;
typedef longlong_t diskaddr_t;
+typedef void zidmap_t;
+
#include <sys/debug.h>
#endif /* !_OPENSOLARIS_SYS_TYPES_H_ */
diff --git a/include/os/freebsd/spl/sys/uio.h b/include/os/freebsd/spl/sys/uio.h
index b71f2f2e5625..b9d41903ea63 100644
--- a/include/os/freebsd/spl/sys/uio.h
+++ b/include/os/freebsd/spl/sys/uio.h
@@ -62,7 +62,7 @@ zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
}
static inline void
-zfs_uio_advance(zfs_uio_t *uio, size_t size)
+zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
{
zfs_uio_resid(uio) -= size;
zfs_uio_offset(uio) += size;
diff --git a/include/os/freebsd/spl/sys/uuid.h b/include/os/freebsd/spl/sys/uuid.h
index 26d46e8d6214..9e76d07b8014 100644
--- a/include/os/freebsd/spl/sys/uuid.h
+++ b/include/os/freebsd/spl/sys/uuid.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/spl/sys/vfs.h b/include/os/freebsd/spl/sys/vfs.h
index 22d57cc473e2..f2196da56bc8 100644
--- a/include/os/freebsd/spl/sys/vfs.h
+++ b/include/os/freebsd/spl/sys/vfs.h
@@ -101,7 +101,7 @@ void vfs_setmntopt(vfs_t *vfsp, const char *name, const char *arg,
void vfs_clearmntopt(vfs_t *vfsp, const char *name);
int vfs_optionisset(const vfs_t *vfsp, const char *opt, char **argp);
int mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype,
- char *fspath, char *fspec, int fsflags);
+ char *fspath, char *fspec, int fsflags, vfs_t *parent_vfsp);
typedef uint64_t vfs_feature_t;
@@ -117,9 +117,5 @@ typedef uint64_t vfs_feature_t;
#define VFSFT_ZEROCOPY_SUPPORTED 0x100000200
/* Support loaning /returning cache buffer */
-#define vfs_set_feature(vfsp, feature) do { } while (0)
-#define vfs_clear_feature(vfsp, feature) do { } while (0)
-#define vfs_has_feature(vfsp, feature) (0)
-
#include <sys/mount.h>
#endif /* _OPENSOLARIS_SYS_VFS_H_ */
diff --git a/include/os/freebsd/spl/sys/vnode.h b/include/os/freebsd/spl/sys/vnode.h
index e0f79a1116b2..75c32f221ffd 100644
--- a/include/os/freebsd/spl/sys/vnode.h
+++ b/include/os/freebsd/spl/sys/vnode.h
@@ -36,7 +36,11 @@ struct xucred;
typedef struct flock flock64_t;
typedef struct vnode vnode_t;
typedef struct vattr vattr_t;
+#if __FreeBSD_version < 1400093
typedef enum vtype vtype_t;
+#else
+#define vtype_t __enum_uint8(vtype)
+#endif
#include <sys/types.h>
#include <sys/queue.h>
@@ -52,6 +56,7 @@ enum symfollow { NO_FOLLOW = NOFOLLOW };
#ifndef IN_BASE
#include_next <sys/vnode.h>
#endif
+#include <sys/ccompat.h>
#include <sys/mount.h>
#include <sys/cred.h>
#include <sys/fcntl.h>
@@ -96,16 +101,17 @@ 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_UNLOCK1(vp);
}
}
#endif
#define vn_exists(vp) do { } while (0)
#define vn_invalid(vp) do { } while (0)
-#define vn_renamepath(tdvp, svp, tnm, lentnm) do { } while (0)
#define vn_free(vp) do { } while (0)
#define vn_matchops(vp, vops) ((vp)->v_op == &(vops))
@@ -142,6 +148,10 @@ vn_flush_cached_data(vnode_t *vp, boolean_t sync)
/*
* Attributes of interest to the caller of setattr or getattr.
*/
+
+#undef AT_UID
+#undef AT_GID
+
#define AT_MODE 0x00002
#define AT_UID 0x00004
#define AT_GID 0x00008
@@ -203,15 +213,6 @@ vattr_init_mask(vattr_t *vap)
#define RLIM64_INFINITY 0
-static __inline int
-vn_rename(char *from, char *to, enum uio_seg seg)
-{
-
- ASSERT(seg == UIO_SYSSPACE);
-
- return (kern_renameat(curthread, AT_FDCWD, from, AT_FDCWD, to, seg));
-}
-
#include <sys/vfs.h>
#endif /* _OPENSOLARIS_SYS_VNODE_H_ */
diff --git a/include/os/freebsd/spl/sys/vnode_impl.h b/include/os/freebsd/spl/sys/vnode_impl.h
index c82b1fc9ad18..4e04b5e80a06 100644
--- a/include/os/freebsd/spl/sys/vnode_impl.h
+++ b/include/os/freebsd/spl/sys/vnode_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -44,8 +44,6 @@
#define IS_DEVVP(vp) \
((vp)->v_type == VCHR || (vp)->v_type == VBLK || (vp)->v_type == VFIFO)
-#define V_XATTRDIR 0x0000 /* attribute unnamed directory */
-
#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
/*
@@ -194,11 +192,6 @@
#define PERMMASK 00777 /* permission bits */
/*
- * VOP_ACCESS flags
- */
-#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
-
-/*
* Flags for vnode operations.
*/
enum rm { RMFILE, RMDIRECTORY }; /* rm or rmdir (remove) */
@@ -235,12 +228,6 @@ struct taskq;
#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
/*
- * Flags for VOP_READDIR
- */
-#define V_RDDIR_ENTFLAGS 0x01 /* request dirent flags */
-#define V_RDDIR_ACCFILTER 0x02 /* filter out inaccessible dirents */
-
-/*
* Public vnode manipulation functions.
*/
diff --git a/include/os/freebsd/spl/sys/zmod.h b/include/os/freebsd/spl/sys/zmod.h
index c606b1db5f61..6e26a568bd44 100644
--- a/include/os/freebsd/spl/sys/zmod.h
+++ b/include/os/freebsd/spl/sys/zmod.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/zfs/sys/arc_os.h b/include/os/freebsd/zfs/sys/arc_os.h
new file mode 100644
index 000000000000..ad2aba23b901
--- /dev/null
+++ b/include/os/freebsd/zfs/sys/arc_os.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Martin Matuska
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_ARC_OS_H
+#define _SYS_ARC_OS_H
+
+int param_set_arc_free_target(SYSCTL_HANDLER_ARGS);
+int param_set_arc_no_grow_shift(SYSCTL_HANDLER_ARGS);
+
+#endif
diff --git a/include/os/freebsd/zfs/sys/freebsd_event.h b/include/os/freebsd/zfs/sys/freebsd_event.h
new file mode 100644
index 000000000000..a32596d918a1
--- /dev/null
+++ b/include/os/freebsd/zfs/sys/freebsd_event.h
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Rob Wing
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ZFS_FREEBSD_EVENT_H
+#define _ZFS_FREEBSD_EVENT_H
+
+#ifdef _KERNEL
+
+void knlist_init_sx(struct knlist *knl, struct sx *lock);
+
+#endif /* !_KERNEL */
+
+#endif /* !_ZFS_FREEBSD_EVENT_H */
diff --git a/include/os/freebsd/zfs/sys/sha2.h b/include/os/freebsd/zfs/sys/sha2.h
deleted file mode 100644
index c3bc33d2f6bb..000000000000
--- a/include/os/freebsd/zfs/sys/sha2.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/* Copyright 2013 Saso Kiselkov. All rights reserved. */
-
-#ifndef _SYS_SHA2_H
-#define _SYS_SHA2_H
-
-#include <sys/types.h> /* for uint_* */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SHA256_DIGEST_LENGTH 32 /* SHA256 digest length in bytes */
-#define SHA384_DIGEST_LENGTH 48 /* SHA384 digest length in bytes */
-#define SHA512_DIGEST_LENGTH 64 /* SHA512 digest length in bytes */
-
-/* Truncated versions of SHA-512 according to FIPS-180-4, section 5.3.6 */
-#define SHA512_224_DIGEST_LENGTH 28 /* SHA512/224 digest length */
-#define SHA512_256_DIGEST_LENGTH 32 /* SHA512/256 digest length */
-
-#define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */
-#define SHA512_HMAC_BLOCK_SIZE 128 /* SHA512-HMAC block size */
-
-#define SHA256 0
-#define SHA256_HMAC 1
-#define SHA256_HMAC_GEN 2
-#define SHA384 3
-#define SHA384_HMAC 4
-#define SHA384_HMAC_GEN 5
-#define SHA512 6
-#define SHA512_HMAC 7
-#define SHA512_HMAC_GEN 8
-#define SHA512_224 9
-#define SHA512_256 10
-
-/*
- * SHA2 context.
- * The contents of this structure are a private interface between the
- * Init/Update/Final calls of the functions defined below.
- * Callers must never attempt to read or write any of the fields
- * in this structure directly.
- */
-
-#include <crypto/sha2/sha256.h>
-#include <crypto/sha2/sha384.h>
-#include <crypto/sha2/sha512.h>
-#include <crypto/sha2/sha512t.h>
-typedef struct {
- uint32_t algotype; /* Algorithm Type */
- union {
- SHA256_CTX SHA256_ctx;
- SHA384_CTX SHA384_ctx;
- SHA512_CTX SHA512_ctx;
- };
-} SHA2_CTX;
-
-extern void SHA256Init(SHA256_CTX *);
-
-extern void SHA256Update(SHA256_CTX *, const void *, size_t);
-
-extern void SHA256Final(void *, SHA256_CTX *);
-
-extern void SHA384Init(SHA384_CTX *);
-
-extern void SHA384Update(SHA384_CTX *, const void *, size_t);
-
-extern void SHA384Final(void *, SHA384_CTX *);
-
-extern void SHA512Init(SHA512_CTX *);
-
-extern void SHA512Update(SHA512_CTX *, const void *, size_t);
-
-extern void SHA512Final(void *, SHA512_CTX *);
-
-
-static inline void
-SHA2Init(uint64_t mech, SHA2_CTX *c)
-{
- switch (mech) {
- case SHA256:
- SHA256_Init(&c->SHA256_ctx);
- break;
- case SHA384:
- SHA384_Init(&c->SHA384_ctx);
- break;
- case SHA512:
- SHA512_Init(&c->SHA512_ctx);
- break;
- case SHA512_256:
- SHA512_256_Init(&c->SHA512_ctx);
- break;
- default:
- panic("unknown mechanism %ju", (uintmax_t)mech);
- }
- c->algotype = (uint32_t)mech;
-}
-
-static inline void
-SHA2Update(SHA2_CTX *c, const void *p, size_t s)
-{
- switch (c->algotype) {
- case SHA256:
- SHA256_Update(&c->SHA256_ctx, p, s);
- break;
- case SHA384:
- SHA384_Update(&c->SHA384_ctx, p, s);
- break;
- case SHA512:
- SHA512_Update(&c->SHA512_ctx, p, s);
- break;
- case SHA512_256:
- SHA512_256_Update(&c->SHA512_ctx, p, s);
- break;
- default:
- panic("unknown mechanism %d", c->algotype);
- }
-}
-
-static inline void
-SHA2Final(void *p, SHA2_CTX *c)
-{
- switch (c->algotype) {
- case SHA256:
- SHA256_Final(p, &c->SHA256_ctx);
- break;
- case SHA384:
- SHA384_Final(p, &c->SHA384_ctx);
- break;
- case SHA512:
- SHA512_Final(p, &c->SHA512_ctx);
- break;
- case SHA512_256:
- SHA512_256_Final(p, &c->SHA512_ctx);
- break;
- default:
- panic("unknown mechanism %d", c->algotype);
- }
-}
-
-#ifdef _SHA2_IMPL
-/*
- * The following types/functions are all private to the implementation
- * of the SHA2 functions and must not be used by consumers of the interface
- */
-
-/*
- * List of support mechanisms in this module.
- *
- * It is important to note that in the module, division or modulus calculations
- * are used on the enumerated type to determine which mechanism is being used;
- * therefore, changing the order or additional mechanisms should be done
- * carefully
- */
-typedef enum sha2_mech_type {
- SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */
- SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */
- SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
- SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */
- SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */
- SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
- SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */
- SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */
- SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
- SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */
- SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */
-} sha2_mech_type_t;
-
-#endif /* _SHA2_IMPL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SHA2_H */
diff --git a/include/os/freebsd/zfs/sys/vdev_os.h b/include/os/freebsd/zfs/sys/vdev_os.h
index 59da954b90e6..ef1b01743b61 100644
--- a/include/os/freebsd/zfs/sys/vdev_os.h
+++ b/include/os/freebsd/zfs/sys/vdev_os.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/zfs/sys/zfs_context_os.h b/include/os/freebsd/zfs/sys/zfs_context_os.h
index 867199501396..457fa3af8142 100644
--- a/include/os/freebsd/zfs/sys/zfs_context_os.h
+++ b/include/os/freebsd/zfs/sys/zfs_context_os.h
@@ -45,8 +45,6 @@
#define HAVE_LARGE_STACKS 1
#endif
-#define cond_resched() kern_yield(PRI_USER)
-
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
((void) sizeof (dc), taskq_create(a, b, maxclsyspri, d, e, f))
@@ -80,7 +78,7 @@ extern int hz;
extern int tick;
typedef int fstrans_cookie_t;
#define spl_fstrans_mark() (0)
-#define spl_fstrans_unmark(x) (x = 0)
+#define spl_fstrans_unmark(x) ((void)x)
#define signal_pending(x) SIGPENDING(x)
#define current curthread
#define thread_join(x)
diff --git a/include/os/freebsd/zfs/sys/zfs_ctldir.h b/include/os/freebsd/zfs/sys/zfs_ctldir.h
index da02863a78e6..14d75df33df0 100644
--- a/include/os/freebsd/zfs/sys/zfs_ctldir.h
+++ b/include/os/freebsd/zfs/sys/zfs_ctldir.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/zfs/sys/zfs_dir.h b/include/os/freebsd/zfs/sys/zfs_dir.h
index 4197e1188c9b..1980b646e38b 100644
--- a/include/os/freebsd/zfs/sys/zfs_dir.h
+++ b/include/os/freebsd/zfs/sys/zfs_dir.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h b/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h
index d36a6d2ce7e2..34757a486028 100644
--- a/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h
+++ b/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -37,6 +37,15 @@
#include <sys/nvpair.h>
#endif /* _KERNEL */
+/*
+ * Legacy ioctl support allows compatibility with pre-OpenZFS tools on
+ * FreeBSD. The need for it will eventually pass (perhaps after FreeBSD
+ * 12 is well out of support), at which point this code can be removed.
+ * For now, downstream consumers may choose to disable this code by
+ * removing the following define.
+ */
+#define ZFS_LEGACY_SUPPORT
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -82,6 +91,7 @@ typedef struct zfs_iocparm {
} zfs_iocparm_t;
+#ifdef ZFS_LEGACY_SUPPORT
#define LEGACY_MAXPATHLEN 1024
#define LEGACY_MAXNAMELEN 256
@@ -135,6 +145,7 @@ typedef struct zfs_cmd_legacy {
uint64_t zc_createtxg;
zfs_stat_t zc_stat;
} zfs_cmd_legacy_t;
+#endif
#ifdef _KERNEL
@@ -145,10 +156,12 @@ nvlist_t *zfs_ioctl_compat_innvl(zfs_cmd_t *, nvlist_t *, const int,
nvlist_t *zfs_ioctl_compat_outnvl(zfs_cmd_t *, nvlist_t *, const int,
const int);
#endif /* _KERNEL */
+#ifdef ZFS_LEGACY_SUPPORT
int zfs_ioctl_legacy_to_ozfs(int request);
int zfs_ioctl_ozfs_to_legacy(int request);
void zfs_cmd_legacy_to_ozfs(zfs_cmd_legacy_t *src, zfs_cmd_t *dst);
void zfs_cmd_ozfs_to_legacy(zfs_cmd_t *src, zfs_cmd_legacy_t *dst);
+#endif
void zfs_cmd_compat_put(zfs_cmd_t *, caddr_t, const int, const int);
diff --git a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
index ccbbf4f73224..7f0f24325d59 100644
--- a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
+++ b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -93,7 +93,6 @@ struct zfsvfs {
zfs_teardown_lock_t z_teardown_lock;
zfs_teardown_inactive_lock_t z_teardown_inactive_lock;
list_t z_all_znodes; /* all vnodes in the fs */
- uint64_t z_nr_znodes; /* number of znodes in the fs */
kmutex_t z_znodes_lock; /* lock for z_all_znodes */
struct zfsctl_root *z_ctldir; /* .zfs directory pointer */
boolean_t z_show_ctldir; /* expose .zfs in the root dir */
@@ -128,9 +127,6 @@ struct zfsvfs {
#define ZFS_TEARDOWN_DESTROY(zfsvfs) \
rms_destroy(&(zfsvfs)->z_teardown_lock)
-#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \
- rms_try_rlock(&(zfsvfs)->z_teardown_lock)
-
#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \
rms_rlock(&(zfsvfs)->z_teardown_lock);
@@ -161,9 +157,6 @@ struct zfsvfs {
#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);
@@ -291,7 +284,6 @@ typedef struct zfid_long {
#define SHORT_FID_LEN (sizeof (zfid_short_t) - sizeof (uint16_t))
#define LONG_FID_LEN (sizeof (zfid_long_t) - sizeof (uint16_t))
-extern uint_t zfs_fsyncer_key;
extern int zfs_super_owner;
extern void zfs_init(void);
diff --git a/include/os/freebsd/zfs/sys/zfs_vnops_os.h b/include/os/freebsd/zfs/sys/zfs_vnops_os.h
index bf5e03b24c06..eddcab575b91 100644
--- a/include/os/freebsd/zfs/sys/zfs_vnops_os.h
+++ b/include/os/freebsd/zfs/sys/zfs_vnops_os.h
@@ -35,20 +35,23 @@ int dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count,
int *rbehind, int *rahead, int last_size);
extern int zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags);
extern int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap,
- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp);
+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns);
extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd,
cred_t *cr, int flags);
-extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr);
+extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
+ zidmap_t *mnt_ns);
extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp,
- const char *tnm, cred_t *cr, int flags);
+ const char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap,
+ zidmap_t *mnt_ns);
extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
- const char *link, znode_t **zpp, cred_t *cr, int flags);
+ const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns);
extern int zfs_link(znode_t *tdzp, znode_t *sp,
const char *name, cred_t *cr, int flags);
extern int zfs_space(znode_t *zp, int cmd, struct flock *bfp, int flag,
offset_t offset, cred_t *cr);
extern int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl,
- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp);
+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp,
+ zidmap_t *mnt_ns);
extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag,
cred_t *cr);
extern int zfs_write_simple(znode_t *zp, const void *data, size_t len,
diff --git a/include/os/freebsd/zfs/sys/zfs_znode_impl.h b/include/os/freebsd/zfs/sys/zfs_znode_impl.h
index 5d64c3fccd3f..050fc3036f87 100644
--- a/include/os/freebsd/zfs/sys/zfs_znode_impl.h
+++ b/include/os/freebsd/zfs/sys/zfs_znode_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -116,34 +116,31 @@ typedef struct zfs_soft_state {
#define Z_ISLNK(type) ((type) == VLNK)
#define Z_ISDIR(type) ((type) == VDIR)
-#define zn_has_cached_data(zp) vn_has_cached_data(ZTOV(zp))
+#define zn_has_cached_data(zp, start, end) \
+ vn_has_cached_data(ZTOV(zp))
#define zn_flush_cached_data(zp, sync) vn_flush_cached_data(ZTOV(zp), sync)
-#define zn_rlimit_fsize(zp, uio) \
+#define zn_rlimit_fsize(size) zfs_rlimit_fsize(size)
+#define zn_rlimit_fsize_uio(zp, uio) \
vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio))
-#define ZFS_ENTER_ERROR(zfsvfs, error) do { \
- ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
- if (__predict_false((zfsvfs)->z_unmounted)) { \
- ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
- return (error); \
- } \
-} while (0)
-
/* Called on entry to each ZFS vnode and vfs operation */
-#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
+static inline int
+zfs_enter(zfsvfs_t *zfsvfs, const char *tag)
+{
+ ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag);
+ if (__predict_false((zfsvfs)->z_unmounted)) {
+ ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag);
+ return (SET_ERROR(EIO));
+ }
+ return (0);
+}
/* Must be called before exiting the vop */
-#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
-
-#define ZFS_VERIFY_ZP_ERROR(zp, error) do { \
- if (__predict_false((zp)->z_sa_hdl == NULL)) { \
- ZFS_EXIT((zp)->z_zfsvfs); \
- return (error); \
- } \
-} while (0)
-
-/* Verifies the znode is valid */
-#define ZFS_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, EIO)
+static inline void
+zfs_exit(zfsvfs_t *zfsvfs, const char *tag)
+{
+ ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag);
+}
/*
* Macros for dealing with dmu_buf_hold
@@ -183,6 +180,8 @@ extern zil_replay_func_t *const zfs_replay_vector[TX_MAX_TYPE];
extern int zfs_znode_parent_and_name(struct znode *zp, struct znode **dzpp,
char *buf);
+
+extern int zfs_rlimit_fsize(off_t fsize);
#ifdef __cplusplus
}
#endif
diff --git a/include/os/linux/Makefile.am b/include/os/linux/Makefile.am
index 4d6901c694c8..f31ae50b96af 100644
--- a/include/os/linux/Makefile.am
+++ b/include/os/linux/Makefile.am
@@ -5,11 +5,13 @@ kernel_linux_HEADERS = \
%D%/kernel/linux/compiler_compat.h \
%D%/kernel/linux/dcache_compat.h \
%D%/kernel/linux/kmap_compat.h \
+ %D%/kernel/linux/mm_compat.h \
%D%/kernel/linux/mod_compat.h \
%D%/kernel/linux/page_compat.h \
%D%/kernel/linux/percpu_compat.h \
%D%/kernel/linux/simd.h \
%D%/kernel/linux/simd_aarch64.h \
+ %D%/kernel/linux/simd_arm.h \
%D%/kernel/linux/simd_powerpc.h \
%D%/kernel/linux/simd_x86.h \
%D%/kernel/linux/utsname_compat.h \
@@ -19,7 +21,6 @@ kernel_linux_HEADERS = \
kernel_sysdir = $(kerneldir)/sys
kernel_sys_HEADERS = \
%D%/zfs/sys/policy.h \
- %D%/zfs/sys/sha2.h \
%D%/zfs/sys/trace_acl.h \
%D%/zfs/sys/trace_arc.h \
%D%/zfs/sys/trace_common.h \
@@ -46,6 +47,7 @@ kernel_sys_HEADERS = \
kernel_spl_rpcdir = $(kerneldir)/spl/rpc
kernel_spl_rpc_HEADERS = \
+ %D%/spl/rpc/types.h \
%D%/spl/rpc/xdr.h
kernel_spl_sysdir = $(kerneldir)/spl/sys
@@ -61,7 +63,6 @@ kernel_spl_sys_HEADERS = \
%D%/spl/sys/ctype.h \
%D%/spl/sys/debug.h \
%D%/spl/sys/disp.h \
- %D%/spl/sys/dkio.h \
%D%/spl/sys/errno.h \
%D%/spl/sys/fcntl.h \
%D%/spl/sys/file.h \
@@ -71,6 +72,7 @@ kernel_spl_sys_HEADERS = \
%D%/spl/sys/kmem_cache.h \
%D%/spl/sys/kstat.h \
%D%/spl/sys/list.h \
+ %D%/spl/sys/misc.h \
%D%/spl/sys/mod_os.h \
%D%/spl/sys/mutex.h \
%D%/spl/sys/param.h \
@@ -108,4 +110,8 @@ kernel_spl_sys_HEADERS = \
%D%/spl/sys/wmsum.h \
%D%/spl/sys/zmod.h \
%D%/spl/sys/zone.h
+
+kernel_spl_ia32dir = $(kernel_spl_sysdir)/ia32
+kernel_spl_ia32_HEADERS = \
+ %D%/spl/sys/ia32/asm_linkage.h
endif
diff --git a/include/os/linux/kernel/linux/blkdev_compat.h b/include/os/linux/kernel/linux/blkdev_compat.h
index 7964937a0f4d..658f546213de 100644
--- a/include/os/linux/kernel/linux/blkdev_compat.h
+++ b/include/os/linux/kernel/linux/blkdev_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -94,6 +94,33 @@ blk_queue_set_write_cache(struct request_queue *q, bool wc, bool fua)
#endif
}
+/*
+ * Detect if a device has a write cache. Used to set the intial value for the
+ * vdev nowritecache flag.
+ *
+ * 4.10: QUEUE_FLAG_WC added. Initialised by the driver, but can be changed
+ * later by the operator. If not set, kernel will return flush requests
+ * immediately without doing anything.
+ * 6.6: QUEUE_FLAG_HW_WC added. Initialised by the driver, can't be changed.
+ * Only controls if the operator is allowed to change _WC. Initial version
+ * buggy; aliased to QUEUE_FLAG_FUA, so unuseable.
+ * 6.6.10, 6.7: QUEUE_FLAG_HW_WC fixed.
+ *
+ * Older than 4.10 we just assume write cache, and let the normal flush fail
+ * detection apply.
+ */
+static inline boolean_t
+zfs_bdev_has_write_cache(struct block_device *bdev)
+{
+#if defined(QUEUE_FLAG_HW_WC) && QUEUE_FLAG_HW_WC != QUEUE_FLAG_FUA
+ return (test_bit(QUEUE_FLAG_HW_WC, &bdev_get_queue(bdev)->queue_flags));
+#elif defined(QUEUE_FLAG_WC)
+ return (test_bit(QUEUE_FLAG_WC, &bdev_get_queue(bdev)->queue_flags));
+#else
+ return (B_TRUE);
+#endif
+}
+
static inline void
blk_queue_set_read_ahead(struct request_queue *q, unsigned long ra_pages)
{
@@ -126,7 +153,8 @@ typedef int bvec_iterator_t;
#endif
static inline void
-bio_set_flags_failfast(struct block_device *bdev, int *flags)
+bio_set_flags_failfast(struct block_device *bdev, int *flags, bool dev,
+ bool transport, bool driver)
{
#ifdef CONFIG_BUG
/*
@@ -148,7 +176,12 @@ bio_set_flags_failfast(struct block_device *bdev, int *flags)
#endif /* BLOCK_EXT_MAJOR */
#endif /* CONFIG_BUG */
- *flags |= REQ_FAILFAST_MASK;
+ if (dev)
+ *flags |= REQ_FAILFAST_DEV;
+ if (transport)
+ *flags |= REQ_FAILFAST_TRANSPORT;
+ if (driver)
+ *flags |= REQ_FAILFAST_DRIVER;
}
/*
@@ -175,7 +208,11 @@ bi_status_to_errno(blk_status_t status)
return (ENOLINK);
case BLK_STS_TARGET:
return (EREMOTEIO);
+#ifdef HAVE_BLK_STS_RESV_CONFLICT
+ case BLK_STS_RESV_CONFLICT:
+#else
case BLK_STS_NEXUS:
+#endif
return (EBADE);
case BLK_STS_MEDIUM:
return (ENODATA);
@@ -209,7 +246,11 @@ errno_to_bi_status(int error)
case EREMOTEIO:
return (BLK_STS_TARGET);
case EBADE:
+#ifdef HAVE_BLK_STS_RESV_CONFLICT
+ return (BLK_STS_RESV_CONFLICT);
+#else
return (BLK_STS_NEXUS);
+#endif
case ENODATA:
return (BLK_STS_MEDIUM);
case EILSEQ:
@@ -262,6 +303,32 @@ bio_set_bi_error(struct bio *bio, int error)
#endif /* HAVE_1ARG_BIO_END_IO_T */
/*
+ * 5.15 MACRO,
+ * GD_DEAD
+ *
+ * 2.6.36 - 5.14 MACRO,
+ * GENHD_FL_UP
+ *
+ * Check the disk status and return B_TRUE if alive
+ * otherwise B_FALSE
+ */
+static inline boolean_t
+zfs_check_disk_status(struct block_device *bdev)
+{
+#if defined(GENHD_FL_UP)
+ return (!!(bdev->bd_disk->flags & GENHD_FL_UP));
+#elif defined(GD_DEAD)
+ return (!test_bit(GD_DEAD, &bdev->bd_disk->state));
+#else
+/*
+ * This is encountered if neither GENHD_FL_UP nor GD_DEAD is available in
+ * the kernel - likely due to an MACRO change that needs to be chased down.
+ */
+#error "Unsupported kernel: no usable disk status check"
+#endif
+}
+
+/*
* 4.1 API,
* 3.10.0 CentOS 7.x API,
* blkdev_reread_part()
@@ -305,6 +372,9 @@ zfs_check_media_change(struct block_device *bdev)
return (0);
}
#define vdev_bdev_reread_part(bdev) zfs_check_media_change(bdev)
+#elif defined(HAVE_DISK_CHECK_MEDIA_CHANGE)
+#define vdev_bdev_reread_part(bdev) disk_check_media_change(bdev->bd_disk)
+#define zfs_check_media_change(bdev) disk_check_media_change(bdev->bd_disk)
#else
/*
* This is encountered if check_disk_change() and bdev_check_media_change()
@@ -355,6 +425,12 @@ vdev_lookup_bdev(const char *path, dev_t *dev)
#endif
}
+#if defined(HAVE_BLK_MODE_T)
+#define blk_mode_is_open_write(flag) ((flag) & BLK_OPEN_WRITE)
+#else
+#define blk_mode_is_open_write(flag) ((flag) & FMODE_WRITE)
+#endif
+
/*
* Kernels without bio_set_op_attrs use bi_rw for the bio flags.
*/
@@ -362,7 +438,11 @@ vdev_lookup_bdev(const char *path, dev_t *dev)
static inline void
bio_set_op_attrs(struct bio *bio, unsigned rw, unsigned flags)
{
+#if defined(HAVE_BIO_BI_OPF)
+ bio->bi_opf = rw | flags;
+#else
bio->bi_rw |= rw | flags;
+#endif /* HAVE_BIO_BI_OPF */
}
#endif
@@ -390,7 +470,7 @@ static inline void
bio_set_flush(struct bio *bio)
{
#if defined(HAVE_REQ_PREFLUSH) /* >= 4.10 */
- bio_set_op_attrs(bio, 0, REQ_PREFLUSH);
+ bio_set_op_attrs(bio, 0, REQ_PREFLUSH | REQ_OP_WRITE);
#elif defined(WRITE_FLUSH_FUA) /* >= 2.6.37 and <= 4.9 */
bio_set_op_attrs(bio, 0, WRITE_FLUSH_FUA);
#else
@@ -510,9 +590,11 @@ static inline boolean_t
bdev_discard_supported(struct block_device *bdev)
{
#if defined(HAVE_BDEV_MAX_DISCARD_SECTORS)
- return (!!bdev_max_discard_sectors(bdev));
+ return (bdev_max_discard_sectors(bdev) > 0 &&
+ bdev_discard_granularity(bdev) > 0);
#elif defined(HAVE_BLK_QUEUE_DISCARD)
- return (!!blk_queue_discard(bdev_get_queue(bdev)));
+ return (blk_queue_discard(bdev_get_queue(bdev)) > 0 &&
+ bdev_get_queue(bdev)->limits.discard_granularity > 0);
#else
#error "Unsupported kernel"
#endif
@@ -556,7 +638,10 @@ blk_generic_start_io_acct(struct request_queue *q __attribute__((unused)),
struct gendisk *disk __attribute__((unused)),
int rw __attribute__((unused)), struct bio *bio)
{
-#if defined(HAVE_BDEV_IO_ACCT)
+#if defined(HAVE_BDEV_IO_ACCT_63)
+ return (bdev_start_io_acct(bio->bi_bdev, bio_op(bio),
+ jiffies));
+#elif defined(HAVE_BDEV_IO_ACCT_OLD)
return (bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio),
bio_op(bio), jiffies));
#elif defined(HAVE_DISK_IO_ACCT)
@@ -582,7 +667,10 @@ blk_generic_end_io_acct(struct request_queue *q __attribute__((unused)),
struct gendisk *disk __attribute__((unused)),
int rw __attribute__((unused)), struct bio *bio, unsigned long start_time)
{
-#if defined(HAVE_BDEV_IO_ACCT)
+#if defined(HAVE_BDEV_IO_ACCT_63)
+ bdev_end_io_acct(bio->bi_bdev, bio_op(bio), bio_sectors(bio),
+ start_time);
+#elif defined(HAVE_BDEV_IO_ACCT_OLD)
bdev_end_io_acct(bio->bi_bdev, bio_op(bio), start_time);
#elif defined(HAVE_DISK_IO_ACCT)
disk_end_io_acct(disk, bio_op(bio), start_time);
diff --git a/include/os/linux/kernel/linux/compiler_compat.h b/include/os/linux/kernel/linux/compiler_compat.h
index a65689642361..98f7d7608043 100644
--- a/include/os/linux/kernel/linux/compiler_compat.h
+++ b/include/os/linux/kernel/linux/compiler_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/kernel/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h
index d0588a82e9ad..ab1711b99f3f 100644
--- a/include/os/linux/kernel/linux/dcache_compat.h
+++ b/include/os/linux/kernel/linux/dcache_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -35,6 +35,36 @@
#define d_make_root(inode) d_alloc_root(inode)
#endif /* HAVE_D_MAKE_ROOT */
+#ifdef HAVE_DENTRY_D_U_ALIASES
+#define d_alias d_u.d_alias
+#endif
+
+/*
+ * Starting from Linux 5.13, flush_dcache_page() becomes an inline function
+ * and under some configurations, may indirectly referencing GPL-only
+ * symbols, e.g., cpu_feature_keys on powerpc and PageHuge on riscv.
+ * Override this function when it is detected being GPL-only.
+ */
+#if defined __powerpc__ && defined HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY
+#include <linux/simd_powerpc.h>
+#define flush_dcache_page(page) do { \
+ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) && \
+ test_bit(PG_dcache_clean, &(page)->flags)) \
+ clear_bit(PG_dcache_clean, &(page)->flags); \
+ } while (0)
+#endif
+/*
+ * For riscv implementation, the use of PageHuge can be safely removed.
+ * Because it handles pages allocated by HugeTLB, while flush_dcache_page
+ * in zfs module is only called on kernel pages.
+ */
+#if defined __riscv && defined HAVE_FLUSH_DCACHE_PAGE_GPL_ONLY
+#define flush_dcache_page(page) do { \
+ if (test_bit(PG_dcache_clean, &(page)->flags)) \
+ clear_bit(PG_dcache_clean, &(page)->flags); \
+ } while (0)
+#endif
+
/*
* 2.6.30 API change,
* The const keyword was added to the 'struct dentry_operations' in
@@ -61,4 +91,21 @@ d_clear_d_op(struct dentry *dentry)
DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE);
}
+/*
+ * Walk and invalidate all dentry aliases of an inode
+ * unless it's a mountpoint
+ */
+static inline void
+zpl_d_drop_aliases(struct inode *inode)
+{
+ struct dentry *dentry;
+ spin_lock(&inode->i_lock);
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ if (!IS_ROOT(dentry) && !d_mountpoint(dentry) &&
+ (dentry->d_inode == inode)) {
+ d_drop(dentry);
+ }
+ }
+ spin_unlock(&inode->i_lock);
+}
#endif /* _ZFS_DCACHE_H */
diff --git a/include/os/linux/kernel/linux/kmap_compat.h b/include/os/linux/kernel/linux/kmap_compat.h
index 42f463ab9ae9..7f9c00af802b 100644
--- a/include/os/linux/kernel/linux/kmap_compat.h
+++ b/include/os/linux/kernel/linux/kmap_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/spa_boot.h b/include/os/linux/kernel/linux/mm_compat.h
index 1d3622f5a108..40056c68d6dd 100644
--- a/include/sys/spa_boot.h
+++ b/include/os/linux/kernel/linux/mm_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -18,25 +18,19 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2023, 2024, Klara Inc.
*/
-#ifndef _SYS_SPA_BOOT_H
-#define _SYS_SPA_BOOT_H
-
-#include <sys/nvpair.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#ifndef _ZFS_MM_COMPAT_H
+#define _ZFS_MM_COMPAT_H
-extern char *spa_get_bootprop(char *prop);
-extern void spa_free_bootprop(char *prop);
+#include <linux/mm.h>
-#ifdef __cplusplus
-}
+/* 5.4 introduced page_size(). Older kernels can use a trivial macro instead */
+#ifndef HAVE_MM_PAGE_SIZE
+#define page_size(p) ((unsigned long)(PAGE_SIZE << compound_order(p)))
#endif
-#endif /* _SYS_SPA_BOOT_H */
+#endif /* _ZFS_MM_COMPAT_H */
diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h
index 78603e54f54c..039865b703ef 100644
--- a/include/os/linux/kernel/linux/mod_compat.h
+++ b/include/os/linux/kernel/linux/mod_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,27 +30,24 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-/* 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
-#define INT int
-#define LONG long
-/* BEGIN CSTYLED */
-#define UINT uint
-#define ULONG ulong
-/* END CSTYLED */
-#define STRING charp
-
enum scope_prefix_types {
zfs,
zfs_arc,
+ zfs_brt,
zfs_condense,
zfs_dbuf,
zfs_dbuf_cache,
@@ -71,7 +68,7 @@ enum scope_prefix_types {
zfs_trim,
zfs_txg,
zfs_vdev,
- zfs_vdev_cache,
+ zfs_vdev_disk,
zfs_vdev_file,
zfs_vdev_mirror,
zfs_vnops,
@@ -81,6 +78,50 @@ enum scope_prefix_types {
};
/*
+ * While we define our own s64/u64 types, there is no reason to reimplement the
+ * existing Linux kernel types, so we use the preprocessor to remap our
+ * "custom" implementations to the kernel ones. This is done because the CPP
+ * does not allow us to write conditional definitions. The fourth definition
+ * exists because the CPP will not allow us to replace things like INT with int
+ * before string concatenation.
+ */
+
+#define spl_param_set_int param_set_int
+#define spl_param_get_int param_get_int
+#define spl_param_ops_int param_ops_int
+#define spl_param_ops_INT param_ops_int
+
+#define spl_param_set_long param_set_long
+#define spl_param_get_long param_get_long
+#define spl_param_ops_long param_ops_long
+#define spl_param_ops_LONG param_ops_long
+
+#define spl_param_set_uint param_set_uint
+#define spl_param_get_uint param_get_uint
+#define spl_param_ops_uint param_ops_uint
+#define spl_param_ops_UINT param_ops_uint
+
+#define spl_param_set_ulong param_set_ulong
+#define spl_param_get_ulong param_get_ulong
+#define spl_param_ops_ulong param_ops_ulong
+#define spl_param_ops_ULONG param_ops_ulong
+
+#define spl_param_set_charp param_set_charp
+#define spl_param_get_charp param_get_charp
+#define spl_param_ops_charp param_ops_charp
+#define spl_param_ops_STRING param_ops_charp
+
+int spl_param_set_s64(const char *val, zfs_kernel_param_t *kp);
+extern int spl_param_get_s64(char *buffer, zfs_kernel_param_t *kp);
+extern const struct kernel_param_ops spl_param_ops_s64;
+#define spl_param_ops_S64 spl_param_ops_s64
+
+extern int spl_param_set_u64(const char *val, zfs_kernel_param_t *kp);
+extern int spl_param_get_u64(char *buffer, zfs_kernel_param_t *kp);
+extern const struct kernel_param_ops spl_param_ops_u64;
+#define spl_param_ops_U64 spl_param_ops_u64
+
+/*
* Declare a module parameter / sysctl node
*
* "scope_prefix" the part of the sysctl / sysfs tree the node resides under
@@ -112,7 +153,8 @@ enum scope_prefix_types {
_Static_assert( \
sizeof (scope_prefix) == sizeof (enum scope_prefix_types), \
"" #scope_prefix " size mismatch with enum scope_prefix_types"); \
- module_param(name_prefix ## name, type, perm); \
+ module_param_cb(name_prefix ## name, &spl_param_ops_ ## type, \
+ &name_prefix ## name, perm); \
MODULE_PARM_DESC(name_prefix ## name, desc)
/*
diff --git a/include/os/linux/kernel/linux/percpu_compat.h b/include/os/linux/kernel/linux/percpu_compat.h
index e7a4242c466c..bf3a5a01c27e 100644
--- a/include/os/linux/kernel/linux/percpu_compat.h
+++ b/include/os/linux/kernel/linux/percpu_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/kernel/linux/simd.h b/include/os/linux/kernel/linux/simd.h
index 4cde248e200c..f4376b218a55 100644
--- a/include/os/linux/kernel/linux/simd.h
+++ b/include/os/linux/kernel/linux/simd.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,13 +28,16 @@
#if defined(__x86)
#include <linux/simd_x86.h>
+#elif defined(__arm__)
+#include <linux/simd_arm.h>
+
#elif defined(__aarch64__)
#include <linux/simd_aarch64.h>
#elif defined(__powerpc__)
#include <linux/simd_powerpc.h>
-#else
+#else
#define kfpu_allowed() 0
#define kfpu_begin() do {} while (0)
#define kfpu_end() do {} while (0)
diff --git a/include/os/linux/kernel/linux/simd_aarch64.h b/include/os/linux/kernel/linux/simd_aarch64.h
index 50937e97ced1..123a0c72bc6a 100644
--- a/include/os/linux/kernel/linux/simd_aarch64.h
+++ b/include/os/linux/kernel/linux/simd_aarch64.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -18,8 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (C) 2016 Romain Dolbeau <romain@dolbeau.org>.
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * Copyright (C) 2022 Sebastian Gottschall <s.gottschall@dd-wrt.com>
*/
/*
@@ -31,24 +34,89 @@
* kfpu_end()
* kfpu_init()
* kfpu_fini()
+ *
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_neon_available()
+ * zfs_sha256_available()
+ * zfs_sha512_available()
*/
#ifndef _LINUX_SIMD_AARCH64_H
#define _LINUX_SIMD_AARCH64_H
-#include <sys/isa_defs.h>
-
-#if defined(__aarch64__)
-
#include <sys/types.h>
#include <asm/neon.h>
+#include <asm/elf.h>
+#include <asm/hwcap.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#include <asm/sysreg.h>
+#else
+#define sys_reg(op0, op1, crn, crm, op2) ( \
+ ((op0) << Op0_shift) | \
+ ((op1) << Op1_shift) | \
+ ((crn) << CRn_shift) | \
+ ((crm) << CRm_shift) | \
+ ((op2) << Op2_shift))
+#endif
+#define ID_AA64PFR0_EL1 sys_reg(3, 0, 0, 1, 0)
+#define ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0)
+
+#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON))
#define kfpu_allowed() 1
#define kfpu_begin() kernel_neon_begin()
#define kfpu_end() kernel_neon_end()
-#define kfpu_init() 0
-#define kfpu_fini() ((void) 0)
+#else
+#define kfpu_allowed() 0
+#define kfpu_begin() do {} while (0)
+#define kfpu_end() do {} while (0)
+#endif
+#define kfpu_init() (0)
+#define kfpu_fini() do {} while (0)
+
+#define get_ftr(id) { \
+ unsigned long __val; \
+ asm("mrs %0, "#id : "=r" (__val)); \
+ __val; \
+}
-#endif /* __aarch64__ */
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+ unsigned long ftr = ((get_ftr(ID_AA64PFR0_EL1)) >> 16) & 0xf;
+ return (ftr == 0 || ftr == 1);
+}
+
+/*
+ * Check if SHA256 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+ unsigned long ftr = ((get_ftr(ID_AA64ISAR0_EL1)) >> 12) & 0x3;
+ return (ftr & 0x1);
+}
+
+/*
+ * Check if SHA512 is available
+ */
+static inline boolean_t
+zfs_sha512_available(void)
+{
+ unsigned long ftr = ((get_ftr(ID_AA64ISAR0_EL1)) >> 12) & 0x3;
+ return (ftr & 0x2);
+}
#endif /* _LINUX_SIMD_AARCH64_H */
diff --git a/include/os/linux/kernel/linux/simd_arm.h b/include/os/linux/kernel/linux/simd_arm.h
new file mode 100644
index 000000000000..bc70eaef3073
--- /dev/null
+++ b/include/os/linux/kernel/linux/simd_arm.h
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+/*
+ * USER API:
+ *
+ * Kernel fpu methods:
+ * kfpu_allowed()
+ * kfpu_begin()
+ * kfpu_end()
+ * kfpu_init()
+ * kfpu_fini()
+ *
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_neon_available()
+ * zfs_sha256_available()
+ */
+
+#ifndef _LINUX_SIMD_ARM_H
+#define _LINUX_SIMD_ARM_H
+
+#include <sys/types.h>
+#include <asm/neon.h>
+#include <asm/elf.h>
+#include <asm/hwcap.h>
+
+#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON))
+#define kfpu_allowed() 1
+#define kfpu_begin() kernel_neon_begin()
+#define kfpu_end() kernel_neon_end()
+#else
+#define kfpu_allowed() 0
+#define kfpu_begin() do {} while (0)
+#define kfpu_end() do {} while (0)
+#endif
+#define kfpu_init() (0)
+#define kfpu_fini() do {} while (0)
+
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+ return (elf_hwcap & HWCAP_NEON);
+}
+
+/*
+ * Check if SHA256 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+ return (elf_hwcap2 & HWCAP2_SHA2);
+}
+
+#endif /* _LINUX_SIMD_ARM_H */
diff --git a/include/os/linux/kernel/linux/simd_powerpc.h b/include/os/linux/kernel/linux/simd_powerpc.h
index 31e51ea20a1d..a649790ce50f 100644
--- a/include/os/linux/kernel/linux/simd_powerpc.h
+++ b/include/os/linux/kernel/linux/simd_powerpc.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,6 +21,7 @@
/*
* Copyright (C) 2019 Romain Dolbeau
* <romain.dolbeau@european-processor-initiative.eu>
+ * Copyright (C) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
/*
@@ -41,15 +42,14 @@
* all relevant feature test functions should be called.
*
* Supported features:
- * zfs_altivec_available()
+ * zfs_altivec_available()
+ * zfs_vsx_available()
+ * zfs_isa207_available()
*/
#ifndef _LINUX_SIMD_POWERPC_H
#define _LINUX_SIMD_POWERPC_H
-/* only for __powerpc__ */
-#if defined(__powerpc__)
-
#include <linux/preempt.h>
#include <linux/export.h>
#include <linux/sched.h>
@@ -57,73 +57,95 @@
#include <sys/types.h>
#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+#include <asm/cpufeature.h>
+#else
+#include <asm/cputable.h>
+#endif
+
#define kfpu_allowed() 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
-#define kfpu_end() \
- { \
- disable_kernel_vsx(); \
- disable_kernel_altivec(); \
- preempt_enable(); \
- }
+#ifdef CONFIG_ALTIVEC
+#define ENABLE_KERNEL_ALTIVEC enable_kernel_altivec();
+#define DISABLE_KERNEL_ALTIVEC disable_kernel_altivec();
+#else
+#define ENABLE_KERNEL_ALTIVEC
+#define DISABLE_KERNEL_ALTIVEC
+#endif
+#ifdef CONFIG_VSX
+#define ENABLE_KERNEL_VSX enable_kernel_vsx();
+#define DISABLE_KERNEL_VSX disable_kernel_vsx();
+#else
+#define ENABLE_KERNEL_VSX
+#define DISABLE_KERNEL_VSX
+#endif
+#ifdef CONFIG_SPE
+#define ENABLE_KERNEL_SPE enable_kernel_spe();
+#define DISABLE_KERNEL_SPE disable_kernel_spe();
+#else
+#define ENABLE_KERNEL_SPE
+#define DISABLE_KERNEL_SPE
+#endif
#define kfpu_begin() \
{ \
preempt_disable(); \
- enable_kernel_altivec(); \
- enable_kernel_vsx(); \
+ ENABLE_KERNEL_ALTIVEC \
+ ENABLE_KERNEL_VSX \
+ ENABLE_KERNEL_SPE \
+ }
+#define kfpu_end() \
+ { \
+ DISABLE_KERNEL_SPE \
+ DISABLE_KERNEL_VSX \
+ DISABLE_KERNEL_ALTIVEC \
+ preempt_enable(); \
}
#else
/* seems that before 4.5 no-one bothered */
#define kfpu_begin()
#define kfpu_end() preempt_enable()
-#endif
+#endif /* Linux version >= 4.5 */
+
#define kfpu_init() 0
#define kfpu_fini() ((void) 0)
+/*
+ * Linux 4.7 makes cpu_has_feature to use jump labels on powerpc if
+ * CONFIG_JUMP_LABEL_FEATURE_CHECKS is enabled, in this case however it
+ * references GPL-only symbol cpu_feature_keys. Therefore we overrides this
+ * interface when it is detected being GPL-only.
+ */
+#if defined(CONFIG_JUMP_LABEL_FEATURE_CHECKS) && \
+ defined(HAVE_CPU_HAS_FEATURE_GPL_ONLY)
+#define cpu_has_feature(feature) early_cpu_has_feature(feature)
+#endif
+
+/*
+ * Check if AltiVec instruction set is available
+ */
+static inline boolean_t
+zfs_altivec_available(void)
+{
+ return (cpu_has_feature(CPU_FTR_ALTIVEC));
+}
+
+/*
+ * Check if VSX is available
+ */
static inline boolean_t
zfs_vsx_available(void)
{
- boolean_t res;
-#if defined(__powerpc64__)
- u64 msr;
-#else
- u32 msr;
-#endif
- kfpu_begin();
- __asm volatile("mfmsr %0" : "=r"(msr));
- res = (msr & 0x800000) != 0;
- kfpu_end();
- return (res);
+ return (cpu_has_feature(CPU_FTR_VSX));
}
/*
- * Check if AltiVec instruction set is available
+ * Check if POWER ISA 2.07 is available (SHA2)
*/
static inline boolean_t
-zfs_altivec_available(void)
+zfs_isa207_available(void)
{
- boolean_t res;
- /* suggested by macallan at netbsd dot org */
-#if defined(__powerpc64__)
- u64 msr;
-#else
- u32 msr;
-#endif
- kfpu_begin();
- __asm volatile("mfmsr %0" : "=r"(msr));
- /*
- * 64 bits -> need to check bit 38
- * Power ISA Version 3.0B
- * p944
- * 32 bits -> Need to check bit 6
- * AltiVec Technology Programming Environments Manual
- * p49 (2-9)
- * They are the same, as ppc counts 'backward' ...
- */
- res = (msr & 0x2000000) != 0;
- kfpu_end();
- return (res);
+ return (cpu_has_feature(CPU_FTR_ARCH_207S));
}
-#endif /* defined(__powerpc) */
#endif /* _LINUX_SIMD_POWERPC_H */
diff --git a/include/os/linux/kernel/linux/simd_x86.h b/include/os/linux/kernel/linux/simd_x86.h
index 3564ea7f1391..699b8a571824 100644
--- a/include/os/linux/kernel/linux/simd_x86.h
+++ b/include/os/linux/kernel/linux/simd_x86.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -53,6 +53,8 @@
* zfs_bmi1_available()
* zfs_bmi2_available()
*
+ * zfs_shani_available()
+ *
* zfs_avx512f_available()
* zfs_avx512cd_available()
* zfs_avx512er_available()
@@ -145,6 +147,15 @@
#error "Toolchain needs to support the XSAVE assembler instruction"
#endif
+#ifndef XFEATURE_MASK_XTILE
+/*
+ * For kernels where this doesn't exist yet, we still don't want to break
+ * by save/restoring this broken nonsense.
+ * See issue #14989 or Intel errata SPR4 for why
+ */
+#define XFEATURE_MASK_XTILE 0x60000
+#endif
+
#include <linux/mm.h>
#include <linux/slab.h>
@@ -313,18 +324,18 @@ kfpu_begin(void)
uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()];
#if defined(HAVE_XSAVES)
if (static_cpu_has(X86_FEATURE_XSAVES)) {
- kfpu_do_xsave("xsaves", state, ~0);
+ kfpu_do_xsave("xsaves", state, ~XFEATURE_MASK_XTILE);
return;
}
#endif
#if defined(HAVE_XSAVEOPT)
if (static_cpu_has(X86_FEATURE_XSAVEOPT)) {
- kfpu_do_xsave("xsaveopt", state, ~0);
+ kfpu_do_xsave("xsaveopt", state, ~XFEATURE_MASK_XTILE);
return;
}
#endif
if (static_cpu_has(X86_FEATURE_XSAVE)) {
- kfpu_do_xsave("xsave", state, ~0);
+ kfpu_do_xsave("xsave", state, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_save_fxsr(state);
} else {
@@ -374,12 +385,12 @@ kfpu_end(void)
uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()];
#if defined(HAVE_XSAVES)
if (static_cpu_has(X86_FEATURE_XSAVES)) {
- kfpu_do_xrstor("xrstors", state, ~0);
+ kfpu_do_xrstor("xrstors", state, ~XFEATURE_MASK_XTILE);
goto out;
}
#endif
if (static_cpu_has(X86_FEATURE_XSAVE)) {
- kfpu_do_xrstor("xrstor", state, ~0);
+ kfpu_do_xrstor("xrstor", state, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_restore_fxsr(state);
} else {
@@ -587,6 +598,19 @@ zfs_movbe_available(void)
}
/*
+ * Check if SHA_NI instruction set is available
+ */
+static inline boolean_t
+zfs_shani_available(void)
+{
+#if defined(X86_FEATURE_SHA_NI)
+ return (!!boot_cpu_has(X86_FEATURE_SHA_NI));
+#else
+ return (B_FALSE);
+#endif
+}
+
+/*
* AVX-512 family of instruction sets:
*
* AVX512F Foundation
diff --git a/include/os/linux/kernel/linux/utsname_compat.h b/include/os/linux/kernel/linux/utsname_compat.h
index 88da45cf504e..4a027bde8788 100644
--- a/include/os/linux/kernel/linux/utsname_compat.h
+++ b/include/os/linux/kernel/linux/utsname_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h
index b5ff1559ece6..aea8bd5ed22c 100644
--- a/include/os/linux/kernel/linux/vfs_compat.h
+++ b/include/os/linux/kernel/linux/vfs_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -325,10 +325,24 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid)
}
/*
+ * 3.15 API change
+ */
+#ifndef RENAME_NOREPLACE
+#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
+#endif
+#ifndef RENAME_EXCHANGE
+#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
+#endif
+#ifndef RENAME_WHITEOUT
+#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
+#endif
+
+/*
* 4.9 API change
*/
#if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \
- defined(HAVE_SETATTR_PREPARE_USERNS))
+ defined(HAVE_SETATTR_PREPARE_USERNS) || \
+ defined(HAVE_SETATTR_PREPARE_IDMAP))
static inline int
setattr_prepare(struct dentry *dentry, struct iattr *ia)
{
@@ -383,6 +397,15 @@ func(struct user_namespace *user_ns, const struct path *path, \
return (func##_impl(user_ns, path, stat, request_mask, \
query_flags)); \
}
+#elif defined(HAVE_IDMAP_IOPS_GETATTR)
+#define ZPL_GETATTR_WRAPPER(func) \
+static int \
+func(struct mnt_idmap *user_ns, const struct path *path, \
+ struct kstat *stat, u32 request_mask, unsigned int query_flags) \
+{ \
+ return (func##_impl(user_ns, path, stat, request_mask, \
+ query_flags)); \
+}
#else
#error
#endif
@@ -434,8 +457,21 @@ zpl_is_32bit_api(void)
* 5.12 API change
* To support id-mapped mounts, generic_fillattr() was modified to
* accept a new struct user_namespace* as its first arg.
+ *
+ * 6.3 API change
+ * generic_fillattr() first arg is changed to struct mnt_idmap *
+ *
+ * 6.6 API change
+ * generic_fillattr() gets new second arg request_mask, a u32 type
+ *
*/
-#ifdef HAVE_GENERIC_FILLATTR_USERNS
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP
+#define zpl_generic_fillattr(idmap, ip, sp) \
+ generic_fillattr(idmap, ip, sp)
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP_REQMASK)
+#define zpl_generic_fillattr(idmap, rqm, ip, sp) \
+ generic_fillattr(idmap, rqm, ip, sp)
+#elif defined(HAVE_GENERIC_FILLATTR_USERNS)
#define zpl_generic_fillattr(user_ns, ip, sp) \
generic_fillattr(user_ns, ip, sp)
#else
diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h
index 54690727eab9..bcc7289ad857 100644
--- a/include/os/linux/kernel/linux/xattr_compat.h
+++ b/include/os/linux/kernel/linux/xattr_compat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -115,24 +115,53 @@ fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \
{ \
return (__ ## fn(dentry->d_inode, name, buffer, size)); \
}
+/*
+ * Android API change,
+ * The xattr_handler->get() callback was changed to take a dentry and inode
+ * and flags, because the dentry might not be attached to an inode yet.
+ */
+#elif defined(HAVE_XATTR_GET_DENTRY_INODE_FLAGS)
+#define ZPL_XATTR_GET_WRAPPER(fn) \
+static int \
+fn(const struct xattr_handler *handler, struct dentry *dentry, \
+ struct inode *inode, const char *name, void *buffer, \
+ size_t size, int flags) \
+{ \
+ return (__ ## fn(inode, name, buffer, size)); \
+}
#else
#error "Unsupported kernel"
#endif
/*
+ * 6.3 API change,
+ * The xattr_handler->set() callback was changed to take the
+ * struct mnt_idmap* as the first arg, to support idmapped
+ * mounts.
+ */
+#if defined(HAVE_XATTR_SET_IDMAP)
+#define ZPL_XATTR_SET_WRAPPER(fn) \
+static int \
+fn(const struct xattr_handler *handler, struct mnt_idmap *user_ns, \
+ struct dentry *dentry, struct inode *inode, const char *name, \
+ const void *buffer, size_t size, int flags) \
+{ \
+ return (__ ## fn(user_ns, inode, name, buffer, size, flags)); \
+}
+/*
* 5.12 API change,
* The xattr_handler->set() callback was changed to take the
* struct user_namespace* as the first arg, to support idmapped
* mounts.
*/
-#if defined(HAVE_XATTR_SET_USERNS)
+#elif defined(HAVE_XATTR_SET_USERNS)
#define ZPL_XATTR_SET_WRAPPER(fn) \
static int \
fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \
struct dentry *dentry, struct inode *inode, const char *name, \
const void *buffer, size_t size, int flags) \
{ \
- return (__ ## fn(inode, name, buffer, size, flags)); \
+ return (__ ## fn(user_ns, inode, name, buffer, size, flags)); \
}
/*
* 4.7 API change,
@@ -146,7 +175,7 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \
struct inode *inode, const char *name, const void *buffer, \
size_t size, int flags) \
{ \
- return (__ ## fn(inode, name, buffer, size, flags)); \
+ return (__ ## fn(kcred->user_ns, inode, name, buffer, size, flags));\
}
/*
* 4.4 API change,
@@ -160,7 +189,8 @@ static int \
fn(const struct xattr_handler *handler, struct dentry *dentry, \
const char *name, const void *buffer, size_t size, int flags) \
{ \
- return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \
+ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, \
+ buffer, size, flags)); \
}
/*
* 2.6.33 API change,
@@ -173,7 +203,8 @@ static int \
fn(struct dentry *dentry, const char *name, const void *buffer, \
size_t size, int flags, int unused_handler_flags) \
{ \
- return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \
+ return (__ ## fn(kcred->user_ns, dentry->d_inode, name, \
+ buffer, size, flags)); \
}
#else
#error "Unsupported kernel"
diff --git a/include/os/linux/spl/sys/dkio.h b/include/os/linux/spl/rpc/types.h
index a90b67d36702..5bbb4f2dec46 100644
--- a/include/os/linux/spl/sys/dkio.h
+++ b/include/os/linux/spl/rpc/types.h
@@ -1,9 +1,6 @@
/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
- * UCRL-CODE-235197
+ * Copyright (c) 2008 Sun Microsystems, Inc.
+ * Written by Ricardo Correia <Ricardo.M.Correia@Sun.COM>
*
* This file is part of the SPL, Solaris Porting Layer.
*
@@ -21,19 +18,13 @@
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _SPL_DKIO_H
-#define _SPL_DKIO_H
+#ifndef _SPL_RPC_TYPES_H
+#define _SPL_RPC_TYPES_H
-#define DFL_SZ(num_exts) \
- (sizeof (dkioc_free_list_t) + (num_exts - 1) * 16)
+#include <sys/types.h>
-#define DKIOC (0x04 << 8)
-#define DKIOCFLUSHWRITECACHE (DKIOC|34) /* flush cache to phys medium */
+/* Just enough to support rpc/xdr.h */
-/*
- * ioctl to free space (e.g. SCSI UNMAP) off a disk.
- * Pass a dkioc_free_list_t containing a list of extents to be freed.
- */
-#define DKIOCFREE (DKIOC|50)
+typedef int bool_t;
-#endif /* _SPL_DKIO_H */
+#endif /* SPL_RPC_TYPES_H */
diff --git a/include/os/linux/spl/rpc/xdr.h b/include/os/linux/spl/rpc/xdr.h
index 1c03a42a9961..5b621fa9c863 100644
--- a/include/os/linux/spl/rpc/xdr.h
+++ b/include/os/linux/spl/rpc/xdr.h
@@ -23,8 +23,6 @@
#include <sys/types.h>
-typedef int bool_t;
-
/*
* XDR enums and types.
*/
@@ -75,9 +73,6 @@ struct xdr_bytesrec {
void xdrmem_create(XDR *xdrs, const caddr_t addr, const uint_t size,
const enum xdr_op op);
-/* Currently not needed. If needed later, we'll add it to struct xdr_ops */
-#define xdr_destroy(xdrs) ((void) 0)
-
#define xdr_control(xdrs, req, info) \
(xdrs)->x_ops->xdr_control((xdrs), (req), (info))
diff --git a/include/os/linux/spl/sys/byteorder.h b/include/os/linux/spl/sys/byteorder.h
index bb5e173ce5e4..e9406b4c0b86 100644
--- a/include/os/linux/spl/sys/byteorder.h
+++ b/include/os/linux/spl/sys/byteorder.h
@@ -36,11 +36,26 @@
#include <sys/isa_defs.h>
+#ifdef __COVERITY__
+/*
+ * Coverity's taint warnings from byteswapping are false positives for us.
+ * Suppress them by hiding byteswapping from Coverity.
+ */
+
+#define BSWAP_8(x) ((x) & 0xff)
+#define BSWAP_16(x) ((x) & 0xffff)
+#define BSWAP_32(x) ((x) & 0xffffffff)
+#define BSWAP_64(x) (x)
+
+#else /* __COVERITY__ */
+
#define BSWAP_8(x) ((x) & 0xff)
#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8))
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
+#endif /* __COVERITY__ */
+
#define LE_16(x) cpu_to_le16(x)
#define LE_32(x) cpu_to_le32(x)
#define LE_64(x) cpu_to_le64(x)
diff --git a/include/os/linux/spl/sys/cmn_err.h b/include/os/linux/spl/sys/cmn_err.h
index d2088371c6bc..bd407559ccd6 100644
--- a/include/os/linux/spl/sys/cmn_err.h
+++ b/include/os/linux/spl/sys/cmn_err.h
@@ -29,6 +29,7 @@
#else
#include <stdarg.h>
#endif
+#include <sys/atomic.h>
#define CE_CONT 0 /* continuation */
#define CE_NOTE 1 /* notice */
@@ -41,8 +42,24 @@ extern void cmn_err(int, const char *, ...)
extern void vcmn_err(int, const char *, va_list)
__attribute__((format(printf, 2, 0)));
extern void vpanic(const char *, va_list)
- __attribute__((format(printf, 1, 0)));
+ __attribute__((format(printf, 1, 0), __noreturn__));
#define fm_panic panic
+#define cmn_err_once(ce, ...) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ cmn_err(ce, __VA_ARGS__); \
+ } \
+} while (0)
+
+#define vcmn_err_once(ce, fmt, ap) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ vcmn_err(ce, fmt, ap); \
+ } \
+} while (0)
+
#endif /* SPL_CMN_ERR_H */
diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h
index b7d3f38d70bb..c19c3c0719ff 100644
--- a/include/os/linux/spl/sys/cred.h
+++ b/include/os/linux/spl/sys/cred.h
@@ -26,11 +26,14 @@
#include <linux/module.h>
#include <linux/cred.h>
+#include <linux/sched.h>
#include <sys/types.h>
#include <sys/vfs.h>
typedef struct cred cred_t;
+extern struct task_struct init_task;
+
#define kcred ((cred_t *)(init_task.cred))
#define CRED() ((cred_t *)current_cred())
@@ -45,6 +48,133 @@ typedef struct cred cred_t;
#define SGID_TO_KGID(x) (KGIDT_INIT(x))
#define KGIDP_TO_SGIDP(x) (&(x)->val)
+extern zidmap_t *zfs_get_init_idmap(void);
+
+/* Check if the user ns is the initial one */
+static inline boolean_t
+zfs_is_init_userns(struct user_namespace *user_ns)
+{
+#if defined(CONFIG_USER_NS)
+ return (user_ns == kcred->user_ns);
+#else
+ return (B_FALSE);
+#endif
+}
+
+static inline struct user_namespace *zfs_i_user_ns(struct inode *inode)
+{
+#ifdef HAVE_SUPER_USER_NS
+ return (inode->i_sb->s_user_ns);
+#else
+ return (kcred->user_ns);
+#endif
+}
+
+static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns,
+ struct user_namespace *fs_userns)
+{
+ return (zfs_is_init_userns(mnt_userns) ||
+ mnt_userns == fs_userns);
+}
+
+static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns,
+ struct user_namespace *fs_userns, uid_t uid)
+{
+ struct user_namespace *owner;
+#ifdef HAVE_IOPS_CREATE_IDMAP
+ if (mnt_userns == zfs_init_idmap)
+ return (uid);
+#endif
+#ifdef HAVE_IDMAP_NO_USERNS
+ struct user_namespace ns;
+ ns.uid_map = mnt_userns->uid_map;
+ owner = &ns;
+#else
+ owner = idmap_owner(mnt_userns);
+#endif
+ if (zfs_no_idmapping(owner, fs_userns))
+ return (uid);
+ if (!zfs_is_init_userns(fs_userns))
+ uid = from_kuid(fs_userns, KUIDT_INIT(uid));
+ if (uid == (uid_t)-1)
+ return (uid);
+ return (__kuid_val(make_kuid(owner, uid)));
+}
+
+static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns,
+ struct user_namespace *fs_userns, gid_t gid)
+{
+ struct user_namespace *owner;
+#ifdef HAVE_IOPS_CREATE_IDMAP
+ if (mnt_userns == zfs_init_idmap)
+ return (gid);
+#endif
+#ifdef HAVE_IDMAP_NO_USERNS
+ struct user_namespace ns;
+ ns.gid_map = mnt_userns->gid_map;
+ owner = &ns;
+#else
+ owner = idmap_owner(mnt_userns);
+#endif
+ if (zfs_no_idmapping(owner, fs_userns))
+ return (gid);
+ if (!zfs_is_init_userns(fs_userns))
+ gid = from_kgid(fs_userns, KGIDT_INIT(gid));
+ if (gid == (gid_t)-1)
+ return (gid);
+ return (__kgid_val(make_kgid(owner, gid)));
+}
+
+static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns,
+ struct user_namespace *fs_userns, uid_t uid)
+{
+ struct user_namespace *owner;
+#ifdef HAVE_IOPS_CREATE_IDMAP
+ if (mnt_userns == zfs_init_idmap)
+ return (uid);
+#endif
+#ifdef HAVE_IDMAP_NO_USERNS
+ struct user_namespace ns;
+ ns.uid_map = mnt_userns->uid_map;
+ owner = &ns;
+#else
+ owner = idmap_owner(mnt_userns);
+#endif
+ if (zfs_no_idmapping(owner, fs_userns))
+ return (uid);
+ uid = from_kuid(owner, KUIDT_INIT(uid));
+ if (uid == (uid_t)-1)
+ return (uid);
+ if (zfs_is_init_userns(fs_userns))
+ return (uid);
+ return (__kuid_val(make_kuid(fs_userns, uid)));
+}
+
+static inline gid_t zfs_vfsgid_to_gid(zidmap_t *mnt_userns,
+ struct user_namespace *fs_userns, gid_t gid)
+{
+ struct user_namespace *owner;
+#ifdef HAVE_IOPS_CREATE_IDMAP
+ if (mnt_userns == zfs_init_idmap)
+ return (gid);
+#endif
+#ifdef HAVE_IDMAP_NO_USERNS
+ struct user_namespace ns;
+ ns.gid_map = mnt_userns->gid_map;
+ owner = &ns;
+#else
+ owner = idmap_owner(mnt_userns);
+#endif
+ if (zfs_no_idmapping(owner, fs_userns))
+ return (gid);
+ gid = from_kgid(owner, KGIDT_INIT(gid));
+ if (gid == (gid_t)-1)
+ return (gid);
+ if (zfs_is_init_userns(fs_userns))
+ return (gid);
+ return (__kgid_val(make_kgid(fs_userns, gid)));
+}
+
extern void crhold(cred_t *cr);
extern void crfree(cred_t *cr);
extern uid_t crgetuid(const cred_t *cr);
@@ -53,5 +183,4 @@ extern gid_t crgetgid(const cred_t *cr);
extern int crgetngroups(const cred_t *cr);
extern gid_t *crgetgroups(const cred_t *cr);
extern int groupmember(gid_t gid, const cred_t *cr);
-
#endif /* _SPL_CRED_H */
diff --git a/include/os/linux/spl/sys/debug.h b/include/os/linux/spl/sys/debug.h
index 9c013370c5f0..f041dde34fc8 100644
--- a/include/os/linux/spl/sys/debug.h
+++ b/include/os/linux/spl/sys/debug.h
@@ -1,24 +1,29 @@
/*
- * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
- * UCRL-CODE-235197
+ * Copyright (c) 2020 iXsystems, Inc.
+ * All rights reserved.
*
- * This file is part of the SPL, Solaris Porting Layer.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The SPL is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
- * The SPL is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the SPL. If not, see <http://www.gnu.org/licenses/>.
+ * $FreeBSD$
*/
/*
@@ -34,37 +39,80 @@
* ASSERT3U() - Assert unsigned X OP Y is true, if not panic.
* ASSERT3P() - Assert pointer X OP Y is true, if not panic.
* ASSERT0() - Assert value is zero, if not panic.
+ * ASSERT0P() - Assert pointer is null, if not panic.
* VERIFY() - Verify X is true, if not panic.
* VERIFY3B() - Verify boolean X OP Y is true, if not panic.
* VERIFY3S() - Verify signed X OP Y is true, if not panic.
* VERIFY3U() - Verify unsigned X OP Y is true, if not panic.
* VERIFY3P() - Verify pointer X OP Y is true, if not panic.
* VERIFY0() - Verify value is zero, if not panic.
+ * VERIFY0P() - Verify pointer is null, if not panic.
*/
#ifndef _SPL_DEBUG_H
#define _SPL_DEBUG_H
+
/*
* Common DEBUG functionality.
*/
+#ifdef __FreeBSD__
+#include <linux/compiler.h>
+#endif
+
+#ifndef __printflike
#define __printflike(a, b) __printf(a, b)
+#endif
#ifndef __maybe_unused
#define __maybe_unused __attribute__((unused))
#endif
-int spl_panic(const char *file, const char *func, int line,
+/*
+ * Without this, we see warnings from objtool during normal Linux builds when
+ * the kernel is built with CONFIG_STACK_VALIDATION=y:
+ *
+ * warning: objtool: tsd_create() falls through to next function __list_add()
+ * warning: objtool: .text: unexpected end of section
+ *
+ * Until the toolchain stops doing this, we must only define this attribute on
+ * spl_panic() when doing static analysis.
+ */
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+__attribute__((__noreturn__))
+#endif
+extern void spl_panic(const char *file, const char *func, int line,
const char *fmt, ...);
-void spl_dumpstack(void);
+extern void spl_dumpstack(void);
+
+static inline int
+spl_assert(const char *buf, const char *file, const char *func, int line)
+{
+ spl_panic(file, func, line, "%s", buf);
+ return (0);
+}
+
+#ifndef expect
+#define expect(expr, value) (__builtin_expect((expr), (value)))
+#endif
+#ifndef __linux__
+#define likely(expr) expect((expr) != 0, 1)
+#define unlikely(expr) expect((expr) != 0, 0)
+#endif
#define PANIC(fmt, a...) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "%s", "VERIFY(" #cond ") failed\n"))
+ spl_assert("VERIFY(" #cond ") failed\n", \
+ __FILE__, __FUNCTION__, __LINE__))
+
+#define VERIFYF(cond, str, ...) do { \
+ if (unlikely(!cond)) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY(" #cond ") failed " str "\n", __VA_ARGS__);\
+ } while (0)
#define VERIFY3B(LEFT, OP, RIGHT) do { \
const boolean_t _verify3_left = (boolean_t)(LEFT); \
@@ -73,8 +121,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%d " #OP " %d)\n", \
- (boolean_t)(_verify3_left), \
- (boolean_t)(_verify3_right)); \
+ (boolean_t)_verify3_left, \
+ (boolean_t)_verify3_right); \
} while (0)
#define VERIFY3S(LEFT, OP, RIGHT) do { \
@@ -84,8 +132,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%lld " #OP " %lld)\n", \
- (long long)(_verify3_left), \
- (long long)(_verify3_right)); \
+ (long long)_verify3_left, \
+ (long long)_verify3_right); \
} while (0)
#define VERIFY3U(LEFT, OP, RIGHT) do { \
@@ -95,8 +143,8 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%llu " #OP " %llu)\n", \
- (unsigned long long)(_verify3_left), \
- (unsigned long long)(_verify3_right)); \
+ (unsigned long long)_verify3_left, \
+ (unsigned long long)_verify3_right); \
} while (0)
#define VERIFY3P(LEFT, OP, RIGHT) do { \
@@ -106,20 +154,116 @@ void spl_dumpstack(void);
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%px " #OP " %px)\n", \
- (void *) (_verify3_left), \
- (void *) (_verify3_right)); \
+ (void *)_verify3_left, \
+ (void *)_verify3_right); \
} while (0)
#define VERIFY0(RIGHT) do { \
+ const int64_t _verify0_right = (int64_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(" #RIGHT ") " \
+ "failed (0 == %lld)\n", \
+ (long long)_verify0_right); \
+ } while (0)
+
+#define VERIFY0P(RIGHT) do { \
+ const uintptr_t _verify0_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(0 == _verify0_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0P(" #RIGHT ") " \
+ "failed (NULL == %px)\n", \
+ (void *)_verify0_right); \
+ } while (0)
+
+/*
+ * Note that you should not put any operations you want to always happen
+ * in the print section for ASSERTs unless you only want them to run on
+ * debug builds!
+ * e.g. ASSERT3UF(2, <, 3, "%s", foo(x)), foo(x) won't run on non-debug
+ * builds.
+ */
+
+#define VERIFY3BF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (boolean_t)(_verify3_left), \
+ (boolean_t)(_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY3SF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (long long)(_verify3_left), \
+ (long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3UF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (unsigned long long)(_verify3_left), \
+ (unsigned long long)(_verify3_right), \
+ __VA_ARGS); \
+ } while (0)
+
+#define VERIFY3PF(LEFT, OP, RIGHT, STR, ...) 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) " STR "\n", \
+ (void *) (_verify3_left), \
+ (void *) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0PF(RIGHT, STR, ...) do { \
+ const uintptr_t _verify3_left = (uintptr_t)(0); \
+ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
+ if (unlikely(!(_verify3_left == _verify3_right))) \
+ spl_panic(__FILE__, __FUNCTION__, __LINE__, \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %px) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
+ } while (0)
+
+#define VERIFY0F(RIGHT, STR, ...) 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)); \
+ "VERIFY0(0 == " #RIGHT ") " \
+ "failed (0 == %lld) " STR "\n", \
+ (long long) (_verify3_right), \
+ __VA_ARGS__); \
} while (0)
+#define VERIFY_IMPLY(A, B) \
+ ((void)(likely((!(A)) || (B)) || \
+ spl_assert("(" #A ") implies (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
+#define VERIFY_EQUIV(A, B) \
+ ((void)(likely(!!(A) == !!(B)) || \
+ spl_assert("(" #A ") is equivalent to (" #B ")", \
+ __FILE__, __FUNCTION__, __LINE__)))
+
/*
* Debugging disabled (--disable-debug)
*/
@@ -135,6 +279,14 @@ void spl_dumpstack(void);
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT3BF(x, y, z, str, ...) ASSERT3B(x, y, z)
+#define ASSERT3SF(x, y, z, str, ...) ASSERT3S(x, y, z)
+#define ASSERT3UF(x, y, z, str, ...) ASSERT3U(x, y, z)
+#define ASSERT3PF(x, y, z, str, ...) ASSERT3P(x, y, z)
+#define ASSERT0PF(x, str, ...) ASSERT0P(x)
+#define ASSERT0F(x, str, ...) ASSERT0(x)
+#define ASSERTF(x, str, ...) ASSERT(x)
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
#define EQUIV(A, B) \
@@ -150,15 +302,17 @@ void spl_dumpstack(void);
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
+#define ASSERT0P VERIFY0P
+#define ASSERT3BF VERIFY3BF
+#define ASSERT3SF VERIFY3SF
+#define ASSERT3UF VERIFY3UF
+#define ASSERT3PF VERIFY3PF
+#define ASSERT0PF VERIFY0PF
+#define ASSERT0F VERIFY0F
+#define ASSERTF VERIFYF
#define ASSERT VERIFY
-#define IMPLY(A, B) \
- ((void)(likely((!(A)) || (B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") implies (" #B ")")))
-#define EQUIV(A, B) \
- ((void)(likely(!!(A) == !!(B)) || \
- spl_panic(__FILE__, __FUNCTION__, __LINE__, \
- "(" #A ") is equivalent to (" #B ")")))
+#define IMPLY VERIFY_IMPLY
+#define EQUIV VERIFY_EQUIV
#endif /* NDEBUG */
diff --git a/include/os/linux/spl/sys/disp.h b/include/os/linux/spl/sys/disp.h
index e106d3c5438e..c8be6ffbf10f 100644
--- a/include/os/linux/spl/sys/disp.h
+++ b/include/os/linux/spl/sys/disp.h
@@ -26,7 +26,9 @@
#include <linux/preempt.h>
-#define kpreempt(unused) schedule()
+#define KPREEMPT_SYNC (-1)
+
+#define kpreempt(unused) cond_resched()
#define kpreempt_disable() preempt_disable()
#define kpreempt_enable() preempt_enable()
diff --git a/include/os/linux/spl/sys/errno.h b/include/os/linux/spl/sys/errno.h
index f6d9212a613f..347b879a50c1 100644
--- a/include/os/linux/spl/sys/errno.h
+++ b/include/os/linux/spl/sys/errno.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/spl/sys/ia32/asm_linkage.h b/include/os/linux/spl/sys/ia32/asm_linkage.h
new file mode 100644
index 000000000000..3aaa4af5dab8
--- /dev/null
+++ b/include/os/linux/spl/sys/ia32/asm_linkage.h
@@ -0,0 +1,212 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _IA32_SYS_ASM_LINKAGE_H
+#define _IA32_SYS_ASM_LINKAGE_H
+
+#if defined(_KERNEL) && defined(__linux__)
+#include <linux/linkage.h>
+#endif
+
+#ifndef ENDBR
+#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
+/* CSTYLED */
+#if __has_include(<cet.h>)
+
+#include <cet.h>
+
+#ifdef _CET_ENDBR
+#define ENDBR _CET_ENDBR
+#endif /* _CET_ENDBR */
+
+#endif /* <cet.h> */
+#endif /* __ELF__ && __CET__ && __has_include */
+#endif /* !ENDBR */
+
+#ifndef ENDBR
+#define ENDBR
+#endif
+#ifndef RET
+#define RET ret
+#endif
+
+/* You can set to nothing on Unix platforms */
+#undef ASMABI
+#define ASMABI __attribute__((sysv_abi))
+
+#define SECTION_TEXT .text
+#define SECTION_STATIC .section .rodata
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _ASM /* The remainder of this file is only for assembly files */
+
+/*
+ * make annoying differences in assembler syntax go away
+ */
+
+/*
+ * D16 and A16 are used to insert instructions prefixes; the
+ * macros help the assembler code be slightly more portable.
+ */
+#if !defined(__GNUC_AS__)
+/*
+ * /usr/ccs/bin/as prefixes are parsed as separate instructions
+ */
+#define D16 data16;
+#define A16 addr16;
+
+/*
+ * (There are some weird constructs in constant expressions)
+ */
+#define _CONST(const) [const]
+#define _BITNOT(const) -1!_CONST(const)
+#define _MUL(a, b) _CONST(a \* b)
+
+#else
+/*
+ * Why not use the 'data16' and 'addr16' prefixes .. well, the
+ * assembler doesn't quite believe in real mode, and thus argues with
+ * us about what we're trying to do.
+ */
+#define D16 .byte 0x66;
+#define A16 .byte 0x67;
+
+#define _CONST(const) (const)
+#define _BITNOT(const) ~_CONST(const)
+#define _MUL(a, b) _CONST(a * b)
+
+#endif
+
+/*
+ * C pointers are different sizes between i386 and amd64.
+ * These constants can be used to compute offsets into pointer arrays.
+ */
+#if defined(__amd64)
+#define CLONGSHIFT 3
+#define CLONGSIZE 8
+#define CLONGMASK 7
+#elif defined(__i386)
+#define CLONGSHIFT 2
+#define CLONGSIZE 4
+#define CLONGMASK 3
+#endif
+
+/*
+ * Since we know we're either ILP32 or LP64 ..
+ */
+#define CPTRSHIFT CLONGSHIFT
+#define CPTRSIZE CLONGSIZE
+#define CPTRMASK CLONGMASK
+
+#if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT)
+#error "inconsistent shift constants"
+#endif
+
+#if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1)
+#error "inconsistent mask constants"
+#endif
+
+#define ASM_ENTRY_ALIGN 16
+
+/*
+ * SSE register alignment and save areas
+ */
+
+#define XMM_SIZE 16
+#define XMM_ALIGN 16
+
+/*
+ * ENTRY provides the standard procedure entry code and an easy way to
+ * insert the calls to mcount for profiling. ENTRY_NP is identical, but
+ * never calls mcount.
+ */
+#undef ENTRY
+#define ENTRY(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+ .type x, @function; \
+x: MCOUNT(x)
+
+#define ENTRY_NP(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+ .type x, @function; \
+x:
+
+#define ENTRY_ALIGN(x, a) \
+ .text; \
+ .balign a; \
+ .globl x; \
+ .type x, @function; \
+x:
+
+#define FUNCTION(x) \
+ .type x, @function; \
+x:
+
+/*
+ * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
+ */
+#define ENTRY2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+ .type x, @function; \
+ .type y, @function; \
+x:; \
+y: MCOUNT(x)
+
+#define ENTRY_NP2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+ .type x, @function; \
+ .type y, @function; \
+x:; \
+y:
+
+
+/*
+ * SET_SIZE trails a function and set the size for the ELF symbol table.
+ */
+#define SET_SIZE(x) \
+ .size x, [.-x]
+
+#define SET_OBJ(x) .type x, @object
+
+
+#endif /* _ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IA32_SYS_ASM_LINKAGE_H */
diff --git a/include/os/linux/spl/sys/isa_defs.h b/include/os/linux/spl/sys/isa_defs.h
index a032aae91658..7c95c94c1cf1 100644
--- a/include/os/linux/spl/sys/isa_defs.h
+++ b/include/os/linux/spl/sys/isa_defs.h
@@ -47,9 +47,6 @@
#endif
#endif
-#define _ALIGNMENT_REQUIRED 1
-
-
/* i386 arch specific defines */
#elif defined(__i386) || defined(__i386__)
@@ -65,8 +62,6 @@
#define _ILP32
#endif
-#define _ALIGNMENT_REQUIRED 0
-
/* powerpc (ppc64) arch specific defines */
#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__)
@@ -88,12 +83,6 @@
#endif
#endif
-/*
- * Illumos doesn't define _ALIGNMENT_REQUIRED for PPC, so default to 1
- * out of paranoia.
- */
-#define _ALIGNMENT_REQUIRED 1
-
/* arm arch specific defines */
#elif defined(__arm) || defined(__arm__)
@@ -115,12 +104,6 @@
#define _ZFS_BIG_ENDIAN
#endif
-/*
- * Illumos doesn't define _ALIGNMENT_REQUIRED for ARM, so default to 1
- * out of paranoia.
- */
-#define _ALIGNMENT_REQUIRED 1
-
/* aarch64 arch specific defines */
#elif defined(__aarch64__)
@@ -157,7 +140,6 @@
#define _ZFS_BIG_ENDIAN
#define _SUNOS_VTOC_16
-#define _ALIGNMENT_REQUIRED 1
/* s390 arch specific defines */
#elif defined(__s390__)
@@ -173,12 +155,6 @@
#define _ZFS_BIG_ENDIAN
-/*
- * Illumos doesn't define _ALIGNMENT_REQUIRED for s390, so default to 1
- * out of paranoia.
- */
-#define _ALIGNMENT_REQUIRED 1
-
/* MIPS arch specific defines */
#elif defined(__mips__)
@@ -197,18 +173,16 @@
#define _SUNOS_VTOC_16
/*
- * Illumos doesn't define _ALIGNMENT_REQUIRED for MIPS, so default to 1
- * out of paranoia.
- */
-#define _ALIGNMENT_REQUIRED 1
-
-/*
* RISC-V arch specific defines
* only RV64G (including atomic) LP64 is supported yet
*/
-#elif defined(__riscv) && defined(_LP64) && _LP64 && \
+#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 && \
defined(__riscv_atomic) && __riscv_atomic
+#if !defined(_LP64)
+#define _LP64 1
+#endif
+
#ifndef __riscv__
#define __riscv__
#endif
@@ -221,12 +195,26 @@
#define _SUNOS_VTOC_16
+/*
+ * LoongArch arch specific defines
+ * only LoongArch64 is supported yet
+ */
+#elif defined(__loongarch__) && defined(__loongarch_lp64)
+
+#if !defined(_LP64)
+#define _LP64
+#endif
+
+#define _ZFS_LITTLE_ENDIAN
+#define _SUNOS_VTOC_16
+
+/* not all LoongArch cores support unaligned accesses in hardware */
#define _ALIGNMENT_REQUIRED 1
#else
/*
* Currently supported:
- * x86_64, x32, i386, arm, powerpc, s390, sparc, mips, and RV64G
+ * x86_64, x32, i386, arm, powerpc, s390, sparc, mips, RV64G, and LoongArch64
*/
#error "Unsupported ISA type"
#endif
diff --git a/include/os/linux/spl/sys/kmem.h b/include/os/linux/spl/sys/kmem.h
index a93e87df8069..8a203f7bb8e2 100644
--- a/include/os/linux/spl/sys/kmem.h
+++ b/include/os/linux/spl/sys/kmem.h
@@ -31,11 +31,18 @@
#include <linux/vmalloc.h>
extern int kmem_debugging(void);
+__attribute__((format(printf, 1, 0)))
extern char *kmem_vasprintf(const char *fmt, va_list ap);
+__attribute__((format(printf, 1, 2)))
extern char *kmem_asprintf(const char *fmt, ...);
extern char *kmem_strdup(const char *str);
extern void kmem_strfree(char *str);
+#define kmem_scnprintf scnprintf
+
+#define POINTER_IS_VALID(p) (!((uintptr_t)(p) & 0x3))
+#define POINTER_INVALIDATE(pp) (*(pp) = (void *)((uintptr_t)(*(pp)) | 0x1))
+
/*
* Memory allocation interfaces
*/
@@ -179,7 +186,9 @@ extern unsigned int spl_kmem_alloc_max;
#define kmem_free(ptr, sz) spl_kmem_free((ptr), (sz))
#define kmem_cache_reap_active spl_kmem_cache_reap_active
+__attribute__((malloc, alloc_size(1)))
extern void *spl_kmem_alloc(size_t sz, int fl, const char *func, int line);
+__attribute__((malloc, alloc_size(1)))
extern void *spl_kmem_zalloc(size_t sz, int fl, const char *func, int line);
extern void spl_kmem_free(const void *ptr, size_t sz);
diff --git a/include/os/linux/spl/sys/kmem_cache.h b/include/os/linux/spl/sys/kmem_cache.h
index bd0ad5052d3d..b159bb52d111 100644
--- a/include/os/linux/spl/sys/kmem_cache.h
+++ b/include/os/linux/spl/sys/kmem_cache.h
@@ -70,8 +70,6 @@ typedef enum kmem_cbrc {
#define KMC_REAP_CHUNK INT_MAX
#define KMC_DEFAULT_SEEKS 1
-#define KMC_RECLAIM_ONCE 0x1 /* Force a single shrinker pass */
-
extern struct list_head spl_kmem_cache_list;
extern struct rw_semaphore spl_kmem_cache_sem;
@@ -98,9 +96,6 @@ extern struct rw_semaphore spl_kmem_cache_sem;
#define SPL_MAX_KMEM_ORDER_NR_PAGES (KMALLOC_MAX_SIZE >> PAGE_SHIFT)
#endif
-#define POINTER_IS_VALID(p) 0 /* Unimplemented */
-#define POINTER_INVALIDATE(pp) /* Unimplemented */
-
typedef int (*spl_kmem_ctor_t)(void *, void *, int);
typedef void (*spl_kmem_dtor_t)(void *, void *);
@@ -111,7 +106,7 @@ typedef struct spl_kmem_magazine {
uint32_t skm_refill; /* Batch refill size */
struct spl_kmem_cache *skm_cache; /* Owned by cache */
unsigned int skm_cpu; /* Owned by cpu */
- void *skm_objs[0]; /* Object pointers */
+ void *skm_objs[]; /* Object pointers */
} spl_kmem_magazine_t;
typedef struct spl_kmem_obj {
@@ -201,6 +196,14 @@ extern uint64_t spl_kmem_cache_entry_size(kmem_cache_t *cache);
spl_kmem_cache_create(name, size, align, ctor, dtor, rclm, priv, vmp, fl)
#define kmem_cache_set_move(skc, move) spl_kmem_cache_set_move(skc, move)
#define kmem_cache_destroy(skc) spl_kmem_cache_destroy(skc)
+/*
+ * This is necessary to be compatible with other kernel modules
+ * or in-tree filesystem that may define kmem_cache_alloc,
+ * like bcachefs does it now.
+ */
+#ifdef kmem_cache_alloc
+#undef kmem_cache_alloc
+#endif
#define kmem_cache_alloc(skc, flags) spl_kmem_cache_alloc(skc, flags)
#define kmem_cache_free(skc, obj) spl_kmem_cache_free(skc, obj)
#define kmem_cache_reap_now(skc) spl_kmem_cache_reap_now(skc)
diff --git a/include/os/linux/spl/sys/kstat.h b/include/os/linux/spl/sys/kstat.h
index 928f70757545..305c411ddfa0 100644
--- a/include/os/linux/spl/sys/kstat.h
+++ b/include/os/linux/spl/sys/kstat.h
@@ -85,7 +85,7 @@ typedef int kid_t; /* unique kstat id */
typedef int kstat_update_t(struct kstat_s *, int); /* dynamic update cb */
typedef struct kstat_module {
- char ksm_name[KSTAT_STRLEN+1]; /* module name */
+ char ksm_name[KSTAT_STRLEN]; /* module name */
struct list_head ksm_module_list; /* module linkage */
struct list_head ksm_kstat_list; /* list of kstat entries */
struct proc_dir_entry *ksm_proc; /* proc entry */
@@ -98,8 +98,8 @@ typedef struct kstat_raw_ops {
} kstat_raw_ops_t;
typedef struct kstat_proc_entry {
- char kpe_name[KSTAT_STRLEN+1]; /* kstat name */
- char kpe_module[KSTAT_STRLEN+1]; /* provider module name */
+ char kpe_name[KSTAT_STRLEN]; /* kstat name */
+ char kpe_module[KSTAT_STRLEN]; /* provider module name */
kstat_module_t *kpe_owner; /* kstat module linkage */
struct list_head kpe_list; /* kstat linkage */
struct proc_dir_entry *kpe_proc; /* procfs entry */
@@ -111,7 +111,7 @@ struct kstat_s {
hrtime_t ks_crtime; /* creation time */
hrtime_t ks_snaptime; /* last access time */
int ks_instance; /* provider module instance */
- char ks_class[KSTAT_STRLEN+1]; /* kstat class */
+ char ks_class[KSTAT_STRLEN]; /* kstat class */
uchar_t ks_type; /* kstat data type */
uchar_t ks_flags; /* kstat flags */
void *ks_data; /* kstat type-specific data */
@@ -177,7 +177,7 @@ typedef struct kstat_io {
} kstat_io_t;
typedef struct kstat_timer {
- char name[KSTAT_STRLEN+1]; /* event name */
+ char name[KSTAT_STRLEN]; /* event name */
u_longlong_t num_events; /* number of events */
hrtime_t elapsed_time; /* cumulative elapsed time */
hrtime_t min_time; /* shortest event duration */
diff --git a/include/os/linux/spl/sys/list.h b/include/os/linux/spl/sys/list.h
index 80300df15abe..046a75e19353 100644
--- a/include/os/linux/spl/sys/list.h
+++ b/include/os/linux/spl/sys/list.h
@@ -48,7 +48,6 @@
typedef struct list_head list_node_t;
typedef struct list {
- size_t list_size;
size_t list_offset;
list_node_t list_head;
} list_t;
@@ -72,7 +71,8 @@ list_link_init(list_node_t *node)
static inline void
list_create(list_t *list, size_t size, size_t offset)
{
- list->list_size = size;
+ (void) size;
+
list->list_offset = offset;
INIT_LIST_HEAD(&list->list_head);
}
diff --git a/include/os/linux/spl/sys/misc.h b/include/os/linux/spl/sys/misc.h
new file mode 100644
index 000000000000..299fe9c1ab07
--- /dev/null
+++ b/include/os/linux/spl/sys/misc.h
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+#ifndef _OS_LINUX_SPL_MISC_H
+#define _OS_LINUX_SPL_MISC_H
+
+#include <linux/kobject.h>
+
+extern void spl_signal_kobj_evt(struct block_device *bdev);
+
+#endif
diff --git a/include/os/linux/spl/sys/mutex.h b/include/os/linux/spl/sys/mutex.h
index 677076a0f134..b4eaa0266d20 100644
--- a/include/os/linux/spl/sys/mutex.h
+++ b/include/os/linux/spl/sys/mutex.h
@@ -128,7 +128,6 @@ spl_mutex_lockdep_on_maybe(kmutex_t *mp) \
#define NESTED_SINGLE 1
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define mutex_enter_nested(mp, subclass) \
{ \
ASSERT3P(mutex_owner(mp), !=, current); \
@@ -137,16 +136,22 @@ spl_mutex_lockdep_on_maybe(kmutex_t *mp) \
spl_mutex_lockdep_on_maybe(mp); \
spl_mutex_set_owner(mp); \
}
-#else /* CONFIG_DEBUG_LOCK_ALLOC */
-#define mutex_enter_nested(mp, subclass) \
-{ \
+
+#define mutex_enter_interruptible(mp) \
+/* CSTYLED */ \
+({ \
+ int _rc_; \
+ \
ASSERT3P(mutex_owner(mp), !=, current); \
spl_mutex_lockdep_off_maybe(mp); \
- mutex_lock(MUTEX(mp)); \
+ _rc_ = mutex_lock_interruptible(MUTEX(mp)); \
spl_mutex_lockdep_on_maybe(mp); \
- spl_mutex_set_owner(mp); \
-}
-#endif /* CONFIG_DEBUG_LOCK_ALLOC */
+ if (!_rc_) { \
+ spl_mutex_set_owner(mp); \
+ } \
+ \
+ _rc_; \
+})
#define mutex_enter(mp) mutex_enter_nested((mp), 0)
@@ -171,6 +176,7 @@ spl_mutex_lockdep_on_maybe(kmutex_t *mp) \
*/
#define mutex_exit(mp) \
{ \
+ ASSERT3P(mutex_owner(mp), ==, current); \
spl_mutex_clear_owner(mp); \
spin_lock(&(mp)->m_lock); \
spl_mutex_lockdep_off_maybe(mp); \
diff --git a/include/os/linux/spl/sys/procfs_list.h b/include/os/linux/spl/sys/procfs_list.h
index 9bb437f55cf7..959d9444e63d 100644
--- a/include/os/linux/spl/sys/procfs_list.h
+++ b/include/os/linux/spl/sys/procfs_list.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/spl/sys/shrinker.h b/include/os/linux/spl/sys/shrinker.h
index e5b7a9c955dd..bca4c850694a 100644
--- a/include/os/linux/spl/sys/shrinker.h
+++ b/include/os/linux/spl/sys/shrinker.h
@@ -29,12 +29,13 @@
/*
* Due to frequent changes in the shrinker API the following
- * compatibility wrappers should be used. They are as follows:
+ * compatibility wrapper should be used.
*
- * SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost);
+ * shrinker = spl_register_shrinker(name, countfunc, scanfunc, seek_cost);
+ * spl_unregister_shrinker(shrinker);
*
- * SPL_SHRINKER_DECLARE is used to declare a shrinker with the name varname,
- * which is passed to spl_register_shrinker()/spl_unregister_shrinker().
+ * spl_register_shrinker is used to create and register a shrinker with the
+ * given name.
* The countfunc returns the number of free-able objects.
* The scanfunc returns the number of objects that were freed.
* The callbacks can return SHRINK_STOP if further calls can't make any more
@@ -57,53 +58,28 @@
* ...scan objects in the cache and reclaim them...
* }
*
- * SPL_SHRINKER_DECLARE(my_shrinker, my_count, my_scan, DEFAULT_SEEKS);
+ * static struct shrinker *my_shrinker;
*
* void my_init_func(void) {
- * spl_register_shrinker(&my_shrinker);
+ * my_shrinker = spl_register_shrinker("my-shrinker",
+ * my_count, my_scan, DEFAULT_SEEKS);
+ * }
+ *
+ * void my_fini_func(void) {
+ * spl_unregister_shrinker(my_shrinker);
* }
*/
-#define spl_register_shrinker(x) register_shrinker(x)
-#define spl_unregister_shrinker(x) unregister_shrinker(x)
+typedef unsigned long (*spl_shrinker_cb)
+ (struct shrinker *, struct shrink_control *);
-/*
- * Linux 3.0 to 3.11 Shrinker API Compatibility.
- */
-#if defined(HAVE_SINGLE_SHRINKER_CALLBACK)
-#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \
-static int \
-__ ## varname ## _wrapper(struct shrinker *shrink, struct shrink_control *sc)\
-{ \
- if (sc->nr_to_scan != 0) { \
- (void) scanfunc(shrink, sc); \
- } \
- return (countfunc(shrink, sc)); \
-} \
- \
-static struct shrinker varname = { \
- .shrink = __ ## varname ## _wrapper, \
- .seeks = seek_cost, \
-}
+struct shrinker *spl_register_shrinker(const char *name,
+ spl_shrinker_cb countfunc, spl_shrinker_cb scanfunc, int seek_cost);
+void spl_unregister_shrinker(struct shrinker *);
+#ifndef SHRINK_STOP
+/* 3.0-3.11 compatibility */
#define SHRINK_STOP (-1)
-
-/*
- * Linux 3.12 and later Shrinker API Compatibility.
- */
-#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
-#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \
-static struct shrinker varname = { \
- .count_objects = countfunc, \
- .scan_objects = scanfunc, \
- .seeks = seek_cost, \
-}
-
-#else
-/*
- * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced.
- */
-#error "Unknown shrinker callback"
#endif
#endif /* SPL_SHRINKER_H */
diff --git a/include/os/linux/spl/sys/string.h b/include/os/linux/spl/sys/string.h
index 38134dcf4c76..f44bf23eb326 100644
--- a/include/os/linux/spl/sys/string.h
+++ b/include/os/linux/spl/sys/string.h
@@ -1 +1,50 @@
+/*
+ * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
+ * UCRL-CODE-235197
+ *
+ * This file is part of the SPL, Solaris Porting Layer.
+ *
+ * The SPL is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The SPL is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the SPL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SPL_STRING_H
+#define _SPL_STRING_H
+
#include <linux/string.h>
+
+/* Fallbacks for kernel missing strlcpy */
+#ifndef HAVE_KERNEL_STRLCPY
+
+#if defined(HAVE_KERNEL_STRSCPY)
+/*
+ * strscpy is strlcpy, but returns an error on truncation. strlcpy is defined
+ * to return strlen(src), so detect error and override it.
+ */
+static inline size_t
+strlcpy(char *dest, const char *src, size_t size)
+{
+ ssize_t ret = strscpy(dest, src, size);
+ if (likely(ret > 0))
+ return ((size_t)ret);
+ return (strlen(src));
+}
+#else
+#error "no strlcpy fallback available"
+#endif
+
+#endif /* HAVE_KERNEL_STRLCPY */
+
+#endif /* _SPL_STRING_H */
diff --git a/include/os/linux/spl/sys/sysmacros.h b/include/os/linux/spl/sys/sysmacros.h
index be1f77e43bda..99e3a6fb41c6 100644
--- a/include/os/linux/spl/sys/sysmacros.h
+++ b/include/os/linux/spl/sys/sysmacros.h
@@ -120,6 +120,16 @@ extern uint32_t zone_get_hostid(void *zone);
extern void spl_setup(void);
extern void spl_cleanup(void);
+/*
+ * Only handles the first 4096 majors and first 256 minors. We don't have a
+ * libc for the kernel module so we define this inline.
+ */
+static inline dev_t
+makedev(unsigned int major, unsigned int minor)
+{
+ return ((major & 0xFFF) << 8) | (minor & 0xFF);
+}
+
#define highbit(x) __fls(x)
#define lowbit(x) __ffs(x)
diff --git a/include/os/linux/spl/sys/taskq.h b/include/os/linux/spl/sys/taskq.h
index 2a6cd8283d16..b73dab631e04 100644
--- a/include/os/linux/spl/sys/taskq.h
+++ b/include/os/linux/spl/sys/taskq.h
@@ -104,6 +104,7 @@ typedef struct taskq {
/* list node for the cpu hotplug callback */
struct hlist_node tq_hp_cb_node;
boolean_t tq_hp_support;
+ unsigned long lastspawnstop; /* when to purge dynamic */
} taskq_t;
typedef struct taskq_ent {
@@ -149,6 +150,8 @@ extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
extern int taskq_empty_ent(taskq_ent_t *);
extern void taskq_init_ent(taskq_ent_t *);
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
+extern taskq_t *taskq_create_synced(const char *, int, pri_t, int, int, uint_t,
+ kthread_t ***);
extern void taskq_destroy(taskq_t *);
extern void taskq_wait_id(taskq_t *, taskqid_t);
extern void taskq_wait_outstanding(taskq_t *, taskqid_t);
diff --git a/include/os/linux/spl/sys/trace.h b/include/os/linux/spl/sys/trace.h
index b148ace6abd3..21ac0e4f84de 100644
--- a/include/os/linux/spl/sys/trace.h
+++ b/include/os/linux/spl/sys/trace.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/spl/sys/trace_spl.h b/include/os/linux/spl/sys/trace_spl.h
index bffd91d9129b..6f0f7b271d56 100644
--- a/include/os/linux/spl/sys/trace_spl.h
+++ b/include/os/linux/spl/sys/trace_spl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/spl/sys/trace_taskq.h b/include/os/linux/spl/sys/trace_taskq.h
index 002e1af1706d..0e25e642f279 100644
--- a/include/os/linux/spl/sys/trace_taskq.h
+++ b/include/os/linux/spl/sys/trace_taskq.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h
index b44c94518750..20ba457f7efe 100644
--- a/include/os/linux/spl/sys/types.h
+++ b/include/os/linux/spl/sys/types.h
@@ -38,7 +38,7 @@ typedef unsigned long ulong_t;
typedef unsigned long long u_longlong_t;
typedef long long longlong_t;
-typedef unsigned long intptr_t;
+typedef long intptr_t;
typedef unsigned long long rlim64_t;
typedef struct task_struct kthread_t;
@@ -54,4 +54,31 @@ typedef ulong_t pgcnt_t;
typedef int major_t;
typedef int minor_t;
+struct user_namespace;
+#ifdef HAVE_IOPS_CREATE_IDMAP
+#include <linux/refcount.h>
+#ifdef HAVE_IDMAP_NO_USERNS
+#include <linux/user_namespace.h>
+struct mnt_idmap {
+ struct uid_gid_map uid_map;
+ struct uid_gid_map gid_map;
+ refcount_t count;
+};
+typedef struct mnt_idmap zidmap_t;
+#define idmap_owner(p) (NULL)
+#else
+struct mnt_idmap {
+ struct user_namespace *owner;
+ refcount_t count;
+};
+typedef struct mnt_idmap zidmap_t;
+#define idmap_owner(p) (((struct mnt_idmap *)p)->owner)
+#endif
+#else
+typedef struct user_namespace zidmap_t;
+#define idmap_owner(p) ((struct user_namespace *)p)
+#endif
+
+extern zidmap_t *zfs_init_idmap;
+
#endif /* _SPL_TYPES_H */
diff --git a/include/os/linux/spl/sys/uio.h b/include/os/linux/spl/sys/uio.h
index fe2b5c07a018..5e6ea8d3c221 100644
--- a/include/os/linux/spl/sys/uio.h
+++ b/include/os/linux/spl/sys/uio.h
@@ -73,13 +73,6 @@ typedef struct zfs_uio {
size_t uio_skip;
struct request *rq;
-
- /*
- * Used for saving rq_for_each_segment() state between calls
- * to zfs_uiomove_bvec_rq().
- */
- struct req_iterator iter;
- struct bio_vec bv;
} zfs_uio_t;
@@ -102,7 +95,7 @@ zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
}
static inline void
-zfs_uio_advance(zfs_uio_t *uio, size_t size)
+zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
{
uio->uio_resid -= size;
uio->uio_loffset += size;
@@ -138,7 +131,6 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq)
} else {
uio->uio_bvec = NULL;
uio->uio_iovcnt = 0;
- memset(&uio->iter, 0, sizeof (uio->iter));
}
uio->uio_loffset = io_offset(bio, rq);
@@ -173,4 +165,16 @@ zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset,
}
#endif
+#if defined(HAVE_ITER_IOV)
+#define zfs_uio_iter_iov(iter) iter_iov((iter))
+#else
+#define zfs_uio_iter_iov(iter) (iter)->iov
+#endif
+
+#if defined(HAVE_IOV_ITER_TYPE)
+#define zfs_uio_iov_iter_type(iter) iov_iter_type((iter))
+#else
+#define zfs_uio_iov_iter_type(iter) (iter)->type
+#endif
+
#endif /* SPL_UIO_H */
diff --git a/include/os/linux/spl/sys/vmem.h b/include/os/linux/spl/sys/vmem.h
index e77af2a7a48c..92585a17e263 100644
--- a/include/os/linux/spl/sys/vmem.h
+++ b/include/os/linux/spl/sys/vmem.h
@@ -91,8 +91,10 @@ typedef struct vmem { } vmem_t;
#define vmem_zalloc(sz, fl) spl_vmem_zalloc((sz), (fl), __func__, __LINE__)
#define vmem_free(ptr, sz) spl_vmem_free((ptr), (sz))
-extern void *spl_vmem_alloc(size_t sz, int fl, const char *func, int line);
-extern void *spl_vmem_zalloc(size_t sz, int fl, const char *func, int line);
+extern void *spl_vmem_alloc(size_t sz, int fl, const char *func, int line)
+ __attribute__((malloc, alloc_size(1)));
+extern void *spl_vmem_zalloc(size_t sz, int fl, const char *func, int line)
+ __attribute__((malloc, alloc_size(1)));
extern void spl_vmem_free(const void *ptr, size_t sz);
int spl_vmem_init(void);
diff --git a/include/os/linux/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h
index b3f121ecf0ca..c6d99fb3183d 100644
--- a/include/os/linux/spl/sys/vmsystm.h
+++ b/include/os/linux/spl/sys/vmsystm.h
@@ -44,7 +44,10 @@
#define zfs_totalhigh_pages totalhigh_pages
#endif
+#define membar_consumer() smp_rmb()
#define membar_producer() smp_wmb()
+#define membar_sync() smp_mb()
+
#define physmem zfs_totalram_pages
#define xcopyin(from, to, size) copy_from_user(to, from, size)
diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h
index 61afc3765504..0c265db78591 100644
--- a/include/os/linux/zfs/sys/policy.h
+++ b/include/os/linux/zfs/sys/policy.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -47,13 +47,14 @@ int secpolicy_vnode_create_gid(const cred_t *);
int secpolicy_vnode_remove(const cred_t *);
int secpolicy_vnode_setdac(const cred_t *, uid_t);
int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t);
-int secpolicy_vnode_setids_setgids(const cred_t *, gid_t);
+int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zidmap_t *,
+ struct user_namespace *);
int secpolicy_zinject(const cred_t *);
int secpolicy_zfs(const cred_t *);
int secpolicy_zfs_proc(const cred_t *, proc_t *);
void secpolicy_setid_clear(vattr_t *, cred_t *);
int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *,
- const vattr_t *, cred_t *);
+ const vattr_t *, cred_t *, zidmap_t *, struct user_namespace *);
int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t);
int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *,
const struct vattr *, int, int (void *, int, cred_t *), void *);
diff --git a/include/os/linux/zfs/sys/sha2.h b/include/os/linux/zfs/sys/sha2.h
deleted file mode 100644
index 48ea0dc5d9d2..000000000000
--- a/include/os/linux/zfs/sys/sha2.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/* Copyright 2013 Saso Kiselkov. All rights reserved. */
-
-#ifndef _SYS_SHA2_H
-#define _SYS_SHA2_H
-
-#include <sys/types.h> /* for uint_* */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SHA256_DIGEST_LENGTH 32 /* SHA256 digest length in bytes */
-#define SHA384_DIGEST_LENGTH 48 /* SHA384 digest length in bytes */
-#define SHA512_DIGEST_LENGTH 64 /* SHA512 digest length in bytes */
-
-/* Truncated versions of SHA-512 according to FIPS-180-4, section 5.3.6 */
-#define SHA512_224_DIGEST_LENGTH 28 /* SHA512/224 digest length */
-#define SHA512_256_DIGEST_LENGTH 32 /* SHA512/256 digest length */
-
-#define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */
-#define SHA512_HMAC_BLOCK_SIZE 128 /* SHA512-HMAC block size */
-
-#define SHA256 0
-#define SHA256_HMAC 1
-#define SHA256_HMAC_GEN 2
-#define SHA384 3
-#define SHA384_HMAC 4
-#define SHA384_HMAC_GEN 5
-#define SHA512 6
-#define SHA512_HMAC 7
-#define SHA512_HMAC_GEN 8
-#define SHA512_224 9
-#define SHA512_256 10
-
-/*
- * SHA2 context.
- * The contents of this structure are a private interface between the
- * Init/Update/Final calls of the functions defined below.
- * Callers must never attempt to read or write any of the fields
- * in this structure directly.
- */
-typedef struct {
- uint32_t algotype; /* Algorithm Type */
-
- /* state (ABCDEFGH) */
- union {
- uint32_t s32[8]; /* for SHA256 */
- uint64_t s64[8]; /* for SHA384/512 */
- } state;
- /* number of bits */
- union {
- uint32_t c32[2]; /* for SHA256 , modulo 2^64 */
- uint64_t c64[2]; /* for SHA384/512, modulo 2^128 */
- } count;
- union {
- uint8_t buf8[128]; /* undigested input */
- uint32_t buf32[32]; /* realigned input */
- uint64_t buf64[16]; /* realigned input */
- } buf_un;
-} SHA2_CTX;
-
-typedef SHA2_CTX SHA256_CTX;
-typedef SHA2_CTX SHA384_CTX;
-typedef SHA2_CTX SHA512_CTX;
-
-extern void SHA2Init(uint64_t mech, SHA2_CTX *);
-
-extern void SHA2Update(SHA2_CTX *, const void *, size_t);
-
-extern void SHA2Final(void *, SHA2_CTX *);
-
-extern void SHA256Init(SHA256_CTX *);
-
-extern void SHA256Update(SHA256_CTX *, const void *, size_t);
-
-extern void SHA256Final(void *, SHA256_CTX *);
-
-extern void SHA384Init(SHA384_CTX *);
-
-extern void SHA384Update(SHA384_CTX *, const void *, size_t);
-
-extern void SHA384Final(void *, SHA384_CTX *);
-
-extern void SHA512Init(SHA512_CTX *);
-
-extern void SHA512Update(SHA512_CTX *, const void *, size_t);
-
-extern void SHA512Final(void *, SHA512_CTX *);
-
-#ifdef _SHA2_IMPL
-/*
- * The following types/functions are all private to the implementation
- * of the SHA2 functions and must not be used by consumers of the interface
- */
-
-/*
- * List of support mechanisms in this module.
- *
- * It is important to note that in the module, division or modulus calculations
- * are used on the enumerated type to determine which mechanism is being used;
- * therefore, changing the order or additional mechanisms should be done
- * carefully
- */
-typedef enum sha2_mech_type {
- SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */
- SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */
- SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
- SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */
- SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */
- SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
- SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */
- SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */
- SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
- SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */
- SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */
-} sha2_mech_type_t;
-
-#endif /* _SHA2_IMPL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SHA2_H */
diff --git a/include/os/linux/zfs/sys/trace_acl.h b/include/os/linux/zfs/sys/trace_acl.h
index 35bf78bed94e..15dc77edafac 100644
--- a/include/os/linux/zfs/sys/trace_acl.h
+++ b/include/os/linux/zfs/sys/trace_acl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -62,9 +62,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__field(uint32_t, z_async_writes_cnt)
__field(mode_t, z_mode)
__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)
@@ -97,9 +95,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__entry->z_async_writes_cnt = zn->z_async_writes_cnt;
__entry->z_mode = zn->z_mode;
__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);
@@ -121,9 +117,8 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
"zn_prefetch %u blksz %u seq %u "
"mapcnt %llu size %llu pflags %llu "
"sync_cnt %u sync_writes_cnt %u async_writes_cnt %u "
- "mode 0x%x is_sa %d is_mapped %d "
- "is_ctldir %d is_stale %d inode { "
- "uid %u gid %u ino %lu nlink %u size %lli "
+ "mode 0x%x is_sa %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",
__entry->z_id, __entry->z_unlinked, __entry->z_atime_dirty,
@@ -131,9 +126,8 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__entry->z_seq, __entry->z_mapcnt, __entry->z_size,
__entry->z_pflags, __entry->z_sync_cnt,
__entry->z_sync_writes_cnt, __entry->z_async_writes_cnt,
- __entry->z_mode, __entry->z_is_sa, __entry->z_is_mapped,
- __entry->z_is_ctldir, __entry->z_is_stale, __entry->i_uid,
- __entry->i_gid, __entry->i_ino, __entry->i_nlink,
+ __entry->z_mode, __entry->z_is_sa, __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,
__entry->z_type, __entry->z_flags, __entry->z_access_mask,
diff --git a/include/os/linux/zfs/sys/trace_arc.h b/include/os/linux/zfs/sys/trace_arc.h
index a318a62b05a4..f749223daa72 100644
--- a/include/os/linux/zfs/sys/trace_arc.h
+++ b/include/os/linux/zfs/sys/trace_arc.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -51,7 +51,6 @@ DECLARE_EVENT_CLASS(zfs_arc_buf_hdr_class,
__array(uint64_t, hdr_dva_word, 2)
__field(uint64_t, hdr_birth)
__field(uint32_t, hdr_flags)
- __field(uint32_t, hdr_bufcnt)
__field(arc_buf_contents_t, hdr_type)
__field(uint16_t, hdr_psize)
__field(uint16_t, hdr_lsize)
@@ -70,7 +69,6 @@ DECLARE_EVENT_CLASS(zfs_arc_buf_hdr_class,
__entry->hdr_dva_word[1] = ab->b_dva.dva_word[1];
__entry->hdr_birth = ab->b_birth;
__entry->hdr_flags = ab->b_flags;
- __entry->hdr_bufcnt = ab->b_l1hdr.b_bufcnt;
__entry->hdr_psize = ab->b_psize;
__entry->hdr_lsize = ab->b_lsize;
__entry->hdr_spa = ab->b_spa;
@@ -84,12 +82,12 @@ DECLARE_EVENT_CLASS(zfs_arc_buf_hdr_class,
__entry->hdr_refcount = ab->b_l1hdr.b_refcnt.rc_count;
),
TP_printk("hdr { dva 0x%llx:0x%llx birth %llu "
- "flags 0x%x bufcnt %u type %u psize %u lsize %u spa %llu "
+ "flags 0x%x type %u psize %u lsize %u spa %llu "
"state_type %u access %lu mru_hits %u mru_ghost_hits %u "
"mfu_hits %u mfu_ghost_hits %u l2_hits %u refcount %lli }",
__entry->hdr_dva_word[0], __entry->hdr_dva_word[1],
__entry->hdr_birth, __entry->hdr_flags,
- __entry->hdr_bufcnt, __entry->hdr_type, __entry->hdr_psize,
+ __entry->hdr_type, __entry->hdr_psize,
__entry->hdr_lsize, __entry->hdr_spa, __entry->hdr_state_type,
__entry->hdr_access, __entry->hdr_mru_hits,
__entry->hdr_mru_ghost_hits, __entry->hdr_mfu_hits,
@@ -103,12 +101,13 @@ DEFINE_EVENT(zfs_arc_buf_hdr_class, name, \
TP_PROTO(arc_buf_hdr_t *ab), \
TP_ARGS(ab))
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__hit);
+DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__iohit);
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__evict);
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__delete);
DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mru);
DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mfu);
+DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__uncached);
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__async__upgrade__sync);
-DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__demand__hit__predictive__prefetch);
DEFINE_ARC_BUF_HDR_EVENT(zfs_l2arc__hit);
DEFINE_ARC_BUF_HDR_EVENT(zfs_l2arc__miss);
@@ -191,7 +190,6 @@ DECLARE_EVENT_CLASS(zfs_arc_miss_class,
__array(uint64_t, hdr_dva_word, 2)
__field(uint64_t, hdr_birth)
__field(uint32_t, hdr_flags)
- __field(uint32_t, hdr_bufcnt)
__field(arc_buf_contents_t, hdr_type)
__field(uint16_t, hdr_psize)
__field(uint16_t, hdr_lsize)
@@ -222,7 +220,6 @@ DECLARE_EVENT_CLASS(zfs_arc_miss_class,
__entry->hdr_dva_word[1] = hdr->b_dva.dva_word[1];
__entry->hdr_birth = hdr->b_birth;
__entry->hdr_flags = hdr->b_flags;
- __entry->hdr_bufcnt = hdr->b_l1hdr.b_bufcnt;
__entry->hdr_psize = hdr->b_psize;
__entry->hdr_lsize = hdr->b_lsize;
__entry->hdr_spa = hdr->b_spa;
@@ -254,7 +251,7 @@ DECLARE_EVENT_CLASS(zfs_arc_miss_class,
__entry->zb_blkid = zb->zb_blkid;
),
TP_printk("hdr { dva 0x%llx:0x%llx birth %llu "
- "flags 0x%x bufcnt %u psize %u lsize %u spa %llu state_type %u "
+ "flags 0x%x psize %u lsize %u spa %llu state_type %u "
"access %lu mru_hits %u mru_ghost_hits %u mfu_hits %u "
"mfu_ghost_hits %u l2_hits %u refcount %lli } "
"bp { dva0 0x%llx:0x%llx dva1 0x%llx:0x%llx dva2 "
@@ -263,7 +260,7 @@ DECLARE_EVENT_CLASS(zfs_arc_miss_class,
"blkid %llu }",
__entry->hdr_dva_word[0], __entry->hdr_dva_word[1],
__entry->hdr_birth, __entry->hdr_flags,
- __entry->hdr_bufcnt, __entry->hdr_psize, __entry->hdr_lsize,
+ __entry->hdr_psize, __entry->hdr_lsize,
__entry->hdr_spa, __entry->hdr_state_type, __entry->hdr_access,
__entry->hdr_mru_hits, __entry->hdr_mru_ghost_hits,
__entry->hdr_mfu_hits, __entry->hdr_mfu_ghost_hits,
@@ -387,12 +384,13 @@ DEFINE_ARC_WAIT_FOR_EVICTION_EVENT(zfs_arc__wait__for__eviction);
#else
DEFINE_DTRACE_PROBE1(arc__hit);
+DEFINE_DTRACE_PROBE1(arc__iohit);
DEFINE_DTRACE_PROBE1(arc__evict);
DEFINE_DTRACE_PROBE1(arc__delete);
DEFINE_DTRACE_PROBE1(new_state__mru);
DEFINE_DTRACE_PROBE1(new_state__mfu);
+DEFINE_DTRACE_PROBE1(new_state__uncached);
DEFINE_DTRACE_PROBE1(arc__async__upgrade__sync);
-DEFINE_DTRACE_PROBE1(arc__demand__hit__predictive__prefetch);
DEFINE_DTRACE_PROBE1(l2arc__hit);
DEFINE_DTRACE_PROBE1(l2arc__miss);
DEFINE_DTRACE_PROBE2(l2arc__read);
diff --git a/include/os/linux/zfs/sys/trace_common.h b/include/os/linux/zfs/sys/trace_common.h
index 6922d1a1810a..6ffa57c86418 100644
--- a/include/os/linux/zfs/sys/trace_common.h
+++ b/include/os/linux/zfs/sys/trace_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -31,7 +31,6 @@
/* ZIO macros */
#define ZIO_TP_STRUCT_ENTRY \
__field(zio_type_t, zio_type) \
- __field(int, zio_cmd) \
__field(zio_priority_t, zio_priority) \
__field(uint64_t, zio_size) \
__field(uint64_t, zio_orig_size) \
@@ -39,10 +38,10 @@
__field(hrtime_t, zio_timestamp) \
__field(hrtime_t, zio_delta) \
__field(uint64_t, zio_delay) \
- __field(enum zio_flag, zio_flags) \
+ __field(zio_flag_t, zio_flags) \
__field(enum zio_stage, zio_stage) \
__field(enum zio_stage, zio_pipeline) \
- __field(enum zio_flag, zio_orig_flags) \
+ __field(zio_flag_t, zio_orig_flags) \
__field(enum zio_stage, zio_orig_stage) \
__field(enum zio_stage, zio_orig_pipeline) \
__field(uint8_t, zio_reexecute) \
@@ -61,7 +60,6 @@
#define ZIO_TP_FAST_ASSIGN \
__entry->zio_type = zio->io_type; \
- __entry->zio_cmd = zio->io_cmd; \
__entry->zio_priority = zio->io_priority; \
__entry->zio_size = zio->io_size; \
__entry->zio_orig_size = zio->io_orig_size; \
@@ -90,15 +88,15 @@
__entry->zp_dedup_verify = zio->io_prop.zp_dedup_verify;
#define ZIO_TP_PRINTK_FMT \
- "zio { type %u cmd %i prio %u size %llu orig_size %llu " \
+ "zio { type %u prio %u size %llu orig_size %llu " \
"offset %llu timestamp %llu delta %llu delay %llu " \
- "flags 0x%x stage 0x%x pipeline 0x%x orig_flags 0x%x " \
+ "flags 0x%llx stage 0x%x pipeline 0x%x orig_flags 0x%llx " \
"orig_stage 0x%x orig_pipeline 0x%x reexecute %u " \
"txg %llu error %d ena %llu prop { checksum %u compress %u " \
"type %u level %u copies %u dedup %u dedup_verify %u nopwrite %u } }"
#define ZIO_TP_PRINTK_ARGS \
- __entry->zio_type, __entry->zio_cmd, __entry->zio_priority, \
+ __entry->zio_type, __entry->zio_priority, \
__entry->zio_size, __entry->zio_orig_size, __entry->zio_offset, \
__entry->zio_timestamp, __entry->zio_delta, __entry->zio_delay, \
__entry->zio_flags, __entry->zio_stage, __entry->zio_pipeline, \
diff --git a/include/os/linux/zfs/sys/trace_dbgmsg.h b/include/os/linux/zfs/sys/trace_dbgmsg.h
index 89722bab4c94..19f533baaaaf 100644
--- a/include/os/linux/zfs/sys/trace_dbgmsg.h
+++ b/include/os/linux/zfs/sys/trace_dbgmsg.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_dbuf.h b/include/os/linux/zfs/sys/trace_dbuf.h
index ba7c6b1a0144..0f6a98b47d60 100644
--- a/include/os/linux/zfs/sys/trace_dbuf.h
+++ b/include/os/linux/zfs/sys/trace_dbuf.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -60,8 +60,12 @@
#define DBUF_TP_FAST_ASSIGN \
if (db != NULL) { \
- __assign_str(os_spa, \
- spa_name(DB_DNODE(db)->dn_objset->os_spa)); \
+ if (POINTER_IS_VALID(DB_DNODE(db)->dn_objset)) { \
+ __assign_str(os_spa, \
+ spa_name(DB_DNODE(db)->dn_objset->os_spa)); \
+ } else { \
+ __assign_str(os_spa, "NULL"); \
+ } \
\
__entry->ds_object = db->db_objset->os_dsl_dataset ? \
db->db_objset->os_dsl_dataset->ds_object : 0; \
diff --git a/include/os/linux/zfs/sys/trace_dmu.h b/include/os/linux/zfs/sys/trace_dmu.h
index 40a4c02eed19..b031d4a2c901 100644
--- a/include/os/linux/zfs/sys/trace_dmu.h
+++ b/include/os/linux/zfs/sys/trace_dmu.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_dnode.h b/include/os/linux/zfs/sys/trace_dnode.h
index b4b391492bc3..2697e871b85f 100644
--- a/include/os/linux/zfs/sys/trace_dnode.h
+++ b/include/os/linux/zfs/sys/trace_dnode.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_multilist.h b/include/os/linux/zfs/sys/trace_multilist.h
index 638578407a0c..33b9aeac9213 100644
--- a/include/os/linux/zfs/sys/trace_multilist.h
+++ b/include/os/linux/zfs/sys/trace_multilist.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_rrwlock.h b/include/os/linux/zfs/sys/trace_rrwlock.h
index 4c74d6257309..dbc94fee0136 100644
--- a/include/os/linux/zfs/sys/trace_rrwlock.h
+++ b/include/os/linux/zfs/sys/trace_rrwlock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_txg.h b/include/os/linux/zfs/sys/trace_txg.h
index f77e35a78340..c95220b1b5d6 100644
--- a/include/os/linux/zfs/sys/trace_txg.h
+++ b/include/os/linux/zfs/sys/trace_txg.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_vdev.h b/include/os/linux/zfs/sys/trace_vdev.h
index 079668d35f12..6a3f6c202527 100644
--- a/include/os/linux/zfs/sys/trace_vdev.h
+++ b/include/os/linux/zfs/sys/trace_vdev.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_zfs.h b/include/os/linux/zfs/sys/trace_zfs.h
index 0e19f8d186d0..5f82e1c093a6 100644
--- a/include/os/linux/zfs/sys/trace_zfs.h
+++ b/include/os/linux/zfs/sys/trace_zfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_zil.h b/include/os/linux/zfs/sys/trace_zil.h
index 8ffda452766c..ae1caa3ac473 100644
--- a/include/os/linux/zfs/sys/trace_zil.h
+++ b/include/os/linux/zfs/sys/trace_zil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -51,7 +51,9 @@
__field(uint64_t, zl_parse_lr_seq) \
__field(uint64_t, zl_parse_blk_count) \
__field(uint64_t, zl_parse_lr_count) \
- __field(uint64_t, zl_cur_used) \
+ __field(uint64_t, zl_cur_size) \
+ __field(uint64_t, zl_cur_left) \
+ __field(uint64_t, zl_cur_max) \
__field(clock_t, zl_replay_time) \
__field(uint64_t, zl_replay_blks)
@@ -72,7 +74,9 @@
__entry->zl_parse_lr_seq = zilog->zl_parse_lr_seq; \
__entry->zl_parse_blk_count = zilog->zl_parse_blk_count;\
__entry->zl_parse_lr_count = zilog->zl_parse_lr_count; \
- __entry->zl_cur_used = zilog->zl_cur_used; \
+ __entry->zl_cur_size = zilog->zl_cur_size; \
+ __entry->zl_cur_left = zilog->zl_cur_left; \
+ __entry->zl_cur_max = zilog->zl_cur_max; \
__entry->zl_replay_time = zilog->zl_replay_time; \
__entry->zl_replay_blks = zilog->zl_replay_blks;
@@ -82,7 +86,8 @@
"replay %u stop_sync %u logbias %u sync %u " \
"parse_error %u parse_blk_seq %llu parse_lr_seq %llu " \
"parse_blk_count %llu parse_lr_count %llu " \
- "cur_used %llu replay_time %lu replay_blks %llu }"
+ "cur_size %llu cur_left %llu cur_max %llu replay_time %lu " \
+ "replay_blks %llu }"
#define ZILOG_TP_PRINTK_ARGS \
__entry->zl_lr_seq, __entry->zl_commit_lr_seq, \
@@ -92,7 +97,8 @@
__entry->zl_stop_sync, __entry->zl_logbias, __entry->zl_sync, \
__entry->zl_parse_error, __entry->zl_parse_blk_seq, \
__entry->zl_parse_lr_seq, __entry->zl_parse_blk_count, \
- __entry->zl_parse_lr_count, __entry->zl_cur_used, \
+ __entry->zl_parse_lr_count, __entry->zl_cur_size, \
+ __entry->zl_cur_left, __entry->zl_cur_max, \
__entry->zl_replay_time, __entry->zl_replay_blks
#define ITX_TP_STRUCT_ENTRY \
@@ -152,6 +158,11 @@
* zilog_t *, ...,
* itx_t *, ...);
*/
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wordered-compare-function-pointers"
+#endif
/* BEGIN CSTYLED */
DECLARE_EVENT_CLASS(zfs_zil_process_itx_class,
TP_PROTO(zilog_t *zilog, itx_t *itx),
@@ -169,6 +180,9 @@ DECLARE_EVENT_CLASS(zfs_zil_process_itx_class,
ZILOG_TP_PRINTK_ARGS, ITX_TP_PRINTK_ARGS)
);
/* END CSTYLED */
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
#define DEFINE_ZIL_PROCESS_ITX_EVENT(name) \
DEFINE_EVENT(zfs_zil_process_itx_class, name, \
@@ -207,6 +221,39 @@ DEFINE_EVENT(zfs_zil_commit_io_error_class, name, \
TP_ARGS(zilog, zcw))
DEFINE_ZIL_COMMIT_IO_ERROR_EVENT(zfs_zil__commit__io__error);
+/*
+ * Generic support for three argument tracepoints of the form:
+ *
+ * DTRACE_PROBE3(...,
+ * zilog_t *, ...,
+ * uint64_t, ...,
+ * uint64_t, ...);
+ */
+/* BEGIN CSTYLED */
+DECLARE_EVENT_CLASS(zfs_zil_block_size_class,
+ TP_PROTO(zilog_t *zilog, uint64_t res, uint64_t s1),
+ TP_ARGS(zilog, res, s1),
+ TP_STRUCT__entry(
+ ZILOG_TP_STRUCT_ENTRY
+ __field(uint64_t, res)
+ __field(uint64_t, s1)
+ ),
+ TP_fast_assign(
+ ZILOG_TP_FAST_ASSIGN
+ __entry->res = res;
+ __entry->s1 = s1;
+ ),
+ TP_printk(
+ ZILOG_TP_PRINTK_FMT " res %llu s1 %llu",
+ ZILOG_TP_PRINTK_ARGS, __entry->res, __entry->s1)
+);
+
+#define DEFINE_ZIL_BLOCK_SIZE_EVENT(name) \
+DEFINE_EVENT(zfs_zil_block_size_class, name, \
+ TP_PROTO(zilog_t *zilog, uint64_t res, uint64_t s1), \
+ TP_ARGS(zilog, res, s1))
+DEFINE_ZIL_BLOCK_SIZE_EVENT(zfs_zil__block__size);
+
#endif /* _TRACE_ZIL_H */
#undef TRACE_INCLUDE_PATH
@@ -220,6 +267,7 @@ DEFINE_ZIL_COMMIT_IO_ERROR_EVENT(zfs_zil__commit__io__error);
DEFINE_DTRACE_PROBE2(zil__process__commit__itx);
DEFINE_DTRACE_PROBE2(zil__process__normal__itx);
DEFINE_DTRACE_PROBE2(zil__commit__io__error);
+DEFINE_DTRACE_PROBE3(zil__block__size);
#endif /* HAVE_DECLARE_EVENT_CLASS */
#endif /* _KERNEL */
diff --git a/include/os/linux/zfs/sys/trace_zio.h b/include/os/linux/zfs/sys/trace_zio.h
index 8655e245c043..223eb559ea7e 100644
--- a/include/os/linux/zfs/sys/trace_zio.h
+++ b/include/os/linux/zfs/sys/trace_zio.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/trace_zrlock.h b/include/os/linux/zfs/sys/trace_zrlock.h
index b504e66f9f7b..6c797c6e231c 100644
--- a/include/os/linux/zfs/sys/trace_zrlock.h
+++ b/include/os/linux/zfs/sys/trace_zrlock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/zfs_context_os.h b/include/os/linux/zfs/sys/zfs_context_os.h
index ac8bccab4f0d..04a5f0c0d239 100644
--- a/include/os/linux/zfs/sys/zfs_context_os.h
+++ b/include/os/linux/zfs/sys/zfs_context_os.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/zfs_ctldir.h b/include/os/linux/zfs/sys/zfs_ctldir.h
index beee34979b64..ad16ab5e4444 100644
--- a/include/os/linux/zfs/sys/zfs_ctldir.h
+++ b/include/os/linux/zfs/sys/zfs_ctldir.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/os/linux/zfs/sys/zfs_dir.h b/include/os/linux/zfs/sys/zfs_dir.h
index 0f15e43452b2..9b2232c68ba4 100644
--- a/include/os/linux/zfs/sys/zfs_dir.h
+++ b/include/os/linux/zfs/sys/zfs_dir.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -52,6 +52,7 @@ extern "C" {
extern int zfs_dirent_lock(zfs_dirlock_t **, znode_t *, char *, znode_t **,
int, int *, pathname_t *);
extern void zfs_dirent_unlock(zfs_dirlock_t *);
+extern int zfs_drop_nlink(znode_t *, dmu_tx_t *, boolean_t *);
extern int zfs_link_create(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int);
extern int zfs_link_destroy(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int,
boolean_t *);
diff --git a/include/os/linux/zfs/sys/zfs_vfsops_os.h b/include/os/linux/zfs/sys/zfs_vfsops_os.h
index 8e03ae99a7fd..b4d5db21f5e5 100644
--- a/include/os/linux/zfs/sys/zfs_vfsops_os.h
+++ b/include/os/linux/zfs/sys/zfs_vfsops_os.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -105,7 +105,6 @@ struct zfsvfs {
rrmlock_t z_teardown_lock;
krwlock_t z_teardown_inactive_lock;
list_t z_all_znodes; /* all znodes in the fs */
- uint64_t z_nr_znodes; /* number of znodes in the fs */
unsigned long z_rollback_time; /* last online rollback time */
unsigned long z_snap_defer_time; /* last snapshot unmount deferral */
kmutex_t z_znodes_lock; /* lock for z_all_znodes */
@@ -143,9 +142,6 @@ struct zfsvfs {
#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);
diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h
index 1d6a58d56b67..830c76e5743a 100644
--- a/include/os/linux/zfs/sys/zfs_vnops_os.h
+++ b/include/os/linux/zfs/sys/zfs_vnops_os.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -45,22 +45,30 @@ extern int zfs_write_simple(znode_t *zp, const void *data, size_t len,
extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags,
cred_t *cr, int *direntflags, pathname_t *realpnp);
extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp);
+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp,
+ zidmap_t *mnt_ns);
extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl,
- int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp);
+ int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp,
+ zidmap_t *mnt_ns);
extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags);
extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap,
- znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp);
+ znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns);
extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd,
cred_t *cr, int flags);
extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr);
-extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip,
- struct kstat *sp);
-extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr);
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK
+extern int zfs_getattr_fast(zidmap_t *, u32 request_mask, struct inode *ip,
+ struct kstat *sp);
+#else
+extern int zfs_getattr_fast(zidmap_t *, struct inode *ip, struct kstat *sp);
+#endif
+extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
+ zidmap_t *mnt_ns);
extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp,
- char *tnm, cred_t *cr, int flags);
+ char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap,
+ zidmap_t *mnt_ns);
extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap,
- char *link, znode_t **zpp, cred_t *cr, int flags);
+ char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns);
extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr);
extern int zfs_link(znode_t *tdzp, znode_t *szp,
char *name, cred_t *cr, int flags);
@@ -68,7 +76,7 @@ extern void zfs_inactive(struct inode *ip);
extern int zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
offset_t offset, cred_t *cr);
extern int zfs_fid(struct inode *ip, fid_t *fidp);
-extern int zfs_getpage(struct inode *ip, struct page *pl[], int nr_pages);
+extern int zfs_getpage(struct inode *ip, struct page *pp);
extern int zfs_putpage(struct inode *ip, struct page *pp,
struct writeback_control *wbc, boolean_t for_sync);
extern int zfs_dirty_inode(struct inode *ip, int flags);
diff --git a/include/os/linux/zfs/sys/zfs_znode_impl.h b/include/os/linux/zfs/sys/zfs_znode_impl.h
index 2e1bd857614d..0be2c445ab76 100644
--- a/include/os/linux/zfs/sys/zfs_znode_impl.h
+++ b/include/os/linux/zfs/sys/zfs_znode_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -47,9 +47,16 @@
extern "C" {
#endif
+#if defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
#define ZNODE_OS_FIELDS \
inode_timespec_t z_btime; /* creation/birth time (cached) */ \
struct inode z_inode;
+#else
+#define ZNODE_OS_FIELDS \
+ inode_timespec_t z_btime; /* creation/birth time (cached) */ \
+ struct inode z_inode; \
+ boolean_t z_is_mapped; /* we are mmap'ed */
+#endif
/*
* Convert between znode pointers and inode pointers
@@ -70,9 +77,17 @@ extern "C" {
#define Z_ISDEV(type) (S_ISCHR(type) || S_ISBLK(type) || S_ISFIFO(type))
#define Z_ISDIR(type) S_ISDIR(type)
-#define zn_has_cached_data(zp) ((zp)->z_is_mapped)
+#if defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
+#define zn_has_cached_data(zp, start, end) \
+ filemap_range_has_page(ZTOI(zp)->i_mapping, start, end)
+#else
+#define zn_has_cached_data(zp, start, end) \
+ ((zp)->z_is_mapped)
+#endif
+
#define zn_flush_cached_data(zp, sync) write_inode_now(ZTOI(zp), sync)
-#define zn_rlimit_fsize(zp, uio) (0)
+#define zn_rlimit_fsize(size) (0)
+#define zn_rlimit_fsize_uio(zp, uio) (0)
/*
* zhold() wraps igrab() on Linux, and igrab() may fail when the
@@ -84,39 +99,41 @@ extern "C" {
#define zrele(zp) iput(ZTOI((zp)))
/* Called on entry to each ZFS inode and vfs operation. */
-#define ZFS_ENTER_ERROR(zfsvfs, error) \
-do { \
- ZFS_TEARDOWN_ENTER_READ(zfsvfs, FTAG); \
- if (unlikely((zfsvfs)->z_unmounted)) { \
- ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
- return (error); \
- } \
-} while (0)
-#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
-#define ZPL_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, -EIO)
+static inline int
+zfs_enter(zfsvfs_t *zfsvfs, const char *tag)
+{
+ ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag);
+ if (unlikely(zfsvfs->z_unmounted)) {
+ ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag);
+ return (SET_ERROR(EIO));
+ }
+ return (0);
+}
/* Must be called before exiting the operation. */
-#define ZFS_EXIT(zfsvfs) \
-do { \
- zfs_exit_fs(zfsvfs); \
- ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
-} while (0)
+static inline void
+zfs_exit(zfsvfs_t *zfsvfs, const char *tag)
+{
+ zfs_exit_fs(zfsvfs);
+ ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag);
+}
-#define ZPL_EXIT(zfsvfs) \
-do { \
- rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \
-} while (0)
+static inline int
+zpl_enter(zfsvfs_t *zfsvfs, const char *tag)
+{
+ return (-zfs_enter(zfsvfs, tag));
+}
-/* Verifies the znode is valid. */
-#define ZFS_VERIFY_ZP_ERROR(zp, error) \
-do { \
- if (unlikely((zp)->z_sa_hdl == NULL)) { \
- ZFS_EXIT(ZTOZSB(zp)); \
- return (error); \
- } \
-} while (0)
-#define ZFS_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, EIO)
-#define ZPL_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, -EIO)
+static inline void
+zpl_exit(zfsvfs_t *zfsvfs, const char *tag)
+{
+ ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag);
+}
+
+/* zfs_verify_zp and zfs_enter_verify_zp are defined in zfs_znode.h */
+#define zpl_verify_zp(zp) (-zfs_verify_zp(zp))
+#define zpl_enter_verify_zp(zfsvfs, zp, tag) \
+ (-zfs_enter_verify_zp(zfsvfs, zp, tag))
/*
* Macros for dealing with dmu_buf_hold
diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
index afb16e5c7907..91a4751fffb0 100644
--- a/include/os/linux/zfs/sys/zpl.h
+++ b/include/os/linux/zfs/sys/zpl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -39,19 +39,28 @@
/* zpl_inode.c */
extern void zpl_vap_init(vattr_t *vap, struct inode *dir,
- umode_t mode, cred_t *cr);
+ umode_t mode, cred_t *cr, zidmap_t *mnt_ns);
extern const struct inode_operations zpl_inode_operations;
+#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
+extern const struct inode_operations_wrapper zpl_dir_inode_operations;
+#else
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;
-extern dentry_operations_t zpl_dentry_operations;
+
+/* zpl_file.c */
extern const struct address_space_operations zpl_address_space_operations;
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+extern const struct file_operations_extend zpl_file_operations;
+#else
extern const struct file_operations zpl_file_operations;
+#endif
extern const struct file_operations zpl_dir_file_operations;
/* zpl_super.c */
-extern void zpl_prune_sb(int64_t nr_to_scan, void *arg);
+extern void zpl_prune_sb(uint64_t nr_to_scan, void *arg);
extern const struct super_operations zpl_super_operations;
extern const struct export_operations zpl_export_operations;
@@ -63,14 +72,20 @@ extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip,
const struct qstr *qstr);
#if defined(CONFIG_FS_POSIX_ACL)
#if defined(HAVE_SET_ACL)
-#if defined(HAVE_SET_ACL_USERNS)
+#if defined(HAVE_SET_ACL_IDMAP_DENTRY)
+extern int zpl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
+ struct posix_acl *acl, int type);
+#elif defined(HAVE_SET_ACL_USERNS)
extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip,
struct posix_acl *acl, int type);
+#elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
+extern int zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
+ struct posix_acl *acl, int type);
#else
extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type);
#endif /* HAVE_SET_ACL_USERNS */
#endif /* HAVE_SET_ACL */
-#if defined(HAVE_GET_ACL_RCU)
+#if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL)
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type, bool rcu);
#elif defined(HAVE_GET_ACL)
extern struct posix_acl *zpl_get_acl(struct inode *ip, int type);
@@ -169,6 +184,55 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
}
#endif /* HAVE_VFS_ITERATE */
+
+/* zpl_file_range.c */
+
+/* handlers for file_operations of the same name */
+extern ssize_t zpl_copy_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, size_t len, unsigned int flags);
+extern loff_t zpl_remap_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, loff_t len, unsigned int flags);
+extern int zpl_clone_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, uint64_t len);
+extern int zpl_dedupe_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, uint64_t len);
+
+/* compat for FICLONE/FICLONERANGE/FIDEDUPERANGE ioctls */
+typedef struct {
+ int64_t fcr_src_fd;
+ uint64_t fcr_src_offset;
+ uint64_t fcr_src_length;
+ uint64_t fcr_dest_offset;
+} zfs_ioc_compat_file_clone_range_t;
+
+typedef struct {
+ int64_t fdri_dest_fd;
+ uint64_t fdri_dest_offset;
+ uint64_t fdri_bytes_deduped;
+ int32_t fdri_status;
+ uint32_t fdri_reserved;
+} zfs_ioc_compat_dedupe_range_info_t;
+
+typedef struct {
+ uint64_t fdr_src_offset;
+ uint64_t fdr_src_length;
+ uint16_t fdr_dest_count;
+ uint16_t fdr_reserved1;
+ uint32_t fdr_reserved2;
+ zfs_ioc_compat_dedupe_range_info_t fdr_info[];
+} zfs_ioc_compat_dedupe_range_t;
+
+#define ZFS_IOC_COMPAT_FICLONE _IOW(0x94, 9, int)
+#define ZFS_IOC_COMPAT_FICLONERANGE \
+ _IOW(0x94, 13, zfs_ioc_compat_file_clone_range_t)
+#define ZFS_IOC_COMPAT_FIDEDUPERANGE \
+ _IOWR(0x94, 54, zfs_ioc_compat_dedupe_range_t)
+
+extern long zpl_ioctl_ficlone(struct file *filp, void *arg);
+extern long zpl_ioctl_ficlonerange(struct file *filp, void *arg);
+extern long zpl_ioctl_fideduperange(struct file *filp, void *arg);
+
+
#if defined(HAVE_INODE_TIMESTAMP_TRUNCATE)
#define zpl_inode_timestamp_truncate(ts, ip) timestamp_truncate(ts, ip)
#elif defined(HAVE_INODE_TIMESPEC64_TIMES)
@@ -181,13 +245,15 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
#if defined(HAVE_INODE_OWNER_OR_CAPABLE)
#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ip)
-#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED)
+#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_USERNS)
#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ns, ip)
+#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAP)
+#define zpl_inode_owner_or_capable(idmap, ip) inode_owner_or_capable(idmap, ip)
#else
#error "Unsupported kernel"
#endif
-#ifdef HAVE_SETATTR_PREPARE_USERNS
+#if defined(HAVE_SETATTR_PREPARE_USERNS) || defined(HAVE_SETATTR_PREPARE_IDMAP)
#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia)
#else
/*
@@ -197,4 +263,35 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(dentry, ia)
#endif
+#ifdef HAVE_INODE_GET_CTIME
+#define zpl_inode_get_ctime(ip) inode_get_ctime(ip)
+#else
+#define zpl_inode_get_ctime(ip) (ip->i_ctime)
+#endif
+#ifdef HAVE_INODE_SET_CTIME_TO_TS
+#define zpl_inode_set_ctime_to_ts(ip, ts) inode_set_ctime_to_ts(ip, ts)
+#else
+#define zpl_inode_set_ctime_to_ts(ip, ts) (ip->i_ctime = ts)
+#endif
+#ifdef HAVE_INODE_GET_ATIME
+#define zpl_inode_get_atime(ip) inode_get_atime(ip)
+#else
+#define zpl_inode_get_atime(ip) (ip->i_atime)
+#endif
+#ifdef HAVE_INODE_SET_ATIME_TO_TS
+#define zpl_inode_set_atime_to_ts(ip, ts) inode_set_atime_to_ts(ip, ts)
+#else
+#define zpl_inode_set_atime_to_ts(ip, ts) (ip->i_atime = ts)
+#endif
+#ifdef HAVE_INODE_GET_MTIME
+#define zpl_inode_get_mtime(ip) inode_get_mtime(ip)
+#else
+#define zpl_inode_get_mtime(ip) (ip->i_mtime)
+#endif
+#ifdef HAVE_INODE_SET_MTIME_TO_TS
+#define zpl_inode_set_mtime_to_ts(ip, ts) inode_set_mtime_to_ts(ip, ts)
+#else
+#define zpl_inode_set_mtime_to_ts(ip, ts) (ip->i_mtime = ts)
+#endif
+
#endif /* _SYS_ZPL_H */
diff --git a/include/sys/abd.h b/include/sys/abd.h
index 5c6bd0c271d4..19fe96292d5f 100644
--- a/include/sys/abd.h
+++ b/include/sys/abd.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -79,6 +79,9 @@ typedef struct abd {
typedef int abd_iter_func_t(void *buf, size_t len, void *priv);
typedef int abd_iter_func2_t(void *bufa, void *bufb, size_t len, void *priv);
+#if defined(__linux__) && defined(_KERNEL)
+typedef int abd_iter_page_func_t(struct page *, size_t, size_t, void *);
+#endif
extern int zfs_abd_scatter_enabled;
@@ -86,10 +89,15 @@ extern int zfs_abd_scatter_enabled;
* Allocations and deallocations
*/
+__attribute__((malloc))
abd_t *abd_alloc(size_t, boolean_t);
+__attribute__((malloc))
abd_t *abd_alloc_linear(size_t, boolean_t);
+__attribute__((malloc))
abd_t *abd_alloc_gang(void);
+__attribute__((malloc))
abd_t *abd_alloc_for_io(size_t, boolean_t);
+__attribute__((malloc))
abd_t *abd_alloc_sametype(abd_t *, size_t);
boolean_t abd_size_alloc_linear(size_t);
void abd_gang_add(abd_t *, abd_t *, boolean_t);
@@ -120,6 +128,10 @@ void abd_release_ownership_of_buf(abd_t *);
int abd_iterate_func(abd_t *, size_t, size_t, abd_iter_func_t *, void *);
int abd_iterate_func2(abd_t *, abd_t *, size_t, size_t, size_t,
abd_iter_func2_t *, void *);
+#if defined(__linux__) && defined(_KERNEL)
+int abd_iterate_page_func(abd_t *, size_t, size_t, abd_iter_page_func_t *,
+ void *);
+#endif
void abd_copy_off(abd_t *, abd_t *, size_t, size_t, size_t);
void abd_copy_from_buf_off(abd_t *, const void *, size_t, size_t);
void abd_copy_to_buf_off(void *, abd_t *, size_t, size_t);
@@ -128,11 +140,11 @@ int abd_cmp_buf_off(abd_t *, const void *, size_t, size_t);
void abd_zero_off(abd_t *, size_t, size_t);
void abd_verify(abd_t *);
-void abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
- ssize_t csize, ssize_t dsize, const unsigned parity,
+void abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd, size_t off,
+ size_t csize, size_t dsize, const unsigned parity,
void (*func_raidz_gen)(void **, const void *, size_t, size_t));
void abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
- ssize_t tsize, const unsigned parity,
+ size_t tsize, const unsigned parity,
void (*func_raidz_rec)(void **t, const size_t tsize, void **c,
const unsigned *mul),
const unsigned *mul);
@@ -208,6 +220,8 @@ void abd_fini(void);
/*
* Linux ABD bio functions
+ * Note: these are only needed to support vdev_classic. See comment in
+ * vdev_disk.c.
*/
#if defined(__linux__) && defined(_KERNEL)
unsigned int abd_bio_map_off(struct bio *, abd_t *, unsigned int, size_t);
diff --git a/include/sys/abd_impl.h b/include/sys/abd_impl.h
index e96f1edfc8ce..f88ea25e245d 100644
--- a/include/sys/abd_impl.h
+++ b/include/sys/abd_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2014 by Chunwei Chen. All rights reserved.
* Copyright (c) 2016, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2023, 2024, Klara Inc.
*/
#ifndef _ABD_IMPL_H
@@ -38,12 +39,30 @@ typedef enum abd_stats_op {
ABDSTAT_DECR /* Decrease abdstat values */
} abd_stats_op_t;
-struct scatterlist; /* forward declaration */
+/* forward declarations */
+struct scatterlist;
+struct page;
struct abd_iter {
/* public interface */
- void *iter_mapaddr; /* addr corresponding to iter_pos */
- size_t iter_mapsize; /* length of data valid at mapaddr */
+ union {
+ /* for abd_iter_map()/abd_iter_unmap() */
+ struct {
+ /* addr corresponding to iter_pos */
+ void *iter_mapaddr;
+ /* length of data valid at mapaddr */
+ size_t iter_mapsize;
+ };
+ /* for abd_iter_page() */
+ struct {
+ /* current page */
+ struct page *iter_page;
+ /* offset of data in page */
+ size_t iter_page_doff;
+ /* size of data in page */
+ size_t iter_page_dsize;
+ };
+ };
/* private */
abd_t *iter_abd; /* ABD being iterated through */
@@ -78,6 +97,7 @@ boolean_t abd_iter_at_end(struct abd_iter *);
void abd_iter_advance(struct abd_iter *, size_t);
void abd_iter_map(struct abd_iter *);
void abd_iter_unmap(struct abd_iter *);
+void abd_iter_page(struct abd_iter *);
/*
* Helper macros
diff --git a/include/sys/arc.h b/include/sys/arc.h
index 8cee8be4bc93..05307aab99e3 100644
--- a/include/sys/arc.h
+++ b/include/sys/arc.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -81,10 +81,10 @@ typedef struct arc_prune arc_prune_t;
typedef void arc_read_done_func_t(zio_t *zio, const zbookmark_phys_t *zb,
const blkptr_t *bp, arc_buf_t *buf, void *priv);
typedef void arc_write_done_func_t(zio_t *zio, arc_buf_t *buf, void *priv);
-typedef void arc_prune_func_t(int64_t bytes, void *priv);
+typedef void arc_prune_func_t(uint64_t bytes, void *priv);
/* Shared module parameters */
-extern int zfs_arc_average_blocksize;
+extern uint_t zfs_arc_average_blocksize;
extern int l2arc_exclude_special;
/* generic arc_done_func_t's which you can use */
@@ -115,7 +115,7 @@ typedef enum arc_flags
ARC_FLAG_PREFETCH = 1 << 2, /* I/O is a prefetch */
ARC_FLAG_CACHED = 1 << 3, /* I/O was in cache */
ARC_FLAG_L2CACHE = 1 << 4, /* cache in L2ARC */
- ARC_FLAG_PREDICTIVE_PREFETCH = 1 << 5, /* I/O from zfetch */
+ ARC_FLAG_UNCACHED = 1 << 5, /* evict after use */
ARC_FLAG_PRESCIENT_PREFETCH = 1 << 6, /* long min lifespan */
/*
@@ -195,13 +195,11 @@ typedef enum arc_buf_flags {
struct arc_buf {
arc_buf_hdr_t *b_hdr;
arc_buf_t *b_next;
- kmutex_t b_evict_lock;
void *b_data;
arc_buf_flags_t b_flags;
};
typedef enum arc_buf_contents {
- ARC_BUFC_INVALID, /* invalid type */
ARC_BUFC_DATA, /* buffer contains data */
ARC_BUFC_METADATA, /* buffer contains metadata */
ARC_BUFC_NUMTYPES
@@ -229,6 +227,7 @@ typedef enum arc_state_type {
ARC_STATE_MFU,
ARC_STATE_MFU_GHOST,
ARC_STATE_L2C_ONLY,
+ ARC_STATE_UNCACHED,
ARC_STATE_NUMTYPES
} arc_state_type_t;
@@ -302,12 +301,11 @@ int arc_referenced(arc_buf_t *buf);
int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
arc_read_done_func_t *done, void *priv, zio_priority_t priority,
int flags, arc_flags_t *arc_flags, const zbookmark_phys_t *zb);
-zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
- blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, const zio_prop_t *zp,
+zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
+ arc_buf_t *buf, boolean_t uncached, boolean_t l2arc, const zio_prop_t *zp,
arc_write_done_func_t *ready, arc_write_done_func_t *child_ready,
- arc_write_done_func_t *physdone, arc_write_done_func_t *done,
- void *priv, zio_priority_t priority, int zio_flags,
- const zbookmark_phys_t *zb);
+ arc_write_done_func_t *done, void *priv, zio_priority_t priority,
+ int zio_flags, const zbookmark_phys_t *zb);
arc_prune_t *arc_add_prune_callback(arc_prune_func_t *func, void *priv);
void arc_remove_prune_callback(arc_prune_t *p);
diff --git a/include/sys/arc_impl.h b/include/sys/arc_impl.h
index 755e87fe6e0e..defebe3b2fbb 100644
--- a/include/sys/arc_impl.h
+++ b/include/sys/arc_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,6 +30,7 @@
#define _SYS_ARC_IMPL_H
#include <sys/arc.h>
+#include <sys/multilist.h>
#include <sys/zio_crypt.h>
#include <sys/zthr.h>
#include <sys/aggsum.h>
@@ -46,6 +47,7 @@ extern "C" {
* ARC_mru_ghost - recently used, no longer in cache
* ARC_mfu - frequently used, currently cached
* ARC_mfu_ghost - frequently used, no longer in cache
+ * ARC_uncached - uncacheable prefetch, to be evicted
* ARC_l2c_only - exists in L2ARC but not other states
* When there are no active references to the buffer, they are
* are linked onto a list in one of these arc states. These are
@@ -81,14 +83,17 @@ typedef struct arc_state {
*/
arc_state_type_t arcs_state;
/*
+ * total amount of data in this state.
+ */
+ zfs_refcount_t arcs_size[ARC_BUFC_NUMTYPES] ____cacheline_aligned;
+ /*
* total amount of evictable data in this state
*/
- zfs_refcount_t arcs_esize[ARC_BUFC_NUMTYPES] ____cacheline_aligned;
+ zfs_refcount_t arcs_esize[ARC_BUFC_NUMTYPES];
/*
- * total amount of data in this state; this includes: evictable,
- * non-evictable, ARC_BUFC_DATA, and ARC_BUFC_METADATA.
+ * amount of hit bytes for this state (counted only for ghost states)
*/
- zfs_refcount_t arcs_size;
+ wmsum_t arcs_hits[ARC_BUFC_NUMTYPES];
} arc_state_t;
typedef struct arc_callback arc_callback_t;
@@ -101,9 +106,14 @@ struct arc_callback {
boolean_t acb_compressed;
boolean_t acb_noauth;
boolean_t acb_nobuf;
+ boolean_t acb_wait;
+ int acb_wait_error;
+ kmutex_t acb_wait_lock;
+ kcondvar_t acb_wait_cv;
zbookmark_phys_t acb_zb;
zio_t *acb_zio_dummy;
zio_t *acb_zio_head;
+ arc_callback_t *acb_prev;
arc_callback_t *acb_next;
};
@@ -113,7 +123,6 @@ struct arc_write_callback {
void *awcb_private;
arc_write_done_func_t *awcb_ready;
arc_write_done_func_t *awcb_children_ready;
- arc_write_done_func_t *awcb_physdone;
arc_write_done_func_t *awcb_done;
arc_buf_t *awcb_buf;
};
@@ -150,13 +159,6 @@ struct arc_write_callback {
* these two allocation states.
*/
typedef struct l1arc_buf_hdr {
- kmutex_t b_freeze_lock;
- zio_cksum_t *b_freeze_cksum;
-
- /* for waiting on reads to complete */
- kcondvar_t b_cv;
- uint8_t b_byteswap;
-
/* protected by arc state mutex */
arc_state_t *b_state;
multilist_node_t b_arc_node;
@@ -167,7 +169,7 @@ typedef struct l1arc_buf_hdr {
uint32_t b_mru_ghost_hits;
uint32_t b_mfu_hits;
uint32_t b_mfu_ghost_hits;
- uint32_t b_bufcnt;
+ uint8_t b_byteswap;
arc_buf_t *b_buf;
/* self protecting */
@@ -175,6 +177,11 @@ typedef struct l1arc_buf_hdr {
arc_callback_t *b_acb;
abd_t *b_pabd;
+
+#ifdef ZFS_DEBUG
+ zio_cksum_t *b_freeze_cksum;
+ kmutex_t b_freeze_lock;
+#endif
} l1arc_buf_hdr_t;
typedef enum l2arc_dev_hdr_flags_t {
@@ -349,8 +356,9 @@ typedef struct l2arc_lb_ptr_buf {
#define L2BLK_SET_PREFETCH(field, x) BF64_SET((field), 39, 1, x)
#define L2BLK_GET_CHECKSUM(field) BF64_GET((field), 40, 8)
#define L2BLK_SET_CHECKSUM(field, x) BF64_SET((field), 40, 8, x)
-#define L2BLK_GET_TYPE(field) BF64_GET((field), 48, 8)
-#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, x)
+/* +/- 1 here are to keep compatibility after ARC_BUFC_INVALID removal. */
+#define L2BLK_GET_TYPE(field) (BF64_GET((field), 48, 8) - 1)
+#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, (x) + 1)
#define L2BLK_GET_PROTECTED(field) BF64_GET((field), 56, 1)
#define L2BLK_SET_PROTECTED(field, x) BF64_SET((field), 56, 1, x)
#define L2BLK_GET_STATE(field) BF64_GET((field), 57, 4)
@@ -424,12 +432,12 @@ typedef struct l2arc_dev {
*/
typedef struct arc_buf_hdr_crypt {
abd_t *b_rabd; /* raw encrypted data */
- dmu_object_type_t b_ot; /* object type */
- uint32_t b_ebufcnt; /* count of encrypted buffers */
/* dsobj for looking up encryption key for l2arc encryption */
uint64_t b_dsobj;
+ dmu_object_type_t b_ot; /* object type */
+
/* encryption parameters */
uint8_t b_salt[ZIO_DATA_SALT_LEN];
uint8_t b_iv[ZIO_DATA_IV_LEN];
@@ -511,20 +519,33 @@ struct arc_buf_hdr {
};
typedef struct arc_stats {
+ /* Number of requests that were satisfied without I/O. */
kstat_named_t arcstat_hits;
+ /* Number of requests for which I/O was already running. */
+ kstat_named_t arcstat_iohits;
+ /* Number of requests for which I/O has to be issued. */
kstat_named_t arcstat_misses;
+ /* Same three, but specifically for demand data. */
kstat_named_t arcstat_demand_data_hits;
+ kstat_named_t arcstat_demand_data_iohits;
kstat_named_t arcstat_demand_data_misses;
+ /* Same three, but specifically for demand metadata. */
kstat_named_t arcstat_demand_metadata_hits;
+ kstat_named_t arcstat_demand_metadata_iohits;
kstat_named_t arcstat_demand_metadata_misses;
+ /* Same three, but specifically for prefetch data. */
kstat_named_t arcstat_prefetch_data_hits;
+ kstat_named_t arcstat_prefetch_data_iohits;
kstat_named_t arcstat_prefetch_data_misses;
+ /* Same three, but specifically for prefetch metadata. */
kstat_named_t arcstat_prefetch_metadata_hits;
+ kstat_named_t arcstat_prefetch_metadata_iohits;
kstat_named_t arcstat_prefetch_metadata_misses;
kstat_named_t arcstat_mru_hits;
kstat_named_t arcstat_mru_ghost_hits;
kstat_named_t arcstat_mfu_hits;
kstat_named_t arcstat_mfu_ghost_hits;
+ kstat_named_t arcstat_uncached_hits;
kstat_named_t arcstat_deleted;
/*
* Number of buffers that could not be evicted because the hash lock
@@ -560,7 +581,9 @@ typedef struct arc_stats {
kstat_named_t arcstat_hash_collisions;
kstat_named_t arcstat_hash_chains;
kstat_named_t arcstat_hash_chain_max;
- kstat_named_t arcstat_p;
+ kstat_named_t arcstat_meta;
+ kstat_named_t arcstat_pd;
+ kstat_named_t arcstat_pm;
kstat_named_t arcstat_c;
kstat_named_t arcstat_c_min;
kstat_named_t arcstat_c_max;
@@ -633,6 +656,8 @@ typedef struct arc_stats {
* are all included in this value.
*/
kstat_named_t arcstat_anon_size;
+ kstat_named_t arcstat_anon_data;
+ kstat_named_t arcstat_anon_metadata;
/*
* Number of bytes consumed by ARC buffers that meet the
* following criteria: backing buffers of type ARC_BUFC_DATA,
@@ -654,6 +679,8 @@ typedef struct arc_stats {
* are all included in this value.
*/
kstat_named_t arcstat_mru_size;
+ kstat_named_t arcstat_mru_data;
+ kstat_named_t arcstat_mru_metadata;
/*
* Number of bytes consumed by ARC buffers that meet the
* following criteria: backing buffers of type ARC_BUFC_DATA,
@@ -678,6 +705,8 @@ typedef struct arc_stats {
* buffers *would have* consumed this number of bytes.
*/
kstat_named_t arcstat_mru_ghost_size;
+ kstat_named_t arcstat_mru_ghost_data;
+ kstat_named_t arcstat_mru_ghost_metadata;
/*
* Number of bytes that *would have been* consumed by ARC
* buffers that are eligible for eviction, of type
@@ -697,6 +726,8 @@ typedef struct arc_stats {
* are all included in this value.
*/
kstat_named_t arcstat_mfu_size;
+ kstat_named_t arcstat_mfu_data;
+ kstat_named_t arcstat_mfu_metadata;
/*
* Number of bytes consumed by ARC buffers that are eligible for
* eviction, of type ARC_BUFC_DATA, and reside in the arc_mfu
@@ -715,6 +746,8 @@ typedef struct arc_stats {
* arcstat_mru_ghost_size for more details.
*/
kstat_named_t arcstat_mfu_ghost_size;
+ kstat_named_t arcstat_mfu_ghost_data;
+ kstat_named_t arcstat_mfu_ghost_metadata;
/*
* Number of bytes that *would have been* consumed by ARC
* buffers that are eligible for eviction, of type
@@ -727,6 +760,23 @@ typedef struct arc_stats {
* ARC_BUFC_METADATA, and linked off the arc_mru_ghost state.
*/
kstat_named_t arcstat_mfu_ghost_evictable_metadata;
+ /*
+ * Total number of bytes that are going to be evicted from ARC due to
+ * ARC_FLAG_UNCACHED being set.
+ */
+ kstat_named_t arcstat_uncached_size;
+ kstat_named_t arcstat_uncached_data;
+ kstat_named_t arcstat_uncached_metadata;
+ /*
+ * Number of data bytes that are going to be evicted from ARC due to
+ * ARC_FLAG_UNCACHED being set.
+ */
+ kstat_named_t arcstat_uncached_evictable_data;
+ /*
+ * Number of metadata bytes that that are going to be evicted from ARC
+ * due to ARC_FLAG_UNCACHED being set.
+ */
+ kstat_named_t arcstat_uncached_evictable_metadata;
kstat_named_t arcstat_l2_hits;
kstat_named_t arcstat_l2_misses;
/*
@@ -839,13 +889,20 @@ typedef struct arc_stats {
kstat_named_t arcstat_loaned_bytes;
kstat_named_t arcstat_prune;
kstat_named_t arcstat_meta_used;
- kstat_named_t arcstat_meta_limit;
kstat_named_t arcstat_dnode_limit;
- kstat_named_t arcstat_meta_max;
- kstat_named_t arcstat_meta_min;
kstat_named_t arcstat_async_upgrade_sync;
+ /* Number of predictive prefetch requests. */
+ kstat_named_t arcstat_predictive_prefetch;
+ /* Number of requests for which predictive prefetch has completed. */
kstat_named_t arcstat_demand_hit_predictive_prefetch;
+ /* Number of requests for which predictive prefetch was running. */
+ kstat_named_t arcstat_demand_iohit_predictive_prefetch;
+ /* Number of prescient prefetch requests. */
+ kstat_named_t arcstat_prescient_prefetch;
+ /* Number of requests for which prescient prefetch has completed. */
kstat_named_t arcstat_demand_hit_prescient_prefetch;
+ /* Number of requests for which prescient prefetch was running. */
+ kstat_named_t arcstat_demand_iohit_prescient_prefetch;
kstat_named_t arcstat_need_free;
kstat_named_t arcstat_sys_free;
kstat_named_t arcstat_raw_size;
@@ -855,19 +912,25 @@ typedef struct arc_stats {
typedef struct arc_sums {
wmsum_t arcstat_hits;
+ wmsum_t arcstat_iohits;
wmsum_t arcstat_misses;
wmsum_t arcstat_demand_data_hits;
+ wmsum_t arcstat_demand_data_iohits;
wmsum_t arcstat_demand_data_misses;
wmsum_t arcstat_demand_metadata_hits;
+ wmsum_t arcstat_demand_metadata_iohits;
wmsum_t arcstat_demand_metadata_misses;
wmsum_t arcstat_prefetch_data_hits;
+ wmsum_t arcstat_prefetch_data_iohits;
wmsum_t arcstat_prefetch_data_misses;
wmsum_t arcstat_prefetch_metadata_hits;
+ wmsum_t arcstat_prefetch_metadata_iohits;
wmsum_t arcstat_prefetch_metadata_misses;
wmsum_t arcstat_mru_hits;
wmsum_t arcstat_mru_ghost_hits;
wmsum_t arcstat_mfu_hits;
wmsum_t arcstat_mfu_ghost_hits;
+ wmsum_t arcstat_uncached_hits;
wmsum_t arcstat_deleted;
wmsum_t arcstat_mutex_miss;
wmsum_t arcstat_access_skip;
@@ -889,7 +952,7 @@ typedef struct arc_sums {
wmsum_t arcstat_data_size;
wmsum_t arcstat_metadata_size;
wmsum_t arcstat_dbuf_size;
- aggsum_t arcstat_dnode_size;
+ wmsum_t arcstat_dnode_size;
wmsum_t arcstat_bonus_size;
wmsum_t arcstat_l2_hits;
wmsum_t arcstat_l2_misses;
@@ -934,10 +997,14 @@ typedef struct arc_sums {
wmsum_t arcstat_memory_direct_count;
wmsum_t arcstat_memory_indirect_count;
wmsum_t arcstat_prune;
- aggsum_t arcstat_meta_used;
+ wmsum_t arcstat_meta_used;
wmsum_t arcstat_async_upgrade_sync;
+ wmsum_t arcstat_predictive_prefetch;
wmsum_t arcstat_demand_hit_predictive_prefetch;
+ wmsum_t arcstat_demand_iohit_predictive_prefetch;
+ wmsum_t arcstat_prescient_prefetch;
wmsum_t arcstat_demand_hit_prescient_prefetch;
+ wmsum_t arcstat_demand_iohit_prescient_prefetch;
wmsum_t arcstat_raw_size;
wmsum_t arcstat_cached_only_in_progress;
wmsum_t arcstat_abd_chunk_waste_size;
@@ -958,7 +1025,9 @@ typedef struct arc_evict_waiter {
#define ARCSTAT_BUMPDOWN(stat) ARCSTAT_INCR(stat, -1)
#define arc_no_grow ARCSTAT(arcstat_no_grow) /* do not grow cache size */
-#define arc_p ARCSTAT(arcstat_p) /* target size of MRU */
+#define arc_meta ARCSTAT(arcstat_meta) /* target frac of metadata */
+#define arc_pd ARCSTAT(arcstat_pd) /* target frac of data MRU */
+#define arc_pm ARCSTAT(arcstat_pm) /* target frac of meta MRU */
#define arc_c ARCSTAT(arcstat_c) /* target size of cache */
#define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */
#define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */
@@ -970,23 +1039,24 @@ typedef struct arc_evict_waiter {
#define arc_mfu (&ARC_mfu)
#define arc_mfu_ghost (&ARC_mfu_ghost)
#define arc_l2c_only (&ARC_l2c_only)
+#define arc_uncached (&ARC_uncached)
extern taskq_t *arc_prune_taskq;
extern arc_stats_t arc_stats;
extern arc_sums_t arc_sums;
extern hrtime_t arc_growtime;
extern boolean_t arc_warm;
-extern int arc_grow_retry;
-extern int arc_no_grow_shift;
-extern int arc_shrink_shift;
+extern uint_t arc_grow_retry;
+extern uint_t arc_no_grow_shift;
+extern uint_t arc_shrink_shift;
extern kmutex_t arc_prune_mtx;
extern list_t arc_prune_list;
extern arc_state_t ARC_mfu;
extern arc_state_t ARC_mru;
extern uint_t zfs_arc_pc_percent;
-extern int arc_lotsfree_percent;
-extern unsigned long zfs_arc_min;
-extern unsigned long zfs_arc_max;
+extern uint_t arc_lotsfree_percent;
+extern uint64_t zfs_arc_min;
+extern uint64_t zfs_arc_max;
extern void arc_reduce_target_size(int64_t to_free);
extern boolean_t arc_reclaim_needed(void);
@@ -995,7 +1065,6 @@ extern void arc_wait_for_eviction(uint64_t, boolean_t);
extern void arc_lowmem_init(void);
extern void arc_lowmem_fini(void);
-extern void arc_prune_async(int64_t);
extern int arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg);
extern uint64_t arc_free_memory(void);
extern int64_t arc_available_memory(void);
@@ -1003,7 +1072,7 @@ extern void arc_tuning_update(boolean_t);
extern void arc_register_hotplug(void);
extern void arc_unregister_hotplug(void);
-extern int param_set_arc_long(ZFS_MODULE_PARAM_ARGS);
+extern int param_set_arc_u64(ZFS_MODULE_PARAM_ARGS);
extern int param_set_arc_int(ZFS_MODULE_PARAM_ARGS);
extern int param_set_arc_min(ZFS_MODULE_PARAM_ARGS);
extern int param_set_arc_max(ZFS_MODULE_PARAM_ARGS);
diff --git a/include/sys/asm_linkage.h b/include/sys/asm_linkage.h
new file mode 100644
index 000000000000..749157d4c3db
--- /dev/null
+++ b/include/sys/asm_linkage.h
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ASM_LINKAGE_H
+#define _SYS_ASM_LINKAGE_H
+
+#define ASMABI
+
+#if defined(__i386) || defined(__amd64)
+
+#include <sys/ia32/asm_linkage.h> /* XX64 x86/sys/asm_linkage.h */
+
+#endif
+
+#if defined(_KERNEL) && defined(HAVE_KERNEL_OBJTOOL)
+
+#include <asm/frame.h>
+
+#else /* userspace */
+#define FRAME_BEGIN
+#define FRAME_END
+#endif
+
+
+#endif /* _SYS_ASM_LINKAGE_H */
diff --git a/include/sys/avl.h b/include/sys/avl.h
index 20e88f2a6b06..8818e3edb292 100644
--- a/include/sys/avl.h
+++ b/include/sys/avl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/avl_impl.h b/include/sys/avl_impl.h
index c464a62a1ca6..85277b42b471 100644
--- a/include/sys/avl_impl.h
+++ b/include/sys/avl_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/bitmap.h b/include/sys/bitmap.h
new file mode 100644
index 000000000000..71eeba592cfd
--- /dev/null
+++ b/include/sys/bitmap.h
@@ -0,0 +1,93 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+#ifndef _SYS_BITMAP_H
+#define _SYS_BITMAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Operations on bitmaps of arbitrary size
+ * A bitmap is a vector of 1 or more ulong_t's.
+ * The user of the package is responsible for range checks and keeping
+ * track of sizes.
+ */
+
+#ifdef _LP64
+#define BT_ULSHIFT 6 /* log base 2 of BT_NBIPUL, to extract word index */
+#define BT_ULSHIFT32 5 /* log base 2 of BT_NBIPUL, to extract word index */
+#else
+#define BT_ULSHIFT 5 /* log base 2 of BT_NBIPUL, to extract word index */
+#endif
+
+#define BT_NBIPUL (1 << BT_ULSHIFT) /* n bits per ulong_t */
+#define BT_ULMASK (BT_NBIPUL - 1) /* to extract bit index */
+
+/*
+ * bitmap is a ulong_t *, bitindex an index_t
+ *
+ * The macros BT_WIM and BT_BIW internal; there is no need
+ * for users of this package to use them.
+ */
+
+/*
+ * word in map
+ */
+#define BT_WIM(bitmap, bitindex) \
+ ((bitmap)[(bitindex) >> BT_ULSHIFT])
+/*
+ * bit in word
+ */
+#define BT_BIW(bitindex) \
+ (1UL << ((bitindex) & BT_ULMASK))
+
+/*
+ * These are public macros
+ *
+ * BT_BITOUL == n bits to n ulong_t's
+ */
+#define BT_BITOUL(nbits) \
+ (((nbits) + BT_NBIPUL - 1l) / BT_NBIPUL)
+#define BT_SIZEOFMAP(nbits) \
+ (BT_BITOUL(nbits) * sizeof (ulong_t))
+#define BT_TEST(bitmap, bitindex) \
+ ((BT_WIM((bitmap), (bitindex)) & BT_BIW(bitindex)) ? 1 : 0)
+#define BT_SET(bitmap, bitindex) \
+ { BT_WIM((bitmap), (bitindex)) |= BT_BIW(bitindex); }
+#define BT_CLEAR(bitmap, bitindex) \
+ { BT_WIM((bitmap), (bitindex)) &= ~BT_BIW(bitindex); }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BITMAP_H */
diff --git a/include/sys/bitops.h b/include/sys/bitops.h
index 69d07d76552a..5c477b38b205 100644
--- a/include/sys/bitops.h
+++ b/include/sys/bitops.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/blake3.h b/include/sys/blake3.h
index b3391c5f2349..b981b18db943 100644
--- a/include/sys/blake3.h
+++ b/include/sys/blake3.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,11 +22,11 @@
/*
* Based on BLAKE3 v1.3.1, https://github.com/BLAKE3-team/BLAKE3
* Copyright (c) 2019-2020 Samuel Neves and Jack O'Connor
- * Copyright (c) 2021 Tino Reichardt <milky-zfs@mcmilk.de>
+ * Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
-#ifndef BLAKE3_H
-#define BLAKE3_H
+#ifndef _SYS_BLAKE3_H
+#define _SYS_BLAKE3_H
#ifdef _KERNEL
#include <sys/types.h>
@@ -72,7 +72,7 @@ typedef struct {
*/
uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN];
- /* const blake3_impl_ops_t *ops */
+ /* const blake3_ops_t *ops */
const void *ops;
} BLAKE3_CTX;
@@ -97,29 +97,8 @@ extern void **blake3_per_cpu_ctx;
extern void blake3_per_cpu_ctx_init(void);
extern void blake3_per_cpu_ctx_fini(void);
-/* return number of supported implementations */
-extern int blake3_get_impl_count(void);
-
-/* return id of selected implementation */
-extern int blake3_get_impl_id(void);
-
-/* return name of selected implementation */
-extern const char *blake3_get_impl_name(void);
-
-/* setup id as fastest implementation */
-extern void blake3_set_impl_fastest(uint32_t id);
-
-/* set implementation by id */
-extern void blake3_set_impl_id(uint32_t id);
-
-/* set implementation by name */
-extern int blake3_set_impl_name(const char *name);
-
-/* set startup implementation */
-extern void blake3_setup_impl(void);
-
#ifdef __cplusplus
}
#endif
-#endif /* BLAKE3_H */
+#endif /* _SYS_BLAKE3_H */
diff --git a/include/sys/bplist.h b/include/sys/bplist.h
index f8deaf8437e6..53dd346767fe 100644
--- a/include/sys/bplist.h
+++ b/include/sys/bplist.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/bpobj.h b/include/sys/bpobj.h
index 16e403526cff..81bc0fe21086 100644
--- a/include/sys/bpobj.h
+++ b/include/sys/bpobj.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -60,7 +60,7 @@ typedef struct bpobj {
kmutex_t bpo_lock;
objset_t *bpo_os;
uint64_t bpo_object;
- int bpo_epb;
+ uint32_t bpo_epb;
uint8_t bpo_havecomp;
uint8_t bpo_havesubobj;
uint8_t bpo_havefreed;
@@ -87,6 +87,7 @@ int livelist_bpobj_iterate_from_nofree(bpobj_t *bpo, bpobj_itor_t func,
void *arg, int64_t start);
void bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx);
+void bpobj_prefetch_subobj(bpobj_t *bpo, uint64_t subobj);
void bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
dmu_tx_t *tx);
diff --git a/include/sys/bptree.h b/include/sys/bptree.h
index 327c128bf493..9d189446ab69 100644
--- a/include/sys/bptree.h
+++ b/include/sys/bptree.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/bqueue.h b/include/sys/bqueue.h
index 797aecd791a3..edcee16227ec 100644
--- a/include/sys/bqueue.h
+++ b/include/sys/bqueue.h
@@ -27,27 +27,30 @@ extern "C" {
typedef struct bqueue {
list_t bq_list;
+ size_t bq_size;
+ list_t bq_dequeuing_list;
+ size_t bq_dequeuing_size;
+ list_t bq_enqueuing_list;
+ size_t bq_enqueuing_size;
kmutex_t bq_lock;
kcondvar_t bq_add_cv;
kcondvar_t bq_pop_cv;
- uint64_t bq_size;
- uint64_t bq_maxsize;
- uint64_t bq_fill_fraction;
+ size_t bq_maxsize;
+ uint_t bq_fill_fraction;
size_t bq_node_offset;
} bqueue_t;
typedef struct bqueue_node {
list_node_t bqn_node;
- uint64_t bqn_size;
+ size_t bqn_size;
} bqueue_node_t;
-int bqueue_init(bqueue_t *, uint64_t, uint64_t, size_t);
+int bqueue_init(bqueue_t *, uint_t, size_t, size_t);
void bqueue_destroy(bqueue_t *);
-void bqueue_enqueue(bqueue_t *, void *, uint64_t);
-void bqueue_enqueue_flush(bqueue_t *, void *, uint64_t);
+void bqueue_enqueue(bqueue_t *, void *, size_t);
+void bqueue_enqueue_flush(bqueue_t *, void *, size_t);
void *bqueue_dequeue(bqueue_t *);
-boolean_t bqueue_empty(bqueue_t *);
#ifdef __cplusplus
}
diff --git a/include/sys/brt.h b/include/sys/brt.h
new file mode 100644
index 000000000000..f73df95058d9
--- /dev/null
+++ b/include/sys/brt.h
@@ -0,0 +1,63 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2020, 2021, 2022 by Pawel Jakub Dawidek
+ */
+
+#ifndef _SYS_BRT_H
+#define _SYS_BRT_H
+
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/fs/zfs.h>
+#include <sys/zio.h>
+#include <sys/dmu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern boolean_t brt_entry_decref(spa_t *spa, const blkptr_t *bp);
+extern uint64_t brt_entry_get_refcount(spa_t *spa, const blkptr_t *bp);
+
+extern uint64_t brt_get_dspace(spa_t *spa);
+extern uint64_t brt_get_used(spa_t *spa);
+extern uint64_t brt_get_saved(spa_t *spa);
+extern uint64_t brt_get_ratio(spa_t *spa);
+
+extern boolean_t brt_maybe_exists(spa_t *spa, const blkptr_t *bp);
+extern void brt_init(void);
+extern void brt_fini(void);
+
+extern void brt_pending_add(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx);
+extern void brt_pending_remove(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx);
+extern void brt_pending_apply(spa_t *spa, uint64_t txg);
+
+extern void brt_create(spa_t *spa);
+extern int brt_load(spa_t *spa);
+extern void brt_unload(spa_t *spa);
+extern void brt_sync(spa_t *spa, uint64_t txg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BRT_H */
diff --git a/include/sys/brt_impl.h b/include/sys/brt_impl.h
new file mode 100644
index 000000000000..9cc06fbb2c3a
--- /dev/null
+++ b/include/sys/brt_impl.h
@@ -0,0 +1,199 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2020, 2021, 2022 by Pawel Jakub Dawidek
+ */
+
+#ifndef _SYS_BRT_IMPL_H
+#define _SYS_BRT_IMPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * BRT - Block Reference Table.
+ */
+#define BRT_OBJECT_VDEV_PREFIX "com.fudosecurity:brt:vdev:"
+
+/*
+ * We divide each VDEV into 16MB chunks. Each chunk is represented in memory
+ * by a 16bit counter, thus 1TB VDEV requires 128kB of memory: (1TB / 16MB) * 2B
+ * Each element in this array represents how many BRT entries do we have in this
+ * chunk of storage. We always load this entire array into memory and update as
+ * needed. By having it in memory we can quickly tell (during zio_free()) if
+ * there are any BRT entries that we might need to update.
+ *
+ * This value cannot be larger than 16MB, at least as long as we support
+ * 512 byte block sizes. With 512 byte block size we can have exactly
+ * 32768 blocks in 16MB. In 32MB we could have 65536 blocks, which is one too
+ * many for a 16bit counter.
+ */
+#define BRT_RANGESIZE (16 * 1024 * 1024)
+_Static_assert(BRT_RANGESIZE / SPA_MINBLOCKSIZE <= UINT16_MAX,
+ "BRT_RANGESIZE is too large.");
+/*
+ * We don't want to update the whole structure every time. Maintain bitmap
+ * of dirty blocks within the regions, so that a single bit represents a
+ * block size of entcounts. For example if we have a 1PB vdev then all
+ * entcounts take 128MB of memory ((64TB / 16MB) * 2B). We can divide this
+ * 128MB array of entcounts into 32kB disk blocks, as we don't want to update
+ * the whole 128MB on disk when we have updated only a single entcount.
+ * We maintain a bitmap where each 32kB disk block within 128MB entcounts array
+ * is represented by a single bit. This gives us 4096 bits. A set bit in the
+ * bitmap means that we had a change in at least one of the 16384 entcounts
+ * that reside on a 32kB disk block (32kB / sizeof (uint16_t)).
+ */
+#define BRT_BLOCKSIZE (32 * 1024)
+#define BRT_RANGESIZE_TO_NBLOCKS(size) \
+ (((size) - 1) / BRT_BLOCKSIZE / sizeof (uint16_t) + 1)
+
+#define BRT_LITTLE_ENDIAN 0
+#define BRT_BIG_ENDIAN 1
+#ifdef _ZFS_LITTLE_ENDIAN
+#define BRT_NATIVE_BYTEORDER BRT_LITTLE_ENDIAN
+#define BRT_NON_NATIVE_BYTEORDER BRT_BIG_ENDIAN
+#else
+#define BRT_NATIVE_BYTEORDER BRT_BIG_ENDIAN
+#define BRT_NON_NATIVE_BYTEORDER BRT_LITTLE_ENDIAN
+#endif
+
+typedef struct brt_vdev_phys {
+ uint64_t bvp_mos_entries;
+ uint64_t bvp_size;
+ uint64_t bvp_byteorder;
+ uint64_t bvp_totalcount;
+ uint64_t bvp_rangesize;
+ uint64_t bvp_usedspace;
+ uint64_t bvp_savedspace;
+} brt_vdev_phys_t;
+
+typedef struct brt_vdev {
+ /*
+ * VDEV id.
+ */
+ uint64_t bv_vdevid;
+ /*
+ * Is the structure initiated?
+ * (bv_entcount and bv_bitmap are allocated?)
+ */
+ boolean_t bv_initiated;
+ /*
+ * Object number in the MOS for the entcount array and brt_vdev_phys.
+ */
+ uint64_t bv_mos_brtvdev;
+ /*
+ * Object number in the MOS for the entries table.
+ */
+ uint64_t bv_mos_entries;
+ /*
+ * Entries to sync.
+ */
+ avl_tree_t bv_tree;
+ /*
+ * Does the bv_entcount[] array needs byte swapping?
+ */
+ boolean_t bv_need_byteswap;
+ /*
+ * Number of entries in the bv_entcount[] array.
+ */
+ uint64_t bv_size;
+ /*
+ * This is the array with BRT entry count per BRT_RANGESIZE.
+ */
+ uint16_t *bv_entcount;
+ /*
+ * Sum of all bv_entcount[]s.
+ */
+ uint64_t bv_totalcount;
+ /*
+ * Space on disk occupied by cloned blocks (without compression).
+ */
+ uint64_t bv_usedspace;
+ /*
+ * How much additional space would be occupied without block cloning.
+ */
+ uint64_t bv_savedspace;
+ /*
+ * brt_vdev_phys needs updating on disk.
+ */
+ boolean_t bv_meta_dirty;
+ /*
+ * bv_entcount[] needs updating on disk.
+ */
+ boolean_t bv_entcount_dirty;
+ /*
+ * bv_entcount[] potentially can be a bit too big to sychronize it all
+ * when we just changed few entcounts. The fields below allow us to
+ * track updates to bv_entcount[] array since the last sync.
+ * A single bit in the bv_bitmap represents as many entcounts as can
+ * fit into a single BRT_BLOCKSIZE.
+ * For example we have 65536 entcounts in the bv_entcount array
+ * (so the whole array is 128kB). We updated bv_entcount[2] and
+ * bv_entcount[5]. In that case only first bit in the bv_bitmap will
+ * be set and we will write only first BRT_BLOCKSIZE out of 128kB.
+ */
+ ulong_t *bv_bitmap;
+ uint64_t bv_nblocks;
+} brt_vdev_t;
+
+/*
+ * In-core brt
+ */
+typedef struct brt {
+ krwlock_t brt_lock;
+ spa_t *brt_spa;
+#define brt_mos brt_spa->spa_meta_objset
+ uint64_t brt_rangesize;
+ uint64_t brt_usedspace;
+ uint64_t brt_savedspace;
+ avl_tree_t brt_pending_tree[TXG_SIZE];
+ kmutex_t brt_pending_lock[TXG_SIZE];
+ /* Sum of all entries across all bv_trees. */
+ uint64_t brt_nentries;
+ brt_vdev_t *brt_vdevs;
+ uint64_t brt_nvdevs;
+} brt_t;
+
+/* Size of bre_offset / sizeof (uint64_t). */
+#define BRT_KEY_WORDS (1)
+
+/*
+ * In-core brt entry.
+ * On-disk we use bre_offset as the key and bre_refcount as the value.
+ */
+typedef struct brt_entry {
+ uint64_t bre_offset;
+ uint64_t bre_refcount;
+ avl_node_t bre_node;
+} brt_entry_t;
+
+typedef struct brt_pending_entry {
+ blkptr_t bpe_bp;
+ int bpe_count;
+ avl_node_t bpe_node;
+} brt_pending_entry_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BRT_IMPL_H */
diff --git a/include/sys/btree.h b/include/sys/btree.h
index a901d654ef1c..6e05eee8f01d 100644
--- a/include/sys/btree.h
+++ b/include/sys/btree.h
@@ -65,7 +65,7 @@ extern "C" {
* them, and increased memory overhead. Increasing these values results in
* higher variance in operation time, and reduces memory overhead.
*/
-#define BTREE_CORE_ELEMS 128
+#define BTREE_CORE_ELEMS 126
#define BTREE_LEAF_SIZE 4096
extern kmem_cache_t *zfs_btree_leaf_cache;
@@ -95,9 +95,6 @@ typedef struct zfs_btree_leaf {
uint8_t btl_elems[];
} zfs_btree_leaf_t;
-#define BTREE_LEAF_ESIZE (BTREE_LEAF_SIZE - \
- offsetof(zfs_btree_leaf_t, btl_elems))
-
typedef struct zfs_btree_index {
zfs_btree_hdr_t *bti_node;
uint32_t bti_offset;
@@ -108,16 +105,69 @@ typedef struct zfs_btree_index {
boolean_t bti_before;
} zfs_btree_index_t;
-typedef struct btree {
- zfs_btree_hdr_t *bt_root;
- int64_t bt_height;
+typedef struct btree zfs_btree_t;
+typedef void * (*bt_find_in_buf_f) (zfs_btree_t *, uint8_t *, uint32_t,
+ const void *, zfs_btree_index_t *);
+
+struct btree {
+ int (*bt_compar) (const void *, const void *);
+ bt_find_in_buf_f bt_find_in_buf;
size_t bt_elem_size;
+ size_t bt_leaf_size;
uint32_t bt_leaf_cap;
+ int32_t bt_height;
uint64_t bt_num_elems;
uint64_t bt_num_nodes;
+ zfs_btree_hdr_t *bt_root;
zfs_btree_leaf_t *bt_bulk; // non-null if bulk loading
- int (*bt_compar) (const void *, const void *);
-} zfs_btree_t;
+};
+
+/*
+ * Implementation of Shar's algorithm designed to accelerate binary search by
+ * eliminating impossible to predict branches.
+ *
+ * For optimality, this should be used to generate the search function in the
+ * same file as the comparator and the comparator should be marked
+ * `__attribute__((always_inline) inline` so that the compiler will inline it.
+ *
+ * Arguments are:
+ *
+ * NAME - The function name for this instance of the search function. Use it
+ * in a subsequent call to zfs_btree_create().
+ * T - The element type stored inside the B-Tree.
+ * COMP - A comparator to compare two nodes, it must return exactly: -1, 0,
+ * or +1 -1 for <, 0 for ==, and +1 for >. For trivial comparisons,
+ * TREE_CMP() from avl.h can be used in a boilerplate function.
+ */
+/* BEGIN CSTYLED */
+#define ZFS_BTREE_FIND_IN_BUF_FUNC(NAME, T, COMP) \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") \
+static void * \
+NAME(zfs_btree_t *tree, uint8_t *buf, uint32_t nelems, \
+ const void *value, zfs_btree_index_t *where) \
+{ \
+ T *i = (T *)buf; \
+ (void) tree; \
+ _Pragma("GCC unroll 9") \
+ while (nelems > 1) { \
+ uint32_t half = nelems / 2; \
+ nelems -= half; \
+ i += (COMP(&i[half - 1], value) < 0) * half; \
+ } \
+ \
+ int comp = COMP(i, value); \
+ where->bti_offset = (i - (T *)buf) + (comp < 0); \
+ where->bti_before = (comp != 0); \
+ \
+ if (comp == 0) { \
+ return (i); \
+ } \
+ \
+ return (NULL); \
+} \
+_Pragma("GCC diagnostic pop")
+/* END CSTYLED */
/*
* Allocate and deallocate caches for btree nodes.
@@ -131,10 +181,19 @@ void zfs_btree_fini(void);
* tree - the tree to be initialized
* compar - function to compare two nodes, it must return exactly: -1, 0, or +1
* -1 for <, 0 for ==, and +1 for >
+ * find - optional function to accelerate searches inside B-Tree nodes
+ * through Shar's algorithm and comparator inlining. Setting this to
+ * NULL will use a generic function. The function should be created
+ * using ZFS_BTREE_FIND_IN_BUF_FUNC() in the same file as compar.
+ * compar should be marked `__attribute__((always_inline)) inline` or
+ * performance is unlikely to improve very much.
* size - the value of sizeof(struct my_type)
+ * lsize - custom leaf size
*/
void zfs_btree_create(zfs_btree_t *, int (*) (const void *, const void *),
- size_t);
+ bt_find_in_buf_f, size_t);
+void zfs_btree_create_custom(zfs_btree_t *, int (*)(const void *, const void *),
+ bt_find_in_buf_f, size_t, size_t);
/*
* Find a node with a matching value in the tree. Returns the matching node
diff --git a/include/sys/crypto/api.h b/include/sys/crypto/api.h
index b3d6c9c071b9..88e0ac4d9699 100644
--- a/include/sys/crypto/api.h
+++ b/include/sys/crypto/api.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/crypto/common.h b/include/sys/crypto/common.h
index 45a95d7eed71..261e88eceeea 100644
--- a/include/sys/crypto/common.h
+++ b/include/sys/crypto/common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/crypto/icp.h b/include/sys/crypto/icp.h
index ae7f7eae529e..8c3f19886fd8 100644
--- a/include/sys/crypto/icp.h
+++ b/include/sys/crypto/icp.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dataset_kstats.h b/include/sys/dataset_kstats.h
index b165b98576dd..c81a07f0c116 100644
--- a/include/sys/dataset_kstats.h
+++ b/include/sys/dataset_kstats.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,6 +30,7 @@
#include <sys/wmsum.h>
#include <sys/dmu.h>
#include <sys/kstat.h>
+#include <sys/zil.h>
typedef struct dataset_sum_stats_t {
wmsum_t dss_writes;
@@ -56,15 +57,21 @@ typedef struct dataset_kstat_values {
* entry is removed from the unlinked set
*/
kstat_named_t dkv_nunlinked;
+ /*
+ * Per dataset zil kstats
+ */
+ zil_kstat_values_t dkv_zil_stats;
} dataset_kstat_values_t;
typedef struct dataset_kstats {
dataset_sum_stats_t dk_sums;
+ zil_sums_t dk_zil_sums;
kstat_t *dk_kstats;
} dataset_kstats_t;
-void dataset_kstats_create(dataset_kstats_t *, objset_t *);
+int dataset_kstats_create(dataset_kstats_t *, objset_t *);
void dataset_kstats_destroy(dataset_kstats_t *);
+void dataset_kstats_rename(dataset_kstats_t *dk, const char *);
void dataset_kstats_update_write_kstats(dataset_kstats_t *, int64_t);
void dataset_kstats_update_read_kstats(dataset_kstats_t *, int64_t);
diff --git a/include/sys/dbuf.h b/include/sys/dbuf.h
index 959e111cee7a..3808a04cba80 100644
--- a/include/sys/dbuf.h
+++ b/include/sys/dbuf.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -55,26 +55,31 @@ extern "C" {
#define DB_RF_NEVERWAIT (1 << 4)
#define DB_RF_CACHED (1 << 5)
#define DB_RF_NO_DECRYPT (1 << 6)
+#define DB_RF_PARTIAL_FIRST (1 << 7)
+#define DB_RF_PARTIAL_MORE (1 << 8)
/*
* The simplified state transition diagram for dbufs looks like:
*
- * +----> READ ----+
- * | |
- * | V
- * (alloc)-->UNCACHED CACHED-->EVICTING-->(free)
- * | ^ ^
- * | | |
- * +----> FILL ----+ |
- * | |
- * | |
- * +--------> NOFILL -------+
+ * +--> READ --+
+ * | |
+ * | V
+ * (alloc)-->UNCACHED CACHED-->EVICTING-->(free)
+ * ^ | ^ ^
+ * | | | |
+ * | +--> FILL --+ |
+ * | | |
+ * | | |
+ * | +------> NOFILL -----+
+ * | |
+ * +---------------+
*
* DB_SEARCH is an invalid state for a dbuf. It is used by dbuf_free_range
* to find all dbufs in a range of a dnode and must be less than any other
* dbuf_states_t (see comment on dn_dbufs in dnode.h).
*/
typedef enum dbuf_states {
+ DB_MARKER = -2,
DB_SEARCH = -1,
DB_UNCACHED,
DB_FILL,
@@ -170,6 +175,7 @@ typedef struct dbuf_dirty_record {
override_states_t dr_override_state;
uint8_t dr_copies;
boolean_t dr_nopwrite;
+ boolean_t dr_brtwrite;
boolean_t dr_has_raw_params;
/*
@@ -190,7 +196,7 @@ typedef struct dbuf_dirty_record {
uint64_t dr_blkid;
abd_t *dr_abd;
zio_prop_t dr_props;
- enum zio_flag dr_flags;
+ zio_flag_t dr_flags;
} dll;
} dt;
} dbuf_dirty_record_t;
@@ -294,6 +300,8 @@ typedef struct dmu_buf_impl {
/* Tells us which dbuf cache this dbuf is in, if any */
dbuf_cached_state_t db_caching_status;
+ uint64_t db_hash;
+
/* Data which is unique to data (leaf) blocks: */
/* User callback information. */
@@ -319,14 +327,19 @@ typedef struct dmu_buf_impl {
uint8_t db_pending_evict;
uint8_t db_dirtycnt;
+
+ /* The buffer was partially read. More reads may follow. */
+ uint8_t db_partial_read;
} dmu_buf_impl_t;
-#define DBUF_RWLOCKS 8192
-#define DBUF_HASH_RWLOCK(h, idx) (&(h)->hash_rwlocks[(idx) & (DBUF_RWLOCKS-1)])
+#define DBUF_HASH_MUTEX(h, idx) \
+ (&(h)->hash_mutexes[(idx) & ((h)->hash_mutex_mask)])
+
typedef struct dbuf_hash_table {
uint64_t hash_table_mask;
+ uint64_t hash_mutex_mask;
dmu_buf_impl_t **hash_table;
- krwlock_t hash_rwlocks[DBUF_RWLOCKS] ____cacheline_aligned;
+ kmutex_t *hash_mutexes;
} dbuf_hash_table_t;
typedef void (*dbuf_prefetch_fn)(void *, uint64_t, uint64_t, boolean_t);
@@ -362,23 +375,25 @@ void dbuf_rele_and_unlock(dmu_buf_impl_t *db, const void *tag,
boolean_t evicting);
dmu_buf_impl_t *dbuf_find(struct objset *os, uint64_t object, uint8_t level,
- uint64_t blkid);
+ uint64_t blkid, uint64_t *hash_out);
int dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags);
+void dmu_buf_will_clone(dmu_buf_t *db, dmu_tx_t *tx);
void dmu_buf_will_not_fill(dmu_buf_t *db, dmu_tx_t *tx);
-void dmu_buf_will_fill(dmu_buf_t *db, dmu_tx_t *tx);
-void dmu_buf_fill_done(dmu_buf_t *db, dmu_tx_t *tx);
+void dmu_buf_will_fill(dmu_buf_t *db, dmu_tx_t *tx, boolean_t canfail);
+boolean_t dmu_buf_fill_done(dmu_buf_t *db, dmu_tx_t *tx, boolean_t failed);
void dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx);
dbuf_dirty_record_t *dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
dbuf_dirty_record_t *dbuf_dirty_lightweight(dnode_t *dn, uint64_t blkid,
dmu_tx_t *tx);
+boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
arc_buf_t *dbuf_loan_arcbuf(dmu_buf_impl_t *db);
void dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
bp_embedded_type_t etype, enum zio_compress comp,
int uncompressed_size, int compressed_size, int byteorder, dmu_tx_t *tx);
int dmu_lightweight_write_by_dnode(dnode_t *dn, uint64_t offset, abd_t *abd,
- const struct zio_prop *zp, enum zio_flag flags, dmu_tx_t *tx);
+ const struct zio_prop *zp, zio_flag_t flags, dmu_tx_t *tx);
void dmu_buf_redact(dmu_buf_t *dbuf, dmu_tx_t *tx);
void dbuf_destroy(dmu_buf_impl_t *db);
diff --git a/include/sys/ddt.h b/include/sys/ddt.h
index 25be6f56dddc..726f1a3902eb 100644
--- a/include/sys/ddt.h
+++ b/include/sys/ddt.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2023, Klara Inc.
*/
#ifndef _SYS_DDT_H
@@ -39,32 +40,50 @@ extern "C" {
struct abd;
/*
- * On-disk DDT formats, in the desired search order (newest version first).
+ * DDT on-disk storage object types. Each one corresponds to specific
+ * implementation, see ddt_ops_t. The value itself is not stored on disk.
+ *
+ * When searching for an entry, objects types will be searched in this order.
+ *
+ * Note that DDT_TYPES is used as the "no type" for new entries that have not
+ * yet been written to a storage object.
*/
-enum ddt_type {
- DDT_TYPE_ZAP = 0,
+typedef enum {
+ DDT_TYPE_ZAP = 0, /* ZAP storage object, ddt_zap */
DDT_TYPES
-};
+} ddt_type_t;
+
+_Static_assert(DDT_TYPES <= UINT8_MAX,
+ "ddt_type_t must fit in a uint8_t");
+
+/* New and updated entries recieve this type, see ddt_sync_entry() */
+#define DDT_TYPE_DEFAULT (DDT_TYPE_ZAP)
/*
- * DDT classes, in the desired search order (highest replication level first).
+ * DDT storage classes. Each class has a separate storage object for each type.
+ * The value itself is not stored on disk.
+ *
+ * When search for an entry, object classes will be searched in this order.
+ *
+ * Note that DDT_CLASSES is used as the "no class" for new entries that have not
+ * yet been written to a storage object.
*/
-enum ddt_class {
- DDT_CLASS_DITTO = 0,
- DDT_CLASS_DUPLICATE,
- DDT_CLASS_UNIQUE,
+typedef enum {
+ DDT_CLASS_DITTO = 0, /* entry has ditto blocks (obsolete) */
+ DDT_CLASS_DUPLICATE, /* entry has multiple references */
+ DDT_CLASS_UNIQUE, /* entry has a single reference */
DDT_CLASSES
-};
-
-#define DDT_TYPE_CURRENT 0
+} ddt_class_t;
-#define DDT_COMPRESS_BYTEORDER_MASK 0x80
-#define DDT_COMPRESS_FUNCTION_MASK 0x7f
+_Static_assert(DDT_CLASSES < UINT8_MAX,
+ "ddt_class_t must fit in a uint8_t");
/*
- * On-disk ddt entry: key (name) and physical storage (value).
+ * The "key" part of an on-disk entry. This is the unique "name" for a block,
+ * that is, that parts of the block pointer that will always be the same for
+ * the same data.
*/
-typedef struct ddt_key {
+typedef struct {
zio_cksum_t ddk_cksum; /* 256-bit block checksum */
/*
* Encoded with logical & physical size, encryption, and compression,
@@ -76,6 +95,10 @@ typedef struct ddt_key {
uint64_t ddk_prop;
} ddt_key_t;
+/*
+ * Macros for accessing parts of a ddt_key_t. These are similar to their BP_*
+ * counterparts.
+ */
#define DDK_GET_LSIZE(ddk) \
BF64_GET_SB((ddk)->ddk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
#define DDK_SET_LSIZE(ddk, x) \
@@ -92,18 +115,25 @@ typedef struct ddt_key {
#define DDK_GET_CRYPT(ddk) BF64_GET((ddk)->ddk_prop, 39, 1)
#define DDK_SET_CRYPT(ddk, x) BF64_SET((ddk)->ddk_prop, 39, 1, x)
-#define DDT_KEY_WORDS (sizeof (ddt_key_t) / sizeof (uint64_t))
-
-#define DDE_GET_NDVAS(dde) (DDK_GET_CRYPT(&dde->dde_key) \
- ? SPA_DVAS_PER_BP - 1 : SPA_DVAS_PER_BP)
-
-typedef struct ddt_phys {
+/*
+ * The "value" part for an on-disk entry. These are the "physical"
+ * characteristics of the stored block, such as its location on disk (DVAs),
+ * birth txg and ref count.
+ *
+ * Note that an entry has an array of four ddt_phys_t, one for each number of
+ * DVAs (copies= property) and another for additional "ditto" copies. Most
+ * users of ddt_phys_t will handle indexing into or counting the phys they
+ * want.
+ */
+typedef struct {
dva_t ddp_dva[SPA_DVAS_PER_BP];
uint64_t ddp_refcnt;
uint64_t ddp_phys_birth;
} ddt_phys_t;
/*
+ * Named indexes into the ddt_phys_t array in each entry.
+ *
* Note, we no longer generate new DDT_PHYS_DITTO-type blocks. However,
* we maintain the ability to free existing dedup-ditto blocks.
*/
@@ -116,99 +146,83 @@ enum ddt_phys_type {
};
/*
- * In-core ddt entry
+ * A "live" entry, holding changes to an entry made this txg, and other data to
+ * support loading, updating and repairing the entry.
*/
-struct ddt_entry {
- ddt_key_t dde_key;
- ddt_phys_t dde_phys[DDT_PHYS_TYPES];
+
+/* State flags for dde_flags */
+#define DDE_FLAG_LOADED (1 << 0) /* entry ready for use */
+
+typedef struct {
+ /* key must be first for ddt_key_compare */
+ ddt_key_t dde_key; /* ddt_tree key */
+ ddt_phys_t dde_phys[DDT_PHYS_TYPES]; /* on-disk data */
+
+ /* in-flight update IOs */
zio_t *dde_lead_zio[DDT_PHYS_TYPES];
+
+ /* copy of data after a repair read, to be rewritten */
struct abd *dde_repair_abd;
- enum ddt_type dde_type;
- enum ddt_class dde_class;
- uint8_t dde_loading;
- uint8_t dde_loaded;
- kcondvar_t dde_cv;
- avl_node_t dde_node;
-};
+
+ /* storage type and class the entry was loaded from */
+ ddt_type_t dde_type;
+ ddt_class_t dde_class;
+
+ uint8_t dde_flags; /* load state flags */
+ kcondvar_t dde_cv; /* signaled when load completes */
+
+ avl_node_t dde_node; /* ddt_tree node */
+} ddt_entry_t;
/*
- * In-core ddt
+ * In-core DDT object. This covers all entries and stats for a the whole pool
+ * for a given checksum type.
*/
-struct ddt {
- kmutex_t ddt_lock;
- avl_tree_t ddt_tree;
- avl_tree_t ddt_repair_tree;
- enum zio_checksum ddt_checksum;
- spa_t *ddt_spa;
- objset_t *ddt_os;
- uint64_t ddt_stat_object;
+typedef struct {
+ kmutex_t ddt_lock; /* protects changes to all fields */
+
+ avl_tree_t ddt_tree; /* "live" (changed) entries this txg */
+
+ avl_tree_t ddt_repair_tree; /* entries being repaired */
+
+ enum zio_checksum ddt_checksum; /* checksum algorithm in use */
+ spa_t *ddt_spa; /* pool this ddt is on */
+ objset_t *ddt_os; /* ddt objset (always MOS) */
+
+ /* per-type/per-class entry store objects */
uint64_t ddt_object[DDT_TYPES][DDT_CLASSES];
+
+ /* object ids for whole-ddt and per-type/per-class stats */
+ uint64_t ddt_stat_object;
+ ddt_object_t ddt_object_stats[DDT_TYPES][DDT_CLASSES];
+
+ /* type/class stats by power-2-sized referenced blocks */
ddt_histogram_t ddt_histogram[DDT_TYPES][DDT_CLASSES];
ddt_histogram_t ddt_histogram_cache[DDT_TYPES][DDT_CLASSES];
- ddt_object_t ddt_object_stats[DDT_TYPES][DDT_CLASSES];
- avl_node_t ddt_node;
-};
+} ddt_t;
/*
- * In-core and on-disk bookmark for DDT walks
+ * In-core and on-disk bookmark for DDT walks. This is a cursor for ddt_walk(),
+ * and is stable across calls, even if the DDT is updated, the pool is
+ * restarted or loaded on another system, or OpenZFS is upgraded.
*/
-typedef struct ddt_bookmark {
+typedef struct {
uint64_t ddb_class;
uint64_t ddb_type;
uint64_t ddb_checksum;
uint64_t ddb_cursor;
} ddt_bookmark_t;
-/*
- * Ops vector to access a specific DDT object type.
- */
-typedef struct ddt_ops {
- char ddt_op_name[32];
- int (*ddt_op_create)(objset_t *os, uint64_t *object, dmu_tx_t *tx,
- boolean_t prehash);
- int (*ddt_op_destroy)(objset_t *os, uint64_t object, dmu_tx_t *tx);
- int (*ddt_op_lookup)(objset_t *os, uint64_t object, ddt_entry_t *dde);
- void (*ddt_op_prefetch)(objset_t *os, uint64_t object,
- ddt_entry_t *dde);
- int (*ddt_op_update)(objset_t *os, uint64_t object, ddt_entry_t *dde,
- dmu_tx_t *tx);
- int (*ddt_op_remove)(objset_t *os, uint64_t object, ddt_entry_t *dde,
- dmu_tx_t *tx);
- int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde,
- uint64_t *walk);
- int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
-} ddt_ops_t;
-
-#define DDT_NAMELEN 107
-
-extern void ddt_object_name(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz, char *name);
-extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz, uint64_t *walk, ddt_entry_t *dde);
-extern int ddt_object_count(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz, uint64_t *count);
-extern int ddt_object_info(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz, dmu_object_info_t *);
-extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz);
-
extern void ddt_bp_fill(const ddt_phys_t *ddp, blkptr_t *bp,
uint64_t txg);
extern void ddt_bp_create(enum zio_checksum checksum, const ddt_key_t *ddk,
const ddt_phys_t *ddp, blkptr_t *bp);
-extern void ddt_key_fill(ddt_key_t *ddk, const blkptr_t *bp);
-
extern void ddt_phys_fill(ddt_phys_t *ddp, const blkptr_t *bp);
extern void ddt_phys_clear(ddt_phys_t *ddp);
extern void ddt_phys_addref(ddt_phys_t *ddp);
extern void ddt_phys_decref(ddt_phys_t *ddp);
-extern void ddt_phys_free(ddt_t *ddt, ddt_key_t *ddk, ddt_phys_t *ddp,
- uint64_t txg);
extern ddt_phys_t *ddt_phys_select(const ddt_entry_t *dde, const blkptr_t *bp);
-extern uint64_t ddt_phys_total_refcnt(const ddt_entry_t *dde);
-
-extern void ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src, uint64_t neg);
extern void ddt_histogram_add(ddt_histogram_t *dst, const ddt_histogram_t *src);
extern void ddt_histogram_stat(ddt_stat_t *dds, const ddt_histogram_t *ddh);
@@ -220,9 +234,6 @@ extern void ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total);
extern uint64_t ddt_get_dedup_dspace(spa_t *spa);
extern uint64_t ddt_get_pool_dedup_ratio(spa_t *spa);
-extern size_t ddt_compress(void *src, uchar_t *dst, size_t s_len, size_t d_len);
-extern void ddt_decompress(uchar_t *src, void *dst, size_t s_len, size_t d_len);
-
extern ddt_t *ddt_select(spa_t *spa, const blkptr_t *bp);
extern void ddt_enter(ddt_t *ddt);
extern void ddt_exit(ddt_t *ddt);
@@ -232,23 +243,21 @@ extern ddt_entry_t *ddt_lookup(ddt_t *ddt, const blkptr_t *bp, boolean_t add);
extern void ddt_prefetch(spa_t *spa, const blkptr_t *bp);
extern void ddt_remove(ddt_t *ddt, ddt_entry_t *dde);
-extern boolean_t ddt_class_contains(spa_t *spa, enum ddt_class max_class,
+extern boolean_t ddt_class_contains(spa_t *spa, ddt_class_t max_class,
const blkptr_t *bp);
extern ddt_entry_t *ddt_repair_start(ddt_t *ddt, const blkptr_t *bp);
extern void ddt_repair_done(ddt_t *ddt, ddt_entry_t *dde);
-extern int ddt_entry_compare(const void *x1, const void *x2);
+extern int ddt_key_compare(const void *x1, const void *x2);
extern void ddt_create(spa_t *spa);
extern int ddt_load(spa_t *spa);
extern void ddt_unload(spa_t *spa);
extern void ddt_sync(spa_t *spa, uint64_t txg);
extern int ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde);
-extern int ddt_object_update(ddt_t *ddt, enum ddt_type type,
- enum ddt_class clazz, ddt_entry_t *dde, dmu_tx_t *tx);
-extern const ddt_ops_t ddt_zap_ops;
+extern boolean_t ddt_addref(spa_t *spa, const blkptr_t *bp);
#ifdef __cplusplus
}
diff --git a/include/sys/ddt_impl.h b/include/sys/ddt_impl.h
new file mode 100644
index 000000000000..52b927b7519d
--- /dev/null
+++ b/include/sys/ddt_impl.h
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2023, Klara Inc.
+ */
+
+#ifndef _SYS_DDT_IMPL_H
+#define _SYS_DDT_IMPL_H
+
+#include <sys/ddt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Ops vector to access a specific DDT object type.
+ */
+typedef struct {
+ char ddt_op_name[32];
+ int (*ddt_op_create)(objset_t *os, uint64_t *object, dmu_tx_t *tx,
+ boolean_t prehash);
+ int (*ddt_op_destroy)(objset_t *os, uint64_t object, dmu_tx_t *tx);
+ int (*ddt_op_lookup)(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk, ddt_phys_t *phys, size_t psize);
+ int (*ddt_op_contains)(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk);
+ void (*ddt_op_prefetch)(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk);
+ int (*ddt_op_update)(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk, const ddt_phys_t *phys, size_t psize,
+ dmu_tx_t *tx);
+ int (*ddt_op_remove)(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk, dmu_tx_t *tx);
+ int (*ddt_op_walk)(objset_t *os, uint64_t object, uint64_t *walk,
+ ddt_key_t *ddk, ddt_phys_t *phys, size_t psize);
+ int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
+} ddt_ops_t;
+
+extern const ddt_ops_t ddt_zap_ops;
+
+extern void ddt_stat_update(ddt_t *ddt, ddt_entry_t *dde, uint64_t neg);
+
+/*
+ * These are only exposed so that zdb can access them. Try not to use them
+ * outside of the DDT implementation proper, and if you do, consider moving
+ * them up.
+ */
+
+/*
+ * Enough room to expand DMU_POOL_DDT format for all possible DDT
+ * checksum/class/type combinations.
+ */
+#define DDT_NAMELEN 32
+
+extern uint64_t ddt_phys_total_refcnt(const ddt_entry_t *dde);
+
+extern void ddt_key_fill(ddt_key_t *ddk, const blkptr_t *bp);
+
+extern void ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src, uint64_t neg);
+
+extern void ddt_object_name(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
+ char *name);
+extern int ddt_object_walk(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
+ uint64_t *walk, ddt_entry_t *dde);
+extern int ddt_object_count(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
+ uint64_t *count);
+extern int ddt_object_info(ddt_t *ddt, ddt_type_t type, ddt_class_t clazz,
+ dmu_object_info_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_DDT_H */
diff --git a/include/sys/dmu.h b/include/sys/dmu.h
index 7c55a5c26189..b5fed64da4ad 100644
--- a/include/sys/dmu.h
+++ b/include/sys/dmu.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -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 */
@@ -136,18 +137,24 @@ typedef enum dmu_object_byteswap {
#endif
#define DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
- ((ot) & DMU_OT_METADATA) : \
+ (((ot) & DMU_OT_METADATA) != 0) : \
DMU_OT_IS_METADATA_IMPL(ot))
#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)
#define DMU_OT_IS_ENCRYPTED(ot) (((ot) & DMU_OT_NEWTYPE) ? \
- ((ot) & DMU_OT_ENCRYPTED) : \
+ (((ot) & DMU_OT_ENCRYPTED) != 0) : \
DMU_OT_IS_ENCRYPTED_IMPL(ot))
/*
@@ -371,6 +378,7 @@ typedef struct dmu_buf {
#define DMU_POOL_DDT_STATS "DDT-statistics"
#define DMU_POOL_CREATION_VERSION "creation_version"
#define DMU_POOL_SCAN "scan"
+#define DMU_POOL_ERRORSCRUB "error_scrub"
#define DMU_POOL_FREE_BPOBJ "free_bpobj"
#define DMU_POOL_BPTREE_OBJ "bptree_obj"
#define DMU_POOL_EMPTY_BPOBJ "empty_bpobj"
@@ -564,11 +572,15 @@ int dmu_buf_hold(objset_t *os, uint64_t object, uint64_t offset,
int dmu_buf_hold_array(objset_t *os, uint64_t object, uint64_t offset,
uint64_t length, int read, const void *tag, int *numbufsp,
dmu_buf_t ***dbpp);
+int dmu_buf_hold_noread(objset_t *os, uint64_t object, uint64_t offset,
+ const void *tag, dmu_buf_t **dbp);
int dmu_buf_hold_by_dnode(dnode_t *dn, uint64_t offset,
const void *tag, dmu_buf_t **dbp, int flags);
int dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset,
uint64_t length, boolean_t read, const void *tag, int *numbufsp,
dmu_buf_t ***dbpp, uint32_t flags);
+int dmu_buf_hold_noread_by_dnode(dnode_t *dn, uint64_t offset, const void *tag,
+ dmu_buf_t **dbp);
/*
* Add a reference to a dmu buffer that has already been held via
* dmu_buf_hold() in the current context.
@@ -640,6 +652,9 @@ typedef struct dmu_buf_user {
*/
taskq_ent_t dbu_tqent;
+ /* Size of user data, for inclusion in dbuf_cache accounting. */
+ uint64_t dbu_size;
+
/*
* This instance's eviction function pointers.
*
@@ -722,13 +737,21 @@ void *dmu_buf_replace_user(dmu_buf_t *db,
void *dmu_buf_remove_user(dmu_buf_t *db, dmu_buf_user_t *user);
/*
+ * User data size accounting. This can be used to artifically inflate the size
+ * of the dbuf during cache accounting, so that dbuf_evict_thread evicts enough
+ * to satisfy memory reclaim requests. It's not used for anything else, and
+ * defaults to 0.
+ */
+uint64_t dmu_buf_user_size(dmu_buf_t *db);
+void dmu_buf_add_user_size(dmu_buf_t *db, uint64_t nadd);
+void dmu_buf_sub_user_size(dmu_buf_t *db, uint64_t nsub);
+
+/*
* Returns the user data (dmu_buf_user_t *) associated with this dbuf.
*/
void *dmu_buf_get_user(dmu_buf_t *db);
objset_t *dmu_buf_get_objset(dmu_buf_t *db);
-dnode_t *dmu_buf_dnode_enter(dmu_buf_t *db);
-void dmu_buf_dnode_exit(dmu_buf_t *db);
/* Block until any in-progress dmu buf user evictions complete. */
void dmu_buf_user_evict_wait(void);
@@ -775,6 +798,11 @@ dmu_tx_t *dmu_tx_create(objset_t *os);
void dmu_tx_hold_write(dmu_tx_t *tx, uint64_t object, uint64_t off, int len);
void dmu_tx_hold_write_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
int len);
+void dmu_tx_hold_append(dmu_tx_t *tx, uint64_t object, uint64_t off, int len);
+void dmu_tx_hold_append_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
+ int len);
+void dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
+ int len);
void dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off,
uint64_t len);
void dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
@@ -865,13 +893,16 @@ int dmu_assign_arcbuf_by_dnode(dnode_t *dn, uint64_t offset,
int dmu_assign_arcbuf_by_dbuf(dmu_buf_t *handle, uint64_t offset,
struct arc_buf *buf, dmu_tx_t *tx);
#define dmu_assign_arcbuf dmu_assign_arcbuf_by_dbuf
-extern int zfs_max_recordsize;
+extern uint_t zfs_max_recordsize;
/*
* Asynchronously try to read in the data.
*/
void dmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
uint64_t len, enum zio_priority pri);
+void dmu_prefetch_by_dnode(dnode_t *dn, int64_t level, uint64_t offset,
+ uint64_t len, enum zio_priority pri);
+void dmu_prefetch_dnode(objset_t *os, uint64_t object, enum zio_priority pri);
typedef struct dmu_object_info {
/* All sizes are in bytes unless otherwise indicated. */
@@ -907,7 +938,7 @@ typedef const struct dmu_object_byteswap_info {
} dmu_object_byteswap_info_t;
extern const dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES];
-extern const dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS];
+extern dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS];
/*
* Get information on a DMU object.
@@ -1052,6 +1083,11 @@ int dmu_sync(struct zio *zio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd);
int dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole,
uint64_t *off);
+int dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset,
+ uint64_t length, struct blkptr *bps, size_t *nbpsp);
+int dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset,
+ uint64_t length, dmu_tx_t *tx, const struct blkptr *bps, size_t nbps);
+
/*
* Initial setup and final teardown.
*/
@@ -1070,7 +1106,7 @@ int dmu_diff(const char *tosnap_name, const char *fromsnap_name,
#define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */
extern uint64_t zfs_crc64_table[256];
-extern int dmu_prefetch_max;
+extern uint_t dmu_prefetch_max;
#ifdef __cplusplus
}
diff --git a/include/sys/dmu_impl.h b/include/sys/dmu_impl.h
index 95ec11ce2400..83ae2b76ba1f 100644
--- a/include/sys/dmu_impl.h
+++ b/include/sys/dmu_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -247,8 +247,6 @@ typedef struct dmu_sendstatus {
void dmu_object_zapify(objset_t *, uint64_t, dmu_object_type_t, dmu_tx_t *);
void dmu_object_free_zapified(objset_t *, uint64_t, dmu_tx_t *);
-int dmu_buf_hold_noread(objset_t *, uint64_t, uint64_t,
- const void *, dmu_buf_t **);
#ifdef __cplusplus
}
diff --git a/include/sys/dmu_objset.h b/include/sys/dmu_objset.h
index 782338fd210a..a9123e862af7 100644
--- a/include/sys/dmu_objset.h
+++ b/include/sys/dmu_objset.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -72,6 +72,10 @@ struct dmu_tx;
*/
#define OBJSET_CRYPT_PORTABLE_FLAGS_MASK (0)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
+#endif
typedef struct objset_phys {
dnode_phys_t os_meta_dnode;
zil_header_t os_zil_header;
@@ -88,6 +92,9 @@ typedef struct objset_phys {
char os_pad1[OBJSET_PHYS_SIZE_V3 - OBJSET_PHYS_SIZE_V2 -
sizeof (dnode_phys_t)];
} objset_phys_t;
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
typedef int (*dmu_objset_upgrade_cb_t)(objset_t *);
@@ -125,6 +132,7 @@ struct objset {
zfs_logbias_op_t os_logbias;
zfs_cache_type_t os_primary_cache;
zfs_cache_type_t os_secondary_cache;
+ zfs_prefetch_type_t os_prefetch;
zfs_sync_type_t os_sync;
zfs_redundant_metadata_type_t os_redundant_metadata;
uint64_t os_recordsize;
diff --git a/include/sys/dmu_recv.h b/include/sys/dmu_recv.h
index 1fdb986e2ed6..3390ca1089f8 100644
--- a/include/sys/dmu_recv.h
+++ b/include/sys/dmu_recv.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,6 +24,7 @@
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2019 Datto Inc.
*/
#ifndef _DMU_RECV_H
@@ -47,6 +48,7 @@ typedef struct dmu_recv_cookie {
boolean_t drc_byteswap;
uint64_t drc_featureflags;
boolean_t drc_force;
+ boolean_t drc_heal;
boolean_t drc_resumable;
boolean_t drc_should_save;
boolean_t drc_raw;
@@ -77,8 +79,8 @@ typedef struct dmu_recv_cookie {
objlist_t *drc_ignore_objlist;
} dmu_recv_cookie_t;
-int dmu_recv_begin(char *, char *, dmu_replay_record_t *,
- boolean_t, boolean_t, nvlist_t *, nvlist_t *, char *,
+int dmu_recv_begin(const char *, const char *, dmu_replay_record_t *,
+ boolean_t, boolean_t, boolean_t, nvlist_t *, nvlist_t *, const char *,
dmu_recv_cookie_t *, zfs_file_t *, offset_t *);
int dmu_recv_stream(dmu_recv_cookie_t *, offset_t *);
int dmu_recv_end(dmu_recv_cookie_t *, void *);
diff --git a/include/sys/dmu_redact.h b/include/sys/dmu_redact.h
index 85f4b0522891..c18e2be103b7 100644
--- a/include/sys/dmu_redact.h
+++ b/include/sys/dmu_redact.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dmu_send.h b/include/sys/dmu_send.h
index d150f816c945..061b81532fb1 100644
--- a/include/sys/dmu_send.h
+++ b/include/sys/dmu_send.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dmu_traverse.h b/include/sys/dmu_traverse.h
index d76bfe3c9af3..7a0b38da7302 100644
--- a/include/sys/dmu_traverse.h
+++ b/include/sys/dmu_traverse.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dmu_tx.h b/include/sys/dmu_tx.h
index ad3f1b0e47ca..aa55da626149 100644
--- a/include/sys/dmu_tx.h
+++ b/include/sys/dmu_tx.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -90,6 +90,8 @@ enum dmu_tx_hold_type {
THT_ZAP,
THT_SPACE,
THT_SPILL,
+ THT_CLONE,
+ THT_APPEND,
THT_NUMTYPES
};
diff --git a/include/sys/dmu_zfetch.h b/include/sys/dmu_zfetch.h
index cd1b79eb8e44..322472fb1ae2 100644
--- a/include/sys/dmu_zfetch.h
+++ b/include/sys/dmu_zfetch.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -36,8 +36,6 @@
extern "C" {
#endif
-extern unsigned long zfetch_array_rd_sz;
-
struct dnode; /* so we can reference dnode */
typedef struct zfetch {
@@ -47,18 +45,24 @@ typedef struct zfetch {
int zf_numstreams; /* number of zstream_t's */
} zfetch_t;
+typedef struct zsrange {
+ uint16_t start;
+ uint16_t end;
+} zsrange_t;
+
+#define ZFETCH_RANGES 9 /* Fits zstream_t into 128 bytes */
+
typedef struct zstream {
+ list_node_t zs_node; /* link for zf_stream */
uint64_t zs_blkid; /* expect next access at this blkid */
+ uint_t zs_atime; /* time last prefetch issued */
+ zsrange_t zs_ranges[ZFETCH_RANGES]; /* ranges from future */
unsigned int zs_pf_dist; /* data prefetch distance in bytes */
unsigned int zs_ipf_dist; /* L1 prefetch distance in bytes */
uint64_t zs_pf_start; /* first data block to prefetch */
uint64_t zs_pf_end; /* data block to prefetch up to */
uint64_t zs_ipf_start; /* first data block to prefetch L1 */
uint64_t zs_ipf_end; /* data block to prefetch L1 up to */
-
- list_node_t zs_node; /* link for zf_stream */
- hrtime_t zs_atime; /* time last prefetch issued */
- zfetch_t *zs_fetch; /* parent fetch */
boolean_t zs_missed; /* stream saw cache misses */
boolean_t zs_more; /* need more distant prefetch */
zfs_refcount_t zs_callers; /* number of pending callers */
@@ -76,7 +80,7 @@ void dmu_zfetch_init(zfetch_t *, struct dnode *);
void dmu_zfetch_fini(zfetch_t *);
zstream_t *dmu_zfetch_prepare(zfetch_t *, uint64_t, uint64_t, boolean_t,
boolean_t);
-void dmu_zfetch_run(zstream_t *, boolean_t, boolean_t);
+void dmu_zfetch_run(zfetch_t *, zstream_t *, boolean_t, boolean_t);
void dmu_zfetch(zfetch_t *, uint64_t, uint64_t, boolean_t, boolean_t,
boolean_t);
diff --git a/include/sys/dnode.h b/include/sys/dnode.h
index 9745ae5bb651..dbe7350d4da7 100644
--- a/include/sys/dnode.h
+++ b/include/sys/dnode.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -36,6 +36,7 @@
#include <sys/dmu_zfetch.h>
#include <sys/zrlock.h>
#include <sys/multilist.h>
+#include <sys/wmsum.h>
#ifdef __cplusplus
extern "C" {
@@ -119,7 +120,11 @@ extern "C" {
#define DN_MAX_LEVELS (DIV_ROUND_UP(DN_MAX_OFFSET_SHIFT - SPA_MINBLOCKSHIFT, \
DN_MIN_INDBLKSHIFT - SPA_BLKPTRSHIFT) + 1)
-#define DN_BONUS(dnp) ((void*)((dnp)->dn_bonus + \
+/*
+ * Use the flexible array instead of the fixed length one dn_bonus
+ * to address memcpy/memmove fortify error
+ */
+#define DN_BONUS(dnp) ((void*)((dnp)->dn_bonus_flexible + \
(((dnp)->dn_nblkptr - 1) * sizeof (blkptr_t))))
#define DN_MAX_BONUS_LEN(dnp) \
((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) ? \
@@ -265,6 +270,10 @@ typedef struct dnode_phys {
sizeof (blkptr_t)];
blkptr_t dn_spill;
};
+ struct {
+ blkptr_t __dn_ignore4;
+ uint8_t dn_bonus_flexible[];
+ };
};
} dnode_phys_t;
@@ -456,15 +465,11 @@ void dnode_free_interior_slots(dnode_t *dn);
#define DNODE_IS_DIRTY(_dn) \
((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa))
-#define DNODE_IS_CACHEABLE(_dn) \
+#define DNODE_LEVEL_IS_CACHEABLE(_dn, _level) \
((_dn)->dn_objset->os_primary_cache == ZFS_CACHE_ALL || \
- (DMU_OT_IS_METADATA((_dn)->dn_type) && \
+ (((_level) > 0 || DMU_OT_IS_METADATA((_dn)->dn_type)) && \
(_dn)->dn_objset->os_primary_cache == ZFS_CACHE_METADATA))
-#define DNODE_META_IS_CACHEABLE(_dn) \
- ((_dn)->dn_objset->os_primary_cache == ZFS_CACHE_ALL || \
- (_dn)->dn_objset->os_primary_cache == ZFS_CACHE_METADATA)
-
/*
* Used for dnodestats kstat.
*/
@@ -587,10 +592,42 @@ typedef struct dnode_stats {
kstat_named_t dnode_move_active;
} dnode_stats_t;
+typedef struct dnode_sums {
+ wmsum_t dnode_hold_dbuf_hold;
+ wmsum_t dnode_hold_dbuf_read;
+ wmsum_t dnode_hold_alloc_hits;
+ wmsum_t dnode_hold_alloc_misses;
+ wmsum_t dnode_hold_alloc_interior;
+ wmsum_t dnode_hold_alloc_lock_retry;
+ wmsum_t dnode_hold_alloc_lock_misses;
+ wmsum_t dnode_hold_alloc_type_none;
+ wmsum_t dnode_hold_free_hits;
+ wmsum_t dnode_hold_free_misses;
+ wmsum_t dnode_hold_free_lock_misses;
+ wmsum_t dnode_hold_free_lock_retry;
+ wmsum_t dnode_hold_free_refcount;
+ wmsum_t dnode_hold_free_overflow;
+ wmsum_t dnode_free_interior_lock_retry;
+ wmsum_t dnode_allocate;
+ wmsum_t dnode_reallocate;
+ wmsum_t dnode_buf_evict;
+ wmsum_t dnode_alloc_next_chunk;
+ wmsum_t dnode_alloc_race;
+ wmsum_t dnode_alloc_next_block;
+ wmsum_t dnode_move_invalid;
+ wmsum_t dnode_move_recheck1;
+ wmsum_t dnode_move_recheck2;
+ wmsum_t dnode_move_special;
+ wmsum_t dnode_move_handle;
+ wmsum_t dnode_move_rwlock;
+ wmsum_t dnode_move_active;
+} dnode_sums_t;
+
extern dnode_stats_t dnode_stats;
+extern dnode_sums_t dnode_sums;
#define DNODE_STAT_INCR(stat, val) \
- atomic_add_64(&dnode_stats.stat.value.ui64, (val));
+ wmsum_add(&dnode_sums.stat, (val))
#define DNODE_STAT_BUMP(stat) \
DNODE_STAT_INCR(stat, 1);
diff --git a/include/sys/dsl_bookmark.h b/include/sys/dsl_bookmark.h
index 353c5c2d260f..d4e559a09037 100644
--- a/include/sys/dsl_bookmark.h
+++ b/include/sys/dsl_bookmark.h
@@ -72,6 +72,7 @@ typedef struct redaction_list_phys {
typedef struct redaction_list {
dmu_buf_user_t rl_dbu;
redaction_list_phys_t *rl_phys;
+ dmu_buf_t *rl_bonus;
dmu_buf_t *rl_dbuf;
uint64_t rl_object;
zfs_refcount_t rl_longholds;
diff --git a/include/sys/dsl_crypt.h b/include/sys/dsl_crypt.h
index db594eece1c3..fbcae3715355 100644
--- a/include/sys/dsl_crypt.h
+++ b/include/sys/dsl_crypt.h
@@ -206,6 +206,7 @@ void dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
dmu_tx_t *tx);
int dmu_objset_create_crypt_check(dsl_dir_t *parentdd,
dsl_crypto_params_t *dcp, boolean_t *will_encrypt);
+boolean_t dmu_objset_crypto_key_equal(objset_t *osa, objset_t *osb);
void dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd,
struct dsl_dataset *origin, dsl_crypto_params_t *dcp, dmu_tx_t *tx);
uint64_t dsl_crypto_key_create_sync(uint64_t crypt, dsl_wrapping_key_t *wkey,
@@ -222,5 +223,6 @@ int spa_do_crypt_abd(boolean_t encrypt, spa_t *spa, const zbookmark_phys_t *zb,
dmu_object_type_t ot, boolean_t dedup, boolean_t bswap, uint8_t *salt,
uint8_t *iv, uint8_t *mac, uint_t datalen, abd_t *pabd, abd_t *cabd,
boolean_t *no_crypt);
+zfs_keystatus_t dsl_dataset_get_keystatus(dsl_dir_t *dd);
#endif
diff --git a/include/sys/dsl_dataset.h b/include/sys/dsl_dataset.h
index 25f86bce2e63..3450527af7e0 100644
--- a/include/sys/dsl_dataset.h
+++ b/include/sys/dsl_dataset.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -301,6 +301,14 @@ typedef struct dsl_dataset_snapshot_arg {
proc_t *ddsa_proc;
} dsl_dataset_snapshot_arg_t;
+typedef struct dsl_dataset_rename_snapshot_arg {
+ const char *ddrsa_fsname;
+ const char *ddrsa_oldsnapname;
+ const char *ddrsa_newsnapname;
+ boolean_t ddrsa_recursive;
+ dmu_tx_t *ddrsa_tx;
+} dsl_dataset_rename_snapshot_arg_t;
+
/*
* The max length of a temporary tag prefix is the number of hex digits
* required to express UINT64_MAX plus one for the hyphen.
@@ -375,7 +383,6 @@ boolean_t dsl_dataset_modified_since_snap(dsl_dataset_t *ds,
void dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx);
void dsl_dataset_sync_done(dsl_dataset_t *ds, dmu_tx_t *tx);
-void dsl_dataset_feature_set_activation(const blkptr_t *bp, dsl_dataset_t *ds);
void dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp,
dmu_tx_t *tx);
int dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp,
@@ -474,6 +481,9 @@ void dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner,
nvlist_t *result);
+int dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx);
+void dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx);
+
uint64_t dsl_dataset_get_remap_deadlist_object(dsl_dataset_t *ds);
void dsl_dataset_create_remap_deadlist(dsl_dataset_t *ds, dmu_tx_t *tx);
boolean_t dsl_dataset_remap_deadlist_exists(dsl_dataset_t *ds);
diff --git a/include/sys/dsl_deadlist.h b/include/sys/dsl_deadlist.h
index 64358bb5fc0b..3feb3bbf062f 100644
--- a/include/sys/dsl_deadlist.h
+++ b/include/sys/dsl_deadlist.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -84,7 +84,7 @@ typedef struct livelist_condense_entry {
boolean_t cancelled;
} livelist_condense_entry_t;
-extern unsigned long zfs_livelist_max_entries;
+extern uint64_t zfs_livelist_max_entries;
extern int zfs_livelist_min_percent_shared;
typedef int deadlist_iter_t(void *args, dsl_deadlist_entry_t *dle);
diff --git a/include/sys/dsl_deleg.h b/include/sys/dsl_deleg.h
index 7f46233a889b..d6abac90bbcc 100644
--- a/include/sys/dsl_deleg.h
+++ b/include/sys/dsl_deleg.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dsl_destroy.h b/include/sys/dsl_destroy.h
index 208d75bacffa..1a9b672a260b 100644
--- a/include/sys/dsl_destroy.h
+++ b/include/sys/dsl_destroy.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dsl_dir.h b/include/sys/dsl_dir.h
index 6c097e372e44..f7c0d9acd10d 100644
--- a/include/sys/dsl_dir.h
+++ b/include/sys/dsl_dir.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -52,6 +52,7 @@ struct zthr;
#define DD_FIELD_SNAPSHOT_COUNT "com.joyent:snapshot_count"
#define DD_FIELD_CRYPTO_KEY_OBJ "com.datto:crypto_key_obj"
#define DD_FIELD_LIVELIST "com.delphix:livelist"
+#define DD_FIELD_SNAPSHOTS_CHANGED "com.ixsystems:snapshots_changed"
typedef enum dd_used {
DD_USED_HEAD,
@@ -115,7 +116,7 @@ struct dsl_dir {
/* gross estimate of space used by in-flight tx's */
uint64_t dd_tempreserved[TXG_SIZE];
/* amount of space we expect to write; == amount of dirty data */
- int64_t dd_space_towrite[TXG_SIZE];
+ uint64_t dd_space_towrite[TXG_SIZE];
dsl_deadlist_t dd_livelist;
bplist_t dd_pending_frees;
@@ -191,7 +192,7 @@ int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
void dsl_dir_new_refreservation(dsl_dir_t *dd, struct dsl_dataset *ds,
uint64_t reservation, cred_t *cr, dmu_tx_t *tx);
-void dsl_dir_snap_cmtime_update(dsl_dir_t *dd);
+void dsl_dir_snap_cmtime_update(dsl_dir_t *dd, dmu_tx_t *tx);
inode_timespec_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value,
dmu_tx_t *tx);
diff --git a/include/sys/dsl_pool.h b/include/sys/dsl_pool.h
index 5bb5ef20d5b1..abcdc77a4b96 100644
--- a/include/sys/dsl_pool.h
+++ b/include/sys/dsl_pool.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -57,13 +57,13 @@ struct dsl_scan;
struct dsl_crypto_params;
struct dsl_deadlist;
-extern unsigned long zfs_dirty_data_max;
-extern unsigned long zfs_dirty_data_max_max;
-extern unsigned long zfs_wrlog_data_max;
-extern int zfs_dirty_data_max_percent;
-extern int zfs_dirty_data_max_max_percent;
-extern int zfs_delay_min_dirty_percent;
-extern unsigned long zfs_delay_scale;
+extern uint64_t zfs_dirty_data_max;
+extern uint64_t zfs_dirty_data_max_max;
+extern uint64_t zfs_wrlog_data_max;
+extern uint_t zfs_dirty_data_max_percent;
+extern uint_t zfs_dirty_data_max_max_percent;
+extern uint_t zfs_delay_min_dirty_percent;
+extern uint64_t zfs_delay_scale;
/* These macros are for indexing into the zfs_all_blkstats_t. */
#define DMU_OT_DEFERRED DMU_OT_NONE
diff --git a/include/sys/dsl_prop.h b/include/sys/dsl_prop.h
index fba8f908dc9e..7a84f2b6922a 100644
--- a/include/sys/dsl_prop.h
+++ b/include/sys/dsl_prop.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dsl_scan.h b/include/sys/dsl_scan.h
index d716510f879d..2e3452e5ebaa 100644
--- a/include/sys/dsl_scan.h
+++ b/include/sys/dsl_scan.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -29,6 +29,7 @@
#include <sys/zfs_context.h>
#include <sys/zio.h>
+#include <sys/zap.h>
#include <sys/ddt.h>
#include <sys/bplist.h>
@@ -60,7 +61,7 @@ typedef struct dsl_scan_phys {
uint64_t scn_end_time;
uint64_t scn_to_examine; /* total bytes to be scanned */
uint64_t scn_examined; /* bytes scanned so far */
- uint64_t scn_to_process;
+ uint64_t scn_skipped; /* bytes skipped by scanner */
uint64_t scn_processed;
uint64_t scn_errors; /* scan I/O error count */
uint64_t scn_ddt_class_max;
@@ -78,6 +79,21 @@ typedef enum dsl_scan_flags {
#define DSL_SCAN_FLAGS_MASK (DSF_VISIT_DS_AGAIN)
+typedef struct dsl_errorscrub_phys {
+ uint64_t dep_func; /* pool_scan_func_t */
+ uint64_t dep_state; /* dsl_scan_state_t */
+ uint64_t dep_cursor; /* serialized zap cursor for tracing progress */
+ uint64_t dep_start_time; /* error scrub start time, unix timestamp */
+ uint64_t dep_end_time; /* error scrub end time, unix timestamp */
+ uint64_t dep_to_examine; /* total error blocks to be scrubbed */
+ uint64_t dep_examined; /* blocks scrubbed so far */
+ uint64_t dep_errors; /* error scrub I/O error count */
+ uint64_t dep_paused_flags; /* flag for paused */
+} dsl_errorscrub_phys_t;
+
+#define ERRORSCRUB_PHYS_NUMINTS (sizeof (dsl_errorscrub_phys_t) \
+ / sizeof (uint64_t))
+
/*
* Every pool will have one dsl_scan_t and this structure will contain
* in-memory information about the scan and a pointer to the on-disk
@@ -151,11 +167,15 @@ typedef struct dsl_scan {
uint64_t scn_avg_zio_size_this_txg;
uint64_t scn_zios_this_txg;
+ /* zap cursor for tracing error scrub progress */
+ zap_cursor_t errorscrub_cursor;
/* members needed for syncing scan status to disk */
dsl_scan_phys_t scn_phys; /* on disk representation of scan */
dsl_scan_phys_t scn_phys_cached;
avl_tree_t scn_queue; /* queue of datasets to scan */
uint64_t scn_queues_pending; /* outstanding data to issue */
+ /* members needed for syncing error scrub status to disk */
+ dsl_errorscrub_phys_t errorscrub_phys;
} dsl_scan_t;
typedef struct dsl_scan_io_queue dsl_scan_io_queue_t;
@@ -171,8 +191,12 @@ int dsl_scan_cancel(struct dsl_pool *);
int dsl_scan(struct dsl_pool *, pool_scan_func_t);
void dsl_scan_assess_vdev(struct dsl_pool *dp, vdev_t *vd);
boolean_t dsl_scan_scrubbing(const struct dsl_pool *dp);
-int dsl_scrub_set_pause_resume(const struct dsl_pool *dp, pool_scrub_cmd_t cmd);
+boolean_t dsl_errorscrubbing(const struct dsl_pool *dp);
+boolean_t dsl_errorscrub_active(dsl_scan_t *scn);
void dsl_scan_restart_resilver(struct dsl_pool *, uint64_t txg);
+int dsl_scrub_set_pause_resume(const struct dsl_pool *dp,
+ pool_scrub_cmd_t cmd);
+void dsl_errorscrub_sync(struct dsl_pool *, dmu_tx_t *);
boolean_t dsl_scan_resilvering(struct dsl_pool *dp);
boolean_t dsl_scan_resilver_scheduled(struct dsl_pool *dp);
boolean_t dsl_dataset_unstable(struct dsl_dataset *ds);
@@ -184,6 +208,7 @@ void dsl_scan_ds_clone_swapped(struct dsl_dataset *ds1, struct dsl_dataset *ds2,
struct dmu_tx *tx);
boolean_t dsl_scan_active(dsl_scan_t *scn);
boolean_t dsl_scan_is_paused_scrub(const dsl_scan_t *scn);
+boolean_t dsl_errorscrub_is_paused(const dsl_scan_t *scn);
void dsl_scan_freed(spa_t *spa, const blkptr_t *bp);
void dsl_scan_io_queue_destroy(dsl_scan_io_queue_t *queue);
void dsl_scan_io_queue_vdev_xfer(vdev_t *svd, vdev_t *tvd);
diff --git a/include/sys/dsl_synctask.h b/include/sys/dsl_synctask.h
index 5a5b306419f1..cbdb20ec1d3a 100644
--- a/include/sys/dsl_synctask.h
+++ b/include/sys/dsl_synctask.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/dsl_userhold.h b/include/sys/dsl_userhold.h
index 071aeb86d1f1..c165edab3c53 100644
--- a/include/sys/dsl_userhold.h
+++ b/include/sys/dsl_userhold.h
@@ -7,7 +7,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/edonr.h b/include/sys/edonr.h
index 79b7cd8c75b8..b19b5eb42c29 100644
--- a/include/sys/edonr.h
+++ b/include/sys/edonr.h
@@ -1,6 +1,4 @@
/*
- * IDI,NTNU
- *
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
@@ -19,15 +17,13 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- *
- * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no>
- *
- * Tweaked Edon-R implementation for SUPERCOP, based on NIST API.
- *
- * $Id: edonr.h 517 2013-02-17 20:34:39Z joern $
*/
+
/*
- * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved
+ * Based on Edon-R implementation for SUPERCOP, based on NIST API.
+ * Copyright (c) 2009, 2010 Jørn Amundsen <jorn.amundsen@ntnu.no>
+ * Copyright (c) 2013 Saso Kiselkov, All rights reserved
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
#ifndef _SYS_EDONR_H_
@@ -40,8 +36,8 @@ extern "C" {
#ifdef _KERNEL
#include <sys/types.h>
#else
-#include <stdint.h> /* uint32_t... */
-#include <stdlib.h> /* size_t ... */
+#include <stdint.h>
+#include <stdlib.h>
#endif
/*
@@ -52,44 +48,27 @@ extern "C" {
*/
/* Specific algorithm definitions */
-#define EdonR224_DIGEST_SIZE 28
-#define EdonR224_BLOCK_SIZE 64
-#define EdonR256_DIGEST_SIZE 32
-#define EdonR256_BLOCK_SIZE 64
-#define EdonR384_DIGEST_SIZE 48
-#define EdonR384_BLOCK_SIZE 128
#define EdonR512_DIGEST_SIZE 64
#define EdonR512_BLOCK_SIZE 128
-
-#define EdonR256_BLOCK_BITSIZE 512
#define EdonR512_BLOCK_BITSIZE 1024
typedef struct {
- uint32_t DoublePipe[16];
- uint8_t LastPart[EdonR256_BLOCK_SIZE * 2];
-} EdonRData256;
-typedef struct {
uint64_t DoublePipe[16];
uint8_t LastPart[EdonR512_BLOCK_SIZE * 2];
} EdonRData512;
typedef struct {
- size_t hashbitlen;
-
- /* + algorithm specific parameters */
- int unprocessed_bits;
uint64_t bits_processed;
+ int unprocessed_bits;
union {
- EdonRData256 p256[1];
EdonRData512 p512[1];
} pipe[1];
} EdonRState;
-void EdonRInit(EdonRState *state, size_t hashbitlen);
+void EdonRInit(EdonRState *state);
void EdonRUpdate(EdonRState *state, const uint8_t *data, size_t databitlen);
void EdonRFinal(EdonRState *state, uint8_t *hashval);
-void EdonRHash(size_t hashbitlen, const uint8_t *data, size_t databitlen,
- uint8_t *hashval);
+void EdonRHash(const uint8_t *data, size_t databitlen, uint8_t *hashval);
#ifdef __cplusplus
}
diff --git a/include/sys/efi_partition.h b/include/sys/efi_partition.h
index 7d5e42e945ad..c4d7fd5088b5 100644
--- a/include/sys/efi_partition.h
+++ b/include/sys/efi_partition.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/fm/fs/zfs.h b/include/sys/fm/fs/zfs.h
index cd080c8ee667..c746600cd2d5 100644
--- a/include/sys/fm/fs/zfs.h
+++ b/include/sys/fm/fs/zfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -78,6 +78,12 @@ extern "C" {
#define FM_EREPORT_PAYLOAD_ZFS_VDEV_READ_ERRORS "vdev_read_errors"
#define FM_EREPORT_PAYLOAD_ZFS_VDEV_WRITE_ERRORS "vdev_write_errors"
#define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_ERRORS "vdev_cksum_errors"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N "vdev_cksum_n"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T "vdev_cksum_t"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N "vdev_io_n"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T "vdev_io_t"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_N "vdev_slow_io_n"
+#define FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_T "vdev_slow_io_t"
#define FM_EREPORT_PAYLOAD_ZFS_VDEV_DELAYS "vdev_delays"
#define FM_EREPORT_PAYLOAD_ZFS_PARENT_GUID "parent_guid"
#define FM_EREPORT_PAYLOAD_ZFS_PARENT_TYPE "parent_type"
@@ -98,8 +104,6 @@ extern "C" {
#define FM_EREPORT_PAYLOAD_ZFS_ZIO_TIMESTAMP "zio_timestamp"
#define FM_EREPORT_PAYLOAD_ZFS_ZIO_DELTA "zio_delta"
#define FM_EREPORT_PAYLOAD_ZFS_PREV_STATE "prev_state"
-#define FM_EREPORT_PAYLOAD_ZFS_CKSUM_EXPECTED "cksum_expected"
-#define FM_EREPORT_PAYLOAD_ZFS_CKSUM_ACTUAL "cksum_actual"
#define FM_EREPORT_PAYLOAD_ZFS_CKSUM_ALGO "cksum_algorithm"
#define FM_EREPORT_PAYLOAD_ZFS_CKSUM_BYTESWAP "cksum_byteswap"
#define FM_EREPORT_PAYLOAD_ZFS_BAD_OFFSET_RANGES "bad_ranges"
@@ -108,8 +112,6 @@ extern "C" {
#define FM_EREPORT_PAYLOAD_ZFS_BAD_RANGE_CLEARS "bad_range_clears"
#define FM_EREPORT_PAYLOAD_ZFS_BAD_SET_BITS "bad_set_bits"
#define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_BITS "bad_cleared_bits"
-#define FM_EREPORT_PAYLOAD_ZFS_BAD_SET_HISTOGRAM "bad_set_histogram"
-#define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_HISTOGRAM "bad_cleared_histogram"
#define FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME "snapshot_name"
#define FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME "device_name"
#define FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME "raw_name"
diff --git a/include/sys/fm/protocol.h b/include/sys/fm/protocol.h
index 78031f7c15ec..d4a9751c8aeb 100644
--- a/include/sys/fm/protocol.h
+++ b/include/sys/fm/protocol.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/fm/util.h b/include/sys/fm/util.h
index 5fb6d1d6072b..038162ab7524 100644
--- a/include/sys/fm/util.h
+++ b/include/sys/fm/util.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -95,7 +95,7 @@ extern void fm_init(void);
extern void fm_fini(void);
extern void zfs_zevent_post_cb(nvlist_t *nvl, nvlist_t *detector);
extern int zfs_zevent_post(nvlist_t *, nvlist_t *, zevent_cb_t *);
-extern void zfs_zevent_drain_all(int *);
+extern void zfs_zevent_drain_all(uint_t *);
extern zfs_file_t *zfs_zevent_fd_hold(int, minor_t *, zfs_zevent_t **);
extern void zfs_zevent_fd_rele(zfs_file_t *);
extern int zfs_zevent_next(zfs_zevent_t *, nvlist_t **, uint64_t *, uint64_t *);
diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h
index f013e6b20603..e191420f2d2d 100644
--- a/include/sys/fs/zfs.h
+++ b/include/sys/fs/zfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, 2017 Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -29,6 +29,7 @@
* Copyright (c) 2019 Datto Inc.
* Portions Copyright 2010 Robert Milkowski
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
+ * Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
*/
#ifndef _SYS_FS_ZFS_H
@@ -189,6 +190,9 @@ typedef enum {
ZFS_PROP_IVSET_GUID, /* not exposed to the user */
ZFS_PROP_REDACTED,
ZFS_PROP_REDACT_SNAPS,
+ ZFS_PROP_SNAPSHOTS_CHANGED,
+ ZFS_PROP_PREFETCH,
+ ZFS_PROP_VOLTHREADING,
ZFS_NUM_PROPS
} zfs_prop_t;
@@ -251,6 +255,9 @@ typedef enum {
ZPOOL_PROP_LOAD_GUID,
ZPOOL_PROP_AUTOTRIM,
ZPOOL_PROP_COMPATIBILITY,
+ ZPOOL_PROP_BCLONEUSED,
+ ZPOOL_PROP_BCLONESAVED,
+ ZPOOL_PROP_BCLONERATIO,
ZPOOL_NUM_PROPS
} zpool_prop_t;
@@ -353,6 +360,14 @@ typedef enum {
VDEV_PROP_BYTES_TRIM,
VDEV_PROP_REMOVING,
VDEV_PROP_ALLOCATING,
+ VDEV_PROP_FAILFAST,
+ VDEV_PROP_CHECKSUM_N,
+ VDEV_PROP_CHECKSUM_T,
+ VDEV_PROP_IO_N,
+ VDEV_PROP_IO_T,
+ VDEV_PROP_RAIDZ_EXPANDING,
+ VDEV_PROP_SLOW_IO_N,
+ VDEV_PROP_SLOW_IO_T,
VDEV_NUM_PROPS
} vdev_prop_t;
@@ -500,7 +515,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 {
@@ -531,6 +548,12 @@ typedef enum zfs_key_location {
ZFS_KEYLOCATION_LOCATIONS
} zfs_keylocation_t;
+typedef enum {
+ ZFS_PREFETCH_NONE = 0,
+ ZFS_PREFETCH_METADATA = 1,
+ ZFS_PREFETCH_ALL = 2
+} zfs_prefetch_type_t;
+
#define DEFAULT_PBKDF2_ITERATIONS 350000
#define MIN_PBKDF2_ITERATIONS 100000
@@ -704,6 +727,7 @@ typedef struct zpool_load_policy {
#define ZPOOL_CONFIG_SCAN_STATS "scan_stats" /* not stored on disk */
#define ZPOOL_CONFIG_REMOVAL_STATS "removal_stats" /* not stored on disk */
#define ZPOOL_CONFIG_CHECKPOINT_STATS "checkpoint_stats" /* not on disk */
+#define ZPOOL_CONFIG_RAIDZ_EXPAND_STATS "raidz_expand_stats" /* not on disk */
#define ZPOOL_CONFIG_VDEV_STATS "vdev_stats" /* not stored on disk */
#define ZPOOL_CONFIG_INDIRECT_SIZE "indirect_size" /* not stored on disk */
@@ -769,6 +793,8 @@ typedef struct zpool_load_policy {
#define ZPOOL_CONFIG_SPARES "spares"
#define ZPOOL_CONFIG_IS_SPARE "is_spare"
#define ZPOOL_CONFIG_NPARITY "nparity"
+#define ZPOOL_CONFIG_RAIDZ_EXPANDING "raidz_expanding"
+#define ZPOOL_CONFIG_RAIDZ_EXPAND_TXGS "raidz_expand_txgs"
#define ZPOOL_CONFIG_HOSTID "hostid"
#define ZPOOL_CONFIG_HOSTNAME "hostname"
#define ZPOOL_CONFIG_LOADED_TIME "initial_load_time"
@@ -804,6 +830,7 @@ typedef struct zpool_load_policy {
#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read"
#define ZPOOL_CONFIG_FEATURE_STATS "feature_stats" /* not stored on disk */
#define ZPOOL_CONFIG_ERRATA "errata" /* not stored on disk */
+#define ZPOOL_CONFIG_VDEV_ROOT_ZAP "com.klarasystems:vdev_zap_root"
#define ZPOOL_CONFIG_VDEV_TOP_ZAP "com.delphix:vdev_zap_top"
#define ZPOOL_CONFIG_VDEV_LEAF_ZAP "com.delphix:vdev_zap_leaf"
#define ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS "com.delphix:has_per_vdev_zaps"
@@ -886,6 +913,15 @@ typedef struct zpool_load_policy {
#define VDEV_TOP_ZAP_ALLOCATION_BIAS \
"org.zfsonlinux:allocation_bias"
+#define VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE \
+ "org.openzfs:raidz_expand_state"
+#define VDEV_TOP_ZAP_RAIDZ_EXPAND_START_TIME \
+ "org.openzfs:raidz_expand_start_time"
+#define VDEV_TOP_ZAP_RAIDZ_EXPAND_END_TIME \
+ "org.openzfs:raidz_expand_end_time"
+#define VDEV_TOP_ZAP_RAIDZ_EXPAND_BYTES_COPIED \
+ "org.openzfs:raidz_expand_bytes_copied"
+
/* vdev metaslab allocation bias */
#define VDEV_ALLOC_BIAS_LOG "log"
#define VDEV_ALLOC_BIAS_SPECIAL "special"
@@ -1023,6 +1059,7 @@ typedef enum pool_scan_func {
POOL_SCAN_NONE,
POOL_SCAN_SCRUB,
POOL_SCAN_RESILVER,
+ POOL_SCAN_ERRORSCRUB,
POOL_SCAN_FUNCS
} pool_scan_func_t;
@@ -1057,12 +1094,18 @@ typedef enum zio_type {
ZIO_TYPE_WRITE,
ZIO_TYPE_FREE,
ZIO_TYPE_CLAIM,
- ZIO_TYPE_IOCTL,
+ ZIO_TYPE_FLUSH,
ZIO_TYPE_TRIM,
ZIO_TYPES
} zio_type_t;
/*
+ * Compatibility: _IOCTL was renamed to _FLUSH; keep the old name available to
+ * user programs.
+ */
+#define ZIO_TYPE_IOCTL ZIO_TYPE_FLUSH
+
+/*
* Pool statistics. Note: all fields should be 64-bit because this
* is passed between kernel and userland as an nvlist uint64 array.
*/
@@ -1074,7 +1117,7 @@ typedef struct pool_scan_stat {
uint64_t pss_end_time; /* scan end time */
uint64_t pss_to_examine; /* total bytes to scan */
uint64_t pss_examined; /* total bytes located by scanner */
- uint64_t pss_to_process; /* total bytes to process */
+ uint64_t pss_skipped; /* total bytes skipped by scanner */
uint64_t pss_processed; /* total processed bytes */
uint64_t pss_errors; /* scan errors */
@@ -1086,6 +1129,20 @@ typedef struct pool_scan_stat {
uint64_t pss_pass_scrub_spent_paused;
uint64_t pss_pass_issued; /* issued bytes per scan pass */
uint64_t pss_issued; /* total bytes checked by scanner */
+
+ /* error scrub values stored on disk */
+ uint64_t pss_error_scrub_func; /* pool_scan_func_t */
+ uint64_t pss_error_scrub_state; /* dsl_scan_state_t */
+ uint64_t pss_error_scrub_start; /* error scrub start time */
+ uint64_t pss_error_scrub_end; /* error scrub end time */
+ uint64_t pss_error_scrub_examined; /* error blocks issued I/O */
+ /* error blocks to be issued I/O */
+ uint64_t pss_error_scrub_to_be_examined;
+
+ /* error scrub values not stored on disk */
+ /* error scrub pause time in milliseconds */
+ uint64_t pss_pass_error_scrub_pause;
+
} pool_scan_stat_t;
typedef struct pool_removal_stat {
@@ -1102,11 +1159,22 @@ typedef struct pool_removal_stat {
uint64_t prs_mapping_memory;
} pool_removal_stat_t;
+typedef struct pool_raidz_expand_stat {
+ uint64_t pres_state; /* dsl_scan_state_t */
+ uint64_t pres_expanding_vdev;
+ uint64_t pres_start_time;
+ uint64_t pres_end_time;
+ uint64_t pres_to_reflow; /* bytes that need to be moved */
+ uint64_t pres_reflowed; /* bytes moved so far */
+ uint64_t pres_waiting_for_resilver;
+} pool_raidz_expand_stat_t;
+
typedef enum dsl_scan_state {
DSS_NONE,
DSS_SCANNING,
DSS_FINISHED,
DSS_CANCELED,
+ DSS_ERRORSCRUBBING,
DSS_NUM_STATES
} dsl_scan_state_t;
@@ -1123,6 +1191,7 @@ typedef struct vdev_rebuild_stat {
uint64_t vrs_pass_time_ms; /* pass run time (millisecs) */
uint64_t vrs_pass_bytes_scanned; /* bytes scanned since start/resume */
uint64_t vrs_pass_bytes_issued; /* bytes rebuilt since start/resume */
+ uint64_t vrs_pass_bytes_skipped; /* bytes skipped since start/resume */
} vdev_rebuild_stat_t;
/*
@@ -1252,6 +1321,7 @@ typedef enum pool_initialize_func {
POOL_INITIALIZE_START,
POOL_INITIALIZE_CANCEL,
POOL_INITIALIZE_SUSPEND,
+ POOL_INITIALIZE_UNINIT,
POOL_INITIALIZE_FUNCS
} pool_initialize_func_t;
@@ -1346,7 +1416,7 @@ typedef enum {
*/
typedef enum zfs_ioc {
/*
- * Core features - 81/128 numbers reserved.
+ * Core features - 88/128 numbers reserved.
*/
#ifdef __FreeBSD__
ZFS_IOC_FIRST = 0,
@@ -1441,6 +1511,7 @@ typedef enum zfs_ioc {
ZFS_IOC_WAIT_FS, /* 0x5a54 */
ZFS_IOC_VDEV_GET_PROPS, /* 0x5a55 */
ZFS_IOC_VDEV_SET_PROPS, /* 0x5a56 */
+ ZFS_IOC_POOL_SCRUB, /* 0x5a57 */
/*
* Per-platform (Optional) - 8/128 numbers reserved.
@@ -1535,6 +1606,10 @@ typedef enum {
ZFS_ERR_BADPROP,
ZFS_ERR_VDEV_NOTSUP,
ZFS_ERR_NOT_USER_NAMESPACE,
+ ZFS_ERR_RESUME_EXISTS,
+ ZFS_ERR_CRYPTO_NOTSUP,
+ ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS,
+ ZFS_ERR_ASHIFT_MISMATCH,
} zfs_errno_t;
/*
@@ -1559,6 +1634,7 @@ typedef enum {
ZPOOL_WAIT_RESILVER,
ZPOOL_WAIT_SCRUB,
ZPOOL_WAIT_TRIM,
+ ZPOOL_WAIT_RAIDZ_EXPAND,
ZPOOL_WAIT_NUM_ACTIVITIES
} zpool_wait_activity_t;
@@ -1651,6 +1727,7 @@ typedef enum {
#define ZFS_ONLINE_UNSPARE 0x2
#define ZFS_ONLINE_FORCEFAULT 0x4
#define ZFS_ONLINE_EXPAND 0x8
+#define ZFS_ONLINE_SPARE 0x10
#define ZFS_OFFLINE_TEMPORARY 0x1
/*
@@ -1757,9 +1834,9 @@ typedef enum {
* against the cost of COWing a giant block to modify one byte, and the
* large latency of reading or writing a large block.
*
- * Note that although blocks up to 16MB are supported, the recordsize
- * property can not be set larger than zfs_max_recordsize (default 1MB).
- * See the comment near zfs_max_recordsize in dsl_dataset.c for details.
+ * The recordsize property can not be set larger than zfs_max_recordsize
+ * (default 16MB on 64-bit and 1MB on 32-bit). See the comment near
+ * zfs_max_recordsize in dsl_dataset.c for details.
*
* Note that although the LSIZE field of the blkptr_t can store sizes up
* to 32MB, the dnode's dn_datablkszsec can only store sizes up to
diff --git a/include/sys/metaslab.h b/include/sys/metaslab.h
index 140739adb562..815b5d0c9cf1 100644
--- a/include/sys/metaslab.h
+++ b/include/sys/metaslab.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -39,6 +39,7 @@ extern "C" {
typedef struct metaslab_ops {
+ const char *msop_name;
uint64_t (*msop_alloc)(metaslab_t *, uint64_t);
} metaslab_ops_t;
@@ -80,7 +81,6 @@ uint64_t metaslab_largest_allocatable(metaslab_t *);
#define METASLAB_ASYNC_ALLOC 0x8
#define METASLAB_DONT_THROTTLE 0x10
#define METASLAB_MUST_RESERVE 0x20
-#define METASLAB_FASTWRITE 0x40
#define METASLAB_ZIL 0x80
int metaslab_alloc(spa_t *, metaslab_class_t *, uint64_t,
@@ -96,8 +96,6 @@ void metaslab_unalloc_dva(spa_t *, const dva_t *, uint64_t);
int metaslab_claim(spa_t *, const blkptr_t *, uint64_t);
int metaslab_claim_impl(vdev_t *, uint64_t, uint64_t, uint64_t);
void metaslab_check_free(spa_t *, const blkptr_t *);
-void metaslab_fastwrite_mark(spa_t *, const blkptr_t *);
-void metaslab_fastwrite_unmark(spa_t *, const blkptr_t *);
void metaslab_stat_init(void);
void metaslab_stat_fini(void);
diff --git a/include/sys/metaslab_impl.h b/include/sys/metaslab_impl.h
index 820c61a252e2..4f434291ddbf 100644
--- a/include/sys/metaslab_impl.h
+++ b/include/sys/metaslab_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -250,7 +250,6 @@ struct metaslab_group {
int64_t mg_activation_count;
metaslab_class_t *mg_class;
vdev_t *mg_vd;
- taskq_t *mg_taskq;
metaslab_group_t *mg_prev;
metaslab_group_t *mg_next;
@@ -313,7 +312,7 @@ struct metaslab_group {
* Each metaslab maintains a set of in-core trees to track metaslab
* operations. The in-core free tree (ms_allocatable) contains the list of
* free segments which are eligible for allocation. As blocks are
- * allocated, the allocated segment are removed from the ms_allocatable and
+ * allocated, the allocated segments are removed from the ms_allocatable and
* added to a per txg allocation tree (ms_allocating). As blocks are
* freed, they are added to the free tree (ms_freeing). These trees
* allow us to process all allocations and frees in syncing context
@@ -366,9 +365,9 @@ struct metaslab_group {
struct metaslab {
/*
* This is the main lock of the metaslab and its purpose is to
- * coordinate our allocations and frees [e.g metaslab_block_alloc(),
+ * coordinate our allocations and frees [e.g., metaslab_block_alloc(),
* metaslab_free_concrete(), ..etc] with our various syncing
- * procedures [e.g. metaslab_sync(), metaslab_sync_done(), ..etc].
+ * procedures [e.g., metaslab_sync(), metaslab_sync_done(), ..etc].
*
* The lock is also used during some miscellaneous operations like
* using the metaslab's histogram for the metaslab group's histogram
diff --git a/include/sys/mmp.h b/include/sys/mmp.h
index ce9c4496a04f..1023334098d8 100644
--- a/include/sys/mmp.h
+++ b/include/sys/mmp.h
@@ -64,7 +64,7 @@ extern void mmp_signal_all_threads(void);
/* Global tuning */
extern int param_set_multihost_interval(ZFS_MODULE_PARAM_ARGS);
-extern ulong_t zfs_multihost_interval;
+extern uint64_t zfs_multihost_interval;
extern uint_t zfs_multihost_fail_intervals;
extern uint_t zfs_multihost_import_intervals;
diff --git a/include/sys/mntent.h b/include/sys/mntent.h
index 8d578f67b8a7..5bb7e080cda8 100644
--- a/include/sys/mntent.h
+++ b/include/sys/mntent.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -108,5 +108,8 @@
#define MNTOPT_NOACL "noacl" /* likewise */
#define MNTOPT_POSIXACL "posixacl" /* likewise */
#define MNTOPT_MNTPOINT "mntpoint" /* mount point hint */
+#define MNTOPT_CASESENSITIVE "casesensitive" /* case sensitivity */
+#define MNTOPT_CASEINSENSITIVE "caseinsensitive" /* case insensitivity */
+#define MNTOPT_CASEMIXED "casemixed" /* case mixed */
#endif /* _SYS_MNTENT_H */
diff --git a/include/sys/multilist.h b/include/sys/multilist.h
index 26f37c37ab38..e7de86f2379b 100644
--- a/include/sys/multilist.h
+++ b/include/sys/multilist.h
@@ -82,12 +82,15 @@ int multilist_is_empty(multilist_t *);
unsigned int multilist_get_num_sublists(multilist_t *);
unsigned int multilist_get_random_index(multilist_t *);
-multilist_sublist_t *multilist_sublist_lock(multilist_t *, unsigned int);
+void multilist_sublist_lock(multilist_sublist_t *);
+multilist_sublist_t *multilist_sublist_lock_idx(multilist_t *, unsigned int);
multilist_sublist_t *multilist_sublist_lock_obj(multilist_t *, void *);
void multilist_sublist_unlock(multilist_sublist_t *);
void multilist_sublist_insert_head(multilist_sublist_t *, void *);
void multilist_sublist_insert_tail(multilist_sublist_t *, void *);
+void multilist_sublist_insert_after(multilist_sublist_t *, void *, void *);
+void multilist_sublist_insert_before(multilist_sublist_t *, void *, void *);
void multilist_sublist_move_forward(multilist_sublist_t *mls, void *obj);
void multilist_sublist_remove(multilist_sublist_t *, void *);
int multilist_sublist_is_empty(multilist_sublist_t *);
diff --git a/include/sys/nvpair.h b/include/sys/nvpair.h
index 81494b62d7ec..2dbd9e3eaf46 100644
--- a/include/sys/nvpair.h
+++ b/include/sys/nvpair.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -76,7 +76,7 @@ typedef struct nvpair {
int16_t nvp_reserve; /* not used */
int32_t nvp_value_elem; /* number of elements for array types */
data_type_t nvp_type; /* type of value */
- /* name string */
+ char nvp_name[]; /* name string */
/* aligned ptr array for string arrays */
/* aligned array of data for value */
} nvpair_t;
@@ -109,7 +109,7 @@ typedef struct nvlist {
#define NV_ALIGN4(x) (((x) + 3) & ~3)
#define NVP_SIZE(nvp) ((nvp)->nvp_size)
-#define NVP_NAME(nvp) ((char *)(nvp) + sizeof (nvpair_t))
+#define NVP_NAME(nvp) ((nvp)->nvp_name)
#define NVP_TYPE(nvp) ((nvp)->nvp_type)
#define NVP_NELEM(nvp) ((nvp)->nvp_value_elem)
#define NVP_VALUE(nvp) ((char *)(nvp) + NV_ALIGN(sizeof (nvpair_t) \
@@ -232,7 +232,8 @@ _SYS_NVPAIR_H int nvlist_lookup_int64(const nvlist_t *, const char *,
int64_t *);
_SYS_NVPAIR_H int nvlist_lookup_uint64(const nvlist_t *, const char *,
uint64_t *);
-_SYS_NVPAIR_H int nvlist_lookup_string(nvlist_t *, const char *, char **);
+_SYS_NVPAIR_H int nvlist_lookup_string(const nvlist_t *, const char *,
+ const char **);
_SYS_NVPAIR_H int nvlist_lookup_nvlist(nvlist_t *, const char *, nvlist_t **);
_SYS_NVPAIR_H int nvlist_lookup_boolean_array(nvlist_t *, const char *,
boolean_t **, uint_t *);
@@ -267,14 +268,14 @@ _SYS_NVPAIR_H int nvlist_lookup_double(const nvlist_t *, const char *,
_SYS_NVPAIR_H int nvlist_lookup_nvpair(nvlist_t *, const char *, nvpair_t **);
_SYS_NVPAIR_H int nvlist_lookup_nvpair_embedded_index(nvlist_t *, const char *,
- nvpair_t **, int *, char **);
+ nvpair_t **, int *, const char **);
_SYS_NVPAIR_H boolean_t nvlist_exists(const nvlist_t *, const char *);
_SYS_NVPAIR_H boolean_t nvlist_empty(const nvlist_t *);
/* processing nvpair */
_SYS_NVPAIR_H nvpair_t *nvlist_next_nvpair(nvlist_t *, const nvpair_t *);
_SYS_NVPAIR_H nvpair_t *nvlist_prev_nvpair(nvlist_t *, const nvpair_t *);
-_SYS_NVPAIR_H char *nvpair_name(const nvpair_t *);
+_SYS_NVPAIR_H const char *nvpair_name(const nvpair_t *);
_SYS_NVPAIR_H data_type_t nvpair_type(const nvpair_t *);
_SYS_NVPAIR_H int nvpair_type_is_array(const nvpair_t *);
_SYS_NVPAIR_H int nvpair_value_boolean_value(const nvpair_t *, boolean_t *);
@@ -287,7 +288,7 @@ _SYS_NVPAIR_H int nvpair_value_int32(const nvpair_t *, int32_t *);
_SYS_NVPAIR_H int nvpair_value_uint32(const nvpair_t *, uint32_t *);
_SYS_NVPAIR_H int nvpair_value_int64(const nvpair_t *, int64_t *);
_SYS_NVPAIR_H int nvpair_value_uint64(const nvpair_t *, uint64_t *);
-_SYS_NVPAIR_H int nvpair_value_string(nvpair_t *, char **);
+_SYS_NVPAIR_H int nvpair_value_string(const nvpair_t *, const char **);
_SYS_NVPAIR_H int nvpair_value_nvlist(nvpair_t *, nvlist_t **);
_SYS_NVPAIR_H int nvpair_value_boolean_array(nvpair_t *, boolean_t **,
uint_t *);
@@ -300,7 +301,8 @@ _SYS_NVPAIR_H int nvpair_value_int32_array(nvpair_t *, int32_t **, uint_t *);
_SYS_NVPAIR_H int nvpair_value_uint32_array(nvpair_t *, uint32_t **, uint_t *);
_SYS_NVPAIR_H int nvpair_value_int64_array(nvpair_t *, int64_t **, uint_t *);
_SYS_NVPAIR_H int nvpair_value_uint64_array(nvpair_t *, uint64_t **, uint_t *);
-_SYS_NVPAIR_H int nvpair_value_string_array(nvpair_t *, char ***, uint_t *);
+_SYS_NVPAIR_H int nvpair_value_string_array(nvpair_t *, const char ***,
+ uint_t *);
_SYS_NVPAIR_H int nvpair_value_nvlist_array(nvpair_t *, nvlist_t ***, uint_t *);
_SYS_NVPAIR_H int nvpair_value_hrtime(nvpair_t *, hrtime_t *);
#if !defined(_KERNEL) && !defined(_STANDALONE)
@@ -373,7 +375,8 @@ _SYS_NVPAIR_H uint8_t fnvlist_lookup_uint8(const nvlist_t *, const char *);
_SYS_NVPAIR_H uint16_t fnvlist_lookup_uint16(const nvlist_t *, const char *);
_SYS_NVPAIR_H uint32_t fnvlist_lookup_uint32(const nvlist_t *, const char *);
_SYS_NVPAIR_H uint64_t fnvlist_lookup_uint64(const nvlist_t *, const char *);
-_SYS_NVPAIR_H char *fnvlist_lookup_string(nvlist_t *, const char *);
+_SYS_NVPAIR_H const char *fnvlist_lookup_string(const nvlist_t *,
+ const char *);
_SYS_NVPAIR_H nvlist_t *fnvlist_lookup_nvlist(nvlist_t *, const char *);
_SYS_NVPAIR_H boolean_t *fnvlist_lookup_boolean_array(nvlist_t *, const char *,
uint_t *);
@@ -406,7 +409,7 @@ _SYS_NVPAIR_H uint8_t fnvpair_value_uint8(const nvpair_t *nvp);
_SYS_NVPAIR_H uint16_t fnvpair_value_uint16(const nvpair_t *nvp);
_SYS_NVPAIR_H uint32_t fnvpair_value_uint32(const nvpair_t *nvp);
_SYS_NVPAIR_H uint64_t fnvpair_value_uint64(const nvpair_t *nvp);
-_SYS_NVPAIR_H char *fnvpair_value_string(nvpair_t *nvp);
+_SYS_NVPAIR_H const char *fnvpair_value_string(const nvpair_t *nvp);
_SYS_NVPAIR_H nvlist_t *fnvpair_value_nvlist(nvpair_t *nvp);
#ifdef __cplusplus
diff --git a/include/sys/nvpair_impl.h b/include/sys/nvpair_impl.h
index 809e5c454712..6cae256285e5 100644
--- a/include/sys/nvpair_impl.h
+++ b/include/sys/nvpair_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/pathname.h b/include/sys/pathname.h
index 52f21316c23d..054223170db1 100644
--- a/include/sys/pathname.h
+++ b/include/sys/pathname.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/qat.h b/include/sys/qat.h
index fe0f2c672f97..76360ba99042 100644
--- a/include/sys/qat.h
+++ b/include/sys/qat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/range_tree.h b/include/sys/range_tree.h
index daa39e20dbd6..d6f60e795288 100644
--- a/include/sys/range_tree.h
+++ b/include/sys/range_tree.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/rrwlock.h b/include/sys/rrwlock.h
index 51ac364af519..367732a8391c 100644
--- a/include/sys/rrwlock.h
+++ b/include/sys/rrwlock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/sa.h b/include/sys/sa.h
index 42479652ab2c..c551acecab30 100644
--- a/include/sys/sa.h
+++ b/include/sys/sa.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/sa_impl.h b/include/sys/sa_impl.h
index fa10aff8a306..744c8dcb7dfb 100644
--- a/include/sys/sa_impl.h
+++ b/include/sys/sa_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/sha2.h b/include/sys/sha2.h
new file mode 100644
index 000000000000..81dfbbb8cea9
--- /dev/null
+++ b/include/sys/sha2.h
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#ifndef _SYS_SHA2_H
+#define _SYS_SHA2_H
+
+#ifdef _KERNEL
+#include <sys/types.h>
+#else
+#include <stdint.h>
+#include <stdlib.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SHA224_BLOCK_LENGTH 64
+#define SHA256_BLOCK_LENGTH 64
+#define SHA384_BLOCK_LENGTH 128
+#define SHA512_BLOCK_LENGTH 128
+
+#define SHA224_DIGEST_LENGTH 28
+#define SHA256_DIGEST_LENGTH 32
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
+#define SHA512_224_DIGEST_LENGTH 28
+#define SHA512_256_DIGEST_LENGTH 32
+
+#define SHA256_HMAC_BLOCK_SIZE 64
+#define SHA512_HMAC_BLOCK_SIZE 128
+
+/* sha256 context */
+typedef struct {
+ uint32_t state[8];
+ uint64_t count[2];
+ uint8_t wbuf[64];
+
+ /* const sha256_ops_t *ops */
+ const void *ops;
+} sha256_ctx;
+
+/* sha512 context */
+typedef struct {
+ uint64_t state[8];
+ uint64_t count[2];
+ uint8_t wbuf[128];
+
+ /* const sha256_ops_t *ops */
+ const void *ops;
+} sha512_ctx;
+
+/* SHA2 context */
+typedef struct {
+ union {
+ sha256_ctx sha256;
+ sha512_ctx sha512;
+ };
+
+ /* algorithm type */
+ int algotype;
+} SHA2_CTX;
+
+/* SHA2 algorithm types */
+typedef enum sha2_mech_type {
+ SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */
+ SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */
+ SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
+ SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */
+ SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */
+ SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
+ SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */
+ SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */
+ SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
+ SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */
+ SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */
+} sha2_mech_type_t;
+
+#define SHA256 0
+#define SHA256_HMAC 1
+#define SHA256_HMAC_GEN 2
+#define SHA384 3
+#define SHA384_HMAC 4
+#define SHA384_HMAC_GEN 5
+#define SHA512 6
+#define SHA512_HMAC 7
+#define SHA512_HMAC_GEN 8
+#define SHA512_224 9
+#define SHA512_256 10
+
+/* SHA2 Init function */
+extern void SHA2Init(int algotype, SHA2_CTX *ctx);
+
+/* SHA2 Update function */
+extern void SHA2Update(SHA2_CTX *ctx, const void *data, size_t len);
+
+/* SHA2 Final function */
+extern void SHA2Final(void *digest, SHA2_CTX *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYS_SHA2_H */
diff --git a/include/sys/spa.h b/include/sys/spa.h
index cd2499b30b40..3073c4d1b937 100644
--- a/include/sys/spa.h
+++ b/include/sys/spa.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,16 +20,16 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2021 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright 2013 Saso Kiselkov. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
- * Copyright (c) 2017, 2019, Datto Inc. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2019, Klara Inc.
+ * Copyright (c) 2019, Datto Inc.
*/
#ifndef _SYS_SPA_H
@@ -62,9 +62,8 @@ typedef struct metaslab_class metaslab_class_t;
typedef struct zio zio_t;
typedef struct zilog zilog_t;
typedef struct spa_aux_vdev spa_aux_vdev_t;
-typedef struct ddt ddt_t;
-typedef struct ddt_entry ddt_entry_t;
typedef struct zbookmark_phys zbookmark_phys_t;
+typedef struct zbookmark_err_phys zbookmark_err_phys_t;
struct bpobj;
struct bplist;
@@ -126,15 +125,15 @@ typedef struct zio_cksum_salt {
*
* 64 56 48 40 32 24 16 8 0
* +-------+-------+-------+-------+-------+-------+-------+-------+
- * 0 | pad | vdev1 | GRID | ASIZE |
+ * 0 | pad | vdev1 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 1 |G| offset1 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
- * 2 | pad | vdev2 | GRID | ASIZE |
+ * 2 | pad | vdev2 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 3 |G| offset2 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
- * 4 | pad | vdev3 | GRID | ASIZE |
+ * 4 | pad | vdev3 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 5 |G| offset3 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
@@ -166,7 +165,6 @@ typedef struct zio_cksum_salt {
* LSIZE logical size
* PSIZE physical size (after compression)
* ASIZE allocated size (including RAID-Z parity and gang block headers)
- * GRID RAID-Z layout information (reserved for future use)
* cksum checksum function
* comp compression function
* G gang block indicator
@@ -191,11 +189,11 @@ typedef struct zio_cksum_salt {
*
* 64 56 48 40 32 24 16 8 0
* +-------+-------+-------+-------+-------+-------+-------+-------+
- * 0 | vdev1 | GRID | ASIZE |
+ * 0 | vdev1 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 1 |G| offset1 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
- * 2 | vdev2 | GRID | ASIZE |
+ * 2 | vdev2 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 3 |G| offset2 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
@@ -356,7 +354,7 @@ typedef enum bp_embedded_type {
#define BPE_NUM_WORDS 14
#define BPE_PAYLOAD_SIZE (BPE_NUM_WORDS * sizeof (uint64_t))
#define BPE_IS_PAYLOADWORD(bp, wp) \
- ((wp) != &(bp)->blk_prop && (wp) != &(bp)->blk_birth)
+ ((wp) != &(bp)->blk_prop && (wp) != (&(bp)->blk_birth_word[1]))
#define SPA_BLKPTRSHIFT 7 /* blkptr_t is 128 bytes */
#define SPA_DVAS_PER_BP 3 /* Number of DVAs in a bp */
@@ -375,8 +373,7 @@ typedef struct blkptr {
dva_t blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
uint64_t blk_prop; /* size, compression, type, etc */
uint64_t blk_pad[2]; /* Extra space for the future */
- uint64_t blk_phys_birth; /* txg when block was allocated */
- uint64_t blk_birth; /* transaction group at birth */
+ uint64_t blk_birth_word[2];
uint64_t blk_fill; /* fill count */
zio_cksum_t blk_cksum; /* 256-bit checksum */
} blkptr_t;
@@ -396,9 +393,6 @@ typedef struct blkptr {
BF64_SET_SB((dva)->dva_word[0], 0, SPA_ASIZEBITS, \
SPA_MINBLOCKSHIFT, 0, x)
-#define DVA_GET_GRID(dva) BF64_GET((dva)->dva_word[0], 24, 8)
-#define DVA_SET_GRID(dva, x) BF64_SET((dva)->dva_word[0], 24, 8, x)
-
#define DVA_GET_VDEV(dva) BF64_GET((dva)->dva_word[0], 32, SPA_VDEVBITS)
#define DVA_SET_VDEV(dva, x) \
BF64_SET((dva)->dva_word[0], 32, SPA_VDEVBITS, x)
@@ -481,15 +475,23 @@ typedef struct blkptr {
#define BP_GET_FREE(bp) BF64_GET((bp)->blk_fill, 0, 1)
#define BP_SET_FREE(bp, x) BF64_SET((bp)->blk_fill, 0, 1, x)
-#define BP_PHYSICAL_BIRTH(bp) \
- (BP_IS_EMBEDDED(bp) ? 0 : \
- (bp)->blk_phys_birth ? (bp)->blk_phys_birth : (bp)->blk_birth)
+#define BP_GET_LOGICAL_BIRTH(bp) (bp)->blk_birth_word[1]
+#define BP_SET_LOGICAL_BIRTH(bp, x) ((bp)->blk_birth_word[1] = (x))
+
+#define BP_GET_PHYSICAL_BIRTH(bp) (bp)->blk_birth_word[0]
+#define BP_SET_PHYSICAL_BIRTH(bp, x) ((bp)->blk_birth_word[0] = (x))
+
+#define BP_GET_BIRTH(bp) \
+ (BP_IS_EMBEDDED(bp) ? 0 : \
+ BP_GET_PHYSICAL_BIRTH(bp) ? BP_GET_PHYSICAL_BIRTH(bp) : \
+ BP_GET_LOGICAL_BIRTH(bp))
#define BP_SET_BIRTH(bp, logical, physical) \
{ \
ASSERT(!BP_IS_EMBEDDED(bp)); \
- (bp)->blk_birth = (logical); \
- (bp)->blk_phys_birth = ((logical) == (physical) ? 0 : (physical)); \
+ BP_SET_LOGICAL_BIRTH(bp, logical); \
+ BP_SET_PHYSICAL_BIRTH(bp, \
+ ((logical) == (physical) ? 0 : (physical))); \
}
#define BP_GET_FILL(bp) \
@@ -542,8 +544,8 @@ typedef struct blkptr {
(dva1)->dva_word[0] == (dva2)->dva_word[0])
#define BP_EQUAL(bp1, bp2) \
- (BP_PHYSICAL_BIRTH(bp1) == BP_PHYSICAL_BIRTH(bp2) && \
- (bp1)->blk_birth == (bp2)->blk_birth && \
+ (BP_GET_BIRTH(bp1) == BP_GET_BIRTH(bp2) && \
+ BP_GET_LOGICAL_BIRTH(bp1) == BP_GET_LOGICAL_BIRTH(bp2) && \
DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) && \
DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) && \
DVA_EQUAL(&(bp1)->blk_dva[2], &(bp2)->blk_dva[2]))
@@ -582,8 +584,8 @@ typedef struct blkptr {
(bp)->blk_prop = 0; \
(bp)->blk_pad[0] = 0; \
(bp)->blk_pad[1] = 0; \
- (bp)->blk_phys_birth = 0; \
- (bp)->blk_birth = 0; \
+ (bp)->blk_birth_word[0] = 0; \
+ (bp)->blk_birth_word[1] = 0; \
(bp)->blk_fill = 0; \
ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0); \
}
@@ -600,7 +602,7 @@ typedef struct blkptr {
/*
* This macro allows code sharing between zfs, libzpool, and mdb.
- * 'func' is either snprintf() or mdb_snprintf().
+ * 'func' is either kmem_scnprintf() or mdb_snprintf().
* 'ws' (whitespace) can be ' ' for single-line format, '\n' for multi-line.
*/
@@ -632,7 +634,7 @@ typedef struct blkptr {
(u_longlong_t)BP_GET_LEVEL(bp), \
type, \
(u_longlong_t)BP_GET_LSIZE(bp), \
- (u_longlong_t)bp->blk_birth); \
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp)); \
} else if (BP_IS_EMBEDDED(bp)) { \
len = func(buf + len, size - len, \
"EMBEDDED [L%llu %s] et=%u %s " \
@@ -643,14 +645,14 @@ typedef struct blkptr {
compress, \
(u_longlong_t)BPE_GET_LSIZE(bp), \
(u_longlong_t)BPE_GET_PSIZE(bp), \
- (u_longlong_t)bp->blk_birth); \
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp)); \
} else if (BP_IS_REDACTED(bp)) { \
len += func(buf + len, size - len, \
"REDACTED [L%llu %s] size=%llxL birth=%lluL", \
(u_longlong_t)BP_GET_LEVEL(bp), \
type, \
(u_longlong_t)BP_GET_LSIZE(bp), \
- (u_longlong_t)bp->blk_birth); \
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp)); \
} else { \
for (int d = 0; d < BP_GET_NDVAS(bp); d++) { \
const dva_t *dva = &bp->blk_dva[d]; \
@@ -663,6 +665,7 @@ typedef struct blkptr {
(u_longlong_t)DVA_GET_ASIZE(dva), \
ws); \
} \
+ ASSERT3S(copies, >, 0); \
if (BP_IS_ENCRYPTED(bp)) { \
len += func(buf + len, size - len, \
"salt=%llx iv=%llx:%llx%c", \
@@ -678,7 +681,7 @@ typedef struct blkptr {
len += func(buf + len, size - len, \
"[L%llu %s] %s %s %s %s %s %s %s%c" \
"size=%llxL/%llxP birth=%lluL/%lluP fill=%llu%c" \
- "cksum=%llx:%llx:%llx:%llx", \
+ "cksum=%016llx:%016llx:%016llx:%016llx", \
(u_longlong_t)BP_GET_LEVEL(bp), \
type, \
checksum, \
@@ -691,8 +694,8 @@ typedef struct blkptr {
ws, \
(u_longlong_t)BP_GET_LSIZE(bp), \
(u_longlong_t)BP_GET_PSIZE(bp), \
- (u_longlong_t)bp->blk_birth, \
- (u_longlong_t)BP_PHYSICAL_BIRTH(bp), \
+ (u_longlong_t)BP_GET_LOGICAL_BIRTH(bp), \
+ (u_longlong_t)BP_GET_BIRTH(bp), \
(u_longlong_t)BP_GET_FILL(bp), \
ws, \
(u_longlong_t)bp->blk_cksum.zc_word[0], \
@@ -721,16 +724,10 @@ typedef enum spa_mode {
* Send TRIM commands in-line during normal pool operation while deleting.
* OFF: no
* ON: yes
- * NB: IN_FREEBSD_BASE is defined within the FreeBSD sources.
*/
typedef enum {
SPA_AUTOTRIM_OFF = 0, /* default */
SPA_AUTOTRIM_ON,
-#ifdef IN_FREEBSD_BASE
- SPA_AUTOTRIM_DEFAULT = SPA_AUTOTRIM_ON,
-#else
- SPA_AUTOTRIM_DEFAULT = SPA_AUTOTRIM_OFF,
-#endif
} spa_autotrim_t;
/*
@@ -773,7 +770,7 @@ extern int bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx);
#define SPA_ASYNC_CONFIG_UPDATE 0x01
#define SPA_ASYNC_REMOVE 0x02
-#define SPA_ASYNC_PROBE 0x04
+#define SPA_ASYNC_FAULT_VDEV 0x04
#define SPA_ASYNC_RESILVER_DONE 0x08
#define SPA_ASYNC_RESILVER 0x10
#define SPA_ASYNC_AUTOEXPAND 0x20
@@ -785,9 +782,10 @@ extern int bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx);
#define SPA_ASYNC_L2CACHE_REBUILD 0x800
#define SPA_ASYNC_L2CACHE_TRIM 0x1000
#define SPA_ASYNC_REBUILD_DONE 0x2000
+#define SPA_ASYNC_DETACH_SPARE 0x4000
/* device manipulation */
-extern int spa_vdev_add(spa_t *spa, nvlist_t *nvroot);
+extern int spa_vdev_add(spa_t *spa, nvlist_t *nvroot, boolean_t ashift_check);
extern int spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot,
int replacing, int rebuild);
extern int spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid,
@@ -826,10 +824,19 @@ extern int spa_scrub_pause_resume(spa_t *spa, pool_scrub_cmd_t flag);
extern void spa_sync(spa_t *spa, uint64_t txg); /* only for DMU use */
extern void spa_sync_allpools(void);
-extern int zfs_sync_pass_deferred_free;
+extern uint_t zfs_sync_pass_deferred_free;
+
+/* spa sync taskqueues */
+taskq_t *spa_sync_tq_create(spa_t *spa, const char *name);
+void spa_sync_tq_destroy(spa_t *spa);
+uint_t spa_acq_allocator(spa_t *spa);
+void spa_rel_allocator(spa_t *spa, uint_t allocator);
+void spa_select_allocator(zio_t *zio);
/* spa namespace global mutex */
extern kmutex_t spa_namespace_lock;
+extern avl_tree_t spa_namespace_avl;
+extern kcondvar_t spa_namespace_cv;
/*
* SPA configuration functions in spa_config.c
@@ -838,9 +845,9 @@ extern kmutex_t spa_namespace_lock;
#define SPA_CONFIG_UPDATE_POOL 0
#define SPA_CONFIG_UPDATE_VDEVS 1
-extern void spa_write_cachefile(spa_t *, boolean_t, boolean_t);
+extern void spa_write_cachefile(spa_t *, boolean_t, boolean_t, boolean_t);
extern void spa_config_load(void);
-extern nvlist_t *spa_all_configs(uint64_t *);
+extern int spa_all_configs(uint64_t *generation, nvlist_t **pools);
extern void spa_config_set(spa_t *spa, nvlist_t *config);
extern nvlist_t *spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg,
int getstats);
@@ -969,11 +976,17 @@ extern int spa_import_progress_set_max_txg(uint64_t pool_guid,
uint64_t max_txg);
extern int spa_import_progress_set_state(uint64_t pool_guid,
spa_load_state_t spa_load_state);
+extern void spa_import_progress_set_notes(spa_t *spa,
+ const char *fmt, ...) __printflike(2, 3);
+extern void spa_import_progress_set_notes_nolog(spa_t *spa,
+ const char *fmt, ...) __printflike(2, 3);
/* Pool configuration locks */
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,
krw_t rw);
extern void spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw);
+extern void spa_config_enter_mmp(spa_t *spa, int locks, const void *tag,
+ krw_t rw);
extern void spa_config_exit(spa_t *spa, int locks, const void *tag);
extern int spa_config_held(spa_t *spa, int locks, krw_t rw);
@@ -1013,7 +1026,7 @@ extern boolean_t spa_indirect_vdevs_loaded(spa_t *spa);
extern blkptr_t *spa_get_rootblkptr(spa_t *spa);
extern void spa_set_rootblkptr(spa_t *spa, const blkptr_t *bp);
extern void spa_altroot(spa_t *, char *, size_t);
-extern int spa_sync_pass(spa_t *spa);
+extern uint32_t spa_sync_pass(spa_t *spa);
extern char *spa_name(spa_t *spa);
extern uint64_t spa_guid(spa_t *spa);
extern uint64_t spa_load_guid(spa_t *spa);
@@ -1057,6 +1070,8 @@ extern uint64_t spa_deadman_synctime(spa_t *spa);
extern uint64_t spa_deadman_ziotime(spa_t *spa);
extern uint64_t spa_dirty_data(spa_t *spa);
extern spa_autotrim_t spa_get_autotrim(spa_t *spa);
+extern int spa_get_allocator(spa_t *spa);
+extern void spa_set_allocator(spa_t *spa, const char *allocator);
/* Miscellaneous support routines */
extern void spa_load_failed(spa_t *spa, const char *fmt, ...)
@@ -1110,6 +1125,8 @@ extern uint32_t spa_get_hostid(spa_t *spa);
extern void spa_activate_allocation_classes(spa_t *, dmu_tx_t *);
extern boolean_t spa_livelist_delete_check(spa_t *spa);
+extern boolean_t spa_mmp_remote_host_activity(spa_t *spa);
+
extern spa_mode_t spa_mode(spa_t *spa);
extern uint64_t zfs_strtonum(const char *str, char **nptr);
@@ -1133,7 +1150,10 @@ extern const char *spa_state_to_name(spa_t *spa);
/* error handling */
struct zbookmark_phys;
-extern void spa_log_error(spa_t *spa, const zbookmark_phys_t *zb);
+extern void spa_log_error(spa_t *spa, const zbookmark_phys_t *zb,
+ const uint64_t birth);
+extern void spa_remove_error(spa_t *spa, zbookmark_phys_t *zb,
+ uint64_t birth);
extern int zfs_ereport_post(const char *clazz, spa_t *spa, vdev_t *vd,
const zbookmark_phys_t *zb, zio_t *zio, uint64_t state);
extern boolean_t zfs_ereport_is_valid(const char *clazz, spa_t *spa, vdev_t *vd,
@@ -1145,8 +1165,9 @@ extern nvlist_t *zfs_event_create(spa_t *spa, vdev_t *vd, const char *type,
extern void zfs_post_remove(spa_t *spa, vdev_t *vd);
extern void zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate);
extern void zfs_post_autoreplace(spa_t *spa, vdev_t *vd);
-extern uint64_t spa_get_errlog_size(spa_t *spa);
+extern uint64_t spa_approx_errlog_size(spa_t *spa);
extern int spa_get_errlog(spa_t *spa, void *uaddr, uint64_t *count);
+extern uint64_t spa_get_last_errlog_size(spa_t *spa);
extern void spa_errlog_rotate(spa_t *spa);
extern void spa_errlog_drain(spa_t *spa);
extern void spa_errlog_sync(spa_t *spa, uint64_t txg);
@@ -1157,10 +1178,13 @@ extern void spa_swap_errlog(spa_t *spa, uint64_t new_head_ds,
extern void sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj,
dmu_tx_t *tx);
extern void spa_upgrade_errlog(spa_t *spa, dmu_tx_t *tx);
-
-/* vdev cache */
-extern void vdev_cache_stat_init(void);
-extern void vdev_cache_stat_fini(void);
+extern int find_top_affected_fs(spa_t *spa, uint64_t head_ds,
+ zbookmark_err_phys_t *zep, uint64_t *top_affected_fs);
+extern int find_birth_txg(struct dsl_dataset *ds, zbookmark_err_phys_t *zep,
+ uint64_t *birth_txg);
+extern void zep_to_zb(uint64_t dataset, zbookmark_err_phys_t *zep,
+ zbookmark_phys_t *zb);
+extern void name_to_errphys(char *buf, zbookmark_err_phys_t *zep);
/* vdev mirror */
extern void vdev_mirror_stat_init(void);
@@ -1201,6 +1225,7 @@ int param_set_deadman_ziotime(ZFS_MODULE_PARAM_ARGS);
int param_set_deadman_synctime(ZFS_MODULE_PARAM_ARGS);
int param_set_slop_shift(ZFS_MODULE_PARAM_ARGS);
int param_set_deadman_failmode(ZFS_MODULE_PARAM_ARGS);
+int param_set_active_allocator(ZFS_MODULE_PARAM_ARGS);
#ifdef ZFS_DEBUG
#define dprintf_bp(bp, fmt, ...) do { \
@@ -1217,9 +1242,9 @@ int param_set_deadman_failmode(ZFS_MODULE_PARAM_ARGS);
extern spa_mode_t spa_mode_global;
extern int zfs_deadman_enabled;
-extern unsigned long zfs_deadman_synctime_ms;
-extern unsigned long zfs_deadman_ziotime_ms;
-extern unsigned long zfs_deadman_checktime_ms;
+extern uint64_t zfs_deadman_synctime_ms;
+extern uint64_t zfs_deadman_ziotime_ms;
+extern uint64_t zfs_deadman_checktime_ms;
extern kmem_cache_t *zio_buf_cache[];
extern kmem_cache_t *zio_data_buf_cache[];
diff --git a/include/sys/spa_checkpoint.h b/include/sys/spa_checkpoint.h
index 9be2b6eeab3c..e4475ff35f44 100644
--- a/include/sys/spa_checkpoint.h
+++ b/include/sys/spa_checkpoint.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/spa_checksum.h b/include/sys/spa_checksum.h
index b87990105a71..2202afdeb8da 100644
--- a/include/sys/spa_checksum.h
+++ b/include/sys/spa_checksum.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
index 9946c4e3c316..a40914ec5fcb 100644
--- a/include/sys/spa_impl.h
+++ b/include/sys/spa_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,13 +20,13 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright 2013 Saso Kiselkov. All rights reserved.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
- * Copyright (c) 2017 Datto Inc.
* Copyright (c) 2017, Intel Corporation.
+ * Copyright (c) 2019 Datto Inc.
*/
#ifndef _SYS_SPA_IMPL_H
@@ -38,6 +38,7 @@
#include <sys/vdev.h>
#include <sys/vdev_rebuild.h>
#include <sys/vdev_removal.h>
+#include <sys/vdev_raidz.h>
#include <sys/metaslab.h>
#include <sys/dmu.h>
#include <sys/dsl_pool.h>
@@ -62,10 +63,17 @@ typedef struct spa_alloc {
avl_tree_t spaa_tree;
} ____cacheline_aligned spa_alloc_t;
+typedef struct spa_allocs_use {
+ kmutex_t sau_lock;
+ uint_t sau_rotor;
+ boolean_t sau_inuse[];
+} spa_allocs_use_t;
+
typedef struct spa_error_entry {
zbookmark_phys_t se_bookmark;
char *se_name;
avl_node_t se_avl;
+ zbookmark_err_phys_t se_zep; /* not accounted in avl_find */
} spa_error_entry_t;
typedef struct spa_history_phys {
@@ -187,6 +195,12 @@ typedef struct spa_taskqs {
taskq_t **stqs_taskq;
} spa_taskqs_t;
+/* one for each thread in the spa sync taskq */
+typedef struct spa_syncthread_info {
+ kthread_t *sti_thread;
+ uint_t sti_allocator;
+} spa_syncthread_info_t;
+
typedef enum spa_all_vdev_zap_action {
AVZ_ACTION_NONE = 0,
AVZ_ACTION_DESTROY, /* Destroy all per-vdev ZAPs and the AVZ. */
@@ -215,7 +229,7 @@ struct spa {
nvlist_t *spa_config_splitting; /* config for splitting */
nvlist_t *spa_load_info; /* info and errors from load */
uint64_t spa_config_txg; /* txg of last config change */
- int spa_sync_pass; /* iterate-to-convergence */
+ uint32_t spa_sync_pass; /* iterate-to-convergence */
pool_state_t spa_state; /* pool state */
int spa_inject_ref; /* injection references */
uint8_t spa_sync_on; /* sync threads are running */
@@ -229,6 +243,7 @@ struct spa {
dsl_pool_t *spa_dsl_pool;
boolean_t spa_is_initializing; /* true while opening pool */
boolean_t spa_is_exporting; /* true while exporting pool */
+ kthread_t *spa_load_thread; /* loading, no namespace lock */
metaslab_class_t *spa_normal_class; /* normal data class */
metaslab_class_t *spa_log_class; /* intent log data class */
metaslab_class_t *spa_embedded_log_class; /* log on normal vdevs */
@@ -249,6 +264,7 @@ struct spa {
uint64_t spa_min_ashift; /* of vdevs in normal class */
uint64_t spa_max_ashift; /* of vdevs in normal class */
uint64_t spa_min_alloc; /* of vdevs in normal class */
+ uint64_t spa_gcd_alloc; /* of vdevs in normal class */
uint64_t spa_config_guid; /* config pool guid */
uint64_t spa_load_guid; /* spa_load initialized guid */
uint64_t spa_last_synced_guid; /* last synced guid */
@@ -260,10 +276,17 @@ struct spa {
* allocation performance in write-heavy workloads.
*/
spa_alloc_t *spa_allocs;
+ spa_allocs_use_t *spa_allocs_use;
int spa_alloc_count;
+ int spa_active_allocator; /* selectable allocator */
+
+ /* per-allocator sync thread taskqs */
+ taskq_t *spa_sync_tq;
+ spa_syncthread_info_t *spa_syncthreads;
spa_aux_vdev_t spa_spares; /* hot spares */
spa_aux_vdev_t spa_l2cache; /* L2ARC cache devices */
+ boolean_t spa_aux_sync_uber; /* need to sync aux uber */
nvlist_t *spa_label_features; /* Features for reading MOS */
uint64_t spa_config_object; /* MOS object for pool config */
uint64_t spa_config_generation; /* config generation number */
@@ -294,6 +317,10 @@ struct spa {
uint64_t spa_scan_pass_exam; /* examined bytes per pass */
uint64_t spa_scan_pass_issued; /* issued bytes per pass */
+ /* error scrub pause time in milliseconds */
+ uint64_t spa_scan_pass_errorscrub_pause;
+ /* total error scrub paused time in milliseconds */
+ uint64_t spa_scan_pass_errorscrub_spent_paused;
/*
* We are in the middle of a resilver, and another resilver
* is needed once this one completes. This is set iff any
@@ -316,6 +343,9 @@ struct spa {
spa_condensing_indirect_t *spa_condensing_indirect;
zthr_t *spa_condense_zthr; /* zthr doing condense. */
+ vdev_raidz_expand_t *spa_raidz_expand;
+ zthr_t *spa_raidz_expand_zthr;
+
uint64_t spa_checkpoint_txg; /* the txg of the checkpoint */
spa_checkpoint_info_t spa_checkpoint_info; /* checkpoint accounting */
zthr_t *spa_checkpoint_discard_zthr;
@@ -349,6 +379,7 @@ struct spa {
kmutex_t spa_errlist_lock; /* error list/ereport lock */
avl_tree_t spa_errlist_last; /* last error list */
avl_tree_t spa_errlist_scrub; /* scrub error list */
+ avl_tree_t spa_errlist_healed; /* list of healed blocks */
uint64_t spa_deflate; /* should we deflate? */
uint64_t spa_history; /* history object */
kmutex_t spa_history_lock; /* history lock */
@@ -379,6 +410,7 @@ struct spa {
uint64_t spa_dedup_dspace; /* Cache get_dedup_dspace() */
uint64_t spa_dedup_checksum; /* default dedup checksum */
uint64_t spa_dspace; /* dspace in normal class */
+ struct brt *spa_brt; /* in-core BRT */
kmutex_t spa_vdev_top_lock; /* dueling offline/remove */
kmutex_t spa_proc_lock; /* protects spa_proc* */
kcondvar_t spa_proc_cv; /* spa_proc_state transitions */
@@ -415,7 +447,9 @@ struct spa {
hrtime_t spa_ccw_fail_time; /* Conf cache write fail time */
taskq_t *spa_zvol_taskq; /* Taskq for minor management */
+ taskq_t *spa_metaslab_taskq; /* Taskq for metaslab preload */
taskq_t *spa_prefetch_taskq; /* Taskq for prefetch threads */
+ taskq_t *spa_upgrade_taskq; /* Taskq for upgrade jobs */
uint64_t spa_multihost; /* multihost aware (mmp) */
mmp_thread_t spa_mmp; /* multihost mmp thread */
list_t spa_leaf_list; /* list of leaf vdevs */
@@ -439,15 +473,13 @@ struct spa {
*/
spa_config_lock_t spa_config_lock[SCL_LOCKS]; /* config changes */
zfs_refcount_t spa_refcount; /* number of opens */
-
- taskq_t *spa_upgrade_taskq; /* taskq for upgrade jobs */
};
extern char *spa_config_path;
extern const char *zfs_deadman_failmode;
-extern int spa_slop_shift;
+extern uint_t spa_slop_shift;
extern void spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
- task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent);
+ task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent, zio_t *zio);
extern void spa_taskq_dispatch_sync(spa_t *, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags);
extern void spa_load_spares(spa_t *spa);
@@ -459,6 +491,8 @@ extern int param_set_deadman_failmode_common(const char *val);
extern void spa_set_deadman_synctime(hrtime_t ns);
extern void spa_set_deadman_ziotime(hrtime_t ns);
extern const char *spa_history_zone(void);
+extern const char *zfs_active_allocator;
+extern int param_set_active_allocator_common(const char *val);
#ifdef __cplusplus
}
diff --git a/include/sys/spa_log_spacemap.h b/include/sys/spa_log_spacemap.h
index 72229df6cd16..f59e69917833 100644
--- a/include/sys/spa_log_spacemap.h
+++ b/include/sys/spa_log_spacemap.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/space_map.h b/include/sys/space_map.h
index cb81e710bd1e..14c5beccee55 100644
--- a/include/sys/space_map.h
+++ b/include/sys/space_map.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/space_reftree.h b/include/sys/space_reftree.h
index ca9d41dc1388..b7a846aec624 100644
--- a/include/sys/space_reftree.h
+++ b/include/sys/space_reftree.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/sysevent.h b/include/sys/sysevent.h
index 6510297d601f..f8ae17497366 100644
--- a/include/sys/sysevent.h
+++ b/include/sys/sysevent.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/sysevent/dev.h b/include/sys/sysevent/dev.h
index 1117538d822d..0783d0073162 100644
--- a/include/sys/sysevent/dev.h
+++ b/include/sys/sysevent/dev.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -244,6 +244,9 @@ extern "C" {
#define DEV_PATH "path"
#define DEV_IS_PART "is_slice"
#define DEV_SIZE "dev_size"
+
+/* Size of the whole parent block device (if dev is a partition) */
+#define DEV_PARENT_SIZE "dev_parent_size"
#endif /* __linux__ */
#define EV_V1 1
diff --git a/include/sys/sysevent/eventdefs.h b/include/sys/sysevent/eventdefs.h
index 2067b355afb4..a21085257967 100644
--- a/include/sys/sysevent/eventdefs.h
+++ b/include/sys/sysevent/eventdefs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -123,6 +123,11 @@ extern "C" {
#define ESC_ZFS_TRIM_CANCEL "trim_cancel"
#define ESC_ZFS_TRIM_RESUME "trim_resume"
#define ESC_ZFS_TRIM_SUSPEND "trim_suspend"
+#define ESC_ZFS_ERRORSCRUB_START "errorscrub_start"
+#define ESC_ZFS_ERRORSCRUB_FINISH "errorscrub_finish"
+#define ESC_ZFS_ERRORSCRUB_ABORT "errorscrub_abort"
+#define ESC_ZFS_ERRORSCRUB_RESUME "errorscrub_resume"
+#define ESC_ZFS_ERRORSCRUB_PAUSED "errorscrub_paused"
/*
* datalink subclass definitions.
diff --git a/include/sys/txg.h b/include/sys/txg.h
index f38f0006c040..46945210cdb5 100644
--- a/include/sys/txg.h
+++ b/include/sys/txg.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -138,7 +138,7 @@ extern void *txg_list_head(txg_list_t *tl, uint64_t txg);
extern void *txg_list_next(txg_list_t *tl, void *p, uint64_t txg);
/* Global tuning */
-extern int zfs_txg_timeout;
+extern uint_t zfs_txg_timeout;
#ifdef ZFS_DEBUG
diff --git a/include/sys/txg_impl.h b/include/sys/txg_impl.h
index 047d51b94c66..8ab7969b25be 100644
--- a/include/sys/txg_impl.h
+++ b/include/sys/txg_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -73,8 +73,7 @@ struct tx_cpu {
kcondvar_t tc_cv[TXG_SIZE];
uint64_t tc_count[TXG_SIZE]; /* tx hold count on each txg */
list_t tc_callbacks[TXG_SIZE]; /* commit cb list */
- char tc_pad[8]; /* pad to fill 3 cache lines */
-};
+} ____cacheline_aligned;
/*
* The tx_state structure maintains the state information about the different
diff --git a/include/sys/u8_textprep.h b/include/sys/u8_textprep.h
index 09ab13af268c..e82037de4fe4 100644
--- a/include/sys/u8_textprep.h
+++ b/include/sys/u8_textprep.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/u8_textprep_data.h b/include/sys/u8_textprep_data.h
index 03f71f26c9e1..2a97966ee56e 100644
--- a/include/sys/u8_textprep_data.h
+++ b/include/sys/u8_textprep_data.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/uberblock.h b/include/sys/uberblock.h
index 044e438387c0..ff3a8c81232a 100644
--- a/include/sys/uberblock.h
+++ b/include/sys/uberblock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/uberblock_impl.h b/include/sys/uberblock_impl.h
index 91699e65131a..e480a4bac0b9 100644
--- a/include/sys/uberblock_impl.h
+++ b/include/sys/uberblock_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -50,20 +50,20 @@ extern "C" {
#define MMP_SEQ_VALID_BIT 0x02
#define MMP_FAIL_INT_VALID_BIT 0x04
-#define MMP_VALID(ubp) (ubp->ub_magic == UBERBLOCK_MAGIC && \
- ubp->ub_mmp_magic == MMP_MAGIC)
-#define MMP_INTERVAL_VALID(ubp) (MMP_VALID(ubp) && (ubp->ub_mmp_config & \
+#define MMP_VALID(ubp) ((ubp)->ub_magic == UBERBLOCK_MAGIC && \
+ (ubp)->ub_mmp_magic == MMP_MAGIC)
+#define MMP_INTERVAL_VALID(ubp) (MMP_VALID(ubp) && ((ubp)->ub_mmp_config & \
MMP_INTERVAL_VALID_BIT))
-#define MMP_SEQ_VALID(ubp) (MMP_VALID(ubp) && (ubp->ub_mmp_config & \
+#define MMP_SEQ_VALID(ubp) (MMP_VALID(ubp) && ((ubp)->ub_mmp_config & \
MMP_SEQ_VALID_BIT))
-#define MMP_FAIL_INT_VALID(ubp) (MMP_VALID(ubp) && (ubp->ub_mmp_config & \
+#define MMP_FAIL_INT_VALID(ubp) (MMP_VALID(ubp) && ((ubp)->ub_mmp_config & \
MMP_FAIL_INT_VALID_BIT))
-#define MMP_INTERVAL(ubp) ((ubp->ub_mmp_config & 0x00000000FFFFFF00) \
+#define MMP_INTERVAL(ubp) (((ubp)->ub_mmp_config & 0x00000000FFFFFF00) \
>> 8)
-#define MMP_SEQ(ubp) ((ubp->ub_mmp_config & 0x0000FFFF00000000) \
+#define MMP_SEQ(ubp) (((ubp)->ub_mmp_config & 0x0000FFFF00000000) \
>> 32)
-#define MMP_FAIL_INT(ubp) ((ubp->ub_mmp_config & 0xFFFF000000000000) \
+#define MMP_FAIL_INT(ubp) (((ubp)->ub_mmp_config & 0xFFFF000000000000) \
>> 48)
#define MMP_INTERVAL_SET(write) \
@@ -75,6 +75,39 @@ extern "C" {
#define MMP_FAIL_INT_SET(fail) \
(((uint64_t)(fail & 0xFFFF) << 48) | MMP_FAIL_INT_VALID_BIT)
+/*
+ * RAIDZ expansion reflow information.
+ *
+ * 64 56 48 40 32 24 16 8 0
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |Scratch | Reflow |
+ * | State | Offset |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+typedef enum raidz_reflow_scratch_state {
+ RRSS_SCRATCH_NOT_IN_USE = 0,
+ RRSS_SCRATCH_VALID,
+ RRSS_SCRATCH_INVALID_SYNCED,
+ RRSS_SCRATCH_INVALID_SYNCED_ON_IMPORT,
+ RRSS_SCRATCH_INVALID_SYNCED_REFLOW
+} raidz_reflow_scratch_state_t;
+
+#define RRSS_GET_OFFSET(ub) \
+ BF64_GET_SB((ub)->ub_raidz_reflow_info, 0, 55, SPA_MINBLOCKSHIFT, 0)
+#define RRSS_SET_OFFSET(ub, x) \
+ BF64_SET_SB((ub)->ub_raidz_reflow_info, 0, 55, SPA_MINBLOCKSHIFT, 0, x)
+
+#define RRSS_GET_STATE(ub) \
+ BF64_GET((ub)->ub_raidz_reflow_info, 55, 9)
+#define RRSS_SET_STATE(ub, x) \
+ BF64_SET((ub)->ub_raidz_reflow_info, 55, 9, x)
+
+#define RAIDZ_REFLOW_SET(ub, state, offset) do { \
+ (ub)->ub_raidz_reflow_info = 0; \
+ RRSS_SET_OFFSET(ub, offset); \
+ RRSS_SET_STATE(ub, state); \
+} while (0)
+
struct uberblock {
uint64_t ub_magic; /* UBERBLOCK_MAGIC */
uint64_t ub_version; /* SPA_VERSION */
@@ -132,10 +165,12 @@ struct uberblock {
* pool from a checkpointed uberblock [see spa_ld_select_uberblock()],
* the value of the field is used to determine which ZIL blocks have
* been allocated according to the ms_sm when we are rewinding to a
- * checkpoint. Specifically, if blk_birth > ub_checkpoint_txg, then
+ * checkpoint. Specifically, if logical birth > ub_checkpoint_txg,then
* the ZIL block is not allocated [see uses of spa_min_claim_txg()].
*/
uint64_t ub_checkpoint_txg;
+
+ uint64_t ub_raidz_reflow_info;
};
#ifdef __cplusplus
diff --git a/include/sys/uio_impl.h b/include/sys/uio_impl.h
index cde3ef40485b..aa34edda5f6a 100644
--- a/include/sys/uio_impl.h
+++ b/include/sys/uio_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/unique.h b/include/sys/unique.h
index d4ba32e5c642..bc7944657521 100644
--- a/include/sys/unique.h
+++ b/include/sys/unique.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/uuid.h b/include/sys/uuid.h
index eab4622a6d9a..19f1baa4432e 100644
--- a/include/sys/uuid.h
+++ b/include/sys/uuid.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/vdev.h b/include/sys/vdev.h
index 8a526d0bf511..38f62b07dc59 100644
--- a/include/sys/vdev.h
+++ b/include/sys/vdev.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -132,15 +132,19 @@ extern void vdev_space_update(vdev_t *vd,
extern int64_t vdev_deflated_space(vdev_t *vd, int64_t space);
+extern uint64_t vdev_psize_to_asize_txg(vdev_t *vd, uint64_t psize,
+ uint64_t txg);
extern uint64_t vdev_psize_to_asize(vdev_t *vd, uint64_t psize);
/*
- * Return the amount of space allocated for a gang block header.
+ * Return the amount of space allocated for a gang block header. Note that
+ * since the physical birth txg is not provided, this must be constant for
+ * a given vdev. (e.g. raidz expansion can't change this)
*/
static inline uint64_t
vdev_gang_header_asize(vdev_t *vd)
{
- return (vdev_psize_to_asize(vd, SPA_GANGBLOCKSIZE));
+ return (vdev_psize_to_asize_txg(vd, SPA_GANGBLOCKSIZE, 0));
}
extern int vdev_fault(spa_t *spa, uint64_t guid, vdev_aux_t aux);
@@ -148,6 +152,7 @@ extern int vdev_degrade(spa_t *spa, uint64_t guid, vdev_aux_t aux);
extern int vdev_online(spa_t *spa, uint64_t guid, uint64_t flags,
vdev_state_t *);
extern int vdev_offline(spa_t *spa, uint64_t guid, uint64_t flags);
+extern int vdev_remove_wanted(spa_t *spa, uint64_t guid);
extern void vdev_clear(spa_t *spa, vdev_t *vd);
extern boolean_t vdev_is_dead(vdev_t *vd);
@@ -157,20 +162,15 @@ extern boolean_t vdev_allocatable(vdev_t *vd);
extern boolean_t vdev_accessible(vdev_t *vd, zio_t *zio);
extern boolean_t vdev_is_spacemap_addressable(vdev_t *vd);
-extern void vdev_cache_init(vdev_t *vd);
-extern void vdev_cache_fini(vdev_t *vd);
-extern boolean_t vdev_cache_read(zio_t *zio);
-extern void vdev_cache_write(zio_t *zio);
-extern void vdev_cache_purge(vdev_t *vd);
-
extern void vdev_queue_init(vdev_t *vd);
extern void vdev_queue_fini(vdev_t *vd);
extern zio_t *vdev_queue_io(zio_t *zio);
extern void vdev_queue_io_done(zio_t *zio);
extern void vdev_queue_change_io_priority(zio_t *zio, zio_priority_t priority);
-extern int vdev_queue_length(vdev_t *vd);
+extern uint32_t vdev_queue_length(vdev_t *vd);
extern uint64_t vdev_queue_last_offset(vdev_t *vd);
+extern uint64_t vdev_queue_class_length(vdev_t *vq, zio_priority_t p);
extern void vdev_config_dirty(vdev_t *vd);
extern void vdev_config_clean(vdev_t *vd);
@@ -185,11 +185,12 @@ extern boolean_t vdev_clear_resilver_deferred(vdev_t *vd, dmu_tx_t *tx);
typedef enum vdev_config_flag {
VDEV_CONFIG_SPARE = 1 << 0,
VDEV_CONFIG_L2CACHE = 1 << 1,
- VDEV_CONFIG_REMOVING = 1 << 2,
- VDEV_CONFIG_MOS = 1 << 3,
- VDEV_CONFIG_MISSING = 1 << 4
+ VDEV_CONFIG_MOS = 1 << 2,
+ VDEV_CONFIG_MISSING = 1 << 3
} vdev_config_flag_t;
+extern void vdev_post_kobj_evt(vdev_t *vd);
+extern void vdev_clear_kobj_evt(vdev_t *vd);
extern void vdev_top_config_generate(spa_t *spa, nvlist_t *config);
extern nvlist_t *vdev_config_generate(spa_t *spa, vdev_t *vd,
boolean_t getstats, vdev_config_flag_t flags);
@@ -207,6 +208,8 @@ extern void vdev_label_write(zio_t *zio, vdev_t *vd, int l, abd_t *buf, uint64_t
offset, uint64_t size, zio_done_func_t *done, void *priv, int flags);
extern int vdev_label_read_bootenv(vdev_t *, nvlist_t *);
extern int vdev_label_write_bootenv(vdev_t *, nvlist_t *);
+extern int vdev_uberblock_sync_list(vdev_t **, int, struct uberblock *, int);
+extern int vdev_check_boot_reserve(spa_t *, vdev_t *);
typedef enum {
VDEV_LABEL_CREATE, /* create/add a new device */
diff --git a/include/sys/vdev_disk.h b/include/sys/vdev_disk.h
index a7e19fbf0c4b..02c583777ebc 100644
--- a/include/sys/vdev_disk.h
+++ b/include/sys/vdev_disk.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/vdev_draid.h b/include/sys/vdev_draid.h
index dd334acbacf1..a204f1e3c74a 100644
--- a/include/sys/vdev_draid.h
+++ b/include/sys/vdev_draid.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/vdev_file.h b/include/sys/vdev_file.h
index 1514a44fcabb..fddecbfe1ab5 100644
--- a/include/sys/vdev_file.h
+++ b/include/sys/vdev_file.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h
index db8fbdeb06df..57ff31e89eb9 100644
--- a/include/sys/vdev_impl.h
+++ b/include/sys/vdev_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
+ * Copyright (c) 2023, Klara Inc.
*/
#ifndef _SYS_VDEV_IMPL_H
@@ -34,7 +35,6 @@
#include <sys/nvpair.h>
#include <sys/space_map.h>
#include <sys/vdev.h>
-#include <sys/dkio.h>
#include <sys/uberblock_impl.h>
#include <sys/vdev_indirect_mapping.h>
#include <sys/vdev_indirect_births.h>
@@ -57,23 +57,22 @@ extern "C" {
* Forward declarations that lots of things need.
*/
typedef struct vdev_queue vdev_queue_t;
-typedef struct vdev_cache vdev_cache_t;
-typedef struct vdev_cache_entry vdev_cache_entry_t;
struct abd;
-extern int zfs_vdev_queue_depth_pct;
-extern int zfs_vdev_def_queue_depth;
-extern uint32_t zfs_vdev_async_write_max_active;
+extern uint_t zfs_vdev_queue_depth_pct;
+extern uint_t zfs_vdev_def_queue_depth;
+extern uint_t zfs_vdev_async_write_max_active;
/*
* Virtual device operations
*/
typedef int vdev_init_func_t(spa_t *spa, nvlist_t *nv, void **tsd);
+typedef void vdev_kobj_post_evt_func_t(vdev_t *vd);
typedef void vdev_fini_func_t(vdev_t *vd);
typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *max_size,
uint64_t *ashift, uint64_t *pshift);
typedef void vdev_close_func_t(vdev_t *vd);
-typedef uint64_t vdev_asize_func_t(vdev_t *vd, uint64_t psize);
+typedef uint64_t vdev_asize_func_t(vdev_t *vd, uint64_t psize, uint64_t txg);
typedef uint64_t vdev_min_asize_func_t(vdev_t *vd);
typedef uint64_t vdev_min_alloc_func_t(vdev_t *vd);
typedef void vdev_io_start_func_t(zio_t *zio);
@@ -123,6 +122,7 @@ typedef const struct vdev_ops {
vdev_config_generate_func_t *vdev_op_config_generate;
vdev_nparity_func_t *vdev_op_nparity;
vdev_ndisks_func_t *vdev_op_ndisks;
+ vdev_kobj_post_evt_func_t *vdev_op_kobj_evt_post;
char vdev_op_type[16];
boolean_t vdev_op_leaf;
} vdev_ops_t;
@@ -130,44 +130,27 @@ typedef const struct vdev_ops {
/*
* Virtual device properties
*/
-struct vdev_cache_entry {
- struct abd *ve_abd;
- uint64_t ve_offset;
- clock_t ve_lastused;
- avl_node_t ve_offset_node;
- avl_node_t ve_lastused_node;
- uint32_t ve_hits;
- uint16_t ve_missed_update;
- zio_t *ve_fill_io;
-};
-
-struct vdev_cache {
- avl_tree_t vc_offset_tree;
- avl_tree_t vc_lastused_tree;
- kmutex_t vc_lock;
-};
-
-typedef struct vdev_queue_class {
- uint32_t vqc_active;
-
- /*
- * Sorted by offset or timestamp, depending on if the queue is
- * LBA-ordered vs FIFO.
- */
- avl_tree_t vqc_queued_tree;
+typedef union vdev_queue_class {
+ struct {
+ ulong_t vqc_list_numnodes;
+ list_t vqc_list;
+ };
+ avl_tree_t vqc_tree;
} vdev_queue_class_t;
struct vdev_queue {
vdev_t *vq_vdev;
vdev_queue_class_t vq_class[ZIO_PRIORITY_NUM_QUEUEABLE];
- avl_tree_t vq_active_tree;
avl_tree_t vq_read_offset_tree;
avl_tree_t vq_write_offset_tree;
- avl_tree_t vq_trim_offset_tree;
uint64_t vq_last_offset;
zio_priority_t vq_last_prio; /* Last sent I/O priority. */
+ uint32_t vq_cqueued; /* Classes with queued I/Os. */
+ uint32_t vq_cactive[ZIO_PRIORITY_NUM_QUEUEABLE];
+ uint32_t vq_active; /* Number of active I/Os. */
uint32_t vq_ia_active; /* Active interactive I/Os. */
uint32_t vq_nia_credit; /* Non-interactive I/Os credit. */
+ list_t vq_active_list; /* List of active I/Os. */
hrtime_t vq_io_complete_ts; /* time last i/o completed */
hrtime_t vq_io_delta_ts;
zio_t vq_io_search; /* used as local for stack reduction */
@@ -275,6 +258,7 @@ struct vdev {
kthread_t *vdev_open_thread; /* thread opening children */
kthread_t *vdev_validate_thread; /* thread validating children */
uint64_t vdev_crtxg; /* txg when top-level was added */
+ uint64_t vdev_root_zap;
/*
* Top-level vdev state.
@@ -285,18 +269,19 @@ struct vdev {
metaslab_group_t *vdev_mg; /* metaslab group */
metaslab_group_t *vdev_log_mg; /* embedded slog metaslab group */
metaslab_t **vdev_ms; /* metaslab array */
- uint64_t vdev_pending_fastwrite; /* allocated fastwrites */
txg_list_t vdev_ms_list; /* per-txg dirty metaslab lists */
txg_list_t vdev_dtl_list; /* per-txg dirty DTL lists */
txg_node_t vdev_txg_node; /* per-txg dirty vdev linkage */
boolean_t vdev_remove_wanted; /* async remove wanted? */
- boolean_t vdev_probe_wanted; /* async probe wanted? */
+ boolean_t vdev_fault_wanted; /* async faulted wanted? */
list_node_t vdev_config_dirty_node; /* config dirty list */
list_node_t vdev_state_dirty_node; /* state dirty list */
uint64_t vdev_deflate_ratio; /* deflation ratio (x512) */
uint64_t vdev_islog; /* is an intent log device */
uint64_t vdev_noalloc; /* device is passivated? */
uint64_t vdev_removing; /* device is being removed? */
+ uint64_t vdev_failfast; /* device failfast setting */
+ boolean_t vdev_rz_expanding; /* raidz is being expanded? */
boolean_t vdev_ishole; /* is a hole in the namespace */
uint64_t vdev_top_zap;
vdev_alloc_bias_t vdev_alloc_bias; /* metaslab allocation bias */
@@ -326,6 +311,7 @@ struct vdev {
list_node_t vdev_trim_node;
kmutex_t vdev_autotrim_lock;
kcondvar_t vdev_autotrim_cv;
+ kcondvar_t vdev_autotrim_kick_cv;
kthread_t *vdev_autotrim_thread;
/* Protects vdev_trim_thread and vdev_trim_state. */
kmutex_t vdev_trim_lock;
@@ -436,8 +422,9 @@ struct vdev {
boolean_t vdev_isl2cache; /* was a l2cache device */
boolean_t vdev_copy_uberblocks; /* post expand copy uberblocks */
boolean_t vdev_resilver_deferred; /* resilver deferred */
+ boolean_t vdev_kobj_flag; /* kobj event record */
+ boolean_t vdev_attaching; /* vdev attach ashift handling */
vdev_queue_t vdev_queue; /* I/O deadline schedule queue */
- vdev_cache_t vdev_cache; /* physical block cache */
spa_aux_vdev_t *vdev_aux; /* for l2cache and spares vdevs */
zio_t *vdev_probe_zio; /* root of current probe */
vdev_aux_t vdev_label_aux; /* on-disk aux state */
@@ -465,6 +452,16 @@ struct vdev {
zfs_ratelimit_t vdev_delay_rl;
zfs_ratelimit_t vdev_deadman_rl;
zfs_ratelimit_t vdev_checksum_rl;
+
+ /*
+ * Vdev properties for tuning ZED or zfsd
+ */
+ uint64_t vdev_checksum_n;
+ uint64_t vdev_checksum_t;
+ uint64_t vdev_io_n;
+ uint64_t vdev_io_t;
+ uint64_t vdev_slow_io_n;
+ uint64_t vdev_slow_io_t;
};
#define VDEV_PAD_SIZE (8 << 10)
@@ -542,6 +539,7 @@ typedef struct vdev_label {
/*
* Size of embedded boot loader region on each label.
* The total size of the first two labels plus the boot area is 4MB.
+ * On RAIDZ, this space is overwritten during RAIDZ expansion.
*/
#define VDEV_BOOT_SIZE (7ULL << 19) /* 3.5M */
@@ -614,7 +612,7 @@ extern vdev_ops_t vdev_indirect_ops;
*/
extern void vdev_default_xlate(vdev_t *vd, const range_seg64_t *logical_rs,
range_seg64_t *physical_rs, range_seg64_t *remain_rs);
-extern uint64_t vdev_default_asize(vdev_t *vd, uint64_t psize);
+extern uint64_t vdev_default_asize(vdev_t *vd, uint64_t psize, uint64_t txg);
extern uint64_t vdev_default_min_asize(vdev_t *vd);
extern uint64_t vdev_get_min_asize(vdev_t *vd);
extern void vdev_set_min_asize(vdev_t *vd);
@@ -641,12 +639,13 @@ extern int vdev_obsolete_counts_are_precise(vdev_t *vd, boolean_t *are_precise);
*/
int vdev_checkpoint_sm_object(vdev_t *vd, uint64_t *sm_obj);
void vdev_metaslab_group_create(vdev_t *vd);
+uint64_t vdev_best_ashift(uint64_t logical, uint64_t a, uint64_t b);
/*
* Vdev ashift optimization tunables
*/
-extern uint64_t zfs_vdev_min_auto_ashift;
-extern uint64_t zfs_vdev_max_auto_ashift;
+extern uint_t zfs_vdev_min_auto_ashift;
+extern uint_t zfs_vdev_max_auto_ashift;
int param_set_min_auto_ashift(ZFS_MODULE_PARAM_ARGS);
int param_set_max_auto_ashift(ZFS_MODULE_PARAM_ARGS);
diff --git a/include/sys/vdev_initialize.h b/include/sys/vdev_initialize.h
index 81d39ebebcb2..78702b7325a0 100644
--- a/include/sys/vdev_initialize.h
+++ b/include/sys/vdev_initialize.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,6 +33,7 @@ extern "C" {
#endif
extern void vdev_initialize(vdev_t *vd);
+extern void vdev_uninitialize(vdev_t *vd);
extern void vdev_initialize_stop(vdev_t *vd,
vdev_initializing_state_t tgt_state, list_t *vd_list);
extern void vdev_initialize_stop_all(vdev_t *vd,
diff --git a/include/sys/vdev_raidz.h b/include/sys/vdev_raidz.h
index c7cf0af6d945..a34bc00ca4df 100644
--- a/include/sys/vdev_raidz.h
+++ b/include/sys/vdev_raidz.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,6 +26,7 @@
#define _SYS_VDEV_RAIDZ_H
#include <sys/types.h>
+#include <sys/zfs_rlock.h>
#ifdef __cplusplus
extern "C" {
@@ -35,6 +36,8 @@ struct zio;
struct raidz_col;
struct raidz_row;
struct raidz_map;
+struct vdev_raidz;
+struct uberblock;
#if !defined(_KERNEL)
struct kernel_param {};
#endif
@@ -44,13 +47,19 @@ struct kernel_param {};
*/
struct raidz_map *vdev_raidz_map_alloc(struct zio *, uint64_t, uint64_t,
uint64_t);
+struct raidz_map *vdev_raidz_map_alloc_expanded(struct zio *,
+ uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, boolean_t);
void vdev_raidz_map_free(struct raidz_map *);
+void vdev_raidz_free(struct vdev_raidz *);
void vdev_raidz_generate_parity_row(struct raidz_map *, struct raidz_row *);
void vdev_raidz_generate_parity(struct raidz_map *);
void vdev_raidz_reconstruct(struct raidz_map *, const int *, int);
void vdev_raidz_child_done(zio_t *);
void vdev_raidz_io_done(zio_t *);
void vdev_raidz_checksum_error(zio_t *, struct raidz_col *, abd_t *);
+struct raidz_row *vdev_raidz_row_alloc(int);
+void vdev_raidz_reflow_copy_scratch(spa_t *);
+void raidz_dtl_reassessed(vdev_t *);
extern const zio_vsd_ops_t vdev_raidz_vsd_ops;
@@ -65,11 +74,101 @@ int vdev_raidz_math_reconstruct(struct raidz_map *, struct raidz_row *,
const int *, const int *, const int);
int vdev_raidz_impl_set(const char *);
+typedef struct vdev_raidz_expand {
+ uint64_t vre_vdev_id;
+
+ kmutex_t vre_lock;
+ kcondvar_t vre_cv;
+
+ /*
+ * How much i/o is outstanding (issued and not completed).
+ */
+ uint64_t vre_outstanding_bytes;
+
+ /*
+ * Next offset to issue i/o for.
+ */
+ uint64_t vre_offset;
+
+ /*
+ * Lowest offset of a failed expansion i/o. The expansion will retry
+ * from here. Once the expansion thread notices the failure and exits,
+ * vre_failed_offset is reset back to UINT64_MAX, and
+ * vre_waiting_for_resilver will be set.
+ */
+ uint64_t vre_failed_offset;
+ boolean_t vre_waiting_for_resilver;
+
+ /*
+ * Offset that is completing each txg
+ */
+ uint64_t vre_offset_pertxg[TXG_SIZE];
+
+ /*
+ * Bytes copied in each txg.
+ */
+ uint64_t vre_bytes_copied_pertxg[TXG_SIZE];
+
+ /*
+ * The rangelock prevents normal read/write zio's from happening while
+ * there are expansion (reflow) i/os in progress to the same offsets.
+ */
+ zfs_rangelock_t vre_rangelock;
+
+ /*
+ * These fields are stored on-disk in the vdev_top_zap:
+ */
+ dsl_scan_state_t vre_state;
+ uint64_t vre_start_time;
+ uint64_t vre_end_time;
+ uint64_t vre_bytes_copied;
+} vdev_raidz_expand_t;
+
typedef struct vdev_raidz {
- int vd_logical_width;
+ /*
+ * Number of child vdevs when this raidz vdev was created (i.e. before
+ * any raidz expansions).
+ */
+ int vd_original_width;
+
+ /*
+ * The current number of child vdevs, which may be more than the
+ * original width if an expansion is in progress or has completed.
+ */
+ int vd_physical_width;
+
int vd_nparity;
+
+ /*
+ * Tree of reflow_node_t's. The lock protects the avl tree only.
+ * The reflow_node_t's describe completed expansions, and are used
+ * to determine the logical width given a block's birth time.
+ */
+ avl_tree_t vd_expand_txgs;
+ kmutex_t vd_expand_lock;
+
+ /*
+ * If this vdev is being expanded, spa_raidz_expand is set to this
+ */
+ vdev_raidz_expand_t vn_vre;
} vdev_raidz_t;
+extern int vdev_raidz_attach_check(vdev_t *);
+extern void vdev_raidz_attach_sync(void *, dmu_tx_t *);
+extern void spa_start_raidz_expansion_thread(spa_t *);
+extern int spa_raidz_expand_get_stats(spa_t *, pool_raidz_expand_stat_t *);
+extern int vdev_raidz_load(vdev_t *);
+
+/* RAIDZ scratch area pause points (for testing) */
+#define RAIDZ_EXPAND_PAUSE_NONE 0
+#define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_1 1
+#define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_2 2
+#define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_3 3
+#define RAIDZ_EXPAND_PAUSE_SCRATCH_VALID 4
+#define RAIDZ_EXPAND_PAUSE_SCRATCH_REFLOWED 5
+#define RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_1 6
+#define RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_2 7
+
#ifdef __cplusplus
}
#endif
diff --git a/include/sys/vdev_raidz_impl.h b/include/sys/vdev_raidz_impl.h
index 890e725e18d8..45cb5864a22b 100644
--- a/include/sys/vdev_raidz_impl.h
+++ b/include/sys/vdev_raidz_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,6 +30,8 @@
#include <sys/kstat.h>
#include <sys/abd.h>
#include <sys/vdev_impl.h>
+#include <sys/abd_impl.h>
+#include <sys/zfs_rlock.h>
#ifdef __cplusplus
extern "C" {
@@ -102,35 +104,39 @@ typedef struct raidz_impl_ops {
char name[RAIDZ_IMPL_NAME_MAX]; /* Name of the implementation */
} raidz_impl_ops_t;
+
typedef struct raidz_col {
- uint64_t rc_devidx; /* child device index for I/O */
+ int rc_devidx; /* child device index for I/O */
+ uint32_t rc_size; /* I/O size */
uint64_t rc_offset; /* device offset */
- uint64_t rc_size; /* I/O size */
abd_t rc_abdstruct; /* rc_abd probably points here */
abd_t *rc_abd; /* I/O data */
abd_t *rc_orig_data; /* pre-reconstruction */
int rc_error; /* I/O error for this device */
- uint8_t rc_tried; /* Did we attempt this I/O column? */
- uint8_t rc_skipped; /* Did we skip this I/O column? */
- uint8_t rc_need_orig_restore; /* need to restore from orig_data? */
- uint8_t rc_force_repair; /* Write good data to this column */
- uint8_t rc_allow_repair; /* Allow repair I/O to this column */
+ uint8_t rc_tried:1; /* Did we attempt this I/O column? */
+ uint8_t rc_skipped:1; /* Did we skip this I/O column? */
+ uint8_t rc_need_orig_restore:1; /* need to restore from orig_data? */
+ uint8_t rc_force_repair:1; /* Write good data to this column */
+ uint8_t rc_allow_repair:1; /* Allow repair I/O to this column */
+ int rc_shadow_devidx; /* for double write during expansion */
+ int rc_shadow_error; /* for double write during expansion */
+ uint64_t rc_shadow_offset; /* for double write during expansion */
} raidz_col_t;
typedef struct raidz_row {
- uint64_t rr_cols; /* Regular column count */
- uint64_t rr_scols; /* Count including skipped columns */
- uint64_t rr_bigcols; /* Remainder data column count */
- uint64_t rr_missingdata; /* Count of missing data devices */
- uint64_t rr_missingparity; /* Count of missing parity devices */
- uint64_t rr_firstdatacol; /* First data column/parity count */
+ int rr_cols; /* Regular column count */
+ int rr_scols; /* Count including skipped columns */
+ int rr_bigcols; /* Remainder data column count */
+ int rr_missingdata; /* Count of missing data devices */
+ int rr_missingparity; /* Count of missing parity devices */
+ int rr_firstdatacol; /* First data column/parity count */
abd_t *rr_abd_empty; /* dRAID empty sector buffer */
int rr_nempty; /* empty sectors included in parity */
#ifdef ZFS_DEBUG
uint64_t rr_offset; /* Logical offset for *_io_verify() */
uint64_t rr_size; /* Physical size for *_io_verify() */
#endif
- raidz_col_t rr_col[0]; /* Flexible array of I/O columns */
+ raidz_col_t rr_col[]; /* Flexible array of I/O columns */
} raidz_row_t;
typedef struct raidz_map {
@@ -138,10 +144,25 @@ typedef struct raidz_map {
int rm_nrows; /* Regular row count */
int rm_nskip; /* RAIDZ sectors skipped for padding */
int rm_skipstart; /* Column index of padding start */
+ int rm_original_width; /* pre-expansion width of raidz vdev */
+ int rm_nphys_cols; /* num entries in rm_phys_col[] */
+ zfs_locked_range_t *rm_lr;
const raidz_impl_ops_t *rm_ops; /* RAIDZ math operations */
- raidz_row_t *rm_row[0]; /* flexible array of rows */
+ raidz_col_t *rm_phys_col; /* if non-NULL, read i/o aggregation */
+ raidz_row_t *rm_row[]; /* flexible array of rows */
} raidz_map_t;
+/*
+ * Nodes in vdev_raidz_t:vd_expand_txgs.
+ * Blocks with physical birth time of re_txg or later have the specified
+ * logical width (until the next node).
+ */
+typedef struct reflow_node {
+ uint64_t re_txg;
+ uint64_t re_logical_width;
+ avl_node_t re_link;
+} reflow_node_t;
+
#define RAIDZ_ORIGINAL_IMPL (INT_MAX)
@@ -321,7 +342,7 @@ vdev_raidz_exp2(const uint8_t a, const unsigned exp)
* Galois Field operations.
*
* gf_exp2 - computes 2 raised to the given power
- * gf_exp2 - computes 4 raised to the given power
+ * gf_exp4 - computes 4 raised to the given power
* gf_mul - multiplication
* gf_div - division
* gf_inv - multiplicative inverse
diff --git a/include/sys/vdev_rebuild.h b/include/sys/vdev_rebuild.h
index b59fbe153903..55ec6c570316 100644
--- a/include/sys/vdev_rebuild.h
+++ b/include/sys/vdev_rebuild.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -79,6 +79,7 @@ typedef struct vdev_rebuild {
uint64_t vr_pass_start_time;
uint64_t vr_pass_bytes_scanned;
uint64_t vr_pass_bytes_issued;
+ uint64_t vr_pass_bytes_skipped;
/* On-disk state updated by vdev_rebuild_zap_update_sync() */
vdev_rebuild_phys_t vr_rebuild_phys;
diff --git a/include/sys/vdev_removal.h b/include/sys/vdev_removal.h
index e3bab0658d62..70b743f4ec6b 100644
--- a/include/sys/vdev_removal.h
+++ b/include/sys/vdev_removal.h
@@ -87,7 +87,7 @@ extern int spa_vdev_remove_cancel(spa_t *);
extern void spa_vdev_removal_destroy(spa_vdev_removal_t *);
extern uint64_t spa_remove_max_segment(spa_t *);
-extern int vdev_removal_max_span;
+extern uint_t vdev_removal_max_span;
#ifdef __cplusplus
}
diff --git a/include/sys/vdev_trim.h b/include/sys/vdev_trim.h
index 16f4be2a41f8..7a94d4af098f 100644
--- a/include/sys/vdev_trim.h
+++ b/include/sys/vdev_trim.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,6 +41,7 @@ extern void vdev_trim_stop_all(vdev_t *vd, vdev_trim_state_t tgt_state);
extern void vdev_trim_stop_wait(spa_t *spa, list_t *vd_list);
extern void vdev_trim_restart(vdev_t *vd);
extern void vdev_autotrim(spa_t *spa);
+extern void vdev_autotrim_kick(spa_t *spa);
extern void vdev_autotrim_stop_all(spa_t *spa);
extern void vdev_autotrim_stop_wait(vdev_t *vd);
extern void vdev_autotrim_restart(spa_t *spa);
diff --git a/include/sys/xvattr.h b/include/sys/xvattr.h
index 277c4694069d..a7994db894b9 100644
--- a/include/sys/xvattr.h
+++ b/include/sys/xvattr.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zap.h b/include/sys/zap.h
index dc2f661fb065..96ddcc324b65 100644
--- a/include/sys/zap.h
+++ b/include/sys/zap.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -253,6 +253,9 @@ int zap_add_by_dnode(dnode_t *dn, const char *key,
int zap_add_uint64(objset_t *ds, uint64_t zapobj, const uint64_t *key,
int key_numints, int integer_size, uint64_t num_integers,
const void *val, dmu_tx_t *tx);
+int zap_add_uint64_by_dnode(dnode_t *dn, const uint64_t *key,
+ int key_numints, int integer_size, uint64_t num_integers,
+ const void *val, dmu_tx_t *tx);
/*
* Set the attribute with the given name to the given value. If an
@@ -267,6 +270,9 @@ int zap_update(objset_t *ds, uint64_t zapobj, const char *name,
int zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
int key_numints,
int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx);
+int zap_update_uint64_by_dnode(dnode_t *dn, const uint64_t *key,
+ int key_numints,
+ int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx);
/*
* Get the length (in integers) and the integer size of the specified
@@ -292,6 +298,8 @@ int zap_remove_norm(objset_t *ds, uint64_t zapobj, const char *name,
int zap_remove_by_dnode(dnode_t *dn, const char *name, dmu_tx_t *tx);
int zap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
int key_numints, dmu_tx_t *tx);
+int zap_remove_uint64_by_dnode(dnode_t *dn, const uint64_t *key,
+ int key_numints, dmu_tx_t *tx);
/*
* Returns (in *count) the number of attributes in the specified zap
diff --git a/include/sys/zap_impl.h b/include/sys/zap_impl.h
index 4549a9bd1177..2959aa9b2ca4 100644
--- a/include/sys/zap_impl.h
+++ b/include/sys/zap_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -66,10 +66,9 @@ typedef struct mzap_phys {
} mzap_phys_t;
typedef struct mzap_ent {
- avl_node_t mze_node;
- int mze_chunkid;
- uint64_t mze_hash;
- uint32_t mze_cd; /* copy from mze_phys->mze_cd */
+ uint32_t mze_hash;
+ uint16_t mze_cd; /* copy from mze_phys->mze_cd */
+ uint16_t mze_chunkid;
} mzap_ent_t;
#define MZE_PHYS(zap, mze) \
@@ -146,6 +145,7 @@ typedef struct zap {
dmu_buf_user_t zap_dbu;
objset_t *zap_objset;
uint64_t zap_object;
+ dnode_t *zap_dnode;
struct dmu_buf *zap_dbuf;
krwlock_t zap_rwlock;
boolean_t zap_ismicro;
@@ -164,7 +164,7 @@ typedef struct zap {
int16_t zap_num_entries;
int16_t zap_num_chunks;
int16_t zap_alloc_next;
- avl_tree_t zap_avl;
+ zfs_btree_t zap_tree;
} zap_micro;
} zap_u;
} zap_t;
@@ -203,7 +203,7 @@ int zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
zap_t **zapp);
void zap_unlockdir(zap_t *zap, const void *tag);
void zap_evict_sync(void *dbu);
-zap_name_t *zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt);
+zap_name_t *zap_name_alloc_str(zap_t *zap, const char *key, matchtype_t mt);
void zap_name_free(zap_name_t *zn);
int zap_hashbits(zap_t *zap);
uint32_t zap_maxcd(zap_t *zap);
diff --git a/include/sys/zap_leaf.h b/include/sys/zap_leaf.h
index a3da1036a5ee..e54456d3472b 100644
--- a/include/sys/zap_leaf.h
+++ b/include/sys/zap_leaf.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -47,7 +47,7 @@ struct zap_stats;
* entries - header space (2*chunksize)
*/
#define ZAP_LEAF_NUMCHUNKS_BS(bs) \
- (((1<<(bs)) - 2*ZAP_LEAF_HASH_NUMENTRIES_BS(bs)) / \
+ (((1U << (bs)) - 2 * ZAP_LEAF_HASH_NUMENTRIES_BS(bs)) / \
ZAP_LEAF_CHUNKSIZE - 2)
#define ZAP_LEAF_NUMCHUNKS(l) (ZAP_LEAF_NUMCHUNKS_BS(((l)->l_bs)))
@@ -80,7 +80,7 @@ struct zap_stats;
* chunks per entry (3).
*/
#define ZAP_LEAF_HASH_SHIFT_BS(bs) ((bs) - 5)
-#define ZAP_LEAF_HASH_NUMENTRIES_BS(bs) (1 << ZAP_LEAF_HASH_SHIFT_BS(bs))
+#define ZAP_LEAF_HASH_NUMENTRIES_BS(bs) (1U << ZAP_LEAF_HASH_SHIFT_BS(bs))
#define ZAP_LEAF_HASH_SHIFT(l) (ZAP_LEAF_HASH_SHIFT_BS(((l)->l_bs)))
#define ZAP_LEAF_HASH_NUMENTRIES(l) (ZAP_LEAF_HASH_NUMENTRIES_BS(((l)->l_bs)))
@@ -132,7 +132,7 @@ typedef struct zap_leaf_phys {
* with the ZAP_LEAF_CHUNK() macro.
*/
- uint16_t l_hash[1];
+ uint16_t l_hash[];
} zap_leaf_phys_t;
typedef union zap_leaf_chunk {
@@ -163,7 +163,7 @@ typedef struct zap_leaf {
dmu_buf_user_t l_dbu;
krwlock_t l_rwlock;
uint64_t l_blkid; /* 1<<ZAP_BLOCK_SHIFT byte block off */
- int l_bs; /* block size shift */
+ uint_t l_bs; /* block size shift */
dmu_buf_t *l_dbuf;
} zap_leaf_t;
@@ -243,7 +243,7 @@ extern boolean_t zap_entry_normalization_conflict(zap_entry_handle_t *zeh,
*/
extern void zap_leaf_init(zap_leaf_t *l, boolean_t sort);
-extern void zap_leaf_byteswap(zap_leaf_phys_t *buf, int len);
+extern void zap_leaf_byteswap(zap_leaf_phys_t *buf, size_t len);
extern void zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort);
extern void zap_leaf_stats(struct zap *zap, zap_leaf_t *l,
struct zap_stats *zs);
diff --git a/include/sys/zcp.h b/include/sys/zcp.h
index f0a78f9cb5c4..6301cc08e7ea 100644
--- a/include/sys/zcp.h
+++ b/include/sys/zcp.h
@@ -33,8 +33,8 @@ extern "C" {
#define ZCP_RUN_INFO_KEY "runinfo"
-extern unsigned long zfs_lua_max_instrlimit;
-extern unsigned long zfs_lua_max_memlimit;
+extern uint64_t zfs_lua_max_instrlimit;
+extern uint64_t zfs_lua_max_memlimit;
int zcp_argerror(lua_State *, int, const char *, ...);
diff --git a/include/sys/zcp_iter.h b/include/sys/zcp_iter.h
index 1d92d0c6d10c..fa6eeef25edd 100644
--- a/include/sys/zcp_iter.h
+++ b/include/sys/zcp_iter.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfeature.h b/include/sys/zfeature.h
index 5abde149a615..bf9361374d33 100644
--- a/include/sys/zfeature.h
+++ b/include/sys/zfeature.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h
index 98387a49adbe..e19288528849 100644
--- a/include/sys/zfs_acl.h
+++ b/include/sys/zfs_acl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -206,7 +206,7 @@ struct zfsvfs;
#ifdef _KERNEL
int zfs_acl_ids_create(struct znode *, int, vattr_t *,
- cred_t *, vsecattr_t *, zfs_acl_ids_t *);
+ cred_t *, vsecattr_t *, zfs_acl_ids_t *, zidmap_t *);
void zfs_acl_ids_free(zfs_acl_ids_t *);
boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t);
int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
@@ -215,15 +215,16 @@ void zfs_acl_rele(void *);
void zfs_oldace_byteswap(ace_t *, int);
void zfs_ace_byteswap(void *, size_t, boolean_t);
extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr);
-extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *);
+extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *,
+ zidmap_t *);
int zfs_fastaccesschk_execute(struct znode *, cred_t *);
-extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *);
-extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *);
+extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zidmap_t *);
+extern int zfs_zaccess_unix(void *, int, cred_t *);
extern int zfs_acl_access(struct znode *, int, cred_t *);
int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t);
-int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *);
+int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zidmap_t *);
int zfs_zaccess_rename(struct znode *, struct znode *,
- struct znode *, struct znode *, cred_t *cr);
+ struct znode *, struct znode *, cred_t *cr, zidmap_t *mnt_ns);
void zfs_acl_free(zfs_acl_t *);
int zfs_vsec_2_aclp(struct zfsvfs *, umode_t, vsecattr_t *, cred_t *,
struct zfs_fuid_info **, zfs_acl_t **);
diff --git a/include/sys/zfs_chksum.h b/include/sys/zfs_chksum.h
index cfd07bd0ffe7..a0e1b35189bb 100644
--- a/include/sys/zfs_chksum.h
+++ b/include/sys/zfs_chksum.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
index 50257f1d6fdd..8f264b50e995 100644
--- a/include/sys/zfs_context.h
+++ b/include/sys/zfs_context.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -50,6 +50,7 @@ extern "C" {
#include <sys/kmem.h>
#include <sys/kmem_cache.h>
#include <sys/vmem.h>
+#include <sys/misc.h>
#include <sys/taskq.h>
#include <sys/param.h>
#include <sys/disp.h>
@@ -150,10 +151,14 @@ extern "C" {
extern void dprintf_setup(int *argc, char **argv);
-extern void cmn_err(int, const char *, ...);
-extern void vcmn_err(int, const char *, va_list);
-extern __attribute__((noreturn)) void panic(const char *, ...);
-extern __attribute__((noreturn)) void vpanic(const char *, va_list);
+extern void cmn_err(int, const char *, ...)
+ __attribute__((format(printf, 2, 3)));
+extern void vcmn_err(int, const char *, va_list)
+ __attribute__((format(printf, 2, 0)));
+extern void panic(const char *, ...)
+ __attribute__((format(printf, 1, 2), noreturn));
+extern void vpanic(const char *, va_list)
+ __attribute__((format(printf, 1, 0), noreturn));
#define fm_panic panic
@@ -219,14 +224,13 @@ typedef pthread_t kthread_t;
#define TS_JOINABLE 0x00000004
#define curthread ((void *)(uintptr_t)pthread_self())
-#define kpreempt(x) yield()
#define getcomm() "unknown"
#define thread_create_named(name, stk, stksize, func, arg, len, \
pp, state, pri) \
- zk_thread_create(func, arg, stksize, state)
+ zk_thread_create(name, func, arg, stksize, state)
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
- zk_thread_create(func, arg, stksize, state)
+ zk_thread_create(#func, func, arg, stksize, state)
#define thread_exit() pthread_exit(NULL)
#define thread_join(t) pthread_join((pthread_t)(t), NULL)
@@ -242,15 +246,17 @@ extern struct proc p0;
#define PS_NONE -1
-extern kthread_t *zk_thread_create(void (*func)(void *), void *arg,
- size_t stksize, int state);
+extern kthread_t *zk_thread_create(const char *name, void (*func)(void *),
+ void *arg, size_t stksize, int state);
#define issig(why) (FALSE)
#define ISSIG(thr, why) (FALSE)
+#define KPREEMPT_SYNC (-1)
+
+#define kpreempt(x) sched_yield()
#define kpreempt_disable() ((void)0)
#define kpreempt_enable() ((void)0)
-#define cond_resched() sched_yield()
/*
* Mutexes
@@ -268,11 +274,13 @@ typedef struct kmutex {
extern void mutex_init(kmutex_t *mp, char *name, int type, void *cookie);
extern void mutex_destroy(kmutex_t *mp);
extern void mutex_enter(kmutex_t *mp);
+extern int mutex_enter_check_return(kmutex_t *mp);
extern void mutex_exit(kmutex_t *mp);
extern int mutex_tryenter(kmutex_t *mp);
#define NESTED_SINGLE 1
#define mutex_enter_nested(mp, class) mutex_enter(mp)
+#define mutex_enter_interruptible(mp) mutex_enter_check_return(mp)
/*
* RW locks
*/
@@ -488,6 +496,8 @@ extern taskq_t *system_taskq;
extern taskq_t *system_delay_taskq;
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
+extern taskq_t *taskq_create_synced(const char *, int, pri_t, int, int, uint_t,
+ kthread_t ***);
#define taskq_create_proc(a, b, c, d, e, p, f) \
(taskq_create(a, b, c, d, e, f))
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
@@ -689,6 +699,11 @@ extern char *kmem_asprintf(const char *fmt, ...);
#define kmem_strfree(str) kmem_free((str), strlen(str) + 1)
#define kmem_strdup(s) strdup(s)
+#ifndef __cplusplus
+extern int kmem_scnprintf(char *restrict str, size_t size,
+ const char *restrict fmt, ...);
+#endif
+
/*
* Hostname information
*/
diff --git a/include/sys/zfs_debug.h b/include/sys/zfs_debug.h
index 7b103510dd07..8d94557a5882 100644
--- a/include/sys/zfs_debug.h
+++ b/include/sys/zfs_debug.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -57,6 +57,8 @@ extern int zfs_dbgmsg_enable;
#define ZFS_DEBUG_TRIM (1 << 11)
#define ZFS_DEBUG_LOG_SPACEMAP (1 << 12)
#define ZFS_DEBUG_METASLAB_ALLOC (1 << 13)
+#define ZFS_DEBUG_BRT (1 << 14)
+#define ZFS_DEBUG_RAIDZ_RECONSTRUCT (1 << 15)
extern void __set_error(const char *file, const char *func, int line, int err);
extern void __zfs_dbgmsg(char *buf);
diff --git a/include/sys/zfs_delay.h b/include/sys/zfs_delay.h
index 40e617dba961..56ac1f3c439b 100644
--- a/include/sys/zfs_delay.h
+++ b/include/sys/zfs_delay.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_file.h b/include/sys/zfs_file.h
index 02cd1a6f041a..e944165adc40 100644
--- a/include/sys/zfs_file.h
+++ b/include/sys/zfs_file.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_fuid.h b/include/sys/zfs_fuid.h
index 1975e57cf62b..d6b2942d1bec 100644
--- a/include/sys/zfs_fuid.h
+++ b/include/sys/zfs_fuid.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_impl.h b/include/sys/zfs_impl.h
new file mode 100644
index 000000000000..df4899f132b8
--- /dev/null
+++ b/include/sys/zfs_impl.h
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#ifndef _SYS_ZFS_IMPL_H
+#define _SYS_ZFS_IMPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* generic implementation backends */
+typedef struct
+{
+ /* algorithm name */
+ const char *name;
+
+ /* get number of supported implementations */
+ uint32_t (*getcnt)(void);
+
+ /* get id of selected implementation */
+ uint32_t (*getid)(void);
+
+ /* get name of selected implementation */
+ const char *(*getname)(void);
+
+ /* setup id as fastest implementation */
+ void (*set_fastest)(uint32_t id);
+
+ /* set implementation by id */
+ void (*setid)(uint32_t id);
+
+ /* set implementation by name */
+ int (*setname)(const char *val);
+} zfs_impl_t;
+
+/* return some set of function pointer */
+extern const zfs_impl_t *zfs_impl_get_ops(const char *algo);
+
+extern const zfs_impl_t zfs_blake3_ops;
+extern const zfs_impl_t zfs_sha256_ops;
+extern const zfs_impl_t zfs_sha512_ops;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_ZFS_IMPL_H */
diff --git a/include/sys/zfs_ioctl.h b/include/sys/zfs_ioctl.h
index 94522179676a..525d40759fdd 100644
--- a/include/sys/zfs_ioctl.h
+++ b/include/sys/zfs_ioctl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2024 by Delphix. All rights reserved.
* Copyright 2016 RackTop Systems.
* Copyright (c) 2017, Intel Corporation.
*/
@@ -124,7 +124,13 @@ typedef enum drr_headertype {
* default use of "zfs send" won't encounter the bug mentioned above.
*/
#define DMU_BACKUP_FEATURE_SWITCH_TO_LARGE_BLOCKS (1 << 27)
-#define DMU_BACKUP_FEATURE_BLAKE3 (1 << 28)
+/* flag #28 is reserved for a Nutanix feature */
+/*
+ * flag #29 is the last unused bit. It is reserved to indicate a to-be-designed
+ * extension to the stream format which will accomodate more feature flags.
+ * If you need to add another feature flag, please reach out to the OpenZFS
+ * community, e.g., on GitHub or Slack.
+ */
/*
* Mask of all supported backup features
@@ -135,7 +141,7 @@ typedef enum drr_headertype {
DMU_BACKUP_FEATURE_COMPRESSED | DMU_BACKUP_FEATURE_LARGE_DNODE | \
DMU_BACKUP_FEATURE_RAW | DMU_BACKUP_FEATURE_HOLDS | \
DMU_BACKUP_FEATURE_REDACTED | DMU_BACKUP_FEATURE_SWITCH_TO_LARGE_BLOCKS | \
- DMU_BACKUP_FEATURE_ZSTD | DMU_BACKUP_FEATURE_BLAKE3)
+ DMU_BACKUP_FEATURE_ZSTD)
/* Are all features in the given flag word currently supported? */
#define DMU_STREAM_SUPPORTED(x) (!((x) & ~DMU_BACKUP_FEATURE_MASK))
@@ -448,6 +454,8 @@ typedef enum zinject_type {
ZINJECT_PANIC,
ZINJECT_DELAY_IO,
ZINJECT_DECRYPT_FAULT,
+ ZINJECT_DELAY_IMPORT,
+ ZINJECT_DELAY_EXPORT,
} zinject_type_t;
typedef struct zfs_share {
@@ -569,7 +577,6 @@ typedef struct zfsdev_state {
extern void *zfsdev_get_state(minor_t minor, enum zfsdev_state_type which);
extern int zfsdev_getminor(zfs_file_t *fp, minor_t *minorp);
-extern uint_t zfs_fsyncer_key;
extern uint_t zfs_allow_log_key;
#endif /* _KERNEL */
diff --git a/include/sys/zfs_ioctl_impl.h b/include/sys/zfs_ioctl_impl.h
index f9e4f6e6c4b2..cb852c5577fd 100644
--- a/include/sys/zfs_ioctl_impl.h
+++ b/include/sys/zfs_ioctl_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,7 +24,7 @@
#define _ZFS_IOCTL_IMPL_H_
extern kmutex_t zfsdev_state_lock;
-extern unsigned long zfs_max_nvlist_src_size;
+extern uint64_t zfs_max_nvlist_src_size;
typedef int zfs_ioc_legacy_func_t(zfs_cmd_t *);
typedef int zfs_ioc_func_t(const char *, nvlist_t *, nvlist_t *);
diff --git a/include/sys/zfs_onexit.h b/include/sys/zfs_onexit.h
index fd3030e3ac2d..91f49d4cc5a3 100644
--- a/include/sys/zfs_onexit.h
+++ b/include/sys/zfs_onexit.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -54,7 +54,7 @@ extern void zfs_onexit_destroy(zfs_onexit_t *zo);
extern zfs_file_t *zfs_onexit_fd_hold(int fd, minor_t *minorp);
extern void zfs_onexit_fd_rele(zfs_file_t *);
extern int zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
- uint64_t *action_handle);
+ uintptr_t *action_handle);
#ifdef __cplusplus
}
diff --git a/include/sys/zfs_project.h b/include/sys/zfs_project.h
index 81a238905225..8a46e5e068db 100644
--- a/include/sys/zfs_project.h
+++ b/include/sys/zfs_project.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_quota.h b/include/sys/zfs_quota.h
index b215b8dd0013..4567cc651afb 100644
--- a/include/sys/zfs_quota.h
+++ b/include/sys/zfs_quota.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_racct.h b/include/sys/zfs_racct.h
index cfcdd336ea42..0e8bd04c1a13 100644
--- a/include/sys/zfs_racct.h
+++ b/include/sys/zfs_racct.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_refcount.h b/include/sys/zfs_refcount.h
index 2f59ebb32b07..77965a0aa580 100644
--- a/include/sys/zfs_refcount.h
+++ b/include/sys/zfs_refcount.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,6 +27,7 @@
#define _SYS_ZFS_REFCOUNT_H
#include <sys/inttypes.h>
+#include <sys/avl.h>
#include <sys/list.h>
#include <sys/zfs_context.h>
@@ -43,19 +44,22 @@ extern "C" {
#ifdef ZFS_DEBUG
typedef struct reference {
- list_node_t ref_link;
+ union {
+ avl_node_t a;
+ list_node_t l;
+ } ref_link;
const void *ref_holder;
uint64_t ref_number;
- uint8_t *ref_removed;
+ boolean_t ref_search;
} reference_t;
typedef struct refcount {
+ uint64_t rc_count;
kmutex_t rc_mtx;
- boolean_t rc_tracked;
- list_t rc_list;
+ avl_tree_t rc_tree;
list_t rc_removed;
- uint64_t rc_count;
- uint64_t rc_removed_count;
+ uint_t rc_removed_count;
+ boolean_t rc_tracked;
} zfs_refcount_t;
/*
@@ -73,13 +77,15 @@ int64_t zfs_refcount_count(zfs_refcount_t *);
int64_t zfs_refcount_add(zfs_refcount_t *, const void *);
int64_t zfs_refcount_remove(zfs_refcount_t *, const void *);
/*
- * Note that (add|remove)_many add/remove one reference with "number" N,
- * _not_ make N references with "number" 1, which is what vanilla
- * zfs_refcount_(add|remove) would do if called N times.
+ * Note that (add|remove)_many adds/removes one reference with "number" N,
+ * _not_ N references with "number" 1, which is what (add|remove)_few does,
+ * or what vanilla zfs_refcount_(add|remove) called N times would do.
*
* Attempting to remove a reference with number N when none exists is a
* panic on debug kernels with reference_tracking enabled.
*/
+void zfs_refcount_add_few(zfs_refcount_t *, uint64_t, const void *);
+void zfs_refcount_remove_few(zfs_refcount_t *, uint64_t, const void *);
int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, const void *);
int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, const void *);
void zfs_refcount_transfer(zfs_refcount_t *, zfs_refcount_t *);
@@ -108,6 +114,10 @@ typedef struct refcount {
#define zfs_refcount_count(rc) atomic_load_64(&(rc)->rc_count)
#define zfs_refcount_add(rc, holder) atomic_inc_64_nv(&(rc)->rc_count)
#define zfs_refcount_remove(rc, holder) atomic_dec_64_nv(&(rc)->rc_count)
+#define zfs_refcount_add_few(rc, number, holder) \
+ atomic_add_64(&(rc)->rc_count, number)
+#define zfs_refcount_remove_few(rc, number, holder) \
+ atomic_add_64(&(rc)->rc_count, -number)
#define zfs_refcount_add_many(rc, number, holder) \
atomic_add_64_nv(&(rc)->rc_count, number)
#define zfs_refcount_remove_many(rc, number, holder) \
diff --git a/include/sys/zfs_rlock.h b/include/sys/zfs_rlock.h
index 2302abb37337..5e5d6d68d6c5 100644
--- a/include/sys/zfs_rlock.h
+++ b/include/sys/zfs_rlock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_sa.h b/include/sys/zfs_sa.h
index 6b0336997c20..1b4b8abf0244 100644
--- a/include/sys/zfs_sa.h
+++ b/include/sys/zfs_sa.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_stat.h b/include/sys/zfs_stat.h
index 465aefaa2063..1589f945cbd7 100644
--- a/include/sys/zfs_stat.h
+++ b/include/sys/zfs_stat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_sysfs.h b/include/sys/zfs_sysfs.h
index d1cb2ef4321c..6fe9b7a9cd2c 100644
--- a/include/sys/zfs_sysfs.h
+++ b/include/sys/zfs_sysfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h
index a438c86f0a0c..19ae7b77b459 100644
--- a/include/sys/zfs_vfsops.h
+++ b/include/sys/zfs_vfsops.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h
index 18259f0dc9b5..e60b99bed192 100644
--- a/include/sys/zfs_vnops.h
+++ b/include/sys/zfs_vnops.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,13 +24,20 @@
#ifndef _SYS_FS_ZFS_VNOPS_H
#define _SYS_FS_ZFS_VNOPS_H
+
#include <sys/zfs_vnops_os.h>
+extern int zfs_bclone_enabled;
+
extern int zfs_fsync(znode_t *, int, cred_t *);
extern int zfs_read(znode_t *, zfs_uio_t *, int, cred_t *);
extern int zfs_write(znode_t *, zfs_uio_t *, int, cred_t *);
extern int zfs_holey(znode_t *, ulong_t, loff_t *);
extern int zfs_access(znode_t *, int, int, cred_t *);
+extern int zfs_clone_range(znode_t *, uint64_t *, znode_t *, uint64_t *,
+ uint64_t *, cred_t *);
+extern int zfs_clone_range_replay(znode_t *, uint64_t, uint64_t, uint64_t,
+ const blkptr_t *, size_t);
extern int zfs_getsecattr(znode_t *, vsecattr_t *, int, cred_t *);
extern int zfs_setsecattr(znode_t *, vsecattr_t *, int, cred_t *);
diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h
index 098cf9dbc16f..d71144807f47 100644
--- a/include/sys/zfs_znode.h
+++ b/include/sys/zfs_znode.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -158,6 +158,7 @@ extern "C" {
#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
extern int zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len);
+extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
#ifdef _KERNEL
#include <sys/zfs_znode_impl.h>
@@ -188,9 +189,7 @@ typedef struct znode {
boolean_t z_atime_dirty; /* atime needs to be synced */
boolean_t z_zn_prefetch; /* Prefetch znodes? */
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 */
@@ -218,11 +217,34 @@ typedef struct znode {
ZNODE_OS_FIELDS;
} znode_t;
+/* Verifies the znode is valid. */
+static inline int
+zfs_verify_zp(znode_t *zp)
+{
+ if (unlikely(zp->z_sa_hdl == NULL))
+ return (SET_ERROR(EIO));
+ return (0);
+}
+
+/* zfs_enter and zfs_verify_zp together */
+static inline int
+zfs_enter_verify_zp(zfsvfs_t *zfsvfs, znode_t *zp, const char *tag)
+{
+ int error;
+ if ((error = zfs_enter(zfsvfs, tag)) != 0)
+ return (error);
+ if ((error = zfs_verify_zp(zp)) != 0) {
+ zfs_exit(zfsvfs, tag);
+ return (error);
+ }
+ return (0);
+}
+
typedef struct znode_hold {
uint64_t zh_obj; /* object id */
- kmutex_t zh_lock; /* lock serializing object access */
avl_node_t zh_node; /* avl tree linkage */
- zfs_refcount_t zh_refcount; /* active consumer reference count */
+ kmutex_t zh_lock; /* lock serializing object access */
+ int zh_refcount; /* active consumer reference count */
} znode_hold_t;
static inline uint64_t
@@ -250,6 +272,8 @@ extern int zfs_freesp(znode_t *, uint64_t, uint64_t, int, boolean_t);
extern void zfs_znode_init(void);
extern void zfs_znode_fini(void);
extern int zfs_znode_hold_compare(const void *, const void *);
+extern znode_hold_t *zfs_znode_hold_enter(zfsvfs_t *, uint64_t);
+extern void zfs_znode_hold_exit(zfsvfs_t *, znode_hold_t *);
extern int zfs_zget(zfsvfs_t *, uint64_t, znode_t **);
extern int zfs_rezget(znode_t *);
extern void zfs_zinactive(znode_t *);
@@ -257,7 +281,6 @@ extern void zfs_znode_delete(znode_t *, dmu_tx_t *);
extern void zfs_remove_op_tables(void);
extern int zfs_create_op_tables(void);
extern dev_t zfs_cmpldev(uint64_t);
-extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
extern int zfs_get_stats(objset_t *os, nvlist_t *nv);
extern boolean_t zfs_get_vfs_flag_unmounted(objset_t *os);
extern void zfs_znode_dmu_fini(znode_t *);
@@ -277,8 +300,14 @@ extern void zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
extern void zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname,
znode_t *szp);
+extern void zfs_log_rename_exchange(zilog_t *zilog, dmu_tx_t *tx,
+ uint64_t txtype, znode_t *sdzp, const char *sname, znode_t *tdzp,
+ const char *dname, znode_t *szp);
+extern void zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx,
+ uint64_t txtype, znode_t *sdzp, const char *sname, znode_t *tdzp,
+ const char *dname, znode_t *szp, znode_t *wzp);
extern void zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
- znode_t *zp, offset_t off, ssize_t len, int ioflag,
+ znode_t *zp, offset_t off, ssize_t len, boolean_t commit,
zil_callback_t callback, void *callback_data);
extern void zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
znode_t *zp, uint64_t off, uint64_t len);
@@ -286,6 +315,9 @@ extern void zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp);
extern void zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
vsecattr_t *vsecp, zfs_fuid_info_t *fuidp);
+extern void zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype,
+ znode_t *zp, uint64_t offset, uint64_t length, uint64_t blksz,
+ const blkptr_t *bps, size_t nbps);
extern void zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx);
extern void zfs_upgrade(zfsvfs_t *zfsvfs, dmu_tx_t *tx);
extern void zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
diff --git a/include/sys/zil.h b/include/sys/zil.h
index 2a7381f016ab..4747ecc067a9 100644
--- a/include/sys/zil.h
+++ b/include/sys/zil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,6 +33,7 @@
#include <sys/zio.h>
#include <sys/dmu.h>
#include <sys/zio_crypt.h>
+#include <sys/wmsum.h>
#ifdef __cplusplus
extern "C" {
@@ -163,7 +164,10 @@ typedef enum zil_create {
#define TX_MKDIR_ACL_ATTR 19 /* mkdir with ACL + attrs */
#define TX_WRITE2 20 /* dmu_sync EALREADY write */
#define TX_SETSAXATTR 21 /* Set sa xattrs on file */
-#define TX_MAX_TYPE 22 /* Max transaction type */
+#define TX_RENAME_EXCHANGE 22 /* Atomic swap via renameat2 */
+#define TX_RENAME_WHITEOUT 23 /* Atomic whiteout via renameat2 */
+#define TX_CLONE_RANGE 24 /* Clone a file range */
+#define TX_MAX_TYPE 25 /* Max transaction type */
/*
* The transactions for mkdir, symlink, remove, rmdir, link, and rename
@@ -173,9 +177,9 @@ typedef enum zil_create {
#define TX_CI ((uint64_t)0x1 << 63) /* case-insensitive behavior requested */
/*
- * Transactions for write, truncate, setattr, acl_v0, and acl can be logged
- * out of order. For convenience in the code, all such records must have
- * lr_foid at the same offset.
+ * Transactions for operations below can be logged out of order.
+ * For convenience in the code, all such records must have lr_foid
+ * at the same offset.
*/
#define TX_OOO(txtype) \
((txtype) == TX_WRITE || \
@@ -184,7 +188,8 @@ typedef enum zil_create {
(txtype) == TX_ACL_V0 || \
(txtype) == TX_ACL || \
(txtype) == TX_WRITE2 || \
- (txtype) == TX_SETSAXATTR)
+ (txtype) == TX_SETSAXATTR || \
+ (txtype) == TX_CLONE_RANGE)
/*
* The number of dnode slots consumed by the object is stored in the 8
@@ -317,6 +322,19 @@ typedef struct {
} lr_rename_t;
typedef struct {
+ lr_rename_t lr_rename; /* common rename portion */
+ /* members related to the whiteout file (based on lr_create_t) */
+ uint64_t lr_wfoid; /* obj id of the new whiteout file */
+ uint64_t lr_wmode; /* mode of object */
+ uint64_t lr_wuid; /* uid of whiteout */
+ uint64_t lr_wgid; /* gid of whiteout */
+ uint64_t lr_wgen; /* generation (txg of creation) */
+ uint64_t lr_wcrtime[2]; /* creation time */
+ uint64_t lr_wrdev; /* always makedev(0, 0) */
+ /* 2 strings: names of source and destination follow this */
+} lr_rename_whiteout_t;
+
+typedef struct {
lr_t lr_common; /* common portion of log record */
uint64_t lr_foid; /* file object to write */
uint64_t lr_offset; /* offset to write to */
@@ -371,6 +389,17 @@ typedef struct {
/* lr_acl_bytes number of variable sized ace's follows */
} lr_acl_t;
+typedef struct {
+ lr_t lr_common; /* common portion of log record */
+ uint64_t lr_foid; /* file object to clone into */
+ uint64_t lr_offset; /* offset to clone to */
+ uint64_t lr_length; /* length of the blocks to clone */
+ uint64_t lr_blksz; /* file's block size */
+ uint64_t lr_nbps; /* number of block pointers */
+ blkptr_t lr_bps[];
+ /* block pointers of the blocks to clone follows */
+} lr_clone_range_t;
+
/*
* ZIL structure definitions, interface function prototype and globals.
*/
@@ -460,24 +489,54 @@ typedef struct zil_stats {
* Transactions which have been allocated to the "normal"
* (i.e. not slog) storage pool. Note that "bytes" accumulate
* the actual log record sizes - which do not include the actual
- * data in case of indirect writes.
+ * data in case of indirect writes. bytes <= write <= alloc.
*/
kstat_named_t zil_itx_metaslab_normal_count;
kstat_named_t zil_itx_metaslab_normal_bytes;
+ kstat_named_t zil_itx_metaslab_normal_write;
+ kstat_named_t zil_itx_metaslab_normal_alloc;
/*
* Transactions which have been allocated to the "slog" storage pool.
* If there are no separate log devices, this is the same as the
- * "normal" pool.
+ * "normal" pool. bytes <= write <= alloc.
*/
kstat_named_t zil_itx_metaslab_slog_count;
kstat_named_t zil_itx_metaslab_slog_bytes;
-} zil_stats_t;
-
-#define ZIL_STAT_INCR(stat, val) \
- atomic_add_64(&zil_stats.stat.value.ui64, (val));
-#define ZIL_STAT_BUMP(stat) \
- ZIL_STAT_INCR(stat, 1);
+ kstat_named_t zil_itx_metaslab_slog_write;
+ kstat_named_t zil_itx_metaslab_slog_alloc;
+} zil_kstat_values_t;
+
+typedef struct zil_sums {
+ wmsum_t zil_commit_count;
+ wmsum_t zil_commit_writer_count;
+ wmsum_t zil_itx_count;
+ wmsum_t zil_itx_indirect_count;
+ wmsum_t zil_itx_indirect_bytes;
+ wmsum_t zil_itx_copied_count;
+ wmsum_t zil_itx_copied_bytes;
+ wmsum_t zil_itx_needcopy_count;
+ wmsum_t zil_itx_needcopy_bytes;
+ wmsum_t zil_itx_metaslab_normal_count;
+ wmsum_t zil_itx_metaslab_normal_bytes;
+ wmsum_t zil_itx_metaslab_normal_write;
+ wmsum_t zil_itx_metaslab_normal_alloc;
+ wmsum_t zil_itx_metaslab_slog_count;
+ wmsum_t zil_itx_metaslab_slog_bytes;
+ wmsum_t zil_itx_metaslab_slog_write;
+ wmsum_t zil_itx_metaslab_slog_alloc;
+} zil_sums_t;
+
+#define ZIL_STAT_INCR(zil, stat, val) \
+ do { \
+ int64_t tmpval = (val); \
+ wmsum_add(&(zil_sums_global.stat), tmpval); \
+ if ((zil)->zl_sums) \
+ wmsum_add(&((zil)->zl_sums->stat), tmpval); \
+ } while (0)
+
+#define ZIL_STAT_BUMP(zil, stat) \
+ ZIL_STAT_INCR(zil, stat, 1);
typedef int zil_parse_blk_func_t(zilog_t *zilog, const blkptr_t *bp, void *arg,
uint64_t txg);
@@ -497,13 +556,14 @@ extern void zil_fini(void);
extern zilog_t *zil_alloc(objset_t *os, zil_header_t *zh_phys);
extern void zil_free(zilog_t *zilog);
-extern zilog_t *zil_open(objset_t *os, zil_get_data_t *get_data);
+extern zilog_t *zil_open(objset_t *os, zil_get_data_t *get_data,
+ zil_sums_t *zil_sums);
extern void zil_close(zilog_t *zilog);
-extern void zil_replay(objset_t *os, void *arg,
+extern boolean_t zil_replay(objset_t *os, void *arg,
zil_replay_func_t *const replay_func[TX_MAX_TYPE]);
extern boolean_t zil_replaying(zilog_t *zilog, dmu_tx_t *tx);
-extern void zil_destroy(zilog_t *zilog, boolean_t keep_first);
+extern boolean_t zil_destroy(zilog_t *zilog, boolean_t keep_first);
extern void zil_destroy_sync(zilog_t *zilog, dmu_tx_t *tx);
extern itx_t *zil_itx_create(uint64_t txtype, size_t lrsize);
@@ -535,7 +595,12 @@ extern void zil_set_sync(zilog_t *zilog, uint64_t syncval);
extern void zil_set_logbias(zilog_t *zilog, uint64_t slogval);
extern uint64_t zil_max_copied_data(zilog_t *zilog);
-extern uint64_t zil_max_log_data(zilog_t *zilog);
+extern uint64_t zil_max_log_data(zilog_t *zilog, size_t hdrsize);
+
+extern void zil_sums_init(zil_sums_t *zs);
+extern void zil_sums_fini(zil_sums_t *zs);
+extern void zil_kstat_values_update(zil_kstat_values_t *zs,
+ zil_sums_t *zil_sums);
extern int zil_replay_disable;
diff --git a/include/sys/zil_impl.h b/include/sys/zil_impl.h
index 8409ce864e90..9a34bafc1c77 100644
--- a/include/sys/zil_impl.h
+++ b/include/sys/zil_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -38,14 +38,22 @@ extern "C" {
/*
* Possible states for a given lwb structure.
*
- * An lwb will start out in the "closed" state, and then transition to
- * the "opened" state via a call to zil_lwb_write_open(). When
- * transitioning from "closed" to "opened" the zilog's "zl_issuer_lock"
- * must be held.
+ * An lwb will start out in the "new" state, and transition to the "opened"
+ * state via a call to zil_lwb_write_open() on first itx assignment. When
+ * transitioning from "new" to "opened" the zilog's "zl_issuer_lock" must be
+ * held.
*
- * After the lwb is "opened", it can transition into the "issued" state
- * via zil_lwb_write_issue(). Again, the zilog's "zl_issuer_lock" must
- * be held when making this transition.
+ * After the lwb is "opened", it can be assigned number of itxs and transition
+ * into the "closed" state via zil_lwb_write_close() when full or on timeout.
+ * When transitioning from "opened" to "closed" the zilog's "zl_issuer_lock"
+ * must be held. New lwb allocation also takes "zl_lock" to protect the list.
+ *
+ * After the lwb is "closed", it can transition into the "ready" state via
+ * zil_lwb_write_issue(). "zl_lock" must be held when making this transition.
+ * Since it is done by the same thread, "zl_issuer_lock" is not needed.
+ *
+ * When lwb in "ready" state receives its block pointer, it can transition to
+ * "issued". "zl_lock" must be held when making this transition.
*
* After the lwb's write zio completes, it transitions into the "write
* done" state via zil_lwb_write_done(); and then into the "flush done"
@@ -62,17 +70,20 @@ extern "C" {
*
* Additionally, correctness when reading an lwb's state is often
* achieved by exploiting the fact that these state transitions occur in
- * this specific order; i.e. "closed" to "opened" to "issued" to "done".
+ * this specific order; i.e. "new" to "opened" to "closed" to "ready" to
+ * "issued" to "write_done" and finally "flush_done".
*
- * Thus, if an lwb is in the "closed" or "opened" state, holding the
+ * Thus, if an lwb is in the "new" or "opened" state, holding the
* "zl_issuer_lock" will prevent a concurrent thread from transitioning
- * that lwb to the "issued" state. Likewise, if an lwb is already in the
- * "issued" state, holding the "zl_lock" will prevent a concurrent
- * thread from transitioning that lwb to the "write done" state.
+ * that lwb to the "closed" state. Likewise, if an lwb is already in the
+ * "ready" state, holding the "zl_lock" will prevent a concurrent thread
+ * from transitioning that lwb to the "issued" state.
*/
typedef enum {
- LWB_STATE_CLOSED,
+ LWB_STATE_NEW,
LWB_STATE_OPENED,
+ LWB_STATE_CLOSED,
+ LWB_STATE_READY,
LWB_STATE_ISSUED,
LWB_STATE_WRITE_DONE,
LWB_STATE_FLUSH_DONE,
@@ -91,22 +102,28 @@ typedef enum {
typedef struct lwb {
zilog_t *lwb_zilog; /* back pointer to log struct */
blkptr_t lwb_blk; /* on disk address of this log blk */
- boolean_t lwb_fastwrite; /* is blk marked for fastwrite? */
+ boolean_t lwb_slim; /* log block has slim format */
boolean_t lwb_slog; /* lwb_blk is on SLOG device */
+ int lwb_error; /* log block allocation error */
+ int lwb_nmax; /* max bytes in the buffer */
int lwb_nused; /* # used bytes in buffer */
+ int lwb_nfilled; /* # filled bytes in buffer */
int lwb_sz; /* size of block and buffer */
lwb_state_t lwb_state; /* the state of this lwb */
char *lwb_buf; /* log write buffer */
+ zio_t *lwb_child_zio; /* parent zio for children */
zio_t *lwb_write_zio; /* zio for the lwb buffer */
zio_t *lwb_root_zio; /* root zio for lwb write and flushes */
+ hrtime_t lwb_issued_timestamp; /* when was the lwb issued? */
uint64_t lwb_issued_txg; /* the txg when the write is issued */
+ uint64_t lwb_alloc_txg; /* the txg when lwb_blk is allocated */
uint64_t lwb_max_txg; /* highest txg in this lwb */
list_node_t lwb_node; /* zilog->zl_lwb_list linkage */
+ list_node_t lwb_issue_node; /* linkage of lwbs ready for issue */
list_t lwb_itxs; /* list of itx's */
list_t lwb_waiters; /* list of zil_commit_waiter's */
avl_tree_t lwb_vdev_tree; /* vdevs to flush after lwb write */
kmutex_t lwb_vdev_lock; /* protects lwb_vdev_tree */
- hrtime_t lwb_issued_timestamp; /* when was the lwb issued? */
} lwb_t;
/*
@@ -164,7 +181,7 @@ typedef struct zil_vdev_node {
avl_node_t zv_node; /* AVL tree linkage */
} zil_vdev_node_t;
-#define ZIL_PREV_BLKS 16
+#define ZIL_BURSTS 8
/*
* Stable storage intent log management structure. One per dataset.
@@ -199,14 +216,18 @@ struct zilog {
uint64_t zl_parse_lr_count; /* number of log records parsed */
itxg_t zl_itxg[TXG_SIZE]; /* intent log txg chains */
list_t zl_itx_commit_list; /* itx list to be committed */
- uint64_t zl_cur_used; /* current commit log size used */
+ uint64_t zl_cur_size; /* current burst full size */
+ uint64_t zl_cur_left; /* current burst remaining size */
+ uint64_t zl_cur_max; /* biggest record in current burst */
list_t zl_lwb_list; /* in-flight log write list */
avl_tree_t zl_bp_tree; /* track bps during log parse */
clock_t zl_replay_time; /* lbolt of when replay started */
uint64_t zl_replay_blks; /* number of log blocks replayed */
zil_header_t zl_old_header; /* debugging aid */
- uint_t zl_prev_blks[ZIL_PREV_BLKS]; /* size - sector rounded */
+ uint_t zl_parallel; /* workload is multi-threaded */
uint_t zl_prev_rotor; /* rotor for zl_prev[] */
+ uint_t zl_prev_opt[ZIL_BURSTS]; /* optimal block size */
+ uint_t zl_prev_min[ZIL_BURSTS]; /* minimal first block size */
txg_node_t zl_dirty_link; /* protected by dp_dirty_zilogs list */
uint64_t zl_dirty_max_txg; /* highest txg used to dirty zilog */
@@ -222,6 +243,9 @@ struct zilog {
* (see zil_max_copied_data()).
*/
uint64_t zl_max_block_size;
+
+ /* Pointer for per dataset zil sums */
+ zil_sums_t *zl_sums;
};
typedef struct zil_bp_node {
diff --git a/include/sys/zio.h b/include/sys/zio.h
index 9bee7cc9b9fd..77c70b9b481c 100644
--- a/include/sys/zio.h
+++ b/include/sys/zio.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,12 +22,12 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2024 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright (c) 2019, Allan Jude
- * Copyright (c) 2019, Klara Inc.
+ * Copyright (c) 2019, 2023, 2024, Klara Inc.
* Copyright (c) 2019-2020, Michael Niewöhner
*/
@@ -163,32 +163,36 @@ typedef enum zio_suspend_reason {
ZIO_SUSPEND_MMP,
} zio_suspend_reason_t;
-enum zio_flag {
+/*
+ * This was originally an enum type. However, those are 32-bit and there is no
+ * way to make a 64-bit enum type. Since we ran out of bits for flags, we were
+ * forced to upgrade it to a uint64_t.
+ */
+typedef uint64_t zio_flag_t;
/*
* Flags inherited by gang, ddt, and vdev children,
* and that must be equal for two zios to aggregate
*/
- ZIO_FLAG_DONT_AGGREGATE = 1U << 0,
- ZIO_FLAG_IO_REPAIR = 1U << 1,
- ZIO_FLAG_SELF_HEAL = 1U << 2,
- ZIO_FLAG_RESILVER = 1U << 3,
- ZIO_FLAG_SCRUB = 1U << 4,
- ZIO_FLAG_SCAN_THREAD = 1U << 5,
- ZIO_FLAG_PHYSICAL = 1U << 6,
+#define ZIO_FLAG_DONT_AGGREGATE (1ULL << 0)
+#define ZIO_FLAG_IO_REPAIR (1ULL << 1)
+#define ZIO_FLAG_SELF_HEAL (1ULL << 2)
+#define ZIO_FLAG_RESILVER (1ULL << 3)
+#define ZIO_FLAG_SCRUB (1ULL << 4)
+#define ZIO_FLAG_SCAN_THREAD (1ULL << 5)
+#define ZIO_FLAG_PHYSICAL (1ULL << 6)
#define ZIO_FLAG_AGG_INHERIT (ZIO_FLAG_CANFAIL - 1)
/*
* Flags inherited by ddt, gang, and vdev children.
*/
- ZIO_FLAG_CANFAIL = 1U << 7, /* must be first for INHERIT */
- ZIO_FLAG_SPECULATIVE = 1U << 8,
- ZIO_FLAG_CONFIG_WRITER = 1U << 9,
- ZIO_FLAG_DONT_RETRY = 1U << 10,
- ZIO_FLAG_DONT_CACHE = 1U << 11,
- ZIO_FLAG_NODATA = 1U << 12,
- ZIO_FLAG_INDUCE_DAMAGE = 1U << 13,
- ZIO_FLAG_IO_ALLOCATING = 1U << 14,
+#define ZIO_FLAG_CANFAIL (1ULL << 7) /* must be first for INHERIT */
+#define ZIO_FLAG_SPECULATIVE (1ULL << 8)
+#define ZIO_FLAG_CONFIG_WRITER (1ULL << 9)
+#define ZIO_FLAG_DONT_RETRY (1ULL << 10)
+#define ZIO_FLAG_NODATA (1ULL << 12)
+#define ZIO_FLAG_INDUCE_DAMAGE (1ULL << 13)
+#define ZIO_FLAG_IO_ALLOCATING (1ULL << 14)
#define ZIO_FLAG_DDT_INHERIT (ZIO_FLAG_IO_RETRY - 1)
#define ZIO_FLAG_GANG_INHERIT (ZIO_FLAG_IO_RETRY - 1)
@@ -196,30 +200,31 @@ enum zio_flag {
/*
* Flags inherited by vdev children.
*/
- ZIO_FLAG_IO_RETRY = 1U << 15, /* must be first for INHERIT */
- ZIO_FLAG_PROBE = 1U << 16,
- ZIO_FLAG_TRYHARD = 1U << 17,
- ZIO_FLAG_OPTIONAL = 1U << 18,
+#define ZIO_FLAG_IO_RETRY (1ULL << 15) /* must be first for INHERIT */
+#define ZIO_FLAG_PROBE (1ULL << 16)
+#define ZIO_FLAG_TRYHARD (1ULL << 17)
+#define ZIO_FLAG_OPTIONAL (1ULL << 18)
#define ZIO_FLAG_VDEV_INHERIT (ZIO_FLAG_DONT_QUEUE - 1)
/*
* Flags not inherited by any children.
*/
- ZIO_FLAG_DONT_QUEUE = 1U << 19, /* must be first for INHERIT */
- ZIO_FLAG_DONT_PROPAGATE = 1U << 20,
- ZIO_FLAG_IO_BYPASS = 1U << 21,
- ZIO_FLAG_IO_REWRITE = 1U << 22,
- ZIO_FLAG_RAW_COMPRESS = 1U << 23,
- ZIO_FLAG_RAW_ENCRYPT = 1U << 24,
- ZIO_FLAG_GANG_CHILD = 1U << 25,
- ZIO_FLAG_DDT_CHILD = 1U << 26,
- ZIO_FLAG_GODFATHER = 1U << 27,
- ZIO_FLAG_NOPWRITE = 1U << 28,
- ZIO_FLAG_REEXECUTED = 1U << 29,
- ZIO_FLAG_DELEGATED = 1U << 30,
- ZIO_FLAG_FASTWRITE = 1U << 31,
-};
+#define ZIO_FLAG_DONT_QUEUE (1ULL << 19) /* must be first for INHERIT */
+#define ZIO_FLAG_DONT_PROPAGATE (1ULL << 20)
+#define ZIO_FLAG_IO_BYPASS (1ULL << 21)
+#define ZIO_FLAG_IO_REWRITE (1ULL << 22)
+#define ZIO_FLAG_RAW_COMPRESS (1ULL << 23)
+#define ZIO_FLAG_RAW_ENCRYPT (1ULL << 24)
+#define ZIO_FLAG_GANG_CHILD (1ULL << 25)
+#define ZIO_FLAG_DDT_CHILD (1ULL << 26)
+#define ZIO_FLAG_GODFATHER (1ULL << 27)
+#define ZIO_FLAG_NOPWRITE (1ULL << 28)
+#define ZIO_FLAG_REEXECUTED (1ULL << 29)
+#define ZIO_FLAG_DELEGATED (1ULL << 30)
+
+#define ZIO_ALLOCATOR_NONE (-1)
+#define ZIO_HAS_ALLOCATOR(zio) ((zio)->io_allocator != ZIO_ALLOCATOR_NONE)
#define ZIO_FLAG_MUSTSUCCEED 0
#define ZIO_FLAG_RAW (ZIO_FLAG_RAW_COMPRESS | ZIO_FLAG_RAW_ENCRYPT)
@@ -299,12 +304,12 @@ struct zbookmark_phys {
uint64_t zb_blkid;
};
-typedef struct zbookmark_err_phys {
+struct zbookmark_err_phys {
uint64_t zb_object;
int64_t zb_level;
uint64_t zb_blkid;
uint64_t zb_birth;
-} zbookmark_err_phys_t;
+};
#define SET_BOOKMARK(zb, objset, object, level, blkid) \
{ \
@@ -338,12 +343,13 @@ typedef struct zio_prop {
enum zio_checksum zp_checksum;
enum zio_compress zp_compress;
uint8_t zp_complevel;
- dmu_object_type_t zp_type;
uint8_t zp_level;
uint8_t zp_copies;
+ dmu_object_type_t zp_type;
boolean_t zp_dedup;
boolean_t zp_dedup_verify;
boolean_t zp_nopwrite;
+ boolean_t zp_brtwrite;
boolean_t zp_encrypt;
boolean_t zp_byteorder;
uint8_t zp_salt[ZIO_DATA_SALT_LEN];
@@ -432,6 +438,12 @@ typedef struct zio_link {
list_node_t zl_child_node;
} zio_link_t;
+enum zio_qstate {
+ ZIO_QS_NONE = 0,
+ ZIO_QS_QUEUED,
+ ZIO_QS_ACTIVE,
+};
+
struct zio {
/* Core information about this I/O */
zbookmark_phys_t io_bookmark;
@@ -439,7 +451,6 @@ struct zio {
zio_type_t io_type;
enum zio_child io_child_type;
enum trim_flag io_trim_flags;
- int io_cmd;
zio_priority_t io_priority;
uint8_t io_reexecute;
uint8_t io_state[ZIO_WAIT_TYPES];
@@ -456,7 +467,6 @@ struct zio {
/* Callback info */
zio_done_func_t *io_ready;
zio_done_func_t *io_children_ready;
- zio_done_func_t *io_physdone;
zio_done_func_t *io_done;
void *io_private;
int64_t io_prev_space_delta; /* DMU private */
@@ -476,6 +486,12 @@ struct zio {
const zio_vsd_ops_t *io_vsd_ops;
metaslab_class_t *io_metaslab_class; /* dva throttle class */
+ enum zio_qstate io_queue_state; /* vdev queue state */
+ union {
+ list_node_t l;
+ avl_node_t a;
+ } io_queue_node ____cacheline_aligned; /* allocator and vdev queues */
+ avl_node_t io_offset_node; /* vdev offset queues */
uint64_t io_offset;
hrtime_t io_timestamp; /* submitted at */
hrtime_t io_queued_timestamp;
@@ -483,25 +499,19 @@ struct zio {
hrtime_t io_delta; /* vdev queue service delta */
hrtime_t io_delay; /* Device access time (disk or */
/* file). */
- avl_node_t io_queue_node;
- avl_node_t io_offset_node;
- avl_node_t io_alloc_node;
zio_alloc_list_t io_alloc_list;
/* Internal pipeline state */
- enum zio_flag io_flags;
+ zio_flag_t io_flags;
enum zio_stage io_stage;
enum zio_stage io_pipeline;
- enum zio_flag io_orig_flags;
+ zio_flag_t io_orig_flags;
enum zio_stage io_orig_stage;
enum zio_stage io_orig_pipeline;
enum zio_stage io_pipeline_trace;
int io_error;
int io_child_error[ZIO_CHILD_TYPES];
uint64_t io_children[ZIO_CHILD_TYPES][ZIO_WAIT_TYPES];
- uint64_t io_child_count;
- uint64_t io_phys_children;
- uint64_t io_parent_count;
uint64_t *io_stall;
zio_t *io_gang_leader;
zio_gang_node_t *io_gang_tree;
@@ -526,57 +536,61 @@ enum blk_verify_flag {
BLK_VERIFY_HALT
};
+enum blk_config_flag {
+ BLK_CONFIG_HELD, // SCL_VDEV held for writer
+ BLK_CONFIG_NEEDED, // SCL_VDEV should be obtained for reader
+ BLK_CONFIG_SKIP, // skip checks which require SCL_VDEV
+};
+
extern int zio_bookmark_compare(const void *, const void *);
extern zio_t *zio_null(zio_t *pio, spa_t *spa, vdev_t *vd,
- zio_done_func_t *done, void *priv, enum zio_flag flags);
+ zio_done_func_t *done, void *priv, zio_flag_t flags);
extern zio_t *zio_root(spa_t *spa,
- zio_done_func_t *done, void *priv, enum zio_flag flags);
+ zio_done_func_t *done, void *priv, zio_flag_t flags);
+
+extern void zio_destroy(zio_t *zio);
extern zio_t *zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
struct abd *data, uint64_t lsize, zio_done_func_t *done, void *priv,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb);
+ zio_priority_t priority, zio_flag_t flags, const zbookmark_phys_t *zb);
extern zio_t *zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
struct abd *data, uint64_t size, uint64_t psize, const zio_prop_t *zp,
zio_done_func_t *ready, zio_done_func_t *children_ready,
- zio_done_func_t *physdone, zio_done_func_t *done,
- void *priv, zio_priority_t priority, enum zio_flag flags,
- const zbookmark_phys_t *zb);
+ zio_done_func_t *done, void *priv, zio_priority_t priority,
+ zio_flag_t flags, const zbookmark_phys_t *zb);
extern zio_t *zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
struct abd *data, uint64_t size, zio_done_func_t *done, void *priv,
- zio_priority_t priority, enum zio_flag flags, zbookmark_phys_t *zb);
+ zio_priority_t priority, zio_flag_t flags, zbookmark_phys_t *zb);
extern void zio_write_override(zio_t *zio, blkptr_t *bp, int copies,
- boolean_t nopwrite);
+ boolean_t nopwrite, boolean_t brtwrite);
extern void zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp);
extern zio_t *zio_claim(zio_t *pio, spa_t *spa, uint64_t txg,
const blkptr_t *bp,
- zio_done_func_t *done, void *priv, enum zio_flag flags);
-
-extern zio_t *zio_ioctl(zio_t *pio, spa_t *spa, vdev_t *vd, int cmd,
- zio_done_func_t *done, void *priv, enum zio_flag flags);
+ zio_done_func_t *done, void *priv, zio_flag_t flags);
extern zio_t *zio_trim(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
zio_done_func_t *done, void *priv, zio_priority_t priority,
- enum zio_flag flags, enum trim_flag trim_flags);
+ zio_flag_t flags, enum trim_flag trim_flags);
extern zio_t *zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset,
uint64_t size, struct abd *data, int checksum,
zio_done_func_t *done, void *priv, zio_priority_t priority,
- enum zio_flag flags, boolean_t labels);
+ zio_flag_t flags, boolean_t labels);
extern zio_t *zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset,
uint64_t size, struct abd *data, int checksum,
zio_done_func_t *done, void *priv, zio_priority_t priority,
- enum zio_flag flags, boolean_t labels);
+ zio_flag_t flags, boolean_t labels);
extern zio_t *zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg,
- const blkptr_t *bp, enum zio_flag flags);
+ const blkptr_t *bp, zio_flag_t flags);
extern int zio_alloc_zil(spa_t *spa, objset_t *os, uint64_t txg,
blkptr_t *new_bp, uint64_t size, boolean_t *slog);
@@ -595,6 +609,7 @@ extern zio_t *zio_walk_parents(zio_t *cio, zio_link_t **);
extern zio_t *zio_walk_children(zio_t *pio, zio_link_t **);
extern zio_t *zio_unique_parent(zio_t *cio);
extern void zio_add_child(zio_t *pio, zio_t *cio);
+extern void zio_add_child_first(zio_t *pio, zio_t *cio);
extern void *zio_buf_alloc(size_t size);
extern void zio_buf_free(void *buf, size_t size);
@@ -609,12 +624,12 @@ extern void zio_resubmit_stage_async(void *);
extern zio_t *zio_vdev_child_io(zio_t *zio, blkptr_t *bp, vdev_t *vd,
uint64_t offset, struct abd *data, uint64_t size, int type,
- zio_priority_t priority, enum zio_flag flags,
+ zio_priority_t priority, zio_flag_t flags,
zio_done_func_t *done, void *priv);
extern zio_t *zio_vdev_delegated_io(vdev_t *vd, uint64_t offset,
struct abd *data, uint64_t size, zio_type_t type, zio_priority_t priority,
- enum zio_flag flags, zio_done_func_t *done, void *priv);
+ zio_flag_t flags, zio_done_func_t *done, void *priv);
extern void zio_vdev_io_bypass(zio_t *zio);
extern void zio_vdev_io_reissue(zio_t *zio);
@@ -639,7 +654,7 @@ extern int zio_resume(spa_t *spa);
extern void zio_resume_wait(spa_t *spa);
extern boolean_t zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp,
- boolean_t config_held, enum blk_verify_flag blk_verify);
+ enum blk_config_flag blk_config, enum blk_verify_flag blk_verify);
/*
* Initial setup and teardown.
@@ -668,6 +683,8 @@ extern int zio_handle_device_injections(vdev_t *vd, zio_t *zio, int err1,
extern int zio_handle_label_injection(zio_t *zio, int error);
extern void zio_handle_ignored_writes(zio_t *zio);
extern hrtime_t zio_handle_io_delay(zio_t *zio);
+extern void zio_handle_import_delay(spa_t *spa, hrtime_t elapsed);
+extern void zio_handle_export_delay(spa_t *spa, hrtime_t elapsed);
/*
* Checksum ereport functions
@@ -696,6 +713,8 @@ extern void spa_handle_ignored_writes(spa_t *spa);
/* zbookmark_phys functions */
boolean_t zbookmark_subtree_completed(const struct dnode_phys *dnp,
const zbookmark_phys_t *subtree_root, const zbookmark_phys_t *last_block);
+boolean_t zbookmark_subtree_tbd(const struct dnode_phys *dnp,
+ const zbookmark_phys_t *subtree_root, const zbookmark_phys_t *last_block);
int zbookmark_compare(uint16_t dbss1, uint8_t ibs1, uint16_t dbss2,
uint8_t ibs2, const zbookmark_phys_t *zb1, const zbookmark_phys_t *zb2);
diff --git a/include/sys/zio_checksum.h b/include/sys/zio_checksum.h
index 989f125e6afd..37fd65b7cb3e 100644
--- a/include/sys/zio_checksum.h
+++ b/include/sys/zio_checksum.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -94,15 +94,13 @@ typedef const struct zio_checksum_info {
} zio_checksum_info_t;
typedef struct zio_bad_cksum {
- zio_cksum_t zbc_expected;
- zio_cksum_t zbc_actual;
const char *zbc_checksum_name;
uint8_t zbc_byteswapped;
uint8_t zbc_injected;
uint8_t zbc_has_cksum; /* expected/actual valid */
} zio_bad_cksum_t;
-_SYS_ZIO_CHECKSUM_H const zio_checksum_info_t
+_SYS_ZIO_CHECKSUM_H zio_checksum_info_t
zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS];
/*
@@ -110,9 +108,9 @@ _SYS_ZIO_CHECKSUM_H const zio_checksum_info_t
*/
/* SHA2 */
-extern zio_checksum_t abd_checksum_SHA256;
-extern zio_checksum_t abd_checksum_SHA512_native;
-extern zio_checksum_t abd_checksum_SHA512_byteswap;
+extern zio_checksum_t abd_checksum_sha256;
+extern zio_checksum_t abd_checksum_sha512_native;
+extern zio_checksum_t abd_checksum_sha512_byteswap;
/* Skein */
extern zio_checksum_t abd_checksum_skein_native;
diff --git a/include/sys/zio_compress.h b/include/sys/zio_compress.h
index 26600b43bb49..691d7b624488 100644
--- a/include/sys/zio_compress.h
+++ b/include/sys/zio_compress.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -152,7 +152,7 @@ typedef const struct zio_compress_info {
zio_decompresslevel_func_t *ci_decompress_level;
} zio_compress_info_t;
-extern const zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS];
+extern zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS];
/*
* lz4 compression init & free
@@ -183,7 +183,7 @@ extern int lz4_decompress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
/*
* Compress and decompress data if necessary.
*/
-extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void *dst,
+extern size_t zio_compress_data(enum zio_compress c, abd_t *src, void **dst,
size_t s_len, uint8_t level);
extern int zio_decompress_data(enum zio_compress c, abd_t *src, void *dst,
size_t s_len, size_t d_len, uint8_t *level);
diff --git a/include/sys/zio_impl.h b/include/sys/zio_impl.h
index 4c998571653a..2b026d48675a 100644
--- a/include/sys/zio_impl.h
+++ b/include/sys/zio_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2024, Klara Inc.
*/
#ifndef _ZIO_IMPL_H
@@ -39,7 +40,7 @@ extern "C" {
*
* The ZFS I/O pipeline is comprised of various stages which are defined
* in the zio_stage enum below. The individual stages are used to construct
- * these basic I/O operations: Read, Write, Free, Claim, and Ioctl.
+ * these basic I/O operations: Read, Write, Free, Claim, Flush and Trim.
*
* I/O operations: (XXX - provide detail for each of the operations)
*
@@ -47,7 +48,8 @@ extern "C" {
* Write:
* Free:
* Claim:
- * Ioctl:
+ * Flush:
+ * Trim:
*
* Although the most common pipeline are used by the basic I/O operations
* above, there are some helper pipelines (one could consider them
@@ -77,6 +79,12 @@ extern "C" {
* and zstd. Compression occurs as part of the write pipeline and is
* performed in the ZIO_STAGE_WRITE_BP_INIT stage.
*
+ * Block cloning:
+ * The block cloning functionality introduces ZIO_STAGE_BRT_FREE stage which
+ * is called during a free pipeline. If the block is referenced in the
+ * Block Cloning Table (BRT) we will just decrease its reference counter
+ * instead of actually freeing the block.
+ *
* Dedup:
* Dedup reads are handled by the ZIO_STAGE_DDT_READ_START and
* ZIO_STAGE_DDT_READ_DONE stages. These stages are added to an existing
@@ -114,43 +122,48 @@ extern "C" {
* zio pipeline stage definitions
*/
enum zio_stage {
- ZIO_STAGE_OPEN = 1 << 0, /* RWFCI */
+ ZIO_STAGE_OPEN = 1 << 0, /* RWFCXT */
+
+ ZIO_STAGE_READ_BP_INIT = 1 << 1, /* R----- */
+ ZIO_STAGE_WRITE_BP_INIT = 1 << 2, /* -W---- */
+ ZIO_STAGE_FREE_BP_INIT = 1 << 3, /* --F--- */
+ ZIO_STAGE_ISSUE_ASYNC = 1 << 4, /* -WF--T */
+ ZIO_STAGE_WRITE_COMPRESS = 1 << 5, /* -W---- */
- ZIO_STAGE_READ_BP_INIT = 1 << 1, /* R---- */
- ZIO_STAGE_WRITE_BP_INIT = 1 << 2, /* -W--- */
- ZIO_STAGE_FREE_BP_INIT = 1 << 3, /* --F-- */
- ZIO_STAGE_ISSUE_ASYNC = 1 << 4, /* RWF-- */
- ZIO_STAGE_WRITE_COMPRESS = 1 << 5, /* -W--- */
+ ZIO_STAGE_ENCRYPT = 1 << 6, /* -W---- */
+ ZIO_STAGE_CHECKSUM_GENERATE = 1 << 7, /* -W---- */
- ZIO_STAGE_ENCRYPT = 1 << 6, /* -W--- */
- ZIO_STAGE_CHECKSUM_GENERATE = 1 << 7, /* -W--- */
+ ZIO_STAGE_NOP_WRITE = 1 << 8, /* -W---- */
- ZIO_STAGE_NOP_WRITE = 1 << 8, /* -W--- */
+ ZIO_STAGE_BRT_FREE = 1 << 9, /* --F--- */
- ZIO_STAGE_DDT_READ_START = 1 << 9, /* R---- */
- ZIO_STAGE_DDT_READ_DONE = 1 << 10, /* R---- */
- ZIO_STAGE_DDT_WRITE = 1 << 11, /* -W--- */
- ZIO_STAGE_DDT_FREE = 1 << 12, /* --F-- */
+ ZIO_STAGE_DDT_READ_START = 1 << 10, /* R----- */
+ ZIO_STAGE_DDT_READ_DONE = 1 << 11, /* R----- */
+ ZIO_STAGE_DDT_WRITE = 1 << 12, /* -W---- */
+ ZIO_STAGE_DDT_FREE = 1 << 13, /* --F--- */
- ZIO_STAGE_GANG_ASSEMBLE = 1 << 13, /* RWFC- */
- ZIO_STAGE_GANG_ISSUE = 1 << 14, /* RWFC- */
+ ZIO_STAGE_GANG_ASSEMBLE = 1 << 14, /* RWFC-- */
+ ZIO_STAGE_GANG_ISSUE = 1 << 15, /* RWFC-- */
- ZIO_STAGE_DVA_THROTTLE = 1 << 15, /* -W--- */
- ZIO_STAGE_DVA_ALLOCATE = 1 << 16, /* -W--- */
- ZIO_STAGE_DVA_FREE = 1 << 17, /* --F-- */
- ZIO_STAGE_DVA_CLAIM = 1 << 18, /* ---C- */
+ ZIO_STAGE_DVA_THROTTLE = 1 << 16, /* -W---- */
+ ZIO_STAGE_DVA_ALLOCATE = 1 << 17, /* -W---- */
+ ZIO_STAGE_DVA_FREE = 1 << 18, /* --F--- */
+ ZIO_STAGE_DVA_CLAIM = 1 << 19, /* ---C-- */
- ZIO_STAGE_READY = 1 << 19, /* RWFCI */
+ ZIO_STAGE_READY = 1 << 20, /* RWFCXT */
- ZIO_STAGE_VDEV_IO_START = 1 << 20, /* RW--I */
- ZIO_STAGE_VDEV_IO_DONE = 1 << 21, /* RW--I */
- ZIO_STAGE_VDEV_IO_ASSESS = 1 << 22, /* RW--I */
+ ZIO_STAGE_VDEV_IO_START = 1 << 21, /* RW--XT */
+ ZIO_STAGE_VDEV_IO_DONE = 1 << 22, /* RW--XT */
+ ZIO_STAGE_VDEV_IO_ASSESS = 1 << 23, /* RW--XT */
- ZIO_STAGE_CHECKSUM_VERIFY = 1 << 23, /* R---- */
+ ZIO_STAGE_CHECKSUM_VERIFY = 1 << 24, /* R----- */
- ZIO_STAGE_DONE = 1 << 24 /* RWFCI */
+ ZIO_STAGE_DONE = 1 << 25 /* RWFCXT */
};
+#define ZIO_ROOT_PIPELINE \
+ ZIO_STAGE_DONE
+
#define ZIO_INTERLOCK_STAGES \
(ZIO_STAGE_READY | \
ZIO_STAGE_DONE)
@@ -233,6 +246,7 @@ enum zio_stage {
#define ZIO_FREE_PIPELINE \
(ZIO_INTERLOCK_STAGES | \
ZIO_STAGE_FREE_BP_INIT | \
+ ZIO_STAGE_BRT_FREE | \
ZIO_STAGE_DVA_FREE)
#define ZIO_DDT_FREE_PIPELINE \
@@ -245,10 +259,9 @@ enum zio_stage {
(ZIO_INTERLOCK_STAGES | \
ZIO_STAGE_DVA_CLAIM)
-#define ZIO_IOCTL_PIPELINE \
+#define ZIO_FLUSH_PIPELINE \
(ZIO_INTERLOCK_STAGES | \
- ZIO_STAGE_VDEV_IO_START | \
- ZIO_STAGE_VDEV_IO_ASSESS)
+ ZIO_VDEV_IO_STAGES)
#define ZIO_TRIM_PIPELINE \
(ZIO_INTERLOCK_STAGES | \
diff --git a/include/sys/zrlock.h b/include/sys/zrlock.h
index b6eba1a18ff4..e2a7a254a6e0 100644
--- a/include/sys/zrlock.h
+++ b/include/sys/zrlock.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -34,9 +34,8 @@ extern "C" {
typedef struct zrlock {
kmutex_t zr_mtx;
- volatile int32_t zr_refcount;
kcondvar_t zr_cv;
- uint16_t zr_pad;
+ volatile int32_t zr_refcount;
#ifdef ZFS_DEBUG
kthread_t *zr_owner;
const char *zr_caller;
diff --git a/include/sys/zvol.h b/include/sys/zvol.h
index a0f18001304e..c79fe1d9ad22 100644
--- a/include/sys/zvol.h
+++ b/include/sys/zvol.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -50,8 +50,9 @@ extern int zvol_get_stats(objset_t *, nvlist_t *);
extern boolean_t zvol_is_zvol(const char *);
extern void zvol_create_cb(objset_t *, void *, cred_t *, dmu_tx_t *);
extern int zvol_set_volsize(const char *, uint64_t);
-extern int zvol_set_snapdev(const char *, zprop_source_t, uint64_t);
-extern int zvol_set_volmode(const char *, zprop_source_t, uint64_t);
+extern int zvol_set_volthreading(const char *, boolean_t);
+extern int zvol_set_common(const char *, zfs_prop_t, zprop_source_t, uint64_t);
+extern int zvol_set_ro(const char *, boolean_t);
extern zvol_state_handle_t *zvol_suspend(const char *);
extern int zvol_resume(zvol_state_handle_t *);
extern void *zvol_tag(zvol_state_handle_t *);
diff --git a/include/sys/zvol_impl.h b/include/sys/zvol_impl.h
index 94203347066b..6c15c84b6bf4 100644
--- a/include/sys/zvol_impl.h
+++ b/include/sys/zvol_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -58,6 +58,7 @@ typedef struct zvol_state {
atomic_t zv_suspend_ref; /* refcount for suspend */
krwlock_t zv_suspend_lock; /* suspend lock */
struct zvol_state_os *zv_zso; /* private platform state */
+ boolean_t zv_threading; /* volthreading property */
} zvol_state_t;
@@ -81,9 +82,9 @@ void zvol_remove_minors_impl(const char *name);
void zvol_last_close(zvol_state_t *zv);
void zvol_insert(zvol_state_t *zv);
void zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off,
- uint64_t len, boolean_t sync);
+ uint64_t len);
void zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
- uint64_t size, int sync);
+ uint64_t size, boolean_t commit);
int zvol_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
struct lwb *lwb, zio_t *zio);
int zvol_init_impl(void);
diff --git a/include/thread_pool.h b/include/thread_pool.h
index 19edebd7da36..2e0aed5f7f57 100644
--- a/include/thread_pool.h
+++ b/include/thread_pool.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/zfeature_common.h b/include/zfeature_common.h
index d98345fe6850..2515ba321759 100644
--- a/include/zfeature_common.h
+++ b/include/zfeature_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -78,6 +78,10 @@ typedef enum spa_feature {
SPA_FEATURE_ZILSAXATTR,
SPA_FEATURE_HEAD_ERRLOG,
SPA_FEATURE_BLAKE3,
+ SPA_FEATURE_BLOCK_CLONING,
+ SPA_FEATURE_AVZ_V2,
+ SPA_FEATURE_REDACTION_LIST_SPILL,
+ SPA_FEATURE_RAIDZ_EXPANSION,
SPA_FEATURES
} spa_feature_t;
diff --git a/include/zfs_comutil.h b/include/zfs_comutil.h
index 51625a5cd03d..25f0959e00b1 100644
--- a/include/zfs_comutil.h
+++ b/include/zfs_comutil.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/zfs_deleg.h b/include/zfs_deleg.h
index 760d16aefcf3..92331b4eeba5 100644
--- a/include/zfs_deleg.h
+++ b/include/zfs_deleg.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/zfs_fletcher.h b/include/zfs_fletcher.h
index 28cb8ba234e5..ca1a092928d6 100644
--- a/include/zfs_fletcher.h
+++ b/include/zfs_fletcher.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -76,19 +76,19 @@ typedef struct zfs_fletcher_superscalar {
} zfs_fletcher_superscalar_t;
typedef struct zfs_fletcher_sse {
- uint64_t v[2] __attribute__((aligned(16)));
+ uint64_t v[2];
} zfs_fletcher_sse_t;
typedef struct zfs_fletcher_avx {
- uint64_t v[4] __attribute__((aligned(32)));
+ uint64_t v[4];
} zfs_fletcher_avx_t;
typedef struct zfs_fletcher_avx512 {
- uint64_t v[8] __attribute__((aligned(64)));
+ uint64_t v[8];
} zfs_fletcher_avx512_t;
typedef struct zfs_fletcher_aarch64_neon {
- uint64_t v[2] __attribute__((aligned(16)));
+ uint64_t v[2];
} zfs_fletcher_aarch64_neon_t;
@@ -126,8 +126,9 @@ typedef struct fletcher_4_func {
fletcher_4_fini_f fini_byteswap;
fletcher_4_compute_f compute_byteswap;
boolean_t (*valid)(void);
+ boolean_t uses_fpu;
const char *name;
-} fletcher_4_ops_t;
+} __attribute__((aligned(64))) fletcher_4_ops_t;
_ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_superscalar_ops;
_ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_superscalar4_ops;
@@ -160,20 +161,4 @@ _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_aarch64_neon_ops;
}
#endif
-#if defined(ZFS_UBSAN_ENABLED)
-#if defined(__has_attribute)
-#if __has_attribute(no_sanitize_undefined)
-#define ZFS_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
-#elif __has_attribute(no_sanitize)
-#define ZFS_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
-#else
-#error "Compiler has to support attribute "
- "`no_sanitize_undefined` or `no_sanitize(\"undefined\")`"
- "when compiling with UBSan enabled"
-#endif /* __has_attribute(no_sanitize_undefined) */
-#endif /* defined(__has_attribute) */
-#else
-#define ZFS_NO_SANITIZE_UNDEFINED
-#endif /* defined(ZFS_UBSAN_ENABLED) */
-
#endif /* _ZFS_FLETCHER_H */
diff --git a/include/zfs_namecheck.h b/include/zfs_namecheck.h
index 4739b065c51c..d3a923909c69 100644
--- a/include/zfs_namecheck.h
+++ b/include/zfs_namecheck.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/include/zfs_prop.h b/include/zfs_prop.h
index dca537c3761a..3513c4b40932 100644
--- a/include/zfs_prop.h
+++ b/include/zfs_prop.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 499ebdaeba9b..050a6cac0a37 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -9,11 +9,11 @@
# These library interfaces are subject to change at any time.
#
#
-# CMDS: zhack/ztest/zdb/ zfs/zpool/zed/
+# CMDS: zhack/ztest/ zfs/zpool/zed/
# raidz_{test,bench} zinject/zstream
# | |
# LIBS: | | libzfsbootenv*
-# | | |
+# |--libzdb--zdb | |
# | | |
# libzpool libzfs* ----------------+
# | | | \ / | | |
@@ -62,6 +62,7 @@ include $(srcdir)/%D%/libspl/Makefile.am
include $(srcdir)/%D%/libtpool/Makefile.am
include $(srcdir)/%D%/libunicode/Makefile.am
include $(srcdir)/%D%/libuutil/Makefile.am
+include $(srcdir)/%D%/libzdb/Makefile.am
include $(srcdir)/%D%/libzfs_core/Makefile.am
include $(srcdir)/%D%/libzfs/Makefile.am
include $(srcdir)/%D%/libzfsbootenv/Makefile.am
diff --git a/lib/libefi/rdwr_efi.c b/lib/libefi/rdwr_efi.c
index 30fddc3db8a8..739219e0410f 100644
--- a/lib/libefi/rdwr_efi.c
+++ b/lib/libefi/rdwr_efi.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -423,7 +423,6 @@ efi_alloc_and_read(int fd, struct dk_gpt **vtoc)
void *tmp;
length = (int) sizeof (struct dk_gpt) +
(int) sizeof (struct dk_part) * (vptr->efi_nparts - 1);
- nparts = vptr->efi_nparts;
if ((tmp = realloc(vptr, length)) == NULL) {
/* cppcheck-suppress doubleFree */
free(vptr);
@@ -565,10 +564,9 @@ int
efi_rescan(int fd)
{
int retry = 10;
- int error;
/* Notify the kernel a devices partition table has been updated */
- while ((error = ioctl(fd, BLKRRPART)) != 0) {
+ while (ioctl(fd, BLKRRPART) != 0) {
if ((--retry == 0) || (errno != EBUSY)) {
(void) fprintf(stderr, "the kernel failed to rescan "
"the partition table: %d\n", errno);
@@ -1364,7 +1362,7 @@ efi_write(int fd, struct dk_gpt *vtoc)
if (NBLOCKS(vtoc->efi_nparts, vtoc->efi_lbasize) < 34) {
dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + vtoc->efi_lbasize;
} else {
- dk_ioc.dki_length = NBLOCKS(vtoc->efi_nparts,
+ dk_ioc.dki_length = (len_t)NBLOCKS(vtoc->efi_nparts,
vtoc->efi_lbasize) *
vtoc->efi_lbasize;
}
diff --git a/lib/libicp/Makefile.am b/lib/libicp/Makefile.am
index b7f1d0e1b1e4..4ba55b2158bc 100644
--- a/lib/libicp/Makefile.am
+++ b/lib/libicp/Makefile.am
@@ -16,7 +16,6 @@ nodist_libicp_la_SOURCES = \
module/icp/algs/blake3/blake3.c \
module/icp/algs/blake3/blake3_generic.c \
module/icp/algs/blake3/blake3_impl.c \
- module/icp/algs/blake3/blake3_x86-64.c \
module/icp/algs/edonr/edonr.c \
module/icp/algs/modes/modes.c \
module/icp/algs/modes/cbc.c \
@@ -26,7 +25,9 @@ nodist_libicp_la_SOURCES = \
module/icp/algs/modes/ctr.c \
module/icp/algs/modes/ccm.c \
module/icp/algs/modes/ecb.c \
- module/icp/algs/sha2/sha2.c \
+ module/icp/algs/sha2/sha2_generic.c \
+ module/icp/algs/sha2/sha256_impl.c \
+ module/icp/algs/sha2/sha512_impl.c \
module/icp/algs/skein/skein.c \
module/icp/algs/skein/skein_block.c \
module/icp/algs/skein/skein_iv.c \
@@ -38,18 +39,31 @@ nodist_libicp_la_SOURCES = \
module/icp/core/kcf_prov_lib.c \
module/icp/core/kcf_callprov.c \
module/icp/core/kcf_mech_tabs.c \
- module/icp/core/kcf_prov_tabs.c
+ module/icp/core/kcf_prov_tabs.c \
+ module/zfs/zfs_impl.c
if TARGET_CPU_AARCH64
nodist_libicp_la_SOURCES += \
module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S \
- module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
+ module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S \
+ module/icp/asm-aarch64/sha2/sha256-armv8.S \
+ module/icp/asm-aarch64/sha2/sha512-armv8.S
+endif
+
+if TARGET_CPU_ARM
+nodist_libicp_la_SOURCES += \
+ module/icp/asm-arm/sha2/sha256-armv7.S \
+ module/icp/asm-arm/sha2/sha512-armv7.S
endif
if TARGET_CPU_POWERPC
nodist_libicp_la_SOURCES += \
module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S \
- module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S
+ module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S \
+ module/icp/asm-ppc64/sha2/sha256-ppc.S \
+ module/icp/asm-ppc64/sha2/sha512-ppc.S \
+ module/icp/asm-ppc64/sha2/sha256-p8.S \
+ module/icp/asm-ppc64/sha2/sha512-p8.S
endif
if TARGET_CPU_X86_64
@@ -60,10 +74,11 @@ nodist_libicp_la_SOURCES += \
module/icp/asm-x86_64/modes/gcm_pclmulqdq.S \
module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S \
module/icp/asm-x86_64/modes/ghash-x86_64.S \
- module/icp/asm-x86_64/sha2/sha256_impl.S \
- module/icp/asm-x86_64/sha2/sha512_impl.S \
+ module/icp/asm-x86_64/sha2/sha256-x86_64.S \
+ module/icp/asm-x86_64/sha2/sha512-x86_64.S \
module/icp/asm-x86_64/blake3/blake3_avx2.S \
module/icp/asm-x86_64/blake3/blake3_avx512.S \
module/icp/asm-x86_64/blake3/blake3_sse2.S \
module/icp/asm-x86_64/blake3/blake3_sse41.S
endif
+
diff --git a/lib/libnvpair/libnvpair.abi b/lib/libnvpair/libnvpair.abi
index de15237da583..ef92f3e9bda6 100644
--- a/lib/libnvpair/libnvpair.abi
+++ b/lib/libnvpair/libnvpair.abi
@@ -1,5 +1,6 @@
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libnvpair.so.3'>
<elf-needed>
+ <dependency name='libtirpc.so.3'/>
<dependency name='libc.so.6'/>
</elf-needed>
<elf-function-symbols>
@@ -234,1106 +235,7 @@
<elf-symbol name='nv_alloc_nosleep' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_fixed_ops' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
- <abi-instr address-size='64' path='../../module/nvpair/fnvpair.c' language='LANG_C99'>
- <function-decl name='fnvlist_alloc' mangled-name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_alloc'>
- <return type-id='5ce45b60'/>
- </function-decl>
- <function-decl name='fnvlist_free' mangled-name='fnvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_free'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_size' mangled-name='fnvlist_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_size'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='b59d7dce'/>
- </function-decl>
- <function-decl name='fnvlist_pack' mangled-name='fnvlist_pack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_pack'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='78c01427' name='sizep'/>
- <return type-id='26a90f95'/>
- </function-decl>
- <function-decl name='fnvlist_pack_free' mangled-name='fnvlist_pack_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_pack_free'>
- <parameter type-id='26a90f95' name='pack'/>
- <parameter type-id='b59d7dce' name='size'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_unpack' mangled-name='fnvlist_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_unpack'>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <return type-id='5ce45b60'/>
- </function-decl>
- <function-decl name='fnvlist_dup' mangled-name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_dup'>
- <parameter type-id='22cce67b' name='nvl'/>
- <return type-id='5ce45b60'/>
- </function-decl>
- <function-decl name='fnvlist_merge' mangled-name='fnvlist_merge' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_merge'>
- <parameter type-id='5ce45b60' name='dst'/>
- <parameter type-id='5ce45b60' name='src'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_num_pairs' mangled-name='fnvlist_num_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_num_pairs'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='b59d7dce'/>
- </function-decl>
- <function-decl name='fnvlist_add_boolean' mangled-name='fnvlist_add_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_boolean_value' mangled-name='fnvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean_value'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='c19b74c3' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_byte' mangled-name='fnvlist_add_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_byte'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='d8bf0010' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int8' mangled-name='fnvlist_add_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int8'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='ee31ee44' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint8' mangled-name='fnvlist_add_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint8'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='b96825af' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int16' mangled-name='fnvlist_add_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int16'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='23bd8cb5' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint16' mangled-name='fnvlist_add_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint16'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='149c6638' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int32' mangled-name='fnvlist_add_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int32'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3ff5601b' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint32' mangled-name='fnvlist_add_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint32'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='8f92235e' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int64' mangled-name='fnvlist_add_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int64'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9da381c4' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint64' mangled-name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint64'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9c313c2d' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_string' mangled-name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_string'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='80f4b756' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_nvlist' mangled-name='fnvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvlist'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='5ce45b60' name='val'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_nvpair' mangled-name='fnvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='3fa542f0' name='pair'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_boolean_array' mangled-name='fnvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='c5f6c15b' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_byte_array' mangled-name='fnvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_byte_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='d1db479e' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int8_array' mangled-name='fnvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a06445da' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint8_array' mangled-name='fnvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9f7200cf' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int16_array' mangled-name='fnvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a3eb883d' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint16_array' mangled-name='fnvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='1b7d11c6' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int32_array' mangled-name='fnvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='1f526493' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint32_array' mangled-name='fnvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a6798dcc' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_int64_array' mangled-name='fnvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='505bed1a' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_uint64_array' mangled-name='fnvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='713a56f5' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_string_array' mangled-name='fnvlist_add_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_string_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='13956559' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_add_nvlist_array' mangled-name='fnvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvlist_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3bbfee2e' name='val'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_remove' mangled-name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_remove'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_remove_nvpair' mangled-name='fnvlist_remove_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_remove_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='3fa542f0' name='pair'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_nvpair' mangled-name='fnvlist_lookup_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='3fa542f0'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_boolean' mangled-name='fnvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_boolean_value' mangled-name='fnvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean_value'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_byte' mangled-name='fnvlist_lookup_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_byte'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='d8bf0010'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int8' mangled-name='fnvlist_lookup_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int8'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='ee31ee44'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int16' mangled-name='fnvlist_lookup_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int16'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='23bd8cb5'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int32' mangled-name='fnvlist_lookup_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int32'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='3ff5601b'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int64' mangled-name='fnvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int64'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='9da381c4'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint8' mangled-name='fnvlist_lookup_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint8'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='b96825af'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint16' mangled-name='fnvlist_lookup_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint16'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='149c6638'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint32' mangled-name='fnvlist_lookup_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint32'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='8f92235e'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint64' mangled-name='fnvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint64'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='9c313c2d'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_string' mangled-name='fnvlist_lookup_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_string'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='26a90f95'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_nvlist' mangled-name='fnvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_nvlist'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='5ce45b60'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_boolean_array' mangled-name='fnvlist_lookup_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='37e3bd22'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_byte_array' mangled-name='fnvlist_lookup_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_byte_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='45b65157'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int8_array' mangled-name='fnvlist_lookup_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='256d5229'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint8_array' mangled-name='fnvlist_lookup_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='ae3e8ca6'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int16_array' mangled-name='fnvlist_lookup_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='f76f73d0'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint16_array' mangled-name='fnvlist_lookup_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='8a121f49'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int32_array' mangled-name='fnvlist_lookup_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='4aafb922'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint32_array' mangled-name='fnvlist_lookup_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='90421557'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_int64_array' mangled-name='fnvlist_lookup_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='cb785ebf'/>
- </function-decl>
- <function-decl name='fnvlist_lookup_uint64_array' mangled-name='fnvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='5d6479ae'/>
- </function-decl>
- <function-decl name='fnvpair_value_boolean_value' mangled-name='fnvpair_value_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_boolean_value'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='fnvpair_value_byte' mangled-name='fnvpair_value_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_byte'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='d8bf0010'/>
- </function-decl>
- <function-decl name='fnvpair_value_int8' mangled-name='fnvpair_value_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int8'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='ee31ee44'/>
- </function-decl>
- <function-decl name='fnvpair_value_int16' mangled-name='fnvpair_value_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int16'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='23bd8cb5'/>
- </function-decl>
- <function-decl name='fnvpair_value_int32' mangled-name='fnvpair_value_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int32'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='3ff5601b'/>
- </function-decl>
- <function-decl name='fnvpair_value_int64' mangled-name='fnvpair_value_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int64'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='9da381c4'/>
- </function-decl>
- <function-decl name='fnvpair_value_uint8' mangled-name='fnvpair_value_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint8'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='b96825af'/>
- </function-decl>
- <function-decl name='fnvpair_value_uint16' mangled-name='fnvpair_value_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint16'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='149c6638'/>
- </function-decl>
- <function-decl name='fnvpair_value_uint32' mangled-name='fnvpair_value_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint32'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='8f92235e'/>
- </function-decl>
- <function-decl name='fnvpair_value_uint64' mangled-name='fnvpair_value_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint64'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='9c313c2d'/>
- </function-decl>
- <function-decl name='fnvpair_value_string' mangled-name='fnvpair_value_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_string'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <return type-id='26a90f95'/>
- </function-decl>
- <function-decl name='fnvpair_value_nvlist' mangled-name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_nvlist'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <return type-id='5ce45b60'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='../../module/nvpair/nvpair.c' language='LANG_C99'>
- <pointer-type-def type-id='37e3bd22' size-in-bits='64' id='03829398'/>
- <pointer-type-def type-id='9b23c9ad' size-in-bits='64' id='c0563f85'/>
- <qualified-type-def type-id='c19b74c3' const='yes' id='12373e33'/>
- <pointer-type-def type-id='12373e33' size-in-bits='64' id='c5f6c15b'/>
- <qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
- <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
- <qualified-type-def type-id='23bd8cb5' const='yes' id='75f7b0c5'/>
- <pointer-type-def type-id='75f7b0c5' size-in-bits='64' id='a3eb883d'/>
- <qualified-type-def type-id='3ff5601b' const='yes' id='922df12b'/>
- <pointer-type-def type-id='922df12b' size-in-bits='64' id='1f526493'/>
- <qualified-type-def type-id='9da381c4' const='yes' id='f07b7694'/>
- <pointer-type-def type-id='f07b7694' size-in-bits='64' id='505bed1a'/>
- <qualified-type-def type-id='ee31ee44' const='yes' id='721c32d4'/>
- <pointer-type-def type-id='721c32d4' size-in-bits='64' id='a06445da'/>
- <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
- <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
- <qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/>
- <pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/>
- <qualified-type-def type-id='57928edf' const='yes' id='642ee20f'/>
- <pointer-type-def type-id='642ee20f' size-in-bits='64' id='dace003f'/>
- <qualified-type-def type-id='d8bf0010' const='yes' id='a9125480'/>
- <pointer-type-def type-id='a9125480' size-in-bits='64' id='d1db479e'/>
- <qualified-type-def type-id='149c6638' const='yes' id='b01a5ac8'/>
- <pointer-type-def type-id='b01a5ac8' size-in-bits='64' id='1b7d11c6'/>
- <qualified-type-def type-id='8f92235e' const='yes' id='b9930aae'/>
- <pointer-type-def type-id='b9930aae' size-in-bits='64' id='a6798dcc'/>
- <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/>
- <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/>
- <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
- <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
- <pointer-type-def type-id='a0eb0f08' size-in-bits='64' id='7408d286'/>
- <pointer-type-def type-id='cebdd548' size-in-bits='64' id='e379e62d'/>
- <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
- <pointer-type-def type-id='f76f73d0' size-in-bits='64' id='7e73928e'/>
- <pointer-type-def type-id='4aafb922' size-in-bits='64' id='9aa04798'/>
- <pointer-type-def type-id='cb785ebf' size-in-bits='64' id='e37ce48f'/>
- <pointer-type-def type-id='256d5229' size-in-bits='64' id='ee181ab9'/>
- <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/>
- <pointer-type-def type-id='3fa542f0' size-in-bits='64' id='0b283d2e'/>
- <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/>
- <pointer-type-def type-id='45b65157' size-in-bits='64' id='3b0247c7'/>
- <pointer-type-def type-id='8a121f49' size-in-bits='64' id='bd8768d9'/>
- <pointer-type-def type-id='90421557' size-in-bits='64' id='9507d3c7'/>
- <pointer-type-def type-id='5d6479ae' size-in-bits='64' id='892b4acc'/>
- <pointer-type-def type-id='ae3e8ca6' size-in-bits='64' id='d8774064'/>
- <pointer-type-def type-id='3502e3ff' size-in-bits='64' id='4dd26a40'/>
- <function-decl name='nv_alloc_init' mangled-name='nv_alloc_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_init'>
- <parameter type-id='11871392' name='nva'/>
- <parameter type-id='ee1d4944' name='nvo'/>
- <parameter is-variadic='yes'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nv_alloc_reset' mangled-name='nv_alloc_reset' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_reset'>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='nv_alloc_fini' mangled-name='nv_alloc_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_fini'>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='nvlist_lookup_nv_alloc' mangled-name='nvlist_lookup_nv_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nv_alloc'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='11871392'/>
- </function-decl>
- <function-decl name='nvlist_nvflag' mangled-name='nvlist_nvflag' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_nvflag'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='3502e3ff'/>
- </function-decl>
- <function-decl name='nvlist_alloc' mangled-name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_alloc'>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='3502e3ff' name='nvflag'/>
- <parameter type-id='95e97e5e' name='kmflag'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_xalloc' mangled-name='nvlist_xalloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xalloc'>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='3502e3ff' name='nvflag'/>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_free' mangled-name='nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_free'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='nvlist_dup' mangled-name='nvlist_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_dup'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='95e97e5e' name='kmflag'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_xdup' mangled-name='nvlist_xdup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xdup'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_remove_all' mangled-name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove_all'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_remove' mangled-name='nvlist_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='8d0687d2' name='type'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_remove_nvpair' mangled-name='nvlist_remove_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='3fa542f0' name='nvp'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_boolean' mangled-name='nvlist_add_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_boolean_value' mangled-name='nvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean_value'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='c19b74c3' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_byte' mangled-name='nvlist_add_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_byte'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='d8bf0010' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int8' mangled-name='nvlist_add_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int8'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='ee31ee44' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint8' mangled-name='nvlist_add_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint8'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='b96825af' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int16' mangled-name='nvlist_add_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int16'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='23bd8cb5' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint16' mangled-name='nvlist_add_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint16'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='149c6638' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int32' mangled-name='nvlist_add_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int32'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3ff5601b' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint32' mangled-name='nvlist_add_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint32'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='8f92235e' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int64' mangled-name='nvlist_add_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int64'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9da381c4' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint64' mangled-name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint64'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9c313c2d' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_double' mangled-name='nvlist_add_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_double'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a0eb0f08' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_string' mangled-name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_string'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='80f4b756' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_boolean_array' mangled-name='nvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='c5f6c15b' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_byte_array' mangled-name='nvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_byte_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='d1db479e' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int8_array' mangled-name='nvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a06445da' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint8_array' mangled-name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9f7200cf' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int16_array' mangled-name='nvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a3eb883d' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint16_array' mangled-name='nvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='1b7d11c6' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int32_array' mangled-name='nvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='1f526493' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint32_array' mangled-name='nvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a6798dcc' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_int64_array' mangled-name='nvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='505bed1a' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_uint64_array' mangled-name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='713a56f5' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_string_array' mangled-name='nvlist_add_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_string_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='13956559' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_hrtime' mangled-name='nvlist_add_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_hrtime'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='cebdd548' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_nvlist' mangled-name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvlist'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='22cce67b' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_nvlist_array' mangled-name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvlist_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3bbfee2e' name='a'/>
- <parameter type-id='3502e3ff' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_next_nvpair' mangled-name='nvlist_next_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_next_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='3fa542f0'/>
- </function-decl>
- <function-decl name='nvlist_prev_nvpair' mangled-name='nvlist_prev_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_prev_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='3fa542f0'/>
- </function-decl>
- <function-decl name='nvlist_empty' mangled-name='nvlist_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_empty'>
- <parameter type-id='22cce67b' name='nvl'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='nvpair_name' mangled-name='nvpair_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_name'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='26a90f95'/>
- </function-decl>
- <function-decl name='nvpair_type' mangled-name='nvpair_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_type'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='8d0687d2'/>
- </function-decl>
- <function-decl name='nvpair_type_is_array' mangled-name='nvpair_type_is_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_type_is_array'>
- <parameter type-id='dace003f' name='nvp'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_boolean' mangled-name='nvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_boolean_value' mangled-name='nvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean_value'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='37e3bd22' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_byte' mangled-name='nvlist_lookup_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_byte'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='45b65157' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int8' mangled-name='nvlist_lookup_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int8'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='256d5229' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint8' mangled-name='nvlist_lookup_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint8'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='ae3e8ca6' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int16' mangled-name='nvlist_lookup_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int16'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='f76f73d0' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint16' mangled-name='nvlist_lookup_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint16'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='8a121f49' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int32' mangled-name='nvlist_lookup_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int32'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='4aafb922' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint32' mangled-name='nvlist_lookup_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint32'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='90421557' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int64' mangled-name='nvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int64'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='cb785ebf' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint64' mangled-name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint64'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='5d6479ae' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_double' mangled-name='nvlist_lookup_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_double'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='7408d286' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_string' mangled-name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_string'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9b23c9ad' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_nvlist' mangled-name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvlist'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='857bb57e' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_boolean_array' mangled-name='nvlist_lookup_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='03829398' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_byte_array' mangled-name='nvlist_lookup_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_byte_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3b0247c7' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int8_array' mangled-name='nvlist_lookup_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='ee181ab9' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint8_array' mangled-name='nvlist_lookup_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint8_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='d8774064' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int16_array' mangled-name='nvlist_lookup_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='7e73928e' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint16_array' mangled-name='nvlist_lookup_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint16_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='bd8768d9' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int32_array' mangled-name='nvlist_lookup_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9aa04798' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint32_array' mangled-name='nvlist_lookup_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint32_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9507d3c7' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_int64_array' mangled-name='nvlist_lookup_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='e37ce48f' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_uint64_array' mangled-name='nvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint64_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='892b4acc' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_string_array' mangled-name='nvlist_lookup_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_string_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='c0563f85' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_nvlist_array' mangled-name='nvlist_lookup_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvlist_array'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='75be733c' name='a'/>
- <parameter type-id='4dd26a40' name='n'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_hrtime' mangled-name='nvlist_lookup_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_hrtime'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='e379e62d' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_pairs' mangled-name='nvlist_lookup_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_pairs'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='95e97e5e' name='flag'/>
- <parameter is-variadic='yes'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_nvpair' mangled-name='nvlist_lookup_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='0b283d2e' name='ret'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_lookup_nvpair_embedded_index' mangled-name='nvlist_lookup_nvpair_embedded_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvpair_embedded_index'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='0b283d2e' name='ret'/>
- <parameter type-id='7292109c' name='ip'/>
- <parameter type-id='9b23c9ad' name='ep'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_exists' mangled-name='nvlist_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_exists'>
- <parameter type-id='22cce67b' name='nvl'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='nvpair_value_boolean_value' mangled-name='nvpair_value_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_boolean_value'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='37e3bd22' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_byte' mangled-name='nvpair_value_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_byte'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='45b65157' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int8' mangled-name='nvpair_value_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int8'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='256d5229' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint8' mangled-name='nvpair_value_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint8'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='ae3e8ca6' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int16' mangled-name='nvpair_value_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int16'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='f76f73d0' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint16' mangled-name='nvpair_value_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint16'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='8a121f49' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int32' mangled-name='nvpair_value_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int32'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='4aafb922' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint32' mangled-name='nvpair_value_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint32'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='90421557' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int64' mangled-name='nvpair_value_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int64'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='cb785ebf' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint64' mangled-name='nvpair_value_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint64'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='5d6479ae' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_double' mangled-name='nvpair_value_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_double'>
- <parameter type-id='dace003f' name='nvp'/>
- <parameter type-id='7408d286' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_string' mangled-name='nvpair_value_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_string'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='9b23c9ad' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_nvlist' mangled-name='nvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_nvlist'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='857bb57e' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_boolean_array' mangled-name='nvpair_value_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_boolean_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='03829398' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_byte_array' mangled-name='nvpair_value_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_byte_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='3b0247c7' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int8_array' mangled-name='nvpair_value_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int8_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='ee181ab9' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint8_array' mangled-name='nvpair_value_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint8_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='d8774064' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int16_array' mangled-name='nvpair_value_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int16_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='7e73928e' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint16_array' mangled-name='nvpair_value_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint16_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='bd8768d9' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int32_array' mangled-name='nvpair_value_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int32_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='9aa04798' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint32_array' mangled-name='nvpair_value_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint32_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='9507d3c7' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_int64_array' mangled-name='nvpair_value_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int64_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='e37ce48f' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_uint64_array' mangled-name='nvpair_value_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint64_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='892b4acc' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_string_array' mangled-name='nvpair_value_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_string_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='c0563f85' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_nvlist_array' mangled-name='nvpair_value_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_nvlist_array'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='75be733c' name='val'/>
- <parameter type-id='4dd26a40' name='nelem'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvpair_value_hrtime' mangled-name='nvpair_value_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_hrtime'>
- <parameter type-id='3fa542f0' name='nvp'/>
- <parameter type-id='e379e62d' name='val'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_add_nvpair' mangled-name='nvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvpair'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='3fa542f0' name='nvp'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_merge' mangled-name='nvlist_merge' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_merge'>
- <parameter type-id='5ce45b60' name='dst'/>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='95e97e5e' name='flag'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_size' mangled-name='nvlist_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_size'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='78c01427' name='size'/>
- <parameter type-id='95e97e5e' name='encoding'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_pack' mangled-name='nvlist_pack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_pack'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='9b23c9ad' name='bufp'/>
- <parameter type-id='78c01427' name='buflen'/>
- <parameter type-id='95e97e5e' name='encoding'/>
- <parameter type-id='95e97e5e' name='kmflag'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_xpack' mangled-name='nvlist_xpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xpack'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='9b23c9ad' name='bufp'/>
- <parameter type-id='78c01427' name='buflen'/>
- <parameter type-id='95e97e5e' name='encoding'/>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_unpack' mangled-name='nvlist_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_unpack'>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='95e97e5e' name='kmflag'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='nvlist_xunpack' mangled-name='nvlist_xunpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xunpack'>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <parameter type-id='857bb57e' name='nvlp'/>
- <parameter type-id='11871392' name='nva'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='../../module/nvpair/nvpair_alloc_fixed.c' language='LANG_C99'>
- <qualified-type-def type-id='ee1d4944' const='yes' id='4b95388f'/>
- <var-decl name='nv_fixed_ops' type-id='4b95388f' mangled-name='nv_fixed_ops' visibility='default' elf-symbol-id='nv_fixed_ops'/>
- </abi-instr>
- <abi-instr address-size='64' path='libnvpair.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libnvpair/libnvpair.c' language='LANG_C99'>
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
<subrange length='1' type-id='7359adad' id='52f813b4'/>
@@ -1341,6 +243,9 @@
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
<subrange length='20' type-id='7359adad' id='fdca39cf'/>
</array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='infinite' id='e84913bd'>
+ <subrange length='infinite' type-id='7359adad' id='031f2035'/>
+ </array-type-def>
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
@@ -1419,6 +324,9 @@
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='nvp_type' type-id='8d0687d2' visibility='default'/>
</data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='nvp_name' type-id='e84913bd' visibility='default'/>
+ </data-member>
</class-decl>
<typedef-decl name='nvpair_t' type-id='1c34e459' id='57928edf'/>
<class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'>
@@ -1448,6 +356,173 @@
<typedef-decl name='uchar_t' type-id='002ac4a6' id='d8bf0010'/>
<typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
<typedef-decl name='hrtime_t' type-id='1eb56b1e' id='cebdd548'/>
+ <typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
+ <typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
+ <class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='buffer' type-id='33976309' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='allocated' type-id='ba516949' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='used' type-id='ba516949' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='translate' type-id='cf536864' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='449'>
+ <var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='451'>
+ <var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='452'>
+ <var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='453'>
+ <var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='454'>
+ <var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='455'>
+ <var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
+ <typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
+ <class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
+ <typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
+ <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
+ <typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
+ <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
+ <typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/>
+ <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
+ <typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/>
+ <typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/>
+ <typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
+ <typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
+ <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
+ <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
+ <typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/>
+ <typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
+ <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
+ <typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/>
+ <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
+ <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
+ <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
+ <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
+ <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='928'>
+ <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1040'>
+ <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1048'>
+ <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1152'>
+ <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1216'>
+ <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1280'>
+ <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1344'>
+ <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1408'>
+ <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1472'>
+ <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1536'>
+ <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1568'>
+ <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
<class-decl name='nvlist_printops' size-in-bits='3456' is-struct='yes' visibility='default' id='ebc6735b'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='print_boolean' type-id='e7f43f72' visibility='default'/>
@@ -1629,7 +704,7 @@
</class-decl>
<class-decl name='__anonymous_struct__12' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7e'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='op' type-id='c0d0f877' visibility='default'/>
+ <var-decl name='op' type-id='bfc48fe4' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='arg' type-id='eaa32e2f' visibility='default'/>
@@ -1733,7 +808,7 @@
</class-decl>
<class-decl name='__anonymous_struct__25' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f8b'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='op' type-id='de20bf07' visibility='default'/>
+ <var-decl name='op' type-id='337f4a72' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='arg' type-id='eaa32e2f' visibility='default'/>
@@ -1779,177 +854,31 @@
<var-decl name='nvprt_custops' type-id='7be54adb' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
- <typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
- <class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='buffer' type-id='33976309' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='allocated' type-id='ba516949' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='used' type-id='ba516949' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='translate' type-id='cf536864' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='449'>
- <var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='451'>
- <var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='452'>
- <var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='453'>
- <var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='454'>
- <var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='455'>
- <var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
- <typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
- <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
- <typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
- <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
- <typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/>
- <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
- <typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/>
- <typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/>
- <typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
- <typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
- <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
- <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
- <typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/>
- <typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
- <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
- <typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/>
- <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
- <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
- <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
- <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
- <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='640'>
- <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='768'>
- <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='832'>
- <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='896'>
- <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='928'>
- <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1024'>
- <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1040'>
- <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1048'>
- <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1088'>
- <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1152'>
- <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1216'>
- <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1280'>
- <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1344'>
- <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1408'>
- <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1472'>
- <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1536'>
- <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1568'>
- <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
+ <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
<pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
<pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
<pointer-type-def type-id='c19b74c3' size-in-bits='64' id='37e3bd22'/>
+ <pointer-type-def type-id='37e3bd22' size-in-bits='64' id='03829398'/>
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
- <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
+ <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
+ <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/>
+ <pointer-type-def type-id='7d3cd834' size-in-bits='64' id='44c8373a'/>
+ <qualified-type-def type-id='57928edf' const='yes' id='642ee20f'/>
+ <pointer-type-def type-id='642ee20f' size-in-bits='64' id='dace003f'/>
+ <qualified-type-def type-id='aca3bac8' const='yes' id='2498fd78'/>
+ <pointer-type-def type-id='2498fd78' size-in-bits='64' id='eed6c816'/>
+ <qualified-type-def type-id='eed6c816' restrict='yes' id='a431a9da'/>
+ <pointer-type-def type-id='a0eb0f08' size-in-bits='64' id='7408d286'/>
+ <pointer-type-def type-id='cebdd548' size-in-bits='64' id='e379e62d'/>
<pointer-type-def type-id='9f88f76e' size-in-bits='64' id='7ef0e988'/>
- <pointer-type-def type-id='c5bb1a2b' size-in-bits='64' id='c0d0f877'/>
- <pointer-type-def type-id='573fea1b' size-in-bits='64' id='de20bf07'/>
+ <pointer-type-def type-id='889f3b42' size-in-bits='64' id='bfc48fe4'/>
+ <pointer-type-def type-id='49055dd8' size-in-bits='64' id='337f4a72'/>
<pointer-type-def type-id='70284cc6' size-in-bits='64' id='3be4d568'/>
<pointer-type-def type-id='700c3bca' size-in-bits='64' id='6d994334'/>
<pointer-type-def type-id='18ac1860' size-in-bits='64' id='506ab59a'/>
@@ -1975,8 +904,8 @@
<pointer-type-def type-id='3bd73b0c' size-in-bits='64' id='7e85a9b6'/>
<pointer-type-def type-id='0d445e26' size-in-bits='64' id='330cc0d0'/>
<pointer-type-def type-id='e4b89f30' size-in-bits='64' id='ed8aa8ba'/>
- <pointer-type-def type-id='be7f4941' size-in-bits='64' id='2809de35'/>
- <pointer-type-def type-id='fe5ae69d' size-in-bits='64' id='90d5edb9'/>
+ <pointer-type-def type-id='78e3bec8' size-in-bits='64' id='b38a1022'/>
+ <pointer-type-def type-id='a5193bb2' size-in-bits='64' id='6263eda4'/>
<pointer-type-def type-id='2783af3c' size-in-bits='64' id='e44553b6'/>
<pointer-type-def type-id='33c6e3d8' size-in-bits='64' id='1263777a'/>
<pointer-type-def type-id='dadb9eca' size-in-bits='64' id='cbda43ac'/>
@@ -2002,27 +931,254 @@
<pointer-type-def type-id='b2fbf64a' size-in-bits='64' id='470a7fd4'/>
<pointer-type-def type-id='cc22d314' size-in-bits='64' id='eddda806'/>
<pointer-type-def type-id='23bd8cb5' size-in-bits='64' id='f76f73d0'/>
+ <pointer-type-def type-id='f76f73d0' size-in-bits='64' id='7e73928e'/>
<pointer-type-def type-id='3ff5601b' size-in-bits='64' id='4aafb922'/>
+ <pointer-type-def type-id='4aafb922' size-in-bits='64' id='9aa04798'/>
<pointer-type-def type-id='9da381c4' size-in-bits='64' id='cb785ebf'/>
+ <pointer-type-def type-id='cb785ebf' size-in-bits='64' id='e37ce48f'/>
<pointer-type-def type-id='ee31ee44' size-in-bits='64' id='256d5229'/>
+ <pointer-type-def type-id='256d5229' size-in-bits='64' id='ee181ab9'/>
<pointer-type-def type-id='ebc6735b' size-in-bits='64' id='7be54adb'/>
<pointer-type-def type-id='d2e8bad9' size-in-bits='64' id='196db161'/>
<pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
<pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
+ <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/>
<pointer-type-def type-id='57928edf' size-in-bits='64' id='3fa542f0'/>
<pointer-type-def type-id='b48d2441' size-in-bits='64' id='33976309'/>
<pointer-type-def type-id='aca3bac8' size-in-bits='64' id='d33f11cb'/>
+ <pointer-type-def type-id='1b941664' size-in-bits='64' id='7e2979d5'/>
+ <qualified-type-def type-id='7e2979d5' restrict='yes' id='fc212857'/>
<pointer-type-def type-id='d8bf0010' size-in-bits='64' id='45b65157'/>
+ <pointer-type-def type-id='45b65157' size-in-bits='64' id='3b0247c7'/>
<pointer-type-def type-id='149c6638' size-in-bits='64' id='8a121f49'/>
+ <pointer-type-def type-id='8a121f49' size-in-bits='64' id='bd8768d9'/>
<pointer-type-def type-id='8f92235e' size-in-bits='64' id='90421557'/>
+ <pointer-type-def type-id='90421557' size-in-bits='64' id='9507d3c7'/>
<pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
+ <pointer-type-def type-id='5d6479ae' size-in-bits='64' id='892b4acc'/>
<pointer-type-def type-id='b96825af' size-in-bits='64' id='ae3e8ca6'/>
+ <pointer-type-def type-id='ae3e8ca6' size-in-bits='64' id='d8774064'/>
+ <pointer-type-def type-id='3502e3ff' size-in-bits='64' id='4dd26a40'/>
<pointer-type-def type-id='002ac4a6' size-in-bits='64' id='cf536864'/>
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
<class-decl name='re_dfa_t' is-struct='yes' visibility='default' is-declaration-only='yes' id='b48d2441'/>
+ <function-decl name='nvlist_next_nvpair' mangled-name='nvlist_next_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_next_nvpair'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='dace003f'/>
+ <return type-id='3fa542f0'/>
+ </function-decl>
+ <function-decl name='nvpair_name' mangled-name='nvpair_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_name'>
+ <parameter type-id='dace003f'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='nvpair_type' mangled-name='nvpair_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_type'>
+ <parameter type-id='dace003f'/>
+ <return type-id='8d0687d2'/>
+ </function-decl>
+ <function-decl name='nvpair_type_is_array' mangled-name='nvpair_type_is_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_type_is_array'>
+ <parameter type-id='dace003f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_boolean_value' mangled-name='nvpair_value_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_boolean_value'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='37e3bd22'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_byte' mangled-name='nvpair_value_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_byte'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='45b65157'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int8' mangled-name='nvpair_value_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int8'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='256d5229'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint8' mangled-name='nvpair_value_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint8'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='ae3e8ca6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int16' mangled-name='nvpair_value_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int16'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='f76f73d0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint16' mangled-name='nvpair_value_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint16'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='8a121f49'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int32' mangled-name='nvpair_value_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int32'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='4aafb922'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint32' mangled-name='nvpair_value_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint32'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='90421557'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int64' mangled-name='nvpair_value_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='cb785ebf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint64' mangled-name='nvpair_value_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_string' mangled-name='nvpair_value_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_string'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_nvlist' mangled-name='nvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_nvlist'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_boolean_array' mangled-name='nvpair_value_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_boolean_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='03829398'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_byte_array' mangled-name='nvpair_value_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_byte_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='3b0247c7'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int8_array' mangled-name='nvpair_value_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int8_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='ee181ab9'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint8_array' mangled-name='nvpair_value_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint8_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='d8774064'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int16_array' mangled-name='nvpair_value_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int16_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='7e73928e'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint16_array' mangled-name='nvpair_value_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint16_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='bd8768d9'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int32_array' mangled-name='nvpair_value_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int32_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='9aa04798'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint32_array' mangled-name='nvpair_value_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint32_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='9507d3c7'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int64_array' mangled-name='nvpair_value_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_int64_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='e37ce48f'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint64_array' mangled-name='nvpair_value_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_uint64_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='892b4acc'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_string_array' mangled-name='nvpair_value_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_string_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='44c8373a'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_nvlist_array' mangled-name='nvpair_value_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_nvlist_array'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='75be733c'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_hrtime' mangled-name='nvpair_value_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_hrtime'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='e379e62d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_double' mangled-name='nvpair_value_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_double'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='7408d286'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='dcgettext' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='regexec' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a431a9da'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='fc212857'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='calloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='strspn' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='nvlist_prtctl_setdest' mangled-name='nvlist_prtctl_setdest' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_prtctl_setdest'>
<parameter type-id='b0c1ff8d' name='pctl'/>
<parameter type-id='822cd80b' name='fp'/>
@@ -2130,7 +1286,7 @@
</function-decl>
<function-decl name='nvlist_prtctlop_string' mangled-name='nvlist_prtctlop_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_prtctlop_string'>
<parameter type-id='b0c1ff8d' name='pctl'/>
- <parameter type-id='2809de35' name='func'/>
+ <parameter type-id='b38a1022' name='func'/>
<parameter type-id='eaa32e2f' name='private'/>
<return type-id='48b5725f'/>
</function-decl>
@@ -2208,7 +1364,7 @@
</function-decl>
<function-decl name='nvlist_prtctlop_string_array' mangled-name='nvlist_prtctlop_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_prtctlop_string_array'>
<parameter type-id='b0c1ff8d' name='pctl'/>
- <parameter type-id='90d5edb9' name='func'/>
+ <parameter type-id='6263eda4' name='func'/>
<parameter type-id='eaa32e2f' name='private'/>
<return type-id='48b5725f'/>
</function-decl>
@@ -2243,16 +1399,16 @@
<function-decl name='nvpair_value_match_regex' mangled-name='nvpair_value_match_regex' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_match_regex'>
<parameter type-id='3fa542f0' name='nvp'/>
<parameter type-id='95e97e5e' name='ai'/>
- <parameter type-id='26a90f95' name='value'/>
+ <parameter type-id='80f4b756' name='value'/>
<parameter type-id='d33f11cb' name='value_regex'/>
- <parameter type-id='9b23c9ad' name='ep'/>
+ <parameter type-id='7d3cd834' name='ep'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='nvpair_value_match' mangled-name='nvpair_value_match' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvpair_value_match'>
<parameter type-id='3fa542f0' name='nvp'/>
<parameter type-id='95e97e5e' name='ai'/>
- <parameter type-id='26a90f95' name='value'/>
- <parameter type-id='9b23c9ad' name='ep'/>
+ <parameter type-id='80f4b756' name='value'/>
+ <parameter type-id='7d3cd834' name='ep'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-type size-in-bits='64' id='9f88f76e'>
@@ -2264,20 +1420,20 @@
<parameter type-id='3502e3ff'/>
<return type-id='95e97e5e'/>
</function-type>
- <function-type size-in-bits='64' id='c5bb1a2b'>
+ <function-type size-in-bits='64' id='889f3b42'>
<parameter type-id='196db161'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='5ce45b60'/>
<parameter type-id='80f4b756'/>
- <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-type>
- <function-type size-in-bits='64' id='573fea1b'>
+ <function-type size-in-bits='64' id='49055dd8'>
<parameter type-id='196db161'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='5ce45b60'/>
<parameter type-id='80f4b756'/>
- <parameter type-id='9b23c9ad'/>
+ <parameter type-id='7d3cd834'/>
<parameter type-id='3502e3ff'/>
<return type-id='95e97e5e'/>
</function-type>
@@ -2492,20 +1648,20 @@
<parameter type-id='3502e3ff'/>
<return type-id='95e97e5e'/>
</function-type>
- <function-type size-in-bits='64' id='be7f4941'>
+ <function-type size-in-bits='64' id='78e3bec8'>
<parameter type-id='b0c1ff8d'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='5ce45b60'/>
<parameter type-id='80f4b756'/>
- <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-type>
- <function-type size-in-bits='64' id='fe5ae69d'>
+ <function-type size-in-bits='64' id='a5193bb2'>
<parameter type-id='b0c1ff8d'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='5ce45b60'/>
<parameter type-id='80f4b756'/>
- <parameter type-id='9b23c9ad'/>
+ <parameter type-id='7d3cd834'/>
<parameter type-id='3502e3ff'/>
<return type-id='95e97e5e'/>
</function-type>
@@ -2712,14 +1868,106 @@
<return type-id='95e97e5e'/>
</function-type>
</abi-instr>
- <abi-instr address-size='64' path='libnvpair_json.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libnvpair/libnvpair_json.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
+ <class-decl name='__mbstate_t' size-in-bits='64' is-struct='yes' naming-typedef-id='55e5b2b5' visibility='default' id='87447a2e'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__count' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='__value' type-id='ac5ab595' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='__anonymous_union__' size-in-bits='32' is-anonymous='yes' visibility='default' id='ac5ab595'>
+ <data-member access='public'>
+ <var-decl name='__wch' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__wchb' type-id='8e0573fd' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='__mbstate_t' type-id='87447a2e' id='55e5b2b5'/>
+ <typedef-decl name='mbstate_t' type-id='55e5b2b5' id='3d7d8cbf'/>
+ <typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/>
+ <pointer-type-def type-id='3d7d8cbf' size-in-bits='64' id='a68021ce'/>
+ <qualified-type-def type-id='a68021ce' restrict='yes' id='03aaab72'/>
+ <pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/>
+ <qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/>
+ <function-decl name='fnvpair_value_boolean_value' mangled-name='fnvpair_value_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_boolean_value'>
+ <parameter type-id='dace003f'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_byte' mangled-name='fnvpair_value_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_byte'>
+ <parameter type-id='dace003f'/>
+ <return type-id='d8bf0010'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int8' mangled-name='fnvpair_value_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int8'>
+ <parameter type-id='dace003f'/>
+ <return type-id='ee31ee44'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int16' mangled-name='fnvpair_value_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int16'>
+ <parameter type-id='dace003f'/>
+ <return type-id='23bd8cb5'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int32' mangled-name='fnvpair_value_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int32'>
+ <parameter type-id='dace003f'/>
+ <return type-id='3ff5601b'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int64' mangled-name='fnvpair_value_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_int64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='9da381c4'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_uint8' mangled-name='fnvpair_value_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint8'>
+ <parameter type-id='dace003f'/>
+ <return type-id='b96825af'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_uint16' mangled-name='fnvpair_value_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint16'>
+ <parameter type-id='dace003f'/>
+ <return type-id='149c6638'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_uint32' mangled-name='fnvpair_value_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint32'>
+ <parameter type-id='dace003f'/>
+ <return type-id='8f92235e'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_uint64' mangled-name='fnvpair_value_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_uint64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_string' mangled-name='fnvpair_value_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_string'>
+ <parameter type-id='dace003f'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_nvlist' mangled-name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_nvlist'>
+ <parameter type-id='3fa542f0'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__ctype_get_mb_cur_max' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='mbrtowc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f1358bc3'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='03aaab72'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
<function-decl name='nvlist_print_json' mangled-name='nvlist_print_json' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_print_json'>
<parameter type-id='822cd80b' name='fp'/>
<parameter type-id='5ce45b60' name='nvl'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='nvpair_alloc_system.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libnvpair/nvpair_alloc_system.c' language='LANG_C99'>
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
@@ -2792,18 +2040,1126 @@
<return type-id='eaa32e2f'/>
</function-type>
</abi-instr>
- <abi-instr address-size='64' path='assert.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
+ <function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b7f2d5e6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
- <parameter type-id='80f4b756' name='file'/>
- <parameter type-id='80f4b756' name='func'/>
- <parameter type-id='95e97e5e' name='line'/>
- <parameter type-id='80f4b756' name='format'/>
+ </abi-instr>
+ <abi-instr address-size='64' path='module/nvpair/fnvpair.c' language='LANG_C99'>
+ <function-decl name='fnvlist_alloc' mangled-name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_alloc'>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_free' mangled-name='fnvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_free'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_size' mangled-name='fnvlist_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_size'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='fnvlist_pack' mangled-name='fnvlist_pack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_pack'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='78c01427' name='sizep'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='fnvlist_pack_free' mangled-name='fnvlist_pack_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_pack_free'>
+ <parameter type-id='26a90f95' name='pack'/>
+ <parameter type-id='b59d7dce' name='size'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_unpack' mangled-name='fnvlist_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_unpack'>
+ <parameter type-id='26a90f95' name='buf'/>
+ <parameter type-id='b59d7dce' name='buflen'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_dup' mangled-name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_dup'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_merge' mangled-name='fnvlist_merge' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_merge'>
+ <parameter type-id='5ce45b60' name='dst'/>
+ <parameter type-id='5ce45b60' name='src'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_num_pairs' mangled-name='fnvlist_num_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_num_pairs'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean' mangled-name='fnvlist_add_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean_value' mangled-name='fnvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean_value'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='c19b74c3' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_byte' mangled-name='fnvlist_add_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_byte'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='d8bf0010' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int8' mangled-name='fnvlist_add_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int8'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='ee31ee44' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint8' mangled-name='fnvlist_add_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint8'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='b96825af' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int16' mangled-name='fnvlist_add_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int16'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='23bd8cb5' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint16' mangled-name='fnvlist_add_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint16'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='149c6638' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int32' mangled-name='fnvlist_add_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int32'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='3ff5601b' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint32' mangled-name='fnvlist_add_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint32'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='8f92235e' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int64' mangled-name='fnvlist_add_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int64'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9da381c4' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint64' mangled-name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint64'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9c313c2d' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_string' mangled-name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_string'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='80f4b756' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvlist' mangled-name='fnvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvlist'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='5ce45b60' name='val'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvpair' mangled-name='fnvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='3fa542f0' name='pair'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean_array' mangled-name='fnvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_boolean_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='c5f6c15b' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_byte_array' mangled-name='fnvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_byte_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='d1db479e' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int8_array' mangled-name='fnvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a06445da' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint8_array' mangled-name='fnvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9f7200cf' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int16_array' mangled-name='fnvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a3eb883d' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint16_array' mangled-name='fnvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='1b7d11c6' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int32_array' mangled-name='fnvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='1f526493' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint32_array' mangled-name='fnvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a6798dcc' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int64_array' mangled-name='fnvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_int64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='505bed1a' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint64_array' mangled-name='fnvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_uint64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='713a56f5' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_string_array' mangled-name='fnvlist_add_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_string_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='13956559' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvlist_array' mangled-name='fnvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_add_nvlist_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='3bbfee2e' name='val'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_remove' mangled-name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_remove'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_remove_nvpair' mangled-name='fnvlist_remove_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_remove_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='3fa542f0' name='pair'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_nvpair' mangled-name='fnvlist_lookup_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='3fa542f0'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_boolean' mangled-name='fnvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_boolean_value' mangled-name='fnvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean_value'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_byte' mangled-name='fnvlist_lookup_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_byte'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='d8bf0010'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int8' mangled-name='fnvlist_lookup_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int8'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='ee31ee44'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int16' mangled-name='fnvlist_lookup_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int16'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='23bd8cb5'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int32' mangled-name='fnvlist_lookup_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int32'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='3ff5601b'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int64' mangled-name='fnvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int64'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='9da381c4'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint8' mangled-name='fnvlist_lookup_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint8'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='b96825af'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint16' mangled-name='fnvlist_lookup_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint16'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='149c6638'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint32' mangled-name='fnvlist_lookup_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint32'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='8f92235e'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint64' mangled-name='fnvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint64'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_string' mangled-name='fnvlist_lookup_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_string'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_nvlist' mangled-name='fnvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_nvlist'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_boolean_array' mangled-name='fnvlist_lookup_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_boolean_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='37e3bd22'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_byte_array' mangled-name='fnvlist_lookup_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_byte_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='45b65157'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int8_array' mangled-name='fnvlist_lookup_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='256d5229'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint8_array' mangled-name='fnvlist_lookup_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='ae3e8ca6'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int16_array' mangled-name='fnvlist_lookup_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='f76f73d0'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint16_array' mangled-name='fnvlist_lookup_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='8a121f49'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int32_array' mangled-name='fnvlist_lookup_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='4aafb922'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint32_array' mangled-name='fnvlist_lookup_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='90421557'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_int64_array' mangled-name='fnvlist_lookup_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_int64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='cb785ebf'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint64_array' mangled-name='fnvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_lookup_uint64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='5d6479ae'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='module/nvpair/nvpair.c' language='LANG_C99'>
+ <typedef-decl name='bool_t' type-id='3ff5601b' id='310a70df'/>
+ <enum-decl name='xdr_op' id='6badf1b8'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='XDR_ENCODE' value='0'/>
+ <enumerator name='XDR_DECODE' value='1'/>
+ <enumerator name='XDR_FREE' value='2'/>
+ </enum-decl>
+ <class-decl name='__rpc_xdr' size-in-bits='384' is-struct='yes' visibility='default' id='755707df'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='x_op' type-id='6badf1b8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='x_ops' type-id='3457e9c5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='x_public' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='x_private' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='x_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='x_handy' type-id='48f7c3f5' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='xdr_ops' size-in-bits='576' is-struct='yes' visibility='default' id='ea1474f2'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='x_getlong' type-id='a4e6dd3f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='x_putlong' type-id='d447b08c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='x_getbytes' type-id='b0b6ccaa' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='x_putbytes' type-id='581c24b7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='x_getpostn' type-id='1c77bdb0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='x_setpostn' type-id='13fdb43e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='x_inline' type-id='788e1f25' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='x_destroy' type-id='d781e3b2' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='x_control' type-id='733fc725' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='XDR' type-id='755707df' id='bc407f0e'/>
+ <typedef-decl name='xdrproc_t' type-id='94d188f0' id='c28db3e9'/>
+ <typedef-decl name='__u_short' type-id='8efea9e5' id='46c660f8'/>
+ <typedef-decl name='__u_int' type-id='f0981eeb' id='8ae6822f'/>
+ <typedef-decl name='__quad_t' type-id='bd54fe1a' id='2632227a'/>
+ <typedef-decl name='__u_quad_t' type-id='7359adad' id='5f3d50a6'/>
+ <typedef-decl name='u_short' type-id='46c660f8' id='32580e96'/>
+ <typedef-decl name='u_int' type-id='8ae6822f' id='48f7c3f5'/>
+ <typedef-decl name='quad_t' type-id='2632227a' id='f5ef0660'/>
+ <typedef-decl name='u_quad_t' type-id='5f3d50a6' id='bd226ac0'/>
+ <pointer-type-def type-id='bc407f0e' size-in-bits='64' id='17fd1621'/>
+ <pointer-type-def type-id='755707df' size-in-bits='64' id='812c6697'/>
+ <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
+ <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
+ <pointer-type-def type-id='9b23c9ad' size-in-bits='64' id='c0563f85'/>
+ <qualified-type-def type-id='c19b74c3' const='yes' id='12373e33'/>
+ <pointer-type-def type-id='12373e33' size-in-bits='64' id='c5f6c15b'/>
+ <qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
+ <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
+ <qualified-type-def type-id='23bd8cb5' const='yes' id='75f7b0c5'/>
+ <pointer-type-def type-id='75f7b0c5' size-in-bits='64' id='a3eb883d'/>
+ <qualified-type-def type-id='3ff5601b' const='yes' id='922df12b'/>
+ <pointer-type-def type-id='922df12b' size-in-bits='64' id='1f526493'/>
+ <qualified-type-def type-id='9da381c4' const='yes' id='f07b7694'/>
+ <pointer-type-def type-id='f07b7694' size-in-bits='64' id='505bed1a'/>
+ <qualified-type-def type-id='ee31ee44' const='yes' id='721c32d4'/>
+ <pointer-type-def type-id='721c32d4' size-in-bits='64' id='a06445da'/>
+ <qualified-type-def type-id='bd54fe1a' const='yes' id='9cb2385f'/>
+ <pointer-type-def type-id='9cb2385f' size-in-bits='64' id='218ee02f'/>
+ <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
+ <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
+ <qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/>
+ <pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/>
+ <qualified-type-def type-id='d8bf0010' const='yes' id='a9125480'/>
+ <pointer-type-def type-id='a9125480' size-in-bits='64' id='d1db479e'/>
+ <qualified-type-def type-id='149c6638' const='yes' id='b01a5ac8'/>
+ <pointer-type-def type-id='b01a5ac8' size-in-bits='64' id='1b7d11c6'/>
+ <qualified-type-def type-id='8f92235e' const='yes' id='b9930aae'/>
+ <pointer-type-def type-id='b9930aae' size-in-bits='64' id='a6798dcc'/>
+ <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/>
+ <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/>
+ <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
+ <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
+ <qualified-type-def type-id='ea1474f2' const='yes' id='485ede6d'/>
+ <pointer-type-def type-id='485ede6d' size-in-bits='64' id='3457e9c5'/>
+ <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
+ <pointer-type-def type-id='441e0c31' size-in-bits='64' id='788e1f25'/>
+ <pointer-type-def type-id='bd54fe1a' size-in-bits='64' id='3ccc2590'/>
+ <pointer-type-def type-id='3fa542f0' size-in-bits='64' id='0b283d2e'/>
+ <pointer-type-def type-id='f5ef0660' size-in-bits='64' id='de23782d'/>
+ <pointer-type-def type-id='a2185560' size-in-bits='64' id='764e437e'/>
+ <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/>
+ <pointer-type-def type-id='e80b47fe' size-in-bits='64' id='94d188f0'/>
+ <pointer-type-def type-id='1c7a4858' size-in-bits='64' id='b0b6ccaa'/>
+ <pointer-type-def type-id='f6358b93' size-in-bits='64' id='581c24b7'/>
+ <pointer-type-def type-id='45354e42' size-in-bits='64' id='d447b08c'/>
+ <pointer-type-def type-id='0760d6d1' size-in-bits='64' id='733fc725'/>
+ <pointer-type-def type-id='be0f9e0b' size-in-bits='64' id='a4e6dd3f'/>
+ <pointer-type-def type-id='16eb5704' size-in-bits='64' id='13fdb43e'/>
+ <pointer-type-def type-id='46870456' size-in-bits='64' id='1c77bdb0'/>
+ <pointer-type-def type-id='48f7c3f5' size-in-bits='64' id='b4c2e924'/>
+ <pointer-type-def type-id='bd226ac0' size-in-bits='64' id='fce59795'/>
+ <pointer-type-def type-id='32580e96' size-in-bits='64' id='ede2c2f5'/>
+ <pointer-type-def type-id='c87cb1d0' size-in-bits='64' id='d781e3b2'/>
+ <function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
+ <function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='xdr_int' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='7292109c'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_u_int' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='b4c2e924'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_short' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='764e437e'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_u_short' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='ede2c2f5'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='9b23c9ad'/>
+ <parameter type-id='b4c2e924'/>
+ <parameter type-id='48f7c3f5'/>
+ <parameter type-id='48f7c3f5'/>
+ <parameter type-id='c28db3e9'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_opaque' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='9b23c9ad'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_char' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='26a90f95'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_double' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='7408d286'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_longlong_t' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='de23782d'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdr_u_longlong_t' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='fce59795'/>
+ <return type-id='310a70df'/>
+ </function-decl>
+ <function-decl name='xdrmem_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='17fd1621'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='48f7c3f5'/>
+ <parameter type-id='6badf1b8'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nv_alloc_init' mangled-name='nv_alloc_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_init'>
+ <parameter type-id='11871392' name='nva'/>
+ <parameter type-id='ee1d4944' name='nvo'/>
<parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nv_alloc_reset' mangled-name='nv_alloc_reset' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_reset'>
+ <parameter type-id='11871392' name='nva'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nv_alloc_fini' mangled-name='nv_alloc_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nv_alloc_fini'>
+ <parameter type-id='11871392' name='nva'/>
<return type-id='48b5725f'/>
</function-decl>
+ <function-decl name='nvlist_lookup_nv_alloc' mangled-name='nvlist_lookup_nv_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nv_alloc'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='11871392'/>
+ </function-decl>
+ <function-decl name='nvlist_nvflag' mangled-name='nvlist_nvflag' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_nvflag'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='3502e3ff'/>
+ </function-decl>
+ <function-decl name='nvlist_alloc' mangled-name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_alloc'>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='3502e3ff' name='nvflag'/>
+ <parameter type-id='95e97e5e' name='kmflag'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_xalloc' mangled-name='nvlist_xalloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xalloc'>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='3502e3ff' name='nvflag'/>
+ <parameter type-id='11871392' name='nva'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_free' mangled-name='nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_free'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nvlist_dup' mangled-name='nvlist_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_dup'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='95e97e5e' name='kmflag'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_xdup' mangled-name='nvlist_xdup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xdup'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='11871392' name='nva'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove_all' mangled-name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove_all'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove' mangled-name='nvlist_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='8d0687d2' name='type'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove_nvpair' mangled-name='nvlist_remove_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_remove_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='3fa542f0' name='nvp'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean' mangled-name='nvlist_add_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean_value' mangled-name='nvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean_value'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='c19b74c3' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_byte' mangled-name='nvlist_add_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_byte'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='d8bf0010' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int8' mangled-name='nvlist_add_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int8'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='ee31ee44' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint8' mangled-name='nvlist_add_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint8'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='b96825af' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int16' mangled-name='nvlist_add_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int16'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='23bd8cb5' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint16' mangled-name='nvlist_add_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint16'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='149c6638' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int32' mangled-name='nvlist_add_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int32'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='3ff5601b' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint32' mangled-name='nvlist_add_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint32'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='8f92235e' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int64' mangled-name='nvlist_add_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int64'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9da381c4' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64' mangled-name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint64'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9c313c2d' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_double' mangled-name='nvlist_add_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_double'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a0eb0f08' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_string' mangled-name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_string'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='80f4b756' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean_array' mangled-name='nvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_boolean_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='c5f6c15b' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_byte_array' mangled-name='nvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_byte_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='d1db479e' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int8_array' mangled-name='nvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a06445da' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint8_array' mangled-name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9f7200cf' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int16_array' mangled-name='nvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a3eb883d' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint16_array' mangled-name='nvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='1b7d11c6' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int32_array' mangled-name='nvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='1f526493' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint32_array' mangled-name='nvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='a6798dcc' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int64_array' mangled-name='nvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_int64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='505bed1a' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64_array' mangled-name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_uint64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='713a56f5' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_string_array' mangled-name='nvlist_add_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_string_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='13956559' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_hrtime' mangled-name='nvlist_add_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_hrtime'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='cebdd548' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist' mangled-name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvlist'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='22cce67b' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist_array' mangled-name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvlist_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='3bbfee2e' name='a'/>
+ <parameter type-id='3502e3ff' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_prev_nvpair' mangled-name='nvlist_prev_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_prev_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='dace003f' name='nvp'/>
+ <return type-id='3fa542f0'/>
+ </function-decl>
+ <function-decl name='nvlist_empty' mangled-name='nvlist_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_empty'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_boolean' mangled-name='nvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_boolean_value' mangled-name='nvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean_value'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='37e3bd22' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_byte' mangled-name='nvlist_lookup_byte' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_byte'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='45b65157' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int8' mangled-name='nvlist_lookup_int8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int8'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='256d5229' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint8' mangled-name='nvlist_lookup_uint8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint8'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='ae3e8ca6' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int16' mangled-name='nvlist_lookup_int16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int16'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='f76f73d0' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint16' mangled-name='nvlist_lookup_uint16' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint16'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='8a121f49' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int32' mangled-name='nvlist_lookup_int32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int32'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='4aafb922' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint32' mangled-name='nvlist_lookup_uint32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint32'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='90421557' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int64' mangled-name='nvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int64'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='cb785ebf' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64' mangled-name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint64'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='5d6479ae' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_double' mangled-name='nvlist_lookup_double' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_double'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='7408d286' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_string' mangled-name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_string'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='7d3cd834' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist' mangled-name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvlist'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='857bb57e' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_boolean_array' mangled-name='nvlist_lookup_boolean_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_boolean_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='03829398' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_byte_array' mangled-name='nvlist_lookup_byte_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_byte_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='3b0247c7' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int8_array' mangled-name='nvlist_lookup_int8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='ee181ab9' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint8_array' mangled-name='nvlist_lookup_uint8_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint8_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='d8774064' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int16_array' mangled-name='nvlist_lookup_int16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='7e73928e' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint16_array' mangled-name='nvlist_lookup_uint16_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint16_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='bd8768d9' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int32_array' mangled-name='nvlist_lookup_int32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9aa04798' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint32_array' mangled-name='nvlist_lookup_uint32_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint32_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='9507d3c7' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int64_array' mangled-name='nvlist_lookup_int64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_int64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='e37ce48f' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64_array' mangled-name='nvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_uint64_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='892b4acc' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_string_array' mangled-name='nvlist_lookup_string_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_string_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='c0563f85' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist_array' mangled-name='nvlist_lookup_nvlist_array' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvlist_array'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='75be733c' name='a'/>
+ <parameter type-id='4dd26a40' name='n'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_hrtime' mangled-name='nvlist_lookup_hrtime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_hrtime'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='e379e62d' name='val'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_pairs' mangled-name='nvlist_lookup_pairs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_pairs'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='95e97e5e' name='flag'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvpair' mangled-name='nvlist_lookup_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='0b283d2e' name='ret'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvpair_embedded_index' mangled-name='nvlist_lookup_nvpair_embedded_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_lookup_nvpair_embedded_index'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='0b283d2e' name='ret'/>
+ <parameter type-id='7292109c' name='ip'/>
+ <parameter type-id='7d3cd834' name='ep'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_exists' mangled-name='nvlist_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_exists'>
+ <parameter type-id='22cce67b' name='nvl'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvpair' mangled-name='nvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_add_nvpair'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='3fa542f0' name='nvp'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_merge' mangled-name='nvlist_merge' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_merge'>
+ <parameter type-id='5ce45b60' name='dst'/>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='95e97e5e' name='flag'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_size' mangled-name='nvlist_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_size'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='78c01427' name='size'/>
+ <parameter type-id='95e97e5e' name='encoding'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_pack' mangled-name='nvlist_pack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_pack'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='9b23c9ad' name='bufp'/>
+ <parameter type-id='78c01427' name='buflen'/>
+ <parameter type-id='95e97e5e' name='encoding'/>
+ <parameter type-id='95e97e5e' name='kmflag'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_xpack' mangled-name='nvlist_xpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xpack'>
+ <parameter type-id='5ce45b60' name='nvl'/>
+ <parameter type-id='9b23c9ad' name='bufp'/>
+ <parameter type-id='78c01427' name='buflen'/>
+ <parameter type-id='95e97e5e' name='encoding'/>
+ <parameter type-id='11871392' name='nva'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_unpack' mangled-name='nvlist_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_unpack'>
+ <parameter type-id='26a90f95' name='buf'/>
+ <parameter type-id='b59d7dce' name='buflen'/>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='95e97e5e' name='kmflag'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_xunpack' mangled-name='nvlist_xunpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_xunpack'>
+ <parameter type-id='26a90f95' name='buf'/>
+ <parameter type-id='b59d7dce' name='buflen'/>
+ <parameter type-id='857bb57e' name='nvlp'/>
+ <parameter type-id='11871392' name='nva'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-type size-in-bits='64' id='441e0c31'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='4aafb922'/>
+ </function-type>
+ <function-type size-in-bits='64' id='e80b47fe'>
+ <parameter type-id='17fd1621'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='1c7a4858'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='f6358b93'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='45354e42'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='218ee02f'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='0760d6d1'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='be0f9e0b'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='3ccc2590'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='16eb5704'>
+ <parameter type-id='812c6697'/>
+ <parameter type-id='48f7c3f5'/>
+ <return type-id='310a70df'/>
+ </function-type>
+ <function-type size-in-bits='64' id='46870456'>
+ <parameter type-id='812c6697'/>
+ <return type-id='48f7c3f5'/>
+ </function-type>
+ <function-type size-in-bits='64' id='c87cb1d0'>
+ <parameter type-id='812c6697'/>
+ <return type-id='48b5725f'/>
+ </function-type>
+ </abi-instr>
+ <abi-instr address-size='64' path='module/nvpair/nvpair_alloc_fixed.c' language='LANG_C99'>
+ <qualified-type-def type-id='ee1d4944' const='yes' id='4b95388f'/>
+ <var-decl name='nv_fixed_ops' type-id='4b95388f' mangled-name='nv_fixed_ops' visibility='default' elf-symbol-id='nv_fixed_ops'/>
</abi-instr>
</abi-corpus>
diff --git a/lib/libnvpair/libnvpair.c b/lib/libnvpair/libnvpair.c
index 0123bb772048..7141c437b810 100644
--- a/lib/libnvpair/libnvpair.c
+++ b/lib/libnvpair/libnvpair.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -70,7 +70,7 @@ struct nvlist_printops {
DEFINEOP(print_int64, int64_t);
DEFINEOP(print_uint64, uint64_t);
DEFINEOP(print_double, double);
- DEFINEOP(print_string, char *);
+ DEFINEOP(print_string, const char *);
DEFINEOP(print_hrtime, hrtime_t);
DEFINEOP(print_nvlist, nvlist_t *);
DEFINEARROP(print_boolean_array, boolean_t *);
@@ -83,7 +83,7 @@ struct nvlist_printops {
DEFINEARROP(print_uint32_array, uint32_t *);
DEFINEARROP(print_int64_array, int64_t *);
DEFINEARROP(print_uint64_array, uint64_t *);
- DEFINEARROP(print_string_array, char **);
+ DEFINEARROP(print_string_array, const char **);
DEFINEARROP(print_nvlist_array, nvlist_t **);
};
@@ -199,6 +199,17 @@ nvprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \
return (1); \
}
+/*
+ * Workaround for GCC 12+ with UBSan enabled deficencies.
+ *
+ * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
+ * below as violating -Wformat-overflow.
+ */
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-overflow"
+#endif
NVLIST_PRTFUNC(boolean, int, int, "%d")
NVLIST_PRTFUNC(boolean_value, boolean_t, int, "%d")
NVLIST_PRTFUNC(byte, uchar_t, uchar_t, "0x%2.2x")
@@ -211,8 +222,12 @@ NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x")
NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld")
NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx")
NVLIST_PRTFUNC(double, double, double, "0x%f")
-NVLIST_PRTFUNC(string, char *, char *, "%s")
+NVLIST_PRTFUNC(string, const char *, const char *, "%s")
NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx")
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic pop
+#endif
/*
* Generate functions to print array-valued nvlist members.
@@ -251,7 +266,7 @@ NVLIST_ARRPRTFUNC(int32_array, int32_t, int32_t, "%d")
NVLIST_ARRPRTFUNC(uint32_array, uint32_t, uint32_t, "0x%x")
NVLIST_ARRPRTFUNC(int64_array, int64_t, longlong_t, "%lld")
NVLIST_ARRPRTFUNC(uint64_array, uint64_t, u_longlong_t, "0x%llx")
-NVLIST_ARRPRTFUNC(string_array, char *, char *, "%s")
+NVLIST_ARRPRTFUNC(string_array, const char *, const char *, "%s")
static int
nvprint_nvlist(nvlist_prtctl_t pctl, void *private,
@@ -368,7 +383,7 @@ nvlist_prtctl_setfmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which,
pctl->nvprt_btwnarrfmt_nl = 0;
} else {
pctl->nvprt_btwnarrfmt = fmt;
- pctl->nvprt_btwnarrfmt_nl = (strstr(fmt, "\n") != NULL);
+ pctl->nvprt_btwnarrfmt_nl = (strchr(fmt, '\n') != NULL);
}
break;
@@ -383,13 +398,13 @@ nvlist_prtctl_dofmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, ...)
{
FILE *fp = pctl->nvprt_fp;
va_list ap;
- char *name;
+ const char *name;
va_start(ap, which);
switch (which) {
case NVLIST_FMT_MEMBER_NAME:
- name = va_arg(ap, char *);
+ name = va_arg(ap, const char *);
(void) fprintf(fp, pctl->nvprt_nmfmt, name);
break;
@@ -438,7 +453,7 @@ NVLIST_PRINTCTL_REPLACE(uint32, uint32_t)
NVLIST_PRINTCTL_REPLACE(int64, int64_t)
NVLIST_PRINTCTL_REPLACE(uint64, uint64_t)
NVLIST_PRINTCTL_REPLACE(double, double)
-NVLIST_PRINTCTL_REPLACE(string, char *)
+NVLIST_PRINTCTL_REPLACE(string, const char *)
NVLIST_PRINTCTL_REPLACE(hrtime, hrtime_t)
NVLIST_PRINTCTL_REPLACE(nvlist, nvlist_t *)
@@ -462,7 +477,7 @@ NVLIST_PRINTCTL_AREPLACE(int32_array, int32_t *)
NVLIST_PRINTCTL_AREPLACE(uint32_array, uint32_t *)
NVLIST_PRINTCTL_AREPLACE(int64_array, int64_t *)
NVLIST_PRINTCTL_AREPLACE(uint64_array, uint64_t *)
-NVLIST_PRINTCTL_AREPLACE(string_array, char **)
+NVLIST_PRINTCTL_AREPLACE(string_array, const char **)
NVLIST_PRINTCTL_AREPLACE(nvlist_array, nvlist_t **)
/*
@@ -565,7 +580,7 @@ static void
nvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl)
{
FILE *fp = pctl->nvprt_fp;
- char *name;
+ const char *name;
uint_t nelem;
nvpair_t *nvp;
@@ -655,7 +670,7 @@ nvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl)
break;
}
case DATA_TYPE_STRING: {
- char *val;
+ const char *val;
(void) nvpair_value_string(nvp, &val);
RENDER(pctl, string, nvl, name, val);
break;
@@ -721,7 +736,7 @@ nvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl)
break;
}
case DATA_TYPE_STRING_ARRAY: {
- char **val;
+ const char **val;
(void) nvpair_value_string_array(nvp, &val, &nelem);
ARENDER(pctl, string_array, nvl, name, val, nelem);
break;
@@ -851,7 +866,7 @@ dump_nvlist(nvlist_t *list, int indent)
break;
case DATA_TYPE_STRING:
- NVP(elem, string, char *, char *, "'%s'");
+ NVP(elem, string, const char *, const char *, "'%s'");
break;
case DATA_TYPE_BYTE_ARRAY:
@@ -892,7 +907,8 @@ dump_nvlist(nvlist_t *list, int indent)
break;
case DATA_TYPE_STRING_ARRAY:
- NVPA(elem, string_array, char *, char *, "'%s'");
+ NVPA(elem, string_array, const char *, const char *,
+ "'%s'");
break;
case DATA_TYPE_NVLIST:
@@ -946,11 +962,11 @@ dump_nvlist(nvlist_t *list, int indent)
*/
int
nvpair_value_match_regex(nvpair_t *nvp, int ai,
- char *value, regex_t *value_regex, char **ep)
+ const char *value, regex_t *value_regex, const char **ep)
{
- char *evalue;
- uint_t a_len;
- int sr;
+ const char *evalue;
+ uint_t a_len;
+ int sr;
if (ep)
*ep = NULL;
@@ -978,7 +994,7 @@ nvpair_value_match_regex(nvpair_t *nvp, int ai,
sr = EOF;
switch (nvpair_type(nvp)) {
case DATA_TYPE_STRING: {
- char *val;
+ const char *val;
/* check string value for match */
if (nvpair_value_string(nvp, &val) == 0) {
@@ -994,7 +1010,7 @@ nvpair_value_match_regex(nvpair_t *nvp, int ai,
break;
}
case DATA_TYPE_STRING_ARRAY: {
- char **val_array;
+ const char **val_array;
/* check indexed string value of array for match */
if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
@@ -1270,7 +1286,7 @@ nvpair_value_match_regex(nvpair_t *nvp, int ai,
}
int
-nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
+nvpair_value_match(nvpair_t *nvp, int ai, const char *value, const char **ep)
{
return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
}
diff --git a/lib/libnvpair/libnvpair_json.c b/lib/libnvpair/libnvpair_json.c
index 19acea8f5094..b8029dd4d271 100644
--- a/lib/libnvpair/libnvpair_json.c
+++ b/lib/libnvpair/libnvpair_json.c
@@ -134,7 +134,7 @@ nvlist_print_json(FILE *fp, nvlist_t *nvl)
switch (type) {
case DATA_TYPE_STRING: {
- char *string = fnvpair_value_string(curr);
+ const char *string = fnvpair_value_string(curr);
if (nvlist_print_json_string(fp, string) == -1)
return (-1);
break;
@@ -220,7 +220,7 @@ nvlist_print_json(FILE *fp, nvlist_t *nvl)
}
case DATA_TYPE_STRING_ARRAY: {
- char **val;
+ const char **val;
uint_t valsz, i;
VERIFY0(nvpair_value_string_array(curr, &val, &valsz));
FPRINTF(fp, "[");
diff --git a/lib/libnvpair/nvpair_alloc_system.c b/lib/libnvpair/nvpair_alloc_system.c
index 59806ea4dc93..ade10f58f605 100644
--- a/lib/libnvpair/nvpair_alloc_system.c
+++ b/lib/libnvpair/nvpair_alloc_system.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libshare/libshare.c b/lib/libshare/libshare.c
index 09529e5b4106..d50b4550d6d0 100644
--- a/lib/libshare/libshare.c
+++ b/lib/libshare/libshare.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Gunnar Beutner
- * Copyright (c) 2018, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2018, 2022 by Delphix. All rights reserved.
*/
#include <stdio.h>
@@ -96,6 +96,16 @@ sa_commit_shares(enum sa_protocol protocol)
fstypes[protocol]->commit_shares();
}
+void
+sa_truncate_shares(enum sa_protocol protocol)
+{
+ /* CSTYLED */
+ VALIDATE_PROTOCOL(protocol, );
+
+ if (fstypes[protocol]->truncate_shares != NULL)
+ fstypes[protocol]->truncate_shares();
+}
+
int
sa_validate_shareopts(const char *options, enum sa_protocol protocol)
{
diff --git a/lib/libshare/libshare_impl.h b/lib/libshare/libshare_impl.h
index 110fe93d250f..d8c924757fe1 100644
--- a/lib/libshare/libshare_impl.h
+++ b/lib/libshare/libshare_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Gunnar Beutner
- * Copyright (c) 2019, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2019, 2022 by Delphix. All rights reserved.
*/
#ifndef _LIBSPL_LIBSHARE_IMPL_H
#define _LIBSPL_LIBSHARE_IMPL_H
@@ -39,6 +39,7 @@ typedef struct {
boolean_t (*const is_shared)(sa_share_impl_t share);
int (*const validate_shareopts)(const char *shareopts);
int (*const commit_shares)(void);
+ void (*const truncate_shares)(void);
} sa_fstype_t;
extern const sa_fstype_t libshare_nfs_type, libshare_smb_type;
diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c
index 2146346cf08c..77ed14f322ed 100644
--- a/lib/libshare/nfs.c
+++ b/lib/libshare/nfs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <errno.h>
#include <libshare.h>
+#include <unistd.h>
+#include <libzutil.h>
#include "nfs.h"
@@ -44,7 +46,8 @@ nfs_exports_lock(const char *name, int *nfs_lock_fd)
*nfs_lock_fd = open(name, O_RDWR | O_CREAT | O_CLOEXEC, 0600);
if (*nfs_lock_fd == -1) {
err = errno;
- fprintf(stderr, "failed to lock %s: %s\n", name, strerror(err));
+ fprintf(stderr, "failed to lock %s: %s\n", name,
+ zfs_strerror(err));
return (err);
}
@@ -52,7 +55,8 @@ nfs_exports_lock(const char *name, int *nfs_lock_fd)
;
if (err != 0) {
err = errno;
- fprintf(stderr, "failed to lock %s: %s\n", name, strerror(err));
+ fprintf(stderr, "failed to lock %s: %s\n", name,
+ zfs_strerror(err));
(void) close(*nfs_lock_fd);
*nfs_lock_fd = -1;
return (err);
@@ -68,7 +72,7 @@ nfs_exports_unlock(const char *name, int *nfs_lock_fd)
if (flock(*nfs_lock_fd, LOCK_UN) != 0)
fprintf(stderr, "failed to unlock %s: %s\n",
- name, strerror(errno));
+ name, zfs_strerror(errno));
(void) close(*nfs_lock_fd);
*nfs_lock_fd = -1;
@@ -90,24 +94,25 @@ nfs_init_tmpfile(const char *prefix, const char *mdir, struct tmpfile *tmpf)
mkdir(mdir, 0755) < 0 &&
errno != EEXIST) {
fprintf(stderr, "failed to create %s: %s\n",
- mdir, strerror(errno));
+ // cppcheck-suppress uninitvar
+ mdir, zfs_strerror(errno));
return (B_FALSE);
}
- strcpy(tmpf->name, prefix);
- strcat(tmpf->name, ".XXXXXXXX");
+ strlcpy(tmpf->name, prefix, sizeof (tmpf->name));
+ strlcat(tmpf->name, ".XXXXXXXX", sizeof (tmpf->name));
int fd = mkostemp(tmpf->name, O_CLOEXEC);
if (fd == -1) {
fprintf(stderr, "Unable to create temporary file: %s",
- strerror(errno));
+ zfs_strerror(errno));
return (B_FALSE);
}
tmpf->fp = fdopen(fd, "w+");
if (tmpf->fp == NULL) {
fprintf(stderr, "Unable to reopen temporary file: %s",
- strerror(errno));
+ zfs_strerror(errno));
close(fd);
return (B_FALSE);
}
@@ -127,14 +132,14 @@ nfs_fini_tmpfile(const char *exports, struct tmpfile *tmpf)
{
if (fflush(tmpf->fp) != 0) {
fprintf(stderr, "Failed to write to temporary file: %s\n",
- strerror(errno));
+ zfs_strerror(errno));
nfs_abort_tmpfile(tmpf);
return (SA_SYSTEM_ERR);
}
if (rename(tmpf->name, exports) == -1) {
fprintf(stderr, "Unable to rename %s -> %s: %s\n",
- tmpf->name, exports, strerror(errno));
+ tmpf->name, exports, zfs_strerror(errno));
nfs_abort_tmpfile(tmpf);
return (SA_SYSTEM_ERR);
}
@@ -211,7 +216,7 @@ nfs_process_exports(const char *exports, const char *mountpoint,
if (fclose(oldfp) != 0) {
fprintf(stderr, "Unable to close file %s: %s\n",
- exports, strerror(errno));
+ exports, zfs_strerror(errno));
error = error != SA_OK ? error : SA_SYSTEM_ERR;
}
}
@@ -281,6 +286,17 @@ fullerr:
return (error);
}
+void
+nfs_reset_shares(const char *lockfile, const char *exports)
+{
+ int nfs_lock_fd = -1;
+
+ if (nfs_exports_lock(lockfile, &nfs_lock_fd) == 0) {
+ (void) ! truncate(exports, 0);
+ nfs_exports_unlock(lockfile, &nfs_lock_fd);
+ }
+}
+
static boolean_t
nfs_is_shared_cb(void *userdata, char *line, boolean_t found_mountpoint)
{
diff --git a/lib/libshare/nfs.h b/lib/libshare/nfs.h
index 24ae1f8adb85..f4340b18f89c 100644
--- a/lib/libshare/nfs.h
+++ b/lib/libshare/nfs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Gunnar Beutner
+ * Copyright (c) 2022 by Delphix. All rights reserved.
*/
#include "libshare_impl.h"
@@ -33,3 +34,4 @@ boolean_t nfs_is_shared_impl(const char *exports, sa_share_impl_t impl_share);
int nfs_toggle_share(const char *lockfile, const char *exports,
const char *expdir, sa_share_impl_t impl_share,
int(*cbk)(sa_share_impl_t impl_share, FILE *tmpfile));
+void nfs_reset_shares(const char *lockfile, const char *exports);
diff --git a/lib/libshare/os/freebsd/nfs.c b/lib/libshare/os/freebsd/nfs.c
index 78977a25f4f5..d4cdb07a4947 100644
--- a/lib/libshare/os/freebsd/nfs.c
+++ b/lib/libshare/os/freebsd/nfs.c
@@ -23,12 +23,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Copyright (c) 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2020, 2022 by Delphix. All rights reserved.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/vfs.h>
@@ -161,7 +158,8 @@ nfs_is_shared(sa_share_impl_t impl_share)
static int
nfs_validate_shareopts(const char *shareopts)
{
- (void) shareopts;
+ if (strlen(shareopts) == 0)
+ return (SA_SYNTAX_ERR);
return (SA_OK);
}
@@ -195,6 +193,12 @@ start:
return (SA_OK);
}
+static void
+nfs_truncate_shares(void)
+{
+ nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE);
+}
+
const sa_fstype_t libshare_nfs_type = {
.enable_share = nfs_enable_share,
.disable_share = nfs_disable_share,
@@ -202,4 +206,5 @@ const sa_fstype_t libshare_nfs_type = {
.validate_shareopts = nfs_validate_shareopts,
.commit_shares = nfs_commit_shares,
+ .truncate_shares = nfs_truncate_shares,
};
diff --git a/lib/libshare/os/freebsd/smb.c b/lib/libshare/os/freebsd/smb.c
index 0f546dc5543e..37a3802e4b89 100644
--- a/lib/libshare/os/freebsd/smb.c
+++ b/lib/libshare/os/freebsd/smb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libshare/os/linux/nfs.c b/lib/libshare/os/linux/nfs.c
index 1da6d1617247..3dce818400fc 100644
--- a/lib/libshare/os/linux/nfs.c
+++ b/lib/libshare/os/linux/nfs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,7 +23,7 @@
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Gunnar Beutner
* Copyright (c) 2012 Cyril Plisko. All rights reserved.
- * Copyright (c) 2019, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2019, 2022 by Delphix. All rights reserved.
*/
#include <dirent.h>
@@ -47,6 +47,7 @@
static boolean_t nfs_available(void);
+static boolean_t exports_available(void);
typedef int (*nfs_shareopt_callback_t)(const char *opt, const char *value,
void *cookie);
@@ -319,12 +320,49 @@ get_linux_shareopts_cb(const char *key, const char *value, void *cookie)
"wdelay" };
char **plinux_opts = (char **)cookie;
+ char *host, *val_dup, *literal, *next;
- /* host-specific options, these are taken care of elsewhere */
- if (strcmp(key, "ro") == 0 || strcmp(key, "rw") == 0 ||
- strcmp(key, "sec") == 0)
+ if (strcmp(key, "sec") == 0)
return (SA_OK);
+ if (strcmp(key, "ro") == 0 || strcmp(key, "rw") == 0) {
+ if (value == NULL || strlen(value) == 0)
+ return (SA_OK);
+ val_dup = strdup(value);
+ host = val_dup;
+ if (host == NULL)
+ return (SA_NO_MEMORY);
+ do {
+ if (*host == '[') {
+ host++;
+ literal = strchr(host, ']');
+ if (literal == NULL) {
+ free(val_dup);
+ return (SA_SYNTAX_ERR);
+ }
+ if (literal[1] == '\0')
+ next = NULL;
+ else if (literal[1] == '/') {
+ next = strchr(literal + 2, ':');
+ if (next != NULL)
+ ++next;
+ } else if (literal[1] == ':')
+ next = literal + 2;
+ else {
+ free(val_dup);
+ return (SA_SYNTAX_ERR);
+ }
+ } else {
+ next = strchr(host, ':');
+ if (next != NULL)
+ ++next;
+ }
+ host = next;
+ } while (host != NULL);
+ free(val_dup);
+ return (SA_OK);
+ }
+
if (strcmp(key, "anon") == 0)
key = "anonuid";
@@ -449,7 +487,7 @@ static int
nfs_disable_share(sa_share_impl_t impl_share)
{
if (!nfs_available())
- return (SA_SYSTEM_ERR);
+ return (SA_OK);
return (nfs_toggle_share(
ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE, ZFS_EXPORTS_DIR, impl_share,
@@ -472,6 +510,10 @@ static int
nfs_validate_shareopts(const char *shareopts)
{
char *linux_opts = NULL;
+
+ if (strlen(shareopts) == 0)
+ return (SA_SYNTAX_ERR);
+
int error = get_linux_shareopts(shareopts, &linux_opts);
if (error != SA_OK)
return (error);
@@ -495,6 +537,14 @@ nfs_commit_shares(void)
return (libzfs_run_process(argv[0], argv, 0));
}
+static void
+nfs_truncate_shares(void)
+{
+ if (!exports_available())
+ return;
+ nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE);
+}
+
const sa_fstype_t libshare_nfs_type = {
.enable_share = nfs_enable_share,
.disable_share = nfs_disable_share,
@@ -502,6 +552,7 @@ const sa_fstype_t libshare_nfs_type = {
.validate_shareopts = nfs_validate_shareopts,
.commit_shares = nfs_commit_shares,
+ .truncate_shares = nfs_truncate_shares,
};
static boolean_t
@@ -518,3 +569,18 @@ nfs_available(void)
return (avail == 1);
}
+
+static boolean_t
+exports_available(void)
+{
+ static int avail;
+
+ if (!avail) {
+ if (access(ZFS_EXPORTS_DIR, F_OK) != 0)
+ avail = -1;
+ else
+ avail = 1;
+ }
+
+ return (avail == 1);
+}
diff --git a/lib/libshare/os/linux/smb.c b/lib/libshare/os/linux/smb.c
index 57965ebfaad1..0679e82104e2 100644
--- a/lib/libshare/os/linux/smb.c
+++ b/lib/libshare/os/linux/smb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -90,21 +90,32 @@ smb_retrieve_shares(void)
/* Go through the directory, looking for shares */
while ((directory = readdir(shares_dir))) {
+ int fd;
+
if (directory->d_name[0] == '.')
continue;
snprintf(file_path, sizeof (file_path),
"%s/%s", SHARE_DIR, directory->d_name);
- if (stat(file_path, &eStat) == -1) {
+ if ((fd = open(file_path, O_RDONLY | O_CLOEXEC)) == -1) {
+ rc = SA_SYSTEM_ERR;
+ goto out;
+ }
+
+ if (fstat(fd, &eStat) == -1) {
+ close(fd);
rc = SA_SYSTEM_ERR;
goto out;
}
- if (!S_ISREG(eStat.st_mode))
+ if (!S_ISREG(eStat.st_mode)) {
+ close(fd);
continue;
+ }
- if ((share_file_fp = fopen(file_path, "re")) == NULL) {
+ if ((share_file_fp = fdopen(fd, "r")) == NULL) {
+ close(fd);
rc = SA_SYSTEM_ERR;
goto out;
}
diff --git a/lib/libshare/smb.h b/lib/libshare/smb.h
index ca3577751923..23d27c7b9134 100644
--- a/lib/libshare/smb.h
+++ b/lib/libshare/smb.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am
index 822bef7e7a8d..eb2377305aca 100644
--- a/lib/libspl/Makefile.am
+++ b/lib/libspl/Makefile.am
@@ -1,6 +1,6 @@
include $(srcdir)/%D%/include/Makefile.am
-libspl_assert_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
+libspl_assert_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS) $(LIBUNWIND_CFLAGS)
libspl_la_CFLAGS = $(libspl_assert_la_CFLAGS)
noinst_LTLIBRARIES += libspl_assert.la libspl.la
@@ -43,3 +43,5 @@ libspl_la_LIBADD = \
libspl_assert.la
libspl_la_LIBADD += $(LIBATOMIC_LIBS) $(LIBCLOCK_GETTIME)
+
+libspl_assert_la_LIBADD = $(BACKTRACE_LIBS) $(LIBUNWIND_LIBS)
diff --git a/lib/libspl/assert.c b/lib/libspl/assert.c
index ad8fdcd8cf0a..e6e3008f0aa6 100644
--- a/lib/libspl/assert.c
+++ b/lib/libspl/assert.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,8 +22,81 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2024, Rob Norris <robn@despairlabs.com>
+ */
#include <assert.h>
+#include <pthread.h>
+
+#if defined(__linux__)
+#include <errno.h>
+#include <sys/prctl.h>
+#ifdef HAVE_GETTID
+#define libspl_gettid() gettid()
+#else
+#include <sys/syscall.h>
+#define libspl_gettid() ((pid_t)syscall(__NR_gettid))
+#endif
+#define libspl_getprogname() (program_invocation_short_name)
+#define libspl_getthreadname(buf, len) \
+ prctl(PR_GET_NAME, (unsigned long)(buf), 0, 0, 0)
+#elif defined(__FreeBSD__)
+#include <pthread_np.h>
+#define libspl_gettid() pthread_getthreadid_np()
+#define libspl_getprogname() getprogname()
+#define libspl_getthreadname(buf, len) \
+ pthread_getname_np(pthread_self(), buf, len);
+#endif
+
+#if defined(HAVE_LIBUNWIND)
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+static inline void
+libspl_dump_backtrace(void)
+{
+ unw_context_t uc;
+ unw_cursor_t cp;
+ unw_word_t ip, off;
+ char funcname[128];
+#ifdef HAVE_LIBUNWIND_ELF
+ char objname[128];
+ unw_word_t objoff;
+#endif
+
+ fprintf(stderr, "Call trace:\n");
+ unw_getcontext(&uc);
+ unw_init_local(&cp, &uc);
+ while (unw_step(&cp) > 0) {
+ unw_get_reg(&cp, UNW_REG_IP, &ip);
+ unw_get_proc_name(&cp, funcname, sizeof (funcname), &off);
+#ifdef HAVE_LIBUNWIND_ELF
+ unw_get_elf_filename(&cp, objname, sizeof (objname), &objoff);
+ fprintf(stderr, " [0x%08lx] %s+0x%2lx (in %s +0x%2lx)\n",
+ ip, funcname, off, objname, objoff);
+#else
+ fprintf(stderr, " [0x%08lx] %s+0x%2lx\n", ip, funcname, off);
+#endif
+ }
+}
+#elif defined(HAVE_BACKTRACE)
+#include <execinfo.h>
+
+static inline void
+libspl_dump_backtrace(void)
+{
+ void *btptrs[100];
+ size_t nptrs = backtrace(btptrs, 100);
+ char **bt = backtrace_symbols(btptrs, nptrs);
+ fprintf(stderr, "Call trace:\n");
+ for (size_t i = 0; i < nptrs; i++)
+ fprintf(stderr, " %s\n", bt[i]);
+ free(bt);
+}
+#else
+#define libspl_dump_backtrace()
+#endif
static boolean_t libspl_assert_ok = B_FALSE;
@@ -33,20 +106,39 @@ libspl_set_assert_ok(boolean_t val)
libspl_assert_ok = val;
}
+static pthread_mutex_t assert_lock = PTHREAD_MUTEX_INITIALIZER;
+
/* printf version of libspl_assert */
void
libspl_assertf(const char *file, const char *func, int line,
const char *format, ...)
{
+ pthread_mutex_lock(&assert_lock);
+
va_list args;
+ char tname[64];
+
+ libspl_getthreadname(tname, sizeof (tname));
+
+ fprintf(stderr, "ASSERT at %s:%d:%s()\n", file, line, func);
va_start(args, format);
vfprintf(stderr, format, args);
- fprintf(stderr, "\n");
- fprintf(stderr, "ASSERT at %s:%d:%s()", file, line, func);
va_end(args);
+
+ fprintf(stderr, "\n"
+ " PID: %-8u COMM: %s\n"
+ " TID: %-8u NAME: %s\n",
+ getpid(), libspl_getprogname(),
+ libspl_gettid(), tname);
+
+ libspl_dump_backtrace();
+
+#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__)
if (libspl_assert_ok) {
+ pthread_mutex_unlock(&assert_lock);
return;
}
+#endif
abort();
}
diff --git a/lib/libspl/atomic.c b/lib/libspl/atomic.c
index 9307cea194e6..8cc350710ba0 100644
--- a/lib/libspl/atomic.c
+++ b/lib/libspl/atomic.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -382,6 +382,12 @@ membar_exit(void)
}
void
+membar_sync(void)
+{
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+}
+
+void
membar_producer(void)
{
__atomic_thread_fence(__ATOMIC_RELEASE);
diff --git a/lib/libspl/getexecname.c b/lib/libspl/getexecname.c
index dca7162034f7..95583b31ee6f 100644
--- a/lib/libspl/getexecname.c
+++ b/lib/libspl/getexecname.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/Makefile.am b/lib/libspl/include/Makefile.am
index 6f0e1818d22e..2c1d21edf19d 100644
--- a/lib/libspl/include/Makefile.am
+++ b/lib/libspl/include/Makefile.am
@@ -26,6 +26,7 @@ libspl_sysdir = $(libspldir)/sys
libspl_sys_HEADERS = \
%D%/sys/acl.h \
%D%/sys/acl_impl.h \
+ %D%/sys/asm_linkage.h \
%D%/sys/callb.h \
%D%/sys/cmn_err.h \
%D%/sys/cred.h \
@@ -45,7 +46,6 @@ libspl_sys_HEADERS = \
%D%/sys/poll.h \
%D%/sys/priv.h \
%D%/sys/processor.h \
- %D%/sys/sha2.h \
%D%/sys/simd.h \
%D%/sys/stack.h \
%D%/sys/stdtypes.h \
@@ -62,6 +62,8 @@ libspl_sys_HEADERS = \
%D%/sys/wmsum.h \
%D%/sys/zone.h
+libspl_ia32dir = $(libspldir)/sys/ia32
+
if BUILD_LINUX
libspl_sys_HEADERS += \
%D%/os/linux/sys/byteorder.h \
@@ -72,6 +74,9 @@ libspl_sys_HEADERS += \
%D%/os/linux/sys/stat.h \
%D%/os/linux/sys/sysmacros.h \
%D%/os/linux/sys/zfs_context_os.h
+
+libspl_ia32_HEADERS = \
+ %D%/os/linux/sys/ia32/asm_linkage.h
endif
if BUILD_FREEBSD
@@ -86,9 +91,13 @@ libspl_sys_HEADERS += \
%D%/os/freebsd/sys/sysmacros.h \
%D%/os/freebsd/sys/vfs.h \
%D%/os/freebsd/sys/zfs_context_os.h
+
+libspl_ia32_HEADERS = \
+ %D%/os/freebsd/sys/ia32/asm_linkage.h
endif
libspl_sys_dktpdir = $(libspl_sysdir)/dktp
libspl_sys_dktp_HEADERS = \
%D%/sys/dktp/fdisk.h
+
diff --git a/lib/libspl/include/assert.h b/lib/libspl/include/assert.h
index e968a2310774..155bbab3020a 100644
--- a/lib/libspl/include/assert.h
+++ b/lib/libspl/include/assert.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -34,12 +34,24 @@
#include <stdarg.h>
#include <sys/types.h>
+/* Workaround for non-Clang compilers */
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+/* We need to workaround libspl_set_assert_ok() that we have for zdb */
+#if __has_feature(attribute_analyzer_noreturn) || defined(__COVERITY__)
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#endif
+
/* Set to non-zero to avoid abort()ing on an assertion failure */
extern void libspl_set_assert_ok(boolean_t val);
/* printf version of libspl_assert */
extern void libspl_assertf(const char *file, const char *func, int line,
- const char *format, ...);
+ const char *format, ...) NORETURN __attribute__((format(printf, 4, 5)));
static inline int
libspl_assert(const char *buf, const char *file, const char *func, int line)
@@ -52,9 +64,21 @@ libspl_assert(const char *buf, const char *file, const char *func, int line)
#undef verify
#endif
+#define PANIC(fmt, a...) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
+
#define VERIFY(cond) \
(void) ((!(cond)) && \
libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
+
+#define VERIFYF(cond, STR, ...) \
+do { \
+ if (!(cond)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s " STR, #cond, \
+ __VA_ARGS__); \
+} while (0)
+
#define verify(cond) \
(void) ((!(cond)) && \
libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
@@ -95,8 +119,8 @@ do { \
const uintptr_t __right = (uintptr_t)(RIGHT); \
if (!(__left OP __right)) \
libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
- "%s %s %s (0x%llx %s 0x%llx)", #LEFT, #OP, #RIGHT, \
- (u_longlong_t)__left, #OP, (u_longlong_t)__right); \
+ "%s %s %s (%p %s %p)", #LEFT, #OP, #RIGHT, \
+ (void *)__left, #OP, (void *)__right); \
} while (0)
#define VERIFY0(LEFT) \
@@ -108,6 +132,88 @@ do { \
(u_longlong_t)__left); \
} while (0)
+#define VERIFY0P(LEFT) \
+do { \
+ const uintptr_t __left = (uintptr_t)(LEFT); \
+ if (!(__left == 0)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s == 0 (%p == 0)", #LEFT, \
+ (void *)__left); \
+} while (0)
+
+/*
+ * This is just here because cstyle gets upset about #LEFT
+ * on a newline.
+ */
+
+/* BEGIN CSTYLED */
+#define VERIFY3BF(LEFT, OP, RIGHT, STR, ...) \
+do { \
+ const boolean_t __left = (boolean_t)(LEFT); \
+ const boolean_t __right = (boolean_t)(RIGHT); \
+ if (!(__left OP __right)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s %s %s (0x%llx %s 0x%llx) " STR, \
+ #LEFT, #OP, #RIGHT, \
+ (u_longlong_t)__left, #OP, (u_longlong_t)__right, \
+ __VA_ARGS__); \
+} while (0)
+
+#define VERIFY3SF(LEFT, OP, RIGHT, STR, ...) \
+do { \
+ const int64_t __left = (int64_t)(LEFT); \
+ const int64_t __right = (int64_t)(RIGHT); \
+ if (!(__left OP __right)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s %s %s (0x%llx %s 0x%llx) " STR, \
+ #LEFT, #OP, #RIGHT, \
+ (u_longlong_t)__left, #OP, (u_longlong_t)__right, \
+ __VA_ARGS__); \
+} while (0)
+
+#define VERIFY3UF(LEFT, OP, RIGHT, STR, ...) \
+do { \
+ const uint64_t __left = (uint64_t)(LEFT); \
+ const uint64_t __right = (uint64_t)(RIGHT); \
+ if (!(__left OP __right)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s %s %s (0x%llx %s 0x%llx) " STR, \
+ #LEFT, #OP, #RIGHT, \
+ (u_longlong_t)__left, #OP, (u_longlong_t)__right, \
+ __VA_ARGS__); \
+} while (0)
+
+#define VERIFY3PF(LEFT, OP, RIGHT, STR, ...) \
+do { \
+ const uintptr_t __left = (uintptr_t)(LEFT); \
+ const uintptr_t __right = (uintptr_t)(RIGHT); \
+ if (!(__left OP __right)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s %s %s (0x%llx %s 0x%llx) " STR, \
+ #LEFT, #OP, #RIGHT, \
+ (u_longlong_t)__left, #OP, (u_longlong_t)__right, \
+ __VA_ARGS__); \
+} while (0)
+/* END CSTYLED */
+
+#define VERIFY0F(LEFT, STR, ...) \
+do { \
+ const uint64_t __left = (uint64_t)(LEFT); \
+ if (!(__left == 0)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s == 0 (0x%llx == 0) " STR, #LEFT, \
+ (u_longlong_t)__left, __VA_ARGS__); \
+} while (0)
+
+#define VERIFY0PF(LEFT, STR, ...) \
+do { \
+ const uintptr_t __left = (uintptr_t)(LEFT); \
+ if (!(__left == 0)) \
+ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
+ "%s == 0 (%p == 0) " STR, #LEFT, \
+ (u_longlong_t)__left, __VA_ARGS__); \
+} while (0)
+
#ifdef assert
#undef assert
#endif
@@ -122,7 +228,16 @@ do { \
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT3BF(x, y, z, str, ...) ASSERT3B(x, y, z)
+#define ASSERT3SF(x, y, z, str, ...) ASSERT3S(x, y, z)
+#define ASSERT3UF(x, y, z, str, ...) ASSERT3U(x, y, z)
+#define ASSERT3PF(x, y, z, str, ...) ASSERT3P(x, y, z)
+#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERT0PF(x, str, ...) ASSERT0P(x)
+#define ASSERT0F(x, str, ...) ASSERT0(x)
#define ASSERT(x) ((void) sizeof ((uintptr_t)(x)))
+#define ASSERTF(x, str, ...) ASSERT(x)
#define assert(x) ((void) sizeof ((uintptr_t)(x)))
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
@@ -134,7 +249,15 @@ do { \
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
+#define ASSERT0P VERIFY0P
+#define ASSERT3BF VERIFY3BF
+#define ASSERT3SF VERIFY3SF
+#define ASSERT3UF VERIFY3UF
+#define ASSERT3PF VERIFY3PF
+#define ASSERT0PF VERIFY0PF
+#define ASSERT0F VERIFY0F
#define ASSERT VERIFY
+#define ASSERTF VERIFYF
#define assert VERIFY
#define IMPLY(A, B) \
((void)(((!(A)) || (B)) || \
diff --git a/lib/libspl/include/atomic.h b/lib/libspl/include/atomic.h
index 8dd1d654a486..4ebdbbda9864 100644
--- a/lib/libspl/include/atomic.h
+++ b/lib/libspl/include/atomic.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -314,6 +314,13 @@ extern void membar_enter(void);
extern void membar_exit(void);
/*
+ * Make all stores and loads emitted prior to the the barrier complete before
+ * crossing it, while also making sure stores and loads emitted after the
+ * barrier only start being executed after crossing it.
+ */
+extern void membar_sync(void);
+
+/*
* Arrange that all stores issued before this point in the code reach
* global visibility before any stores that follow; useful in producer
* modules that update a data item, then set a flag that it is available.
diff --git a/lib/libspl/include/libgen.h b/lib/libspl/include/libgen.h
index c46d7454e49f..d8c80509e99e 100644
--- a/lib/libspl/include/libgen.h
+++ b/lib/libspl/include/libgen.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/libshare.h b/lib/libspl/include/libshare.h
index ae0e2c39dc6d..deeb15c97704 100644
--- a/lib/libspl/include/libshare.h
+++ b/lib/libspl/include/libshare.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,7 +22,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright (c) 2019, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2019, 2022 by Delphix. All rights reserved.
*/
#ifndef _LIBSPL_LIBSHARE_H
#define _LIBSPL_LIBSHARE_H extern __attribute__((visibility("default")))
@@ -88,6 +88,7 @@ _LIBSPL_LIBSHARE_H int sa_enable_share(const char *, const char *, const char *,
_LIBSPL_LIBSHARE_H int sa_disable_share(const char *, enum sa_protocol);
_LIBSPL_LIBSHARE_H boolean_t sa_is_shared(const char *, enum sa_protocol);
_LIBSPL_LIBSHARE_H void sa_commit_shares(enum sa_protocol);
+_LIBSPL_LIBSHARE_H void sa_truncate_shares(enum sa_protocol);
/* protocol specific interfaces */
_LIBSPL_LIBSHARE_H int sa_validate_shareopts(const char *, enum sa_protocol);
diff --git a/lib/libspl/include/os/freebsd/sys/byteorder.h b/lib/libspl/include/os/freebsd/sys/byteorder.h
index d4227ddc5465..bd6728820ed4 100644
--- a/lib/libspl/include/os/freebsd/sys/byteorder.h
+++ b/lib/libspl/include/os/freebsd/sys/byteorder.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -59,6 +59,18 @@ extern "C" {
*/
#if !defined(_XPG4_2) || defined(__EXTENSIONS__)
+#ifdef __COVERITY__
+/*
+ * Coverity's taint warnings from byteswapping are false positives for us.
+ * Suppress them by hiding byteswapping from Coverity.
+ */
+#define BSWAP_8(x) ((x) & 0xff)
+#define BSWAP_16(x) ((x) & 0xffff)
+#define BSWAP_32(x) ((x) & 0xffffffff)
+#define BSWAP_64(x) (x)
+
+#else /* __COVERITY__ */
+
/*
* Macros to reverse byte order
*/
@@ -67,6 +79,8 @@ extern "C" {
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
+#endif /* __COVERITY__ */
+
#define BMASK_8(x) ((x) & 0xff)
#define BMASK_16(x) ((x) & 0xffff)
#define BMASK_32(x) ((x) & 0xffffffff)
diff --git a/lib/libspl/include/os/freebsd/sys/file.h b/lib/libspl/include/os/freebsd/sys/file.h
index 5a20686dc069..f46b883f524a 100644
--- a/lib/libspl/include/os/freebsd/sys/file.h
+++ b/lib/libspl/include/os/freebsd/sys/file.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/freebsd/sys/ia32/asm_linkage.h b/lib/libspl/include/os/freebsd/sys/ia32/asm_linkage.h
new file mode 100644
index 000000000000..1c4d74423644
--- /dev/null
+++ b/lib/libspl/include/os/freebsd/sys/ia32/asm_linkage.h
@@ -0,0 +1,184 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _IA32_SYS_ASM_LINKAGE_H
+#define _IA32_SYS_ASM_LINKAGE_H
+
+#if defined(__linux__) && defined(CONFIG_SLS)
+#define RET ret; int3
+#else
+#define RET ret
+#endif
+
+/* Tell compiler to call assembler like Unix */
+#undef ASMABI
+#define ASMABI __attribute__((sysv_abi))
+
+#define ENDBR
+
+#define SECTION_TEXT .text
+#define SECTION_STATIC .section .rodata
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _ASM /* The remainder of this file is only for assembly files */
+
+/*
+ * make annoying differences in assembler syntax go away
+ */
+
+/*
+ * D16 and A16 are used to insert instructions prefixes; the
+ * macros help the assembler code be slightly more portable.
+ */
+#if !defined(__GNUC_AS__)
+/*
+ * /usr/ccs/bin/as prefixes are parsed as separate instructions
+ */
+#define D16 data16;
+#define A16 addr16;
+
+/*
+ * (There are some weird constructs in constant expressions)
+ */
+#define _CONST(const) [const]
+#define _BITNOT(const) -1!_CONST(const)
+#define _MUL(a, b) _CONST(a \* b)
+
+#else
+/*
+ * Why not use the 'data16' and 'addr16' prefixes .. well, the
+ * assembler doesn't quite believe in real mode, and thus argues with
+ * us about what we're trying to do.
+ */
+#define D16 .byte 0x66;
+#define A16 .byte 0x67;
+
+#define _CONST(const) (const)
+#define _BITNOT(const) ~_CONST(const)
+#define _MUL(a, b) _CONST(a * b)
+
+#endif
+
+/*
+ * C pointers are different sizes between i386 and amd64.
+ * These constants can be used to compute offsets into pointer arrays.
+ */
+#if defined(__amd64)
+#define CLONGSHIFT 3
+#define CLONGSIZE 8
+#define CLONGMASK 7
+#elif defined(__i386)
+#define CLONGSHIFT 2
+#define CLONGSIZE 4
+#define CLONGMASK 3
+#endif
+
+/*
+ * Since we know we're either ILP32 or LP64 ..
+ */
+#define CPTRSHIFT CLONGSHIFT
+#define CPTRSIZE CLONGSIZE
+#define CPTRMASK CLONGMASK
+
+#if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT)
+#error "inconsistent shift constants"
+#endif
+
+#if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1)
+#error "inconsistent mask constants"
+#endif
+
+#define ASM_ENTRY_ALIGN 16
+
+/*
+ * SSE register alignment and save areas
+ */
+
+#define XMM_SIZE 16
+#define XMM_ALIGN 16
+
+/*
+ * ENTRY provides the standard procedure entry code and an easy way to
+ * insert the calls to mcount for profiling. ENTRY_NP is identical, but
+ * never calls mcount.
+ */
+#define ENTRY(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+x: MCOUNT(x)
+
+#define ENTRY_NP(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+x:
+
+#define ENTRY_ALIGN(x, a) \
+ .text; \
+ .balign a; \
+ .globl x; \
+x:
+
+#define FUNCTION(x) \
+ .type x, @function; \
+x:
+
+/*
+ * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
+ */
+#define ENTRY2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+x:; \
+y: MCOUNT(x)
+
+#define ENTRY_NP2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+x:; \
+y:
+
+
+/*
+ * SET_SIZE trails a function and set the size for the ELF symbol table.
+ */
+#define SET_SIZE(x)
+
+#define SET_OBJ(x)
+
+#endif /* _ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IA32_SYS_ASM_LINKAGE_H */
diff --git a/lib/libspl/include/os/freebsd/sys/mnttab.h b/lib/libspl/include/os/freebsd/sys/mnttab.h
index aa3132fb3cc0..514e1b67547a 100644
--- a/lib/libspl/include/os/freebsd/sys/mnttab.h
+++ b/lib/libspl/include/os/freebsd/sys/mnttab.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/freebsd/sys/mount.h b/lib/libspl/include/os/freebsd/sys/mount.h
index e99518571270..61c421fe4edb 100644
--- a/lib/libspl/include/os/freebsd/sys/mount.h
+++ b/lib/libspl/include/os/freebsd/sys/mount.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/freebsd/sys/param.h b/lib/libspl/include/os/freebsd/sys/param.h
index cb5260ea3d7e..1ff3ca8025fc 100644
--- a/lib/libspl/include/os/freebsd/sys/param.h
+++ b/lib/libspl/include/os/freebsd/sys/param.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -57,6 +57,8 @@
extern size_t spl_pagesize(void);
#define PAGESIZE (spl_pagesize())
+#ifndef HAVE_EXECVPE
extern int execvpe(const char *name, char * const argv[], char * const envp[]);
+#endif
#endif
diff --git a/lib/libspl/include/os/freebsd/sys/stat.h b/lib/libspl/include/os/freebsd/sys/stat.h
index 38c684d62a1b..af488244bd05 100644
--- a/lib/libspl/include/os/freebsd/sys/stat.h
+++ b/lib/libspl/include/os/freebsd/sys/stat.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -76,8 +76,12 @@ fstat64_blk(int fd, struct stat64 *st)
/*
* Only Intel-based Macs have a separate stat64; Arm-based Macs are like
* FreeBSD and have a full 64-bit stat from the start.
+ *
+ * On Linux, musl libc is full 64-bit too and has deprecated its own version
+ * of these defines since version 1.2.4.
*/
-#if defined(__APPLE__) && !(defined(__i386__) || defined(__x86_64__))
+#if (defined(__APPLE__) && !(defined(__i386__) || defined(__x86_64__))) || \
+ (defined(__linux__) && !defined(__GLIBC__))
#define stat64 stat
#define fstat64 fstat
#endif
diff --git a/lib/libspl/include/os/linux/sys/byteorder.h b/lib/libspl/include/os/linux/sys/byteorder.h
index 47af7700f031..50f0f1e77936 100644
--- a/lib/libspl/include/os/linux/sys/byteorder.h
+++ b/lib/libspl/include/os/linux/sys/byteorder.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -90,6 +90,18 @@ extern in_port_t ntohs(in_port_t);
#if !defined(_XPG4_2) || defined(__EXTENSIONS__)
+#ifdef __COVERITY__
+/*
+ * Coverity's taint warnings from byteswapping are false positives for us.
+ * Suppress them by hiding byteswapping from Coverity.
+ */
+#define BSWAP_8(x) ((x) & 0xff)
+#define BSWAP_16(x) ((x) & 0xffff)
+#define BSWAP_32(x) ((x) & 0xffffffff)
+#define BSWAP_64(x) (x)
+
+#else /* __COVERITY__ */
+
/*
* Macros to reverse byte order
*/
@@ -98,6 +110,8 @@ extern in_port_t ntohs(in_port_t);
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
+#endif /* __COVERITY__ */
+
#define BMASK_8(x) ((x) & 0xff)
#define BMASK_16(x) ((x) & 0xffff)
#define BMASK_32(x) ((x) & 0xffffffff)
diff --git a/lib/libspl/include/os/linux/sys/errno.h b/lib/libspl/include/os/linux/sys/errno.h
index 30d20ab895c5..f0ad60b0bcff 100644
--- a/lib/libspl/include/os/linux/sys/errno.h
+++ b/lib/libspl/include/os/linux/sys/errno.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/ia32/asm_linkage.h b/lib/libspl/include/os/linux/sys/ia32/asm_linkage.h
new file mode 100644
index 000000000000..f07596123341
--- /dev/null
+++ b/lib/libspl/include/os/linux/sys/ia32/asm_linkage.h
@@ -0,0 +1,211 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _IA32_SYS_ASM_LINKAGE_H
+#define _IA32_SYS_ASM_LINKAGE_H
+
+#if defined(_KERNEL) && defined(__linux__)
+#include <linux/linkage.h>
+#endif
+
+#ifndef ENDBR
+#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
+/* CSTYLED */
+#if __has_include(<cet.h>)
+
+#include <cet.h>
+
+#ifdef _CET_ENDBR
+#define ENDBR _CET_ENDBR
+#endif /* _CET_ENDBR */
+
+#endif /* <cet.h> */
+#endif /* __ELF__ && __CET__ && __has_include */
+#endif /* !ENDBR */
+
+#ifndef ENDBR
+#define ENDBR
+#endif
+#ifndef RET
+#define RET ret
+#endif
+
+/* You can set to nothing on Unix platforms */
+#undef ASMABI
+#define ASMABI __attribute__((sysv_abi))
+
+#define SECTION_TEXT .text
+#define SECTION_STATIC .section .rodata
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _ASM /* The remainder of this file is only for assembly files */
+
+/*
+ * make annoying differences in assembler syntax go away
+ */
+
+/*
+ * D16 and A16 are used to insert instructions prefixes; the
+ * macros help the assembler code be slightly more portable.
+ */
+#if !defined(__GNUC_AS__)
+/*
+ * /usr/ccs/bin/as prefixes are parsed as separate instructions
+ */
+#define D16 data16;
+#define A16 addr16;
+
+/*
+ * (There are some weird constructs in constant expressions)
+ */
+#define _CONST(const) [const]
+#define _BITNOT(const) -1!_CONST(const)
+#define _MUL(a, b) _CONST(a \* b)
+
+#else
+/*
+ * Why not use the 'data16' and 'addr16' prefixes .. well, the
+ * assembler doesn't quite believe in real mode, and thus argues with
+ * us about what we're trying to do.
+ */
+#define D16 .byte 0x66;
+#define A16 .byte 0x67;
+
+#define _CONST(const) (const)
+#define _BITNOT(const) ~_CONST(const)
+#define _MUL(a, b) _CONST(a * b)
+
+#endif
+
+/*
+ * C pointers are different sizes between i386 and amd64.
+ * These constants can be used to compute offsets into pointer arrays.
+ */
+#if defined(__amd64)
+#define CLONGSHIFT 3
+#define CLONGSIZE 8
+#define CLONGMASK 7
+#elif defined(__i386)
+#define CLONGSHIFT 2
+#define CLONGSIZE 4
+#define CLONGMASK 3
+#endif
+
+/*
+ * Since we know we're either ILP32 or LP64 ..
+ */
+#define CPTRSHIFT CLONGSHIFT
+#define CPTRSIZE CLONGSIZE
+#define CPTRMASK CLONGMASK
+
+#if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT)
+#error "inconsistent shift constants"
+#endif
+
+#if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1)
+#error "inconsistent mask constants"
+#endif
+
+#define ASM_ENTRY_ALIGN 16
+
+/*
+ * SSE register alignment and save areas
+ */
+
+#define XMM_SIZE 16
+#define XMM_ALIGN 16
+
+/*
+ * ENTRY provides the standard procedure entry code and an easy way to
+ * insert the calls to mcount for profiling. ENTRY_NP is identical, but
+ * never calls mcount.
+ */
+#undef ENTRY
+#define ENTRY(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+ .type x, @function; \
+x: MCOUNT(x)
+
+#define ENTRY_NP(x) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x; \
+ .type x, @function; \
+x:
+
+#define ENTRY_ALIGN(x, a) \
+ .text; \
+ .balign a; \
+ .globl x; \
+ .type x, @function; \
+x:
+
+#define FUNCTION(x) \
+ .type x, @function; \
+x:
+
+/*
+ * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
+ */
+#define ENTRY2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+ .type x, @function; \
+ .type y, @function; \
+x:; \
+y: MCOUNT(x)
+
+#define ENTRY_NP2(x, y) \
+ .text; \
+ .balign ASM_ENTRY_ALIGN; \
+ .globl x, y; \
+ .type x, @function; \
+ .type y, @function; \
+x:; \
+y:
+
+
+/*
+ * SET_SIZE trails a function and set the size for the ELF symbol table.
+ */
+#define SET_SIZE(x) \
+ .size x, [.-x]
+
+#define SET_OBJ(x) .type x, @object
+
+#endif /* _ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IA32_SYS_ASM_LINKAGE_H */
diff --git a/lib/libspl/include/os/linux/sys/mnttab.h b/lib/libspl/include/os/linux/sys/mnttab.h
index 21592aaaacee..7b540a383d27 100644
--- a/lib/libspl/include/os/linux/sys/mnttab.h
+++ b/lib/libspl/include/os/linux/sys/mnttab.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/mount.h b/lib/libspl/include/os/linux/sys/mount.h
index d7c6f750e23d..a98fd6974b90 100644
--- a/lib/libspl/include/os/linux/sys/mount.h
+++ b/lib/libspl/include/os/linux/sys/mount.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/param.h b/lib/libspl/include/os/linux/sys/param.h
index 26335187fdca..c35678529ba8 100644
--- a/lib/libspl/include/os/linux/sys/param.h
+++ b/lib/libspl/include/os/linux/sys/param.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/stat.h b/lib/libspl/include/os/linux/sys/stat.h
index 3e8d27e4c19a..e7f592620512 100644
--- a/lib/libspl/include/os/linux/sys/stat.h
+++ b/lib/libspl/include/os/linux/sys/stat.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/sysmacros.h b/lib/libspl/include/os/linux/sys/sysmacros.h
index 31f347c6fd5a..5765ee25c6cb 100644
--- a/lib/libspl/include/os/linux/sys/sysmacros.h
+++ b/lib/libspl/include/os/linux/sys/sysmacros.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/os/linux/sys/zfs_context_os.h b/lib/libspl/include/os/linux/sys/zfs_context_os.h
index 81ced5207749..04abfa09d8f1 100644
--- a/lib/libspl/include/os/linux/sys/zfs_context_os.h
+++ b/lib/libspl/include/os/linux/sys/zfs_context_os.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/rpc/xdr.h b/lib/libspl/include/rpc/xdr.h
index 51d71f693bbf..882b72456c21 100644
--- a/lib/libspl/include/rpc/xdr.h
+++ b/lib/libspl/include/rpc/xdr.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/statcommon.h b/lib/libspl/include/statcommon.h
index 1f376f5c7c24..971997a447a5 100644
--- a/lib/libspl/include/statcommon.h
+++ b/lib/libspl/include/statcommon.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/stdlib.h b/lib/libspl/include/stdlib.h
index a4ce4f781fc5..2dd371463d40 100644
--- a/lib/libspl/include/stdlib.h
+++ b/lib/libspl/include/stdlib.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/string.h b/lib/libspl/include/string.h
index a7d40fa61943..f8605790a6f3 100644
--- a/lib/libspl/include/string.h
+++ b/lib/libspl/include/string.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/acl.h b/lib/libspl/include/sys/acl.h
index 31168421b088..43646f3e28fc 100644
--- a/lib/libspl/include/sys/acl.h
+++ b/lib/libspl/include/sys/acl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/acl_impl.h b/lib/libspl/include/sys/acl_impl.h
index 717334906415..e7f7bcd907cd 100644
--- a/lib/libspl/include/sys/acl_impl.h
+++ b/lib/libspl/include/sys/acl_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/include/sys/asm_linkage.h b/lib/libspl/include/sys/asm_linkage.h
index 49a494b46e0b..84aa0854a9ff 100644
--- a/module/icp/include/sys/asm_linkage.h
+++ b/lib/libspl/include/sys/asm_linkage.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/callb.h b/lib/libspl/include/sys/callb.h
index 8ffd18788865..783208ed16a4 100644
--- a/lib/libspl/include/sys/callb.h
+++ b/lib/libspl/include/sys/callb.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/cmn_err.h b/lib/libspl/include/sys/cmn_err.h
index 63ff4eb29bc8..6a29e6cff2e1 100644
--- a/lib/libspl/include/sys/cmn_err.h
+++ b/lib/libspl/include/sys/cmn_err.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,4 +27,38 @@
#ifndef _LIBSPL_SYS_CMN_ERR_H
#define _LIBSPL_SYS_CMN_ERR_H
+#include <atomic.h>
+
+#define cmn_err_once(ce, ...) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ cmn_err(ce, __VA_ARGS__); \
+ } \
+} while (0)
+
+#define vcmn_err_once(ce, fmt, ap) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ vcmn_err(ce, fmt, ap); \
+ } \
+} while (0)
+
+#define zcmn_err_once(zone, ce, ...) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ zcmn_err(zone, ce, __VA_ARGS__); \
+ } \
+} while (0)
+
+#define vzcmn_err_once(zone, ce, fmt, ap) \
+do { \
+ static volatile uint32_t printed = 0; \
+ if (atomic_cas_32(&printed, 0, 1) == 0) { \
+ vzcmn_err(zone, ce, fmt, ap); \
+ } \
+} while (0)
+
#endif
diff --git a/lib/libspl/include/sys/cred.h b/lib/libspl/include/sys/cred.h
index 463b3abfc977..45eb65089df1 100644
--- a/lib/libspl/include/sys/cred.h
+++ b/lib/libspl/include/sys/cred.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/debug.h b/lib/libspl/include/sys/debug.h
index af18da94804c..ef3f0afb68c3 100644
--- a/lib/libspl/include/sys/debug.h
+++ b/lib/libspl/include/sys/debug.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/dkio.h b/lib/libspl/include/sys/dkio.h
index f3c641f669b7..9517b580bdf5 100644
--- a/lib/libspl/include/sys/dkio.h
+++ b/lib/libspl/include/sys/dkio.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/dklabel.h b/lib/libspl/include/sys/dklabel.h
index 8c2ca06c0cbc..a1fddd34799a 100644
--- a/lib/libspl/include/sys/dklabel.h
+++ b/lib/libspl/include/sys/dklabel.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/dktp/fdisk.h b/lib/libspl/include/sys/dktp/fdisk.h
index e90135f362e6..53db7d815438 100644
--- a/lib/libspl/include/sys/dktp/fdisk.h
+++ b/lib/libspl/include/sys/dktp/fdisk.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/feature_tests.h b/lib/libspl/include/sys/feature_tests.h
index 877e0a15a89e..396052f125af 100644
--- a/lib/libspl/include/sys/feature_tests.h
+++ b/lib/libspl/include/sys/feature_tests.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/inttypes.h b/lib/libspl/include/sys/inttypes.h
index d7d063985316..85ddef9ee74c 100644
--- a/lib/libspl/include/sys/inttypes.h
+++ b/lib/libspl/include/sys/inttypes.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/isa_defs.h b/lib/libspl/include/sys/isa_defs.h
index 3922445db31c..302f31e989cb 100644
--- a/lib/libspl/include/sys/isa_defs.h
+++ b/lib/libspl/include/sys/isa_defs.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -227,9 +227,13 @@ extern "C" {
* RISC-V arch specific defines
* only RV64G (including atomic) LP64 is supported yet
*/
-#elif defined(__riscv) && defined(_LP64) && _LP64 && \
+#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 && \
defined(__riscv_atomic) && __riscv_atomic
+#if !defined(_LP64)
+#define _LP64 1
+#endif
+
#ifndef __riscv__
#define __riscv__
#endif
@@ -242,10 +246,26 @@ extern "C" {
#define _SUNOS_VTOC_16
+/*
+ * LoongArch arch specific defines
+ * only LoongArch64 is supported yet
+ */
+#elif defined(__loongarch__) && defined(__loongarch_lp64)
+
+#if !defined(_LP64)
+#define _LP64
+#endif
+
+#define _ZFS_LITTLE_ENDIAN
+#define _SUNOS_VTOC_16
+
+/* not all LoongArch cores support unaligned accesses in hardware */
+#define _ALIGNMENT_REQUIRED 1
+
#else
/*
* Currently supported:
- * x86_64, x32, i386, arm, powerpc, s390, sparc, mips, and RV64G
+ * x86_64, x32, i386, arm, powerpc, s390, sparc, mips, RV64G, and LoongArch64
*/
#error "Unsupported ISA type"
#endif
diff --git a/lib/libspl/include/sys/kmem.h b/lib/libspl/include/sys/kmem.h
index 06c614e51d1c..9a4f63d0221c 100644
--- a/lib/libspl/include/sys/kmem.h
+++ b/lib/libspl/include/sys/kmem.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/kstat.h b/lib/libspl/include/sys/kstat.h
index c2de0778485c..e6057bf6b98e 100644
--- a/lib/libspl/include/sys/kstat.h
+++ b/lib/libspl/include/sys/kstat.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/list.h b/lib/libspl/include/sys/list.h
index 6db92ed42955..6c32402a7bd1 100644
--- a/lib/libspl/include/sys/list.h
+++ b/lib/libspl/include/sys/list.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/list_impl.h b/lib/libspl/include/sys/list_impl.h
index b5655b972c11..629db34da067 100644
--- a/lib/libspl/include/sys/list_impl.h
+++ b/lib/libspl/include/sys/list_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -39,7 +39,6 @@ struct list_node {
};
struct list {
- size_t list_size;
size_t list_offset;
struct list_node list_head;
};
diff --git a/lib/libspl/include/sys/mhd.h b/lib/libspl/include/sys/mhd.h
index fcc062d51c84..956009b499ee 100644
--- a/lib/libspl/include/sys/mhd.h
+++ b/lib/libspl/include/sys/mhd.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/mkdev.h b/lib/libspl/include/sys/mkdev.h
index 5978de65de50..4878920f3f13 100644
--- a/lib/libspl/include/sys/mkdev.h
+++ b/lib/libspl/include/sys/mkdev.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/policy.h b/lib/libspl/include/sys/policy.h
index 2f695b35cd0b..b0a810f09841 100644
--- a/lib/libspl/include/sys/policy.h
+++ b/lib/libspl/include/sys/policy.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/poll.h b/lib/libspl/include/sys/poll.h
index 6ab0bddc0be5..8f6d591537b2 100644
--- a/lib/libspl/include/sys/poll.h
+++ b/lib/libspl/include/sys/poll.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/priv.h b/lib/libspl/include/sys/priv.h
index 76c76d1830c2..c3f8b7bc41c7 100644
--- a/lib/libspl/include/sys/priv.h
+++ b/lib/libspl/include/sys/priv.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/processor.h b/lib/libspl/include/sys/processor.h
index 78e95d01f1b5..d778438c1b3f 100644
--- a/lib/libspl/include/sys/processor.h
+++ b/lib/libspl/include/sys/processor.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/sha2.h b/lib/libspl/include/sys/sha2.h
deleted file mode 100644
index 8bdc23a5f61e..000000000000
--- a/lib/libspl/include/sys/sha2.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/* Copyright 2013 Saso Kiselkov. All rights reserved. */
-
-#ifndef _SYS_SHA2_H
-#define _SYS_SHA2_H
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SHA256_DIGEST_LENGTH 32 /* SHA256 digest length in bytes */
-#define SHA384_DIGEST_LENGTH 48 /* SHA384 digest length in bytes */
-#define SHA512_DIGEST_LENGTH 64 /* SHA512 digest length in bytes */
-
-/* Truncated versions of SHA-512 according to FIPS-180-4, section 5.3.6 */
-#define SHA512_224_DIGEST_LENGTH 28 /* SHA512/224 digest length */
-#define SHA512_256_DIGEST_LENGTH 32 /* SHA512/256 digest length */
-
-#define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */
-#define SHA512_HMAC_BLOCK_SIZE 128 /* SHA512-HMAC block size */
-
-#define SHA256 0
-#define SHA256_HMAC 1
-#define SHA256_HMAC_GEN 2
-#define SHA384 3
-#define SHA384_HMAC 4
-#define SHA384_HMAC_GEN 5
-#define SHA512 6
-#define SHA512_HMAC 7
-#define SHA512_HMAC_GEN 8
-#define SHA512_224 9
-#define SHA512_256 10
-
-/*
- * SHA2 context.
- * The contents of this structure are a private interface between the
- * Init/Update/Final calls of the functions defined below.
- * Callers must never attempt to read or write any of the fields
- * in this structure directly.
- */
-typedef struct {
- uint32_t algotype; /* Algorithm Type */
-
- /* state (ABCDEFGH) */
- union {
- uint32_t s32[8]; /* for SHA256 */
- uint64_t s64[8]; /* for SHA384/512 */
- } state;
- /* number of bits */
- union {
- uint32_t c32[2]; /* for SHA256 , modulo 2^64 */
- uint64_t c64[2]; /* for SHA384/512, modulo 2^128 */
- } count;
- union {
- uint8_t buf8[128]; /* undigested input */
- uint32_t buf32[32]; /* realigned input */
- uint64_t buf64[16]; /* realigned input */
- } buf_un;
-} SHA2_CTX;
-
-typedef SHA2_CTX SHA256_CTX;
-typedef SHA2_CTX SHA384_CTX;
-typedef SHA2_CTX SHA512_CTX;
-
-extern void SHA256Init(SHA256_CTX *);
-
-extern void SHA256Update(SHA256_CTX *, const void *, size_t);
-
-extern void SHA256Final(void *, SHA256_CTX *);
-
-extern void SHA384Init(SHA384_CTX *);
-
-extern void SHA384Update(SHA384_CTX *, const void *, size_t);
-
-extern void SHA384Final(void *, SHA384_CTX *);
-
-extern void SHA512Init(SHA512_CTX *);
-
-extern void SHA512Update(SHA512_CTX *, const void *, size_t);
-
-extern void SHA512Final(void *, SHA512_CTX *);
-
-extern void SHA2Init(uint64_t mech, SHA2_CTX *);
-
-extern void SHA2Update(SHA2_CTX *, const void *, size_t);
-
-extern void SHA2Final(void *, SHA2_CTX *);
-
-#ifdef _SHA2_IMPL
-/*
- * The following types/functions are all private to the implementation
- * of the SHA2 functions and must not be used by consumers of the interface
- */
-
-/*
- * List of support mechanisms in this module.
- *
- * It is important to note that in the module, division or modulus calculations
- * are used on the enumerated type to determine which mechanism is being used;
- * therefore, changing the order or additional mechanisms should be done
- * carefully
- */
-typedef enum sha2_mech_type {
- SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */
- SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */
- SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */
- SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */
- SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */
- SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */
- SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */
- SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */
- SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */
- SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */
- SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */
-} sha2_mech_type_t;
-
-#endif /* _SHA2_IMPL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SHA2_H */
diff --git a/lib/libspl/include/sys/simd.h b/lib/libspl/include/sys/simd.h
index 6a6d8b7c6191..41f9df506468 100644
--- a/lib/libspl/include/sys/simd.h
+++ b/lib/libspl/include/sys/simd.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,8 +20,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
#ifndef _LIBSPL_SYS_SIMD_H
@@ -30,6 +30,28 @@
#include <sys/isa_defs.h>
#include <sys/types.h>
+/* including <sys/auxv.h> clashes with AT_UID and others */
+#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__)
+#if defined(__FreeBSD__)
+#define AT_HWCAP 25
+#define AT_HWCAP2 26
+extern int elf_aux_info(int aux, void *buf, int buflen);
+static inline unsigned long getauxval(unsigned long key)
+{
+ unsigned long val = 0UL;
+
+ if (elf_aux_info((int)key, &val, sizeof (val)) != 0)
+ return (0UL);
+
+ return (val);
+}
+#elif defined(__linux__)
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+extern unsigned long getauxval(unsigned long type);
+#endif /* __linux__ */
+#endif /* arm || aarch64 || powerpc */
+
#if defined(__x86)
#include <cpuid.h>
@@ -78,7 +100,8 @@ typedef enum cpuid_inst_sets {
AVX512VL,
AES,
PCLMULQDQ,
- MOVBE
+ MOVBE,
+ SHA_NI
} cpuid_inst_sets_t;
/*
@@ -103,6 +126,7 @@ typedef struct cpuid_feature_desc {
#define _AES_BIT (1U << 25)
#define _PCLMULQDQ_BIT (1U << 1)
#define _MOVBE_BIT (1U << 22)
+#define _SHA_NI_BIT (1U << 29)
/*
* Descriptions of supported instruction sets
@@ -131,6 +155,7 @@ static const cpuid_feature_desc_t cpuid_features[] = {
[AES] = {1U, 0U, _AES_BIT, ECX },
[PCLMULQDQ] = {1U, 0U, _PCLMULQDQ_BIT, ECX },
[MOVBE] = {1U, 0U, _MOVBE_BIT, ECX },
+ [SHA_NI] = {7U, 0U, _SHA_NI_BIT, EBX },
};
/*
@@ -204,6 +229,7 @@ CPUID_FEATURE_CHECK(avx512vl, AVX512VL);
CPUID_FEATURE_CHECK(aes, AES);
CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ);
CPUID_FEATURE_CHECK(movbe, MOVBE);
+CPUID_FEATURE_CHECK(shani, SHA_NI);
/*
* Detect register set support
@@ -346,6 +372,15 @@ zfs_movbe_available(void)
}
/*
+ * Check if SHA_NI instruction is available
+ */
+static inline boolean_t
+zfs_shani_available(void)
+{
+ return (__cpuid_has_shani());
+}
+
+/*
* AVX-512 family of instruction sets:
*
* AVX512F Foundation
@@ -443,72 +478,111 @@ zfs_avx512vbmi_available(void)
__zmm_enabled());
}
-#elif defined(__aarch64__)
+#elif defined(__arm__)
#define kfpu_allowed() 1
#define kfpu_initialize(tsk) do {} while (0)
#define kfpu_begin() do {} while (0)
#define kfpu_end() do {} while (0)
-#elif defined(__powerpc__)
+#define HWCAP_NEON 0x00001000
+#define HWCAP2_SHA2 0x00000008
+
+/*
+ * Check if NEON is available
+ */
+static inline boolean_t
+zfs_neon_available(void)
+{
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & HWCAP_NEON);
+}
+
+/*
+ * Check if SHA2 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
+{
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & HWCAP2_SHA2);
+}
+
+#elif defined(__aarch64__)
#define kfpu_allowed() 1
#define kfpu_initialize(tsk) do {} while (0)
#define kfpu_begin() do {} while (0)
#define kfpu_end() do {} while (0)
+#define HWCAP_FP 0x00000001
+#define HWCAP_SHA2 0x00000040
+#define HWCAP_SHA512 0x00200000
+
/*
- * Check if AltiVec instruction set is available
- * No easy way beyond 'altivec works' :-(
+ * Check if NEON is available
*/
-#include <signal.h>
-#include <setjmp.h>
+static inline boolean_t
+zfs_neon_available(void)
+{
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & HWCAP_FP);
+}
-#if defined(__ALTIVEC__) && !defined(__FreeBSD__)
-static jmp_buf env;
-static void sigillhandler(int x)
+/*
+ * Check if SHA2 is available
+ */
+static inline boolean_t
+zfs_sha256_available(void)
{
- (void) x;
- longjmp(env, 1);
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & HWCAP_SHA2);
}
-#endif
+
+/*
+ * Check if SHA512 is available
+ */
+static inline boolean_t
+zfs_sha512_available(void)
+{
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & HWCAP_SHA512);
+}
+
+#elif defined(__powerpc__)
+
+#define kfpu_allowed() 0
+#define kfpu_initialize(tsk) do {} while (0)
+#define kfpu_begin() do {} while (0)
+#define kfpu_end() do {} while (0)
+
+#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+#define PPC_FEATURE_HAS_VSX 0x00000080
+#define PPC_FEATURE2_ARCH_2_07 0x80000000
static inline boolean_t
zfs_altivec_available(void)
{
- boolean_t has_altivec = B_FALSE;
-#if defined(__ALTIVEC__) && !defined(__FreeBSD__)
- sighandler_t savesig;
- savesig = signal(SIGILL, sigillhandler);
- if (setjmp(env)) {
- signal(SIGILL, savesig);
- has_altivec = B_FALSE;
- } else {
- __asm__ __volatile__("vor 0,0,0\n" : : : "v0");
- signal(SIGILL, savesig);
- has_altivec = B_TRUE;
- }
-#endif
- return (has_altivec);
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & PPC_FEATURE_HAS_ALTIVEC);
}
+
static inline boolean_t
zfs_vsx_available(void)
{
- boolean_t has_vsx = B_FALSE;
-#if defined(__ALTIVEC__) && !defined(__FreeBSD__)
- sighandler_t savesig;
- savesig = signal(SIGILL, sigillhandler);
- if (setjmp(env)) {
- signal(SIGILL, savesig);
- has_vsx = B_FALSE;
- } else {
- __asm__ __volatile__("xssubsp 0,0,0\n");
- signal(SIGILL, savesig);
- has_vsx = B_TRUE;
- }
-#endif
- return (has_vsx);
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ return (hwcap & PPC_FEATURE_HAS_VSX);
}
+
+static inline boolean_t
+zfs_isa207_available(void)
+{
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ unsigned long hwcap2 = getauxval(AT_HWCAP2);
+ return ((hwcap & PPC_FEATURE_HAS_VSX) &&
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07));
+}
+
#else
#define kfpu_allowed() 0
diff --git a/lib/libspl/include/sys/stack.h b/lib/libspl/include/sys/stack.h
index 59807e97b6a0..ed63d3cb9da2 100644
--- a/lib/libspl/include/sys/stack.h
+++ b/lib/libspl/include/sys/stack.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/stdtypes.h b/lib/libspl/include/sys/stdtypes.h
index c26e2dc96c4e..9ad51a03f27c 100644
--- a/lib/libspl/include/sys/stdtypes.h
+++ b/lib/libspl/include/sys/stdtypes.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/sunddi.h b/lib/libspl/include/sys/sunddi.h
index ccd2b29b9b09..4e2c370f7b80 100644
--- a/lib/libspl/include/sys/sunddi.h
+++ b/lib/libspl/include/sys/sunddi.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/systeminfo.h b/lib/libspl/include/sys/systeminfo.h
index cc6c1793c00e..e0418db89fc6 100644
--- a/lib/libspl/include/sys/systeminfo.h
+++ b/lib/libspl/include/sys/systeminfo.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/time.h b/lib/libspl/include/sys/time.h
index c9f6165047d2..0f7d5196b31c 100644
--- a/lib/libspl/include/sys/time.h
+++ b/lib/libspl/include/sys/time.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -101,7 +101,7 @@ gethrtime(void)
{
struct timespec ts;
(void) clock_gettime(CLOCK_MONOTONIC, &ts);
- return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
+ return ((((uint64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
}
#endif /* _LIBSPL_SYS_TIME_H */
diff --git a/lib/libspl/include/sys/types.h b/lib/libspl/include/sys/types.h
index 8dc38ae3394f..90e3cf9bdaf8 100644
--- a/lib/libspl/include/sys/types.h
+++ b/lib/libspl/include/sys/types.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -47,31 +47,6 @@
typedef uint_t zoneid_t;
typedef int projid_t;
-/*
- * Definitions remaining from previous partial support for 64-bit file
- * offsets. This partial support for devices greater than 2gb requires
- * compiler support for long long.
- */
-#ifdef _LONG_LONG_LTOH
-typedef union {
- offset_t _f; /* Full 64 bit offset value */
- struct {
- int32_t _l; /* lower 32 bits of offset value */
- int32_t _u; /* upper 32 bits of offset value */
- } _p;
-} lloff_t;
-#endif
-
-#ifdef _LONG_LONG_HTOL
-typedef union {
- offset_t _f; /* Full 64 bit offset value */
- struct {
- int32_t _u; /* upper 32 bits of offset value */
- int32_t _l; /* lower 32 bits of offset value */
- } _p;
-} lloff_t;
-#endif
-
#include <sys/param.h> /* for NBBY */
#endif
diff --git a/lib/libspl/include/sys/types32.h b/lib/libspl/include/sys/types32.h
index bb41aa34bee0..eadc67c7122a 100644
--- a/lib/libspl/include/sys/types32.h
+++ b/lib/libspl/include/sys/types32.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/uio.h b/lib/libspl/include/sys/uio.h
index 81ade54b5409..665bfc42301b 100644
--- a/lib/libspl/include/sys/uio.h
+++ b/lib/libspl/include/sys/uio.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -90,7 +90,7 @@ zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len)
}
static inline void
-zfs_uio_advance(zfs_uio_t *uio, size_t size)
+zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
{
uio->uio_resid -= size;
uio->uio_loffset += size;
diff --git a/lib/libspl/include/sys/vnode.h b/lib/libspl/include/sys/vnode.h
index efcdd2c5a5ae..111cc8fd8357 100644
--- a/lib/libspl/include/sys/vnode.h
+++ b/lib/libspl/include/sys/vnode.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/sys/zone.h b/lib/libspl/include/sys/zone.h
index bbb964dcef22..00d740fb6fff 100644
--- a/lib/libspl/include/sys/zone.h
+++ b/lib/libspl/include/sys/zone.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/umem.h b/lib/libspl/include/umem.h
index 288aaf3ecc36..9039212baf14 100644
--- a/lib/libspl/include/umem.h
+++ b/lib/libspl/include/umem.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -83,6 +83,7 @@ const char *_umem_debug_init(void);
const char *_umem_options_init(void);
const char *_umem_logging_init(void);
+__attribute__((malloc, alloc_size(1)))
static inline void *
umem_alloc(size_t size, int flags)
{
@@ -95,6 +96,7 @@ umem_alloc(size_t size, int flags)
return (ptr);
}
+__attribute__((malloc, alloc_size(1)))
static inline void *
umem_alloc_aligned(size_t size, size_t align, int flags)
{
@@ -116,6 +118,7 @@ umem_alloc_aligned(size_t size, size_t align, int flags)
return (ptr);
}
+__attribute__((malloc, alloc_size(1)))
static inline void *
umem_zalloc(size_t size, int flags)
{
@@ -134,6 +137,21 @@ umem_free(const void *ptr, size_t size __maybe_unused)
free((void *)ptr);
}
+/*
+ * umem_free_aligned was added for supporting portability
+ * with non-POSIX platforms that require a different free
+ * to be used with aligned allocations.
+ */
+static inline void
+umem_free_aligned(void *ptr, size_t size __maybe_unused)
+{
+#ifndef _WIN32
+ free((void *)ptr);
+#else
+ _aligned_free(ptr);
+#endif
+}
+
static inline void
umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused)
{}
@@ -170,6 +188,7 @@ umem_cache_destroy(umem_cache_t *cp)
umem_free(cp, sizeof (umem_cache_t));
}
+__attribute__((malloc))
static inline void *
umem_cache_alloc(umem_cache_t *cp, int flags)
{
@@ -193,7 +212,10 @@ umem_cache_free(umem_cache_t *cp, void *ptr)
if (cp->cache_destructor)
cp->cache_destructor(ptr, cp->cache_private);
- umem_free(ptr, cp->cache_bufsize);
+ if (cp->cache_align != 0)
+ umem_free_aligned(ptr, cp->cache_bufsize);
+ else
+ umem_free(ptr, cp->cache_bufsize);
}
static inline void
diff --git a/lib/libspl/include/unistd.h b/lib/libspl/include/unistd.h
index 0246991b4b61..edb610e87848 100644
--- a/lib/libspl/include/unistd.h
+++ b/lib/libspl/include/unistd.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/include/zone.h b/lib/libspl/include/zone.h
index 0af4e7a2fa49..341d574a7460 100644
--- a/lib/libspl/include/zone.h
+++ b/lib/libspl/include/zone.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/libspl_impl.h b/lib/libspl/libspl_impl.h
index cda56e64c962..3a19df64440c 100644
--- a/lib/libspl/libspl_impl.h
+++ b/lib/libspl/libspl_impl.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/list.c b/lib/libspl/list.c
index 0f2f3731b235..aaa71dc73c98 100644
--- a/lib/libspl/list.c
+++ b/lib/libspl/list.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -65,7 +65,8 @@ list_create(list_t *list, size_t size, size_t offset)
ASSERT(size > 0);
ASSERT(size >= offset + sizeof (list_node_t));
- list->list_size = size;
+ (void) size;
+
list->list_offset = offset;
list->list_head.next = list->list_head.prev = &list->list_head;
}
@@ -194,7 +195,6 @@ list_move_tail(list_t *dst, list_t *src)
list_node_t *dstnode = &dst->list_head;
list_node_t *srcnode = &src->list_head;
- ASSERT(dst->list_size == src->list_size);
ASSERT(dst->list_offset == src->list_offset);
if (list_empty(src))
diff --git a/lib/libspl/mkdirp.c b/lib/libspl/mkdirp.c
index fce2c1c82eb7..dff95a192af7 100644
--- a/lib/libspl/mkdirp.c
+++ b/lib/libspl/mkdirp.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/os/freebsd/getexecname.c b/lib/libspl/os/freebsd/getexecname.c
index 256b28c1b70e..5f1692adf1dd 100644
--- a/lib/libspl/os/freebsd/getexecname.c
+++ b/lib/libspl/os/freebsd/getexecname.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/os/freebsd/gethostid.c b/lib/libspl/os/freebsd/gethostid.c
index 7bd567fe61b5..4e095d670710 100644
--- a/lib/libspl/os/freebsd/gethostid.c
+++ b/lib/libspl/os/freebsd/gethostid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/os/freebsd/getmntany.c b/lib/libspl/os/freebsd/getmntany.c
index 0ef24059e84f..fc1c9de6df81 100644
--- a/lib/libspl/os/freebsd/getmntany.c
+++ b/lib/libspl/os/freebsd/getmntany.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -36,6 +36,7 @@
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <libzutil.h>
int
getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
@@ -49,13 +50,13 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
if (stat64(path, statbuf) != 0) {
(void) fprintf(stderr, "cannot open '%s': %s\n",
- path, strerror(errno));
+ path, zfs_strerror(errno));
return (-1);
}
if (statfs(path, &sfs) != 0) {
(void) fprintf(stderr, "%s: %s\n", path,
- strerror(errno));
+ zfs_strerror(errno));
return (-1);
}
statfs2mnttab(&sfs, (struct mnttab *)entry);
diff --git a/lib/libspl/os/freebsd/mnttab.c b/lib/libspl/os/freebsd/mnttab.c
index f0cc04d89ded..26a4cd992cfb 100644
--- a/lib/libspl/os/freebsd/mnttab.c
+++ b/lib/libspl/os/freebsd/mnttab.c
@@ -29,9 +29,6 @@
* functions.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/mntent.h>
@@ -74,7 +71,7 @@ hasmntopt(struct mnttab *mnt, const char *opt)
if (mnt->mnt_mntopts == NULL)
return (NULL);
- (void) strcpy(opts, mnt->mnt_mntopts);
+ (void) strlcpy(opts, mnt->mnt_mntopts, MNT_LINE_MAX);
f = mntopt(&opts);
for (; *f; f = mntopt(&opts)) {
if (strncmp(opt, f, strlen(opt)) == 0)
diff --git a/lib/libspl/os/linux/getexecname.c b/lib/libspl/os/linux/getexecname.c
index a640556bcbec..4b54c193973a 100644
--- a/lib/libspl/os/linux/getexecname.c
+++ b/lib/libspl/os/linux/getexecname.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/os/linux/gethostid.c b/lib/libspl/os/linux/gethostid.c
index c04b7fd3eef3..fcef8798c615 100644
--- a/lib/libspl/os/linux/gethostid.c
+++ b/lib/libspl/os/linux/gethostid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -59,6 +59,7 @@ unsigned long
get_system_hostid(void)
{
unsigned long hostid = get_spl_hostid();
+ uint32_t system_hostid;
/*
* We do not use gethostid(3) because it can return a bogus ID,
@@ -69,8 +70,11 @@ get_system_hostid(void)
if (hostid == 0) {
int fd = open("/etc/hostid", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
- if (read(fd, &hostid, 4) < 0)
+ if (read(fd, &system_hostid, sizeof (system_hostid))
+ != sizeof (system_hostid))
hostid = 0;
+ else
+ hostid = system_hostid;
(void) close(fd);
}
}
diff --git a/lib/libspl/os/linux/getmntany.c b/lib/libspl/os/linux/getmntany.c
index 3713ff38e17f..a46c4e931719 100644
--- a/lib/libspl/os/linux/getmntany.c
+++ b/lib/libspl/os/linux/getmntany.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -38,6 +38,7 @@
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <libzutil.h>
#define BUFSIZE (MNT_LINE_MAX + 2)
@@ -122,7 +123,7 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
*/
if (stat64(path, statbuf) != 0) {
(void) fprintf(stderr, "cannot open '%s': %s\n",
- path, strerror(errno));
+ path, zfs_strerror(errno));
return (-1);
}
diff --git a/lib/libspl/os/linux/zone.c b/lib/libspl/os/linux/zone.c
index 65c02dfe7aab..f8a10bfa167a 100644
--- a/lib/libspl/os/linux/zone.c
+++ b/lib/libspl/os/linux/zone.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,21 +41,21 @@ getzoneid(void)
int c = snprintf(path, sizeof (path), "/proc/self/ns/user");
/* This API doesn't have any error checking... */
- if (c < 0)
- return (0);
+ if (c < 0 || c >= sizeof (path))
+ return (GLOBAL_ZONEID);
ssize_t r = readlink(path, buf, sizeof (buf) - 1);
if (r < 0)
- return (0);
+ return (GLOBAL_ZONEID);
cp = strchr(buf, '[');
if (cp == NULL)
- return (0);
+ return (GLOBAL_ZONEID);
cp++;
unsigned long n = strtoul(cp, NULL, 10);
if (n == ULONG_MAX && errno == ERANGE)
- return (0);
+ return (GLOBAL_ZONEID);
zoneid_t z = (zoneid_t)n;
return (z);
diff --git a/lib/libspl/page.c b/lib/libspl/page.c
index 5b0d3f2e5786..fb8827867781 100644
--- a/lib/libspl/page.c
+++ b/lib/libspl/page.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/strlcat.c b/lib/libspl/strlcat.c
index 4528d875ed5e..88e244534ca1 100644
--- a/lib/libspl/strlcat.c
+++ b/lib/libspl/strlcat.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/strlcpy.c b/lib/libspl/strlcpy.c
index d483b91f6121..c3f59bd84b0d 100644
--- a/lib/libspl/strlcpy.c
+++ b/lib/libspl/strlcpy.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libspl/timestamp.c b/lib/libspl/timestamp.c
index 8d14ae645734..9b435221f5fb 100644
--- a/lib/libspl/timestamp.c
+++ b/lib/libspl/timestamp.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libtpool/thread_pool.c b/lib/libtpool/thread_pool.c
index 58b706ddebf5..7802f8c1750f 100644
--- a/lib/libtpool/thread_pool.c
+++ b/lib/libtpool/thread_pool.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,6 +28,7 @@
#include <signal.h>
#include <errno.h>
#include <assert.h>
+#include <limits.h>
#include "thread_pool_impl.h"
static pthread_mutex_t thread_pool_lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/lib/libtpool/thread_pool_impl.h b/lib/libtpool/thread_pool_impl.h
index 5349c2ade8c3..6cde8d0d235c 100644
--- a/lib/libtpool/thread_pool_impl.h
+++ b/lib/libtpool/thread_pool_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libuutil/Makefile.am b/lib/libuutil/Makefile.am
index 339f9a064745..b973ce3cca4c 100644
--- a/lib/libuutil/Makefile.am
+++ b/lib/libuutil/Makefile.am
@@ -9,7 +9,6 @@ libuutil_la_SOURCES = \
%D%/uu_ident.c \
%D%/uu_list.c \
%D%/uu_misc.c \
- %D%/uu_pname.c \
%D%/uu_string.c
libuutil_la_LIBADD = \
diff --git a/lib/libuutil/libuutil.abi b/lib/libuutil/libuutil.abi
index 766d8843000d..e942d24c6531 100644
--- a/lib/libuutil/libuutil.abi
+++ b/lib/libuutil/libuutil.abi
@@ -1,6 +1,5 @@
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libuutil.so.3'>
<elf-needed>
- <dependency name='libpthread.so.0'/>
<dependency name='libc.so.6'/>
<dependency name='ld-linux-x86-64.so.2'/>
</elf-needed>
@@ -173,12 +172,12 @@
<elf-symbol name='membar_enter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_exit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_producer' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='membar_sync' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='mkdirp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='print_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_alt_exit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_avl_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_avl_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_avl_find' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -203,13 +202,8 @@
<elf-symbol name='uu_avl_walk_next' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_avl_walk_start' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_check_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_die' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_error' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_exit_fatal' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_exit_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_exit_usage' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_free' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_getpname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_list_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_list_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_list_find' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -239,145 +233,21 @@
<elf-symbol name='uu_msprintf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_panic' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_set_error' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_setpname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strbw' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strcaseeq' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strdup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_streq' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strerror' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strndup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_vdie' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_vwarn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_vxdie' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_warn' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_xdie' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_zalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
- <elf-variable-symbols>
- <elf-symbol name='uu_exit_fatal_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_exit_ok_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='uu_exit_usage_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- </elf-variable-symbols>
- <abi-instr address-size='64' path='../../module/avl/avl.c' language='LANG_C99'>
- <typedef-decl name='avl_tree_t' type-id='b351119f' id='f20fbd51'/>
- <typedef-decl name='avl_index_t' type-id='e475ab95' id='fba6cb51'/>
- <pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
- <pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/>
- <function-decl name='avl_walk' mangled-name='avl_walk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_walk'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='oldnode'/>
- <parameter type-id='95e97e5e' name='left'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_first' mangled-name='avl_first' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_first'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_last' mangled-name='avl_last' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_last'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_nearest' mangled-name='avl_nearest' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_nearest'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='fba6cb51' name='where'/>
- <parameter type-id='95e97e5e' name='direction'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_find' mangled-name='avl_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_find'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='value'/>
- <parameter type-id='32adbf30' name='where'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_insert' mangled-name='avl_insert' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='new_data'/>
- <parameter type-id='fba6cb51' name='where'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_insert_here' mangled-name='avl_insert_here' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert_here'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='new_data'/>
- <parameter type-id='eaa32e2f' name='here'/>
- <parameter type-id='95e97e5e' name='direction'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='new_node'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_remove' mangled-name='avl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_remove'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='data'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_update_lt' mangled-name='avl_update_lt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_lt'>
- <parameter type-id='a3681dea' name='t'/>
- <parameter type-id='eaa32e2f' name='obj'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='avl_update_gt' mangled-name='avl_update_gt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_gt'>
- <parameter type-id='a3681dea' name='t'/>
- <parameter type-id='eaa32e2f' name='obj'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='avl_update' mangled-name='avl_update' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update'>
- <parameter type-id='a3681dea' name='t'/>
- <parameter type-id='eaa32e2f' name='obj'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='avl_swap' mangled-name='avl_swap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_swap'>
- <parameter type-id='a3681dea' name='tree1'/>
- <parameter type-id='a3681dea' name='tree2'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_create' mangled-name='avl_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_create'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='585e1de9' name='compar'/>
- <parameter type-id='b59d7dce' name='size'/>
- <parameter type-id='b59d7dce' name='offset'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_destroy' mangled-name='avl_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='ee1f298e'/>
- </function-decl>
- <function-decl name='avl_is_empty' mangled-name='avl_is_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_is_empty'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='avl_destroy_nodes' mangled-name='avl_destroy_nodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy_nodes'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='63e171df' name='cookie'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-type size-in-bits='64' id='96ee24a5'>
- <parameter type-id='eaa32e2f'/>
- <parameter type-id='eaa32e2f'/>
- <return type-id='95e97e5e'/>
- </function-type>
- </abi-instr>
- <abi-instr address-size='64' path='assert.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
- <parameter type-id='80f4b756' name='file'/>
- <parameter type-id='80f4b756' name='func'/>
- <parameter type-id='95e97e5e' name='line'/>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
- <return type-id='48b5725f'/>
- </function-decl>
</abi-instr>
- <abi-instr address-size='64' path='atomic.c' language='LANG_C99'>
- <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <abi-instr address-size='64' path='lib/libspl/atomic.c' language='LANG_C99'>
<typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
<typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
<typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
@@ -448,11 +318,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_add_long' mangled-name='atomic_add_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'>
<parameter type-id='fe09dd29' name='target'/>
<parameter type-id='79a0948f' name='bits'/>
@@ -473,11 +338,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_sub_long' mangled-name='atomic_sub_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_or_8' mangled-name='atomic_or_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8'>
<parameter type-id='aa323ea4' name='target'/>
<parameter type-id='b96825af' name='bits'/>
@@ -714,13 +574,18 @@
<function-decl name='membar_consumer' mangled-name='membar_consumer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_consumer'>
<return type-id='48b5725f'/>
</function-decl>
+ <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
</abi-instr>
- <abi-instr address-size='64' path='getexecname.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
</function-decl>
+ <function-decl name='getexecname_impl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
</abi-instr>
- <abi-instr address-size='64' path='list.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/list.c' language='LANG_C99'>
<typedef-decl name='list_node_t' type-id='b0b5e45e' id='b21843b2'/>
<typedef-decl name='list_t' type-id='e824dae9' id='0899125f'/>
<class-decl name='list_node' size-in-bits='128' is-struct='yes' visibility='default' id='b0b5e45e'>
@@ -831,34 +696,113 @@
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='mkdirp.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/mkdirp.c' language='LANG_C99'>
<typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
<typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
+ <typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/>
+ <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
+ <qualified-type-def type-id='928221d2' const='yes' id='effb3702'/>
+ <pointer-type-def type-id='effb3702' size-in-bits='64' id='f077d3f8'/>
+ <qualified-type-def type-id='f077d3f8' restrict='yes' id='598aab80'/>
+ <pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/>
+ <qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/>
+ <function-decl name='calloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='access' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f1358bc3'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='598aab80'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='e1c52942'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'>
<parameter type-id='80f4b756' name='d'/>
<parameter type-id='d50d396c' name='mode'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/gethostid.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/getexecname.c' language='LANG_C99'>
+ <function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
+ <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
+ <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
+ <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
+ <function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='3a47d82b'/>
+ </function-decl>
+ <function-decl name='getenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='close' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
<function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
<return type-id='7359adad'/>
</function-decl>
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/getmntany.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
<subrange length='3' type-id='7359adad' id='56f209d2'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
- <subrange length='1' type-id='7359adad' id='52f813b4'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
- <subrange length='20' type-id='7359adad' id='fdca39cf'/>
- </array-type-def>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
@@ -893,6 +837,26 @@
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
</data-member>
</class-decl>
+ <class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='mnt_type' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
<class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
@@ -945,103 +909,9 @@
<typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
<typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
<typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
- <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
- <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
- <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
<typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
<typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
- <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
- <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
- <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='640'>
- <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='768'>
- <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='832'>
- <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='896'>
- <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='928'>
- <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1024'>
- <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1040'>
- <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1048'>
- <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1088'>
- <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1152'>
- <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1216'>
- <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1280'>
- <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1344'>
- <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1408'>
- <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1472'>
- <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1536'>
- <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1568'>
- <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
- </data-member>
- </class-decl>
<class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
@@ -1050,18 +920,39 @@
<var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
</data-member>
</class-decl>
- <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
- <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
- <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
- <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
- <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
- <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
+ <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
+ <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
+ <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='3cad23cd'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='b6b61d2f'/>
+ </function-decl>
+ <function-decl name='feof' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f1cadedf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'>
<parameter type-id='822cd80b' name='fp'/>
<parameter type-id='9d424d31' name='mgetp'/>
@@ -1080,18 +971,28 @@
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/zone.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/zone.c' language='LANG_C99'>
<typedef-decl name='zoneid_t' type-id='3502e3ff' id='4da03624'/>
+ <function-decl name='strtoul' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='7359adad'/>
+ </function-decl>
<function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'>
<return type-id='4da03624'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='page.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/page.c' language='LANG_C99'>
+ <function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
<function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
<return type-id='b59d7dce'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='strlcat.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/strlcat.c' language='LANG_C99'>
<function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'>
<parameter type-id='26a90f95' name='dst'/>
<parameter type-id='80f4b756' name='src'/>
@@ -1099,30 +1000,118 @@
<return type-id='b59d7dce'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='strlcpy.c' language='LANG_C99'>
- <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
- <parameter type-id='26a90f95' name='dst'/>
- <parameter type-id='80f4b756' name='src'/>
- <parameter type-id='b59d7dce' name='len'/>
+ <abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
+ <typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
+ <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
+ <class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='tm_min' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='tm_year' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='tm_zone' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
+ <qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/>
+ <pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/>
+ <qualified-type-def type-id='9f201474' restrict='yes' id='d6e2847c'/>
+ <qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/>
+ <pointer-type-def type-id='e824a34f' size-in-bits='64' id='d6ad37ff'/>
+ <qualified-type-def type-id='d6ad37ff' restrict='yes' id='f8c6051d'/>
+ <pointer-type-def type-id='c9d12d66' size-in-bits='64' id='b2eb2c3f'/>
+ <pointer-type-def type-id='dddf6ca2' size-in-bits='64' id='d915a820'/>
+ <qualified-type-def type-id='d915a820' restrict='yes' id='f099ad08'/>
+ <function-decl name='nl_langinfo' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='03b79a94'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='time' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b2eb2c3f'/>
+ <return type-id='c9d12d66'/>
+ </function-decl>
+ <function-decl name='strftime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f8c6051d'/>
<return type-id='b59d7dce'/>
</function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='timestamp.c' language='LANG_C99'>
+ <function-decl name='localtime_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='d6e2847c'/>
+ <parameter type-id='f099ad08'/>
+ <return type-id='d915a820'/>
+ </function-decl>
+ <function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='print_timestamp' mangled-name='print_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='print_timestamp'>
<parameter type-id='3502e3ff' name='timestamp_fmt'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='uu_alloc.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libuutil/uu_alloc.c' language='LANG_C99'>
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
+ <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
<type-decl name='variadic parameter type' id='2c1145c5'/>
<type-decl name='void' id='48b5725f'/>
+ <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
+ <function-decl name='uu_set_error' mangled-name='uu_set_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_set_error'>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='strnlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
<function-decl name='uu_zalloc' mangled-name='uu_zalloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_zalloc'>
<parameter type-id='b59d7dce' name='n'/>
<return type-id='eaa32e2f'/>
@@ -1151,13 +1140,16 @@
<return type-id='26a90f95'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='uu_avl.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libuutil/uu_avl.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='bf311473' size-in-bits='128' id='f0f65199'>
<subrange length='2' type-id='7359adad' id='52efc4ef'/>
</array-type-def>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='320' id='36c46961'>
<subrange length='40' type-id='7359adad' id='8f80b239'/>
</array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='512' id='59daf3ef'>
<subrange length='64' type-id='7359adad' id='b10be967'/>
</array-type-def>
@@ -1169,7 +1161,6 @@
<subrange length='3' type-id='7359adad' id='56f209d2'/>
</array-type-def>
<type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
- <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
<typedef-decl name='uu_compare_fn_t' type-id='add6e811' id='40f93560'/>
<typedef-decl name='uu_walk_fn_t' type-id='96ee24a5' id='9d1aa0dc'/>
<typedef-decl name='uu_avl_pool_t' type-id='12a530a8' id='7f84e390'/>
@@ -1204,16 +1195,16 @@
</class-decl>
<class-decl name='uu_avl' size-in-bits='960' is-struct='yes' visibility='default' id='4af029d1'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='ua_next_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ua_next' type-id='a5c21a38' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='ua_prev_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ua_prev' type-id='a5c21a38' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='ua_pool' type-id='de82c773' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='ua_parent_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ua_parent' type-id='eaa32e2f' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='ua_debug' type-id='b96825af' visibility='default'/>
@@ -1260,6 +1251,8 @@
<var-decl name='uap_null_avl' type-id='bb7f0973' visibility='default'/>
</data-member>
</class-decl>
+ <typedef-decl name='avl_tree_t' type-id='b351119f' id='f20fbd51'/>
+ <typedef-decl name='avl_index_t' type-id='e475ab95' id='fba6cb51'/>
<class-decl name='avl_node' size-in-bits='192' is-struct='yes' visibility='default' id='428b67b3'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='avl_child' type-id='f0f65199' visibility='default'/>
@@ -1287,6 +1280,15 @@
</class-decl>
<typedef-decl name='ulong_t' type-id='7359adad' id='ee1f298e'/>
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
+ <union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='8e0573fd' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/>
<union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'>
<data-member access='public'>
<var-decl name='__data' type-id='4c734837' visibility='default'/>
@@ -1341,8 +1343,14 @@
<typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
<typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
<pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
+ <pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
<pointer-type-def type-id='428b67b3' size-in-bits='64' id='bf311473'/>
+ <pointer-type-def type-id='b351119f' size-in-bits='64' id='716943c7'/>
+ <pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/>
+ <qualified-type-def type-id='8afd6070' const='yes' id='1d853360'/>
+ <pointer-type-def type-id='1d853360' size-in-bits='64' id='c2afbd7e'/>
<pointer-type-def type-id='96ee24a5' size-in-bits='64' id='585e1de9'/>
+ <pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/>
<pointer-type-def type-id='5d7f5fc8' size-in-bits='64' id='813a2225'/>
<pointer-type-def type-id='73a65116' size-in-bits='64' id='2dc35b9d'/>
<pointer-type-def type-id='7f84e390' size-in-bits='64' id='de82c773'/>
@@ -1351,6 +1359,96 @@
<pointer-type-def type-id='40f93560' size-in-bits='64' id='d502b39f'/>
<pointer-type-def type-id='9d1aa0dc' size-in-bits='64' id='30a42b6d'/>
<pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
+ <function-decl name='uu_check_name' mangled-name='uu_check_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_check_name'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='uu_panic' mangled-name='uu_panic' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_panic'>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_create' mangled-name='avl_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_create'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='585e1de9'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_find' mangled-name='avl_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_find'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='32adbf30'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_insert' mangled-name='avl_insert' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='fba6cb51'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_first' mangled-name='avl_first' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_first'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_last' mangled-name='avl_last' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_last'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_nearest' mangled-name='avl_nearest' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_nearest'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='fba6cb51'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_remove' mangled-name='avl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_remove'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='ee1f298e'/>
+ </function-decl>
+ <function-decl name='avl_destroy_nodes' mangled-name='avl_destroy_nodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy_nodes'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='63e171df'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_destroy' mangled-name='avl_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_walk' mangled-name='avl_walk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_walk'>
+ <parameter type-id='716943c7'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_init' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <parameter type-id='c2afbd7e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='uu_avl_pool_create' mangled-name='uu_avl_pool_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_avl_pool_create'>
<parameter type-id='80f4b756' name='name'/>
<parameter type-id='b59d7dce' name='objsize'/>
@@ -1466,6 +1564,11 @@
<function-decl name='uu_avl_release' mangled-name='uu_avl_release' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_avl_release'>
<return type-id='48b5725f'/>
</function-decl>
+ <function-type size-in-bits='64' id='96ee24a5'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
<function-type size-in-bits='64' id='add6e811'>
<parameter type-id='eaa32e2f'/>
<parameter type-id='eaa32e2f'/>
@@ -1473,15 +1576,14 @@
<return type-id='95e97e5e'/>
</function-type>
</abi-instr>
- <abi-instr address-size='64' path='uu_ident.c' language='LANG_C99'>
- <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
- <function-decl name='uu_check_name' mangled-name='uu_check_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_check_name'>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='3502e3ff' name='flags'/>
- <return type-id='95e97e5e'/>
+ <abi-instr address-size='64' path='lib/libuutil/uu_ident.c' language='LANG_C99'>
+ <function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='uu_list.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libuutil/uu_list.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='e475ab95' size-in-bits='128' id='d0e9cdae'>
<subrange length='2' type-id='7359adad' id='52efc4ef'/>
</array-type-def>
@@ -1526,16 +1628,16 @@
</class-decl>
<class-decl name='uu_list' size-in-bits='896' is-struct='yes' visibility='default' id='1d04bdf0'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='ul_next_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ul_next' type-id='0c0b229b' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='ul_prev_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ul_prev' type-id='0c0b229b' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='ul_pool' type-id='0941e04e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='ul_parent_enc' type-id='e475ab95' visibility='default'/>
+ <var-decl name='ul_parent' type-id='eaa32e2f' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='ul_offset' type-id='b59d7dce' visibility='default'/>
@@ -1726,25 +1828,16 @@
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='uu_misc.c' language='LANG_C99'>
- <function-decl name='uu_set_error' mangled-name='uu_set_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_set_error'>
- <parameter type-id='3502e3ff' name='code'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='uu_error' mangled-name='uu_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_error'>
- <return type-id='8f92235e'/>
- </function-decl>
- <function-decl name='uu_strerror' mangled-name='uu_strerror' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_strerror'>
- <parameter type-id='8f92235e' name='code'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='uu_panic' mangled-name='uu_panic' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_panic'>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
- <return type-id='48b5725f'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='uu_pname.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libuutil/uu_misc.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
+ <subrange length='1' type-id='7359adad' id='52f813b4'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
+ <subrange length='20' type-id='7359adad' id='fdca39cf'/>
+ </array-type-def>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
@@ -1759,65 +1852,179 @@
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
</data-member>
</class-decl>
+ <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/>
+ <typedef-decl name='pthread_key_t' type-id='f0981eeb' id='2de5383b'/>
+ <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
+ <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
+ <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
+ <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
+ <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='928'>
+ <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1040'>
+ <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1048'>
+ <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1152'>
+ <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1216'>
+ <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1280'>
+ <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1344'>
+ <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1408'>
+ <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1472'>
+ <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1536'>
+ <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1568'>
+ <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
+ <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
+ <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
+ <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
+ <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
+ <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
+ <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
+ <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
<pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
- <var-decl name='uu_exit_ok_value' type-id='95e97e5e' mangled-name='uu_exit_ok_value' visibility='default' elf-symbol-id='uu_exit_ok_value'/>
- <var-decl name='uu_exit_fatal_value' type-id='95e97e5e' mangled-name='uu_exit_fatal_value' visibility='default' elf-symbol-id='uu_exit_fatal_value'/>
- <var-decl name='uu_exit_usage_value' type-id='95e97e5e' mangled-name='uu_exit_usage_value' visibility='default' elf-symbol-id='uu_exit_usage_value'/>
- <function-decl name='uu_exit_ok' mangled-name='uu_exit_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_exit_ok'>
+ <pointer-type-def type-id='2de5383b' size-in-bits='64' id='ce04b822'/>
+ <pointer-type-def type-id='ee076206' size-in-bits='64' id='953b12f8'/>
+ <pointer-type-def type-id='c5c76c9c' size-in-bits='64' id='b7f9d8e6'/>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <function-decl name='__errno_location' visibility='default' binding='global' size-in-bits='64'>
<return type-id='7292109c'/>
</function-decl>
- <function-decl name='uu_exit_fatal' mangled-name='uu_exit_fatal' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_exit_fatal'>
- <return type-id='7292109c'/>
+ <function-decl name='dcgettext' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
</function-decl>
- <function-decl name='uu_exit_usage' mangled-name='uu_exit_usage' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_exit_usage'>
- <return type-id='7292109c'/>
+ <function-decl name='pthread_self' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='4051f5e7'/>
</function-decl>
- <function-decl name='uu_alt_exit' mangled-name='uu_alt_exit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_alt_exit'>
- <parameter type-id='95e97e5e' name='profile'/>
- <return type-id='48b5725f'/>
+ <function-decl name='pthread_key_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='ce04b822'/>
+ <parameter type-id='b7f9d8e6'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='uu_vwarn' mangled-name='uu_vwarn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_vwarn'>
- <parameter type-id='80f4b756' name='format'/>
- <parameter type-id='b7f2d5e6' name='alist'/>
- <return type-id='48b5725f'/>
+ <function-decl name='pthread_getspecific' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2de5383b'/>
+ <return type-id='eaa32e2f'/>
</function-decl>
- <function-decl name='uu_warn' mangled-name='uu_warn' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_warn'>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
- <return type-id='48b5725f'/>
+ <function-decl name='pthread_setspecific' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2de5383b'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='uu_vdie' mangled-name='uu_vdie' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_vdie'>
- <parameter type-id='80f4b756' name='format'/>
- <parameter type-id='b7f2d5e6' name='alist'/>
- <return type-id='48b5725f'/>
+ <function-decl name='pthread_atfork' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='953b12f8'/>
+ <parameter type-id='953b12f8'/>
+ <parameter type-id='953b12f8'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='uu_die' mangled-name='uu_die' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_die'>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
+ <function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='uu_vxdie' mangled-name='uu_vxdie' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_vxdie'>
- <parameter type-id='95e97e5e' name='status'/>
- <parameter type-id='80f4b756' name='format'/>
- <parameter type-id='b7f2d5e6' name='alist'/>
- <return type-id='48b5725f'/>
+ <function-decl name='pause' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='uu_xdie' mangled-name='uu_xdie' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_xdie'>
- <parameter type-id='95e97e5e' name='status'/>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
- <return type-id='48b5725f'/>
+ <function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b7f2d5e6'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='uu_setpname' mangled-name='uu_setpname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_setpname'>
- <parameter type-id='26a90f95' name='arg0'/>
- <return type-id='80f4b756'/>
+ <function-decl name='uu_error' mangled-name='uu_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_error'>
+ <return type-id='8f92235e'/>
</function-decl>
- <function-decl name='uu_getpname' mangled-name='uu_getpname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_getpname'>
+ <function-decl name='uu_strerror' mangled-name='uu_strerror' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_strerror'>
+ <parameter type-id='8f92235e' name='code'/>
<return type-id='80f4b756'/>
</function-decl>
+ <function-type size-in-bits='64' id='ee076206'>
+ <return type-id='48b5725f'/>
+ </function-type>
+ <function-type size-in-bits='64' id='c5c76c9c'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-type>
</abi-instr>
- <abi-instr address-size='64' path='uu_string.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libuutil/uu_string.c' language='LANG_C99'>
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
<enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'>
<underlying-type type-id='9cac1fee'/>
@@ -1825,6 +2032,22 @@
<enumerator name='B_TRUE' value='1'/>
</enum-decl>
<typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/>
+ <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strcasecmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='uu_streq' mangled-name='uu_streq' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='uu_streq'>
<parameter type-id='80f4b756' name='a'/>
<parameter type-id='80f4b756' name='b'/>
@@ -1841,4 +2064,50 @@
<return type-id='c19b74c3'/>
</function-decl>
</abi-instr>
+ <abi-instr address-size='64' path='module/avl/avl.c' language='LANG_C99'>
+ <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_insert_here' mangled-name='avl_insert_here' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert_here'>
+ <parameter type-id='a3681dea' name='tree'/>
+ <parameter type-id='eaa32e2f' name='new_data'/>
+ <parameter type-id='eaa32e2f' name='here'/>
+ <parameter type-id='95e97e5e' name='direction'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'>
+ <parameter type-id='a3681dea' name='tree'/>
+ <parameter type-id='eaa32e2f' name='new_node'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_update_lt' mangled-name='avl_update_lt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_lt'>
+ <parameter type-id='a3681dea' name='t'/>
+ <parameter type-id='eaa32e2f' name='obj'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='avl_update_gt' mangled-name='avl_update_gt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_gt'>
+ <parameter type-id='a3681dea' name='t'/>
+ <parameter type-id='eaa32e2f' name='obj'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='avl_update' mangled-name='avl_update' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update'>
+ <parameter type-id='a3681dea' name='t'/>
+ <parameter type-id='eaa32e2f' name='obj'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='avl_swap' mangled-name='avl_swap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_swap'>
+ <parameter type-id='a3681dea' name='tree1'/>
+ <parameter type-id='a3681dea' name='tree2'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_is_empty' mangled-name='avl_is_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_is_empty'>
+ <parameter type-id='a3681dea' name='tree'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ </abi-instr>
</abi-corpus>
diff --git a/lib/libuutil/uu_alloc.c b/lib/libuutil/uu_alloc.c
index 2bef759d525e..2850bf6d1b35 100644
--- a/lib/libuutil/uu_alloc.c
+++ b/lib/libuutil/uu_alloc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libuutil/uu_avl.c b/lib/libuutil/uu_avl.c
index 53def0e073fd..ef1497b31439 100644
--- a/lib/libuutil/uu_avl.c
+++ b/lib/libuutil/uu_avl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -97,8 +97,8 @@ uu_avl_pool_create(const char *name, size_t objsize, size_t nodeoffset,
(void) pthread_mutex_init(&pp->uap_lock, NULL);
- pp->uap_null_avl.ua_next_enc = UU_PTR_ENCODE(&pp->uap_null_avl);
- pp->uap_null_avl.ua_prev_enc = UU_PTR_ENCODE(&pp->uap_null_avl);
+ pp->uap_null_avl.ua_next = &pp->uap_null_avl;
+ pp->uap_null_avl.ua_prev = &pp->uap_null_avl;
(void) pthread_mutex_lock(&uu_apool_list_lock);
pp->uap_next = next = &uu_null_apool;
@@ -114,10 +114,8 @@ void
uu_avl_pool_destroy(uu_avl_pool_t *pp)
{
if (pp->uap_debug) {
- if (pp->uap_null_avl.ua_next_enc !=
- UU_PTR_ENCODE(&pp->uap_null_avl) ||
- pp->uap_null_avl.ua_prev_enc !=
- UU_PTR_ENCODE(&pp->uap_null_avl)) {
+ if (pp->uap_null_avl.ua_next != &pp->uap_null_avl ||
+ pp->uap_null_avl.ua_prev != &pp->uap_null_avl) {
uu_panic("uu_avl_pool_destroy: Pool \"%.*s\" (%p) has "
"outstanding avls, or is corrupt.\n",
(int)sizeof (pp->uap_name), pp->uap_name,
@@ -224,7 +222,7 @@ uu_avl_create(uu_avl_pool_t *pp, void *parent, uint32_t flags)
}
ap->ua_pool = pp;
- ap->ua_parent_enc = UU_PTR_ENCODE(parent);
+ ap->ua_parent = parent;
ap->ua_debug = pp->uap_debug || (flags & UU_AVL_DEBUG);
ap->ua_index = (pp->uap_last_index = INDEX_NEXT(pp->uap_last_index));
@@ -236,11 +234,11 @@ uu_avl_create(uu_avl_pool_t *pp, void *parent, uint32_t flags)
(void) pthread_mutex_lock(&pp->uap_lock);
next = &pp->uap_null_avl;
- prev = UU_PTR_DECODE(next->ua_prev_enc);
- ap->ua_next_enc = UU_PTR_ENCODE(next);
- ap->ua_prev_enc = UU_PTR_ENCODE(prev);
- next->ua_prev_enc = UU_PTR_ENCODE(ap);
- prev->ua_next_enc = UU_PTR_ENCODE(ap);
+ prev = next->ua_prev;
+ ap->ua_next = next;
+ ap->ua_prev = prev;
+ next->ua_prev = ap;
+ prev->ua_next = ap;
(void) pthread_mutex_unlock(&pp->uap_lock);
return (ap);
@@ -263,11 +261,11 @@ uu_avl_destroy(uu_avl_t *ap)
}
}
(void) pthread_mutex_lock(&pp->uap_lock);
- UU_AVL_PTR(ap->ua_next_enc)->ua_prev_enc = ap->ua_prev_enc;
- UU_AVL_PTR(ap->ua_prev_enc)->ua_next_enc = ap->ua_next_enc;
+ ap->ua_next->ua_prev = ap->ua_prev;
+ ap->ua_prev->ua_next = ap->ua_next;
(void) pthread_mutex_unlock(&pp->uap_lock);
- ap->ua_prev_enc = UU_PTR_ENCODE(NULL);
- ap->ua_next_enc = UU_PTR_ENCODE(NULL);
+ ap->ua_prev = NULL;
+ ap->ua_next = NULL;
ap->ua_pool = NULL;
avl_destroy(&ap->ua_tree);
diff --git a/lib/libuutil/uu_ident.c b/lib/libuutil/uu_ident.c
index 382139316ebc..d0cab0a64d09 100644
--- a/lib/libuutil/uu_ident.c
+++ b/lib/libuutil/uu_ident.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libuutil/uu_list.c b/lib/libuutil/uu_list.c
index c3a447d01de3..aa8b129cc22a 100644
--- a/lib/libuutil/uu_list.c
+++ b/lib/libuutil/uu_list.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -93,8 +93,8 @@ uu_list_pool_create(const char *name, size_t objsize,
(void) pthread_mutex_init(&pp->ulp_lock, NULL);
- pp->ulp_null_list.ul_next_enc = UU_PTR_ENCODE(&pp->ulp_null_list);
- pp->ulp_null_list.ul_prev_enc = UU_PTR_ENCODE(&pp->ulp_null_list);
+ pp->ulp_null_list.ul_next = &pp->ulp_null_list;
+ pp->ulp_null_list.ul_prev = &pp->ulp_null_list;
(void) pthread_mutex_lock(&uu_lpool_list_lock);
pp->ulp_next = next = &uu_null_lpool;
@@ -110,10 +110,8 @@ void
uu_list_pool_destroy(uu_list_pool_t *pp)
{
if (pp->ulp_debug) {
- if (pp->ulp_null_list.ul_next_enc !=
- UU_PTR_ENCODE(&pp->ulp_null_list) ||
- pp->ulp_null_list.ul_prev_enc !=
- UU_PTR_ENCODE(&pp->ulp_null_list)) {
+ if (pp->ulp_null_list.ul_next != &pp->ulp_null_list ||
+ pp->ulp_null_list.ul_prev != &pp->ulp_null_list) {
uu_panic("uu_list_pool_destroy: Pool \"%.*s\" (%p) has "
"outstanding lists, or is corrupt.\n",
(int)sizeof (pp->ulp_name), pp->ulp_name,
@@ -202,7 +200,7 @@ uu_list_create(uu_list_pool_t *pp, void *parent, uint32_t flags)
}
lp->ul_pool = pp;
- lp->ul_parent_enc = UU_PTR_ENCODE(parent);
+ lp->ul_parent = parent;
lp->ul_offset = pp->ulp_nodeoffset;
lp->ul_debug = pp->ulp_debug || (flags & UU_LIST_DEBUG);
lp->ul_sorted = (flags & UU_LIST_SORTED);
@@ -217,11 +215,11 @@ uu_list_create(uu_list_pool_t *pp, void *parent, uint32_t flags)
(void) pthread_mutex_lock(&pp->ulp_lock);
next = &pp->ulp_null_list;
- prev = UU_PTR_DECODE(next->ul_prev_enc);
- lp->ul_next_enc = UU_PTR_ENCODE(next);
- lp->ul_prev_enc = UU_PTR_ENCODE(prev);
- next->ul_prev_enc = UU_PTR_ENCODE(lp);
- prev->ul_next_enc = UU_PTR_ENCODE(lp);
+ prev = next->ul_prev;
+ lp->ul_next = next;
+ lp->ul_prev = prev;
+ next->ul_prev = lp;
+ prev->ul_next = lp;
(void) pthread_mutex_unlock(&pp->ulp_lock);
return (lp);
@@ -250,11 +248,11 @@ uu_list_destroy(uu_list_t *lp)
}
(void) pthread_mutex_lock(&pp->ulp_lock);
- UU_LIST_PTR(lp->ul_next_enc)->ul_prev_enc = lp->ul_prev_enc;
- UU_LIST_PTR(lp->ul_prev_enc)->ul_next_enc = lp->ul_next_enc;
+ lp->ul_next->ul_prev = lp->ul_prev;
+ lp->ul_prev->ul_next = lp->ul_next;
(void) pthread_mutex_unlock(&pp->ulp_lock);
- lp->ul_prev_enc = UU_PTR_ENCODE(NULL);
- lp->ul_next_enc = UU_PTR_ENCODE(NULL);
+ lp->ul_prev = NULL;
+ lp->ul_next = NULL;
lp->ul_pool = NULL;
uu_free(lp);
}
@@ -507,14 +505,20 @@ uu_list_walk(uu_list_t *lp, uu_walk_fn_t *func, void *private, uint32_t flags)
}
if (lp->ul_debug || robust) {
- uu_list_walk_t my_walk;
+ uu_list_walk_t *my_walk;
void *e;
- list_walk_init(&my_walk, lp, flags);
+ my_walk = uu_zalloc(sizeof (*my_walk));
+ if (my_walk == NULL)
+ return (-1);
+
+ list_walk_init(my_walk, lp, flags);
while (status == UU_WALK_NEXT &&
- (e = uu_list_walk_next(&my_walk)) != NULL)
+ (e = uu_list_walk_next(my_walk)) != NULL)
status = (*func)(e, private);
- list_walk_fini(&my_walk);
+ list_walk_fini(my_walk);
+
+ uu_free(my_walk);
} else {
if (!reverse) {
for (np = lp->ul_null_node.uln_next;
diff --git a/lib/libuutil/uu_misc.c b/lib/libuutil/uu_misc.c
index a8478ace9a73..762d00c3cd32 100644
--- a/lib/libuutil/uu_misc.c
+++ b/lib/libuutil/uu_misc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libuutil/uu_pname.c b/lib/libuutil/uu_pname.c
deleted file mode 100644
index 610b8585dcbf..000000000000
--- a/lib/libuutil/uu_pname.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-
-#include "libuutil_common.h"
-
-#include <libintl.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <wchar.h>
-#include <unistd.h>
-
-static const char *pname;
-
-static __attribute__((noreturn)) void
-uu_die_internal(int status, const char *format, va_list alist);
-
-int uu_exit_ok_value = EXIT_SUCCESS;
-int uu_exit_fatal_value = EXIT_FAILURE;
-int uu_exit_usage_value = 2;
-
-int *
-uu_exit_ok(void)
-{
- return (&uu_exit_ok_value);
-}
-
-int *
-uu_exit_fatal(void)
-{
- return (&uu_exit_fatal_value);
-}
-
-int *
-uu_exit_usage(void)
-{
- return (&uu_exit_usage_value);
-}
-
-void
-uu_alt_exit(int profile)
-{
- switch (profile) {
- case UU_PROFILE_DEFAULT:
- uu_exit_ok_value = EXIT_SUCCESS;
- uu_exit_fatal_value = EXIT_FAILURE;
- uu_exit_usage_value = 2;
- break;
- case UU_PROFILE_LAUNCHER:
- uu_exit_ok_value = EXIT_SUCCESS;
- uu_exit_fatal_value = 124;
- uu_exit_usage_value = 125;
- break;
- }
-}
-
-static __attribute__((format(printf, 2, 0))) void
-uu_warn_internal(int err, const char *format, va_list alist)
-{
- if (pname != NULL)
- (void) fprintf(stderr, "%s: ", pname);
-
- if (format != NULL)
- (void) vfprintf(stderr, format, alist);
-
- if (strrchr(format, '\n') == NULL)
- (void) fprintf(stderr, ": %s\n", strerror(err));
-}
-
-void
-uu_vwarn(const char *format, va_list alist)
-{
- uu_warn_internal(errno, format, alist);
-}
-
-void
-uu_warn(const char *format, ...)
-{
- va_list alist;
- va_start(alist, format);
- uu_warn_internal(errno, format, alist);
- va_end(alist);
-}
-
-static __attribute__((format(printf, 2, 0))) __attribute__((noreturn)) void
-uu_die_internal(int status, const char *format, va_list alist)
-{
- uu_warn_internal(errno, format, alist);
-#ifdef DEBUG
- {
- char *cp;
-
- if (!issetugid()) {
- cp = getenv("UU_DIE_ABORTS");
- if (cp != NULL && *cp != '\0')
- abort();
- }
- }
-#endif
- exit(status);
-}
-
-void
-uu_vdie(const char *format, va_list alist)
-{
- uu_die_internal(UU_EXIT_FATAL, format, alist);
-}
-
-void
-uu_die(const char *format, ...)
-{
- va_list alist;
- va_start(alist, format);
- uu_die_internal(UU_EXIT_FATAL, format, alist);
- va_end(alist);
-}
-
-void
-uu_vxdie(int status, const char *format, va_list alist)
-{
- uu_die_internal(status, format, alist);
-}
-
-void
-uu_xdie(int status, const char *format, ...)
-{
- va_list alist;
- va_start(alist, format);
- uu_die_internal(status, format, alist);
- va_end(alist);
-}
-
-const char *
-uu_setpname(char *arg0)
-{
- /*
- * Having a NULL argv[0], while uncommon, is possible. It
- * makes more sense to handle this event in uu_setpname rather
- * than in each of its consumers.
- */
- if (arg0 == NULL) {
- pname = getexecname();
- if (pname == NULL)
- pname = "unknown_command";
- return (pname);
- }
-
- /*
- * Guard against '/' at end of command invocation.
- */
- for (;;) {
- char *p = strrchr(arg0, '/');
- if (p == NULL) {
- pname = arg0;
- break;
- } else {
- if (*(p + 1) == '\0') {
- *p = '\0';
- continue;
- }
-
- pname = p + 1;
- break;
- }
- }
-
- return (pname);
-}
-
-const char *
-uu_getpname(void)
-{
- return (pname);
-}
diff --git a/lib/libuutil/uu_string.c b/lib/libuutil/uu_string.c
index 67024c3b50b4..eff0727b7564 100644
--- a/lib/libuutil/uu_string.c
+++ b/lib/libuutil/uu_string.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzdb/Makefile.am b/lib/libzdb/Makefile.am
new file mode 100644
index 000000000000..ec4fd92b984e
--- /dev/null
+++ b/lib/libzdb/Makefile.am
@@ -0,0 +1,7 @@
+libzdb_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
+libzdb_la_CFLAGS += -fvisibility=hidden
+
+noinst_LTLIBRARIES += libzdb.la
+
+libzdb_la_SOURCES = \
+ %D%/libzdb.c
diff --git a/lib/libzdb/libzdb.c b/lib/libzdb/libzdb.c
new file mode 100644
index 000000000000..12144dc65e75
--- /dev/null
+++ b/lib/libzdb/libzdb.c
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <openssl/evp.h>
+#include <sys/zfs_context.h>
+#include <sys/spa.h>
+#include <sys/spa_impl.h>
+#include <sys/dmu.h>
+#include <sys/zap.h>
+#include <sys/fs/zfs.h>
+#include <sys/zfs_znode.h>
+#include <sys/zfs_sa.h>
+#include <sys/sa.h>
+#include <sys/sa_impl.h>
+#include <sys/vdev.h>
+#include <sys/vdev_impl.h>
+#include <sys/metaslab_impl.h>
+#include <sys/dmu_objset.h>
+#include <sys/dsl_dir.h>
+#include <sys/dsl_dataset.h>
+#include <sys/dsl_pool.h>
+#include <sys/dsl_bookmark.h>
+#include <sys/dbuf.h>
+#include <sys/zil.h>
+#include <sys/zil_impl.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/dmu_send.h>
+#include <sys/dmu_traverse.h>
+#include <sys/zio_checksum.h>
+#include <sys/zio_compress.h>
+#include <sys/zfs_fuid.h>
+#include <sys/arc.h>
+#include <sys/arc_impl.h>
+#include <sys/ddt.h>
+#include <sys/zfeature.h>
+#include <sys/abd.h>
+#include <sys/blkptr.h>
+#include <sys/dsl_crypt.h>
+#include <sys/dsl_scan.h>
+#include <sys/btree.h>
+#include <sys/brt.h>
+#include <sys/brt_impl.h>
+#include <zfs_comutil.h>
+#include <sys/zstd/zstd.h>
+
+#include <libnvpair.h>
+#include <libzutil.h>
+
+#include <libzdb.h>
+
+const char *
+zdb_ot_name(dmu_object_type_t type)
+{
+ if (type < DMU_OT_NUMTYPES)
+ return (dmu_ot[type].ot_name);
+ else if ((type & DMU_OT_NEWTYPE) &&
+ ((type & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS))
+ return (dmu_ot_byteswap[type & DMU_OT_BYTESWAP_MASK].ob_name);
+ else
+ return ("UNKNOWN");
+}
+
+int
+livelist_compare(const void *larg, const void *rarg)
+{
+ const blkptr_t *l = larg;
+ const blkptr_t *r = rarg;
+
+ /* Sort them according to dva[0] */
+ uint64_t l_dva0_vdev, r_dva0_vdev;
+ l_dva0_vdev = DVA_GET_VDEV(&l->blk_dva[0]);
+ r_dva0_vdev = DVA_GET_VDEV(&r->blk_dva[0]);
+ if (l_dva0_vdev < r_dva0_vdev)
+ return (-1);
+ else if (l_dva0_vdev > r_dva0_vdev)
+ return (+1);
+
+ /* if vdevs are equal, sort by offsets. */
+ uint64_t l_dva0_offset;
+ uint64_t r_dva0_offset;
+ l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
+ r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
+ if (l_dva0_offset < r_dva0_offset) {
+ return (-1);
+ } else if (l_dva0_offset > r_dva0_offset) {
+ return (+1);
+ }
+
+ /*
+ * Since we're storing blkptrs without cancelling FREE/ALLOC pairs,
+ * it's possible the offsets are equal. In that case, sort by txg
+ */
+ if (BP_GET_LOGICAL_BIRTH(l) < BP_GET_LOGICAL_BIRTH(r)) {
+ return (-1);
+ } else if (BP_GET_LOGICAL_BIRTH(l) > BP_GET_LOGICAL_BIRTH(r)) {
+ return (+1);
+ }
+ return (0);
+}
diff --git a/lib/libzfs/Makefile.am b/lib/libzfs/Makefile.am
index f5eb84679204..5e74d908de3d 100644
--- a/lib/libzfs/Makefile.am
+++ b/lib/libzfs/Makefile.am
@@ -34,8 +34,6 @@ dist_libzfs_la_SOURCES += \
endif
nodist_libzfs_la_SOURCES = \
- module/icp/algs/sha2/sha2.c \
- \
module/zcommon/cityhash.c \
module/zcommon/zfeature_common.c \
module/zcommon/zfs_comutil.c \
@@ -52,7 +50,6 @@ nodist_libzfs_la_SOURCES = \
module/zcommon/zpool_prop.c \
module/zcommon/zprop_common.c
-
libzfs_la_LIBADD = \
libshare.la \
libzfs_core.la \
@@ -60,7 +57,7 @@ libzfs_la_LIBADD = \
libzutil.la \
libuutil.la
-libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL)
+libzfs_la_LIBADD += -lrt -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL)
libzfs_la_LDFLAGS = -pthread
diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi
index fb5e01b82c40..2bbaae6345ab 100644
--- a/lib/libzfs/libzfs.abi
+++ b/lib/libzfs/libzfs.abi
@@ -3,15 +3,12 @@
<dependency name='libzfs_core.so.3'/>
<dependency name='libnvpair.so.3'/>
<dependency name='libuuid.so.1'/>
- <dependency name='librt.so.1'/>
<dependency name='libblkid.so.1'/>
<dependency name='libudev.so.1'/>
<dependency name='libuutil.so.3'/>
<dependency name='libm.so.6'/>
- <dependency name='libcrypto.so.1.1'/>
+ <dependency name='libcrypto.so.3'/>
<dependency name='libz.so.1'/>
- <dependency name='libdl.so.2'/>
- <dependency name='libpthread.so.0'/>
<dependency name='libc.so.6'/>
<dependency name='ld-linux-x86-64.so.2'/>
</elf-needed>
@@ -182,6 +179,7 @@
<elf-symbol name='fletcher_4_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fletcher_4_native_varsize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fletcher_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fsleep' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='get_dataset_depth' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='get_system_hostid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -191,6 +189,7 @@
<elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='is_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='is_mpath_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='libpc_error_description' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_add_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -234,6 +233,7 @@
<elf-symbol name='membar_enter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_exit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_producer' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='membar_sync' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='mkdirp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='mountpoint_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='permset_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -245,6 +245,7 @@
<elf-symbol name='sa_enable_share' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='sa_errorstr' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='sa_is_shared' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='sa_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='sa_validate_shareopts' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='snapshot_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -260,6 +261,8 @@
<elf-symbol name='tpool_suspended' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='tpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='update_vdev_config_dev_strs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='update_vdev_config_dev_sysfs_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='vdev_expand_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='vdev_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='vdev_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -338,14 +341,21 @@
<elf-symbol name='zfs_is_shared' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_isnumber' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_bookmarks' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_bookmarks_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_children' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_children_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_dependents' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_dependents_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_filesystems' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_filesystems_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_root' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_snapshots' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_snapshots_sorted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_snapshots_sorted_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_snapshots_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_iter_snapspec' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_iter_snapspec_v2' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_mod_supported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_mount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_mount_at' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -388,6 +398,7 @@
<elf-symbol name='zfs_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_prop_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_prop_set_list' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_prop_set_list_flags' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_prop_setonce' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -413,6 +424,8 @@
<elf-symbol name='zfs_send_resume_token_to_nvlist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_send_saved' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_set_fsacl' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_setproctitle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_setproctitle_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_share' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_show_diffs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_smb_acl_add' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -428,6 +441,7 @@
<elf-symbol name='zfs_strcmp_pathname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zfs_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_type_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_unmount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_unmountall' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -453,6 +467,7 @@
<elf-symbol name='zpool_disable_datasets_os' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_disable_volume_os' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_discard_checkpoint' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_disk_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_dump_ddt' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_enable_datasets' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_events_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -476,14 +491,15 @@
<elf-symbol name='zpool_get_history' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_load_policy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='zpool_get_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_prop_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_state_str' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_get_userprop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_vdev_prop_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_getenv_int' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_history_unpack' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_import_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -503,6 +519,8 @@
<elf-symbol name='zpool_open' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_open_canfail' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_pool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_prepare_and_label_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_prepare_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_print_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -549,6 +567,10 @@
<elf-symbol name='zpool_vdev_path_to_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_remove' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_remove_cancel' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_vdev_remove_wanted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_vdev_script_alloc_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_vdev_script_free_env' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_vdev_set_removed_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_split' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_wait_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -575,16 +597,16 @@
<elf-variable-symbols>
<elf-symbol name='efi_debug' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fletcher_4_abd_ops' size='24' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_avx2_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_avx512bw_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_avx512f_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_sse2_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_ssse3_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_superscalar4_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='fletcher_4_superscalar_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_avx2_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_avx512bw_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_avx512f_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_sse2_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_ssse3_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_superscalar4_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='spa_feature_table' size='2072' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='spa_feature_table' size='2296' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_deleg_perm_tab' size='512' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -592,188 +614,61 @@
<elf-symbol name='zfs_userquota_prop_prefixes' size='96' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
<abi-instr address-size='64' path='lib/libefi/rdwr_efi.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='288' id='16e6f2c6'>
- <subrange length='36' type-id='7359adad' id='ae666bde'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a65ae39c' size-in-bits='960' id='fa198beb'>
- <subrange length='1' type-id='7359adad' id='52f813b4'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='b96825af' size-in-bits='48' id='0f562bd0'>
- <subrange length='6' type-id='7359adad' id='52fa524b'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='384' id='dba89ba3'>
- <subrange length='12' type-id='7359adad' id='84827bdc'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='256' id='01d84ed4'>
- <subrange length='8' type-id='7359adad' id='56e0c0b1'/>
- </array-type-def>
- <class-decl name='dk_part' size-in-bits='960' is-struct='yes' visibility='default' id='a65ae39c'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='p_start' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='p_size' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='p_guid' type-id='214f32ea' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='p_tag' type-id='d908a348' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='272'>
- <var-decl name='p_flag' type-id='d908a348' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='288'>
- <var-decl name='p_name' type-id='16e6f2c6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='p_uguid' type-id='214f32ea' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='p_resv' type-id='01d84ed4' visibility='default'/>
- </data-member>
- </class-decl>
- <class-decl name='dk_gpt' size-in-bits='1920' is-struct='yes' visibility='default' id='dd4a2e5a'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='efi_version' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32'>
- <var-decl name='efi_nparts' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='efi_part_size' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='96'>
- <var-decl name='efi_lbasize' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='efi_last_lba' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='efi_first_u_lba' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='efi_last_u_lba' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='efi_disk_uguid' type-id='214f32ea' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='efi_flags' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='480'>
- <var-decl name='efi_reserved1' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='efi_altern_lba' type-id='804dc465' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='efi_reserved' type-id='dba89ba3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='efi_parts' type-id='fa198beb' visibility='default'/>
- </data-member>
- </class-decl>
- <class-decl name='uuid' size-in-bits='128' is-struct='yes' visibility='default' id='214f32ea'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='time_low' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32'>
- <var-decl name='time_mid' type-id='149c6638' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='48'>
- <var-decl name='time_hi_and_version' type-id='149c6638' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='clock_seq_hi_and_reserved' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='72'>
- <var-decl name='clock_seq_low' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='80'>
- <var-decl name='node_addr' type-id='0f562bd0' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='ushort_t' type-id='8efea9e5' id='d908a348'/>
- <pointer-type-def type-id='dd4a2e5a' size-in-bits='64' id='0d8119a8'/>
- <pointer-type-def type-id='0d8119a8' size-in-bits='64' id='c43b27a6'/>
+ <typedef-decl name='uInt' type-id='f0981eeb' id='09110a74'/>
<var-decl name='efi_debug' type-id='95e97e5e' mangled-name='efi_debug' visibility='default' elf-symbol-id='efi_debug'/>
- <function-decl name='efi_alloc_and_init' mangled-name='efi_alloc_and_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_init'>
- <parameter type-id='95e97e5e' name='fd'/>
- <parameter type-id='8f92235e' name='nparts'/>
- <parameter type-id='c43b27a6' name='vtoc'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='efi_alloc_and_read' mangled-name='efi_alloc_and_read' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_read'>
- <parameter type-id='95e97e5e' name='fd'/>
- <parameter type-id='c43b27a6' name='vtoc'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='efi_rescan' mangled-name='efi_rescan' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_rescan'>
- <parameter type-id='95e97e5e' name='fd'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='efi_use_whole_disk' mangled-name='efi_use_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_use_whole_disk'>
- <parameter type-id='95e97e5e' name='fd'/>
- <return type-id='95e97e5e'/>
+ <function-decl name='uuid_generate' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='cf536864'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='efi_write' mangled-name='efi_write' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_write'>
- <parameter type-id='95e97e5e' name='fd'/>
- <parameter type-id='0d8119a8' name='vtoc'/>
+ <function-decl name='uuid_is_null' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='354f7eb9'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='efi_free' mangled-name='efi_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_free'>
- <parameter type-id='0d8119a8' name='ptr'/>
- <return type-id='48b5725f'/>
+ <function-decl name='crc32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5bbcce85'/>
+ <parameter type-id='e8cb3e0e'/>
+ <parameter type-id='09110a74'/>
+ <return type-id='5bbcce85'/>
</function-decl>
<function-decl name='efi_err_check' mangled-name='efi_err_check' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_err_check'>
<parameter type-id='0d8119a8' name='vtoc'/>
<return type-id='48b5725f'/>
</function-decl>
- <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
- <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
</abi-instr>
<abi-instr address-size='64' path='lib/libshare/libshare.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='128' id='2d6895a3'>
<subrange length='2' type-id='7359adad' id='52efc4ef'/>
</array-type-def>
<var-decl name='sa_protocol_names' type-id='2d6895a3' mangled-name='sa_protocol_names' visibility='default' elf-symbol-id='sa_protocol_names'/>
- <function-decl name='sa_enable_share' mangled-name='sa_enable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_enable_share'>
- <parameter type-id='80f4b756' name='zfsname'/>
- <parameter type-id='80f4b756' name='mountpoint'/>
- <parameter type-id='80f4b756' name='shareopts'/>
- <parameter type-id='9155d4b5' name='protocol'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='sa_disable_share' mangled-name='sa_disable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_disable_share'>
- <parameter type-id='80f4b756' name='mountpoint'/>
- <parameter type-id='9155d4b5' name='protocol'/>
+ <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libshare/nfs.c' language='LANG_C99'>
+ <function-decl name='rename' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='sa_is_shared' mangled-name='sa_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_is_shared'>
- <parameter type-id='80f4b756' name='mountpoint'/>
- <parameter type-id='9155d4b5' name='protocol'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='memchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
</function-decl>
- <function-decl name='sa_commit_shares' mangled-name='sa_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_commit_shares'>
- <parameter type-id='9155d4b5' name='protocol'/>
- <return type-id='48b5725f'/>
+ <function-decl name='flock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='sa_validate_shareopts' mangled-name='sa_validate_shareopts' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_validate_shareopts'>
- <parameter type-id='80f4b756' name='options'/>
- <parameter type-id='9155d4b5' name='protocol'/>
+ <function-decl name='fchmod' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='e1c52942'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='sa_errorstr' mangled-name='sa_errorstr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_errorstr'>
- <parameter type-id='95e97e5e' name='err'/>
- <return type-id='80f4b756'/>
+ <function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='e1c52942'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <enum-decl name='sa_protocol' id='9155d4b5'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='SA_PROTOCOL_NFS' value='0'/>
- <enumerator name='SA_PROTOCOL_SMB' value='1'/>
- <enumerator name='SA_PROTOCOL_COUNT' value='2'/>
- </enum-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libshare/os/linux/nfs.c' language='LANG_C99'>
<class-decl name='sa_share_impl' size-in-bits='192' is-struct='yes' visibility='default' id='72b09bf8'>
@@ -788,7 +683,7 @@
</data-member>
</class-decl>
<typedef-decl name='sa_share_impl_t' type-id='946a2c6b' id='a48b47d0'/>
- <class-decl name='sa_fstype_t' size-in-bits='320' is-struct='yes' naming-typedef-id='639af739' visibility='default' id='944afa86'>
+ <class-decl name='sa_fstype_t' size-in-bits='384' is-struct='yes' naming-typedef-id='639af739' visibility='default' id='944afa86'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='enable_share' type-id='2f78a9c1' visibility='default'/>
</data-member>
@@ -804,6 +699,9 @@
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='commit_shares' type-id='797ee7da' visibility='default'/>
</data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='truncate_shares' type-id='5d51038b' visibility='default'/>
+ </data-member>
</class-decl>
<typedef-decl name='sa_fstype_t' type-id='944afa86' id='639af739'/>
<qualified-type-def type-id='639af739' const='yes' id='d19dbca9'/>
@@ -815,9 +713,35 @@
<qualified-type-def type-id='70487b28' const='yes' id='f194a8fb'/>
<pointer-type-def type-id='c13578bc' size-in-bits='64' id='fa1f29ce'/>
<qualified-type-def type-id='fa1f29ce' const='yes' id='2f78a9c1'/>
+ <pointer-type-def type-id='723e6cf2' size-in-bits='64' id='1d99e49c'/>
<pointer-type-def type-id='86373eb1' size-in-bits='64' id='f337456d'/>
<qualified-type-def type-id='f337456d' const='yes' id='81020bc2'/>
+ <qualified-type-def type-id='953b12f8' const='yes' id='5d51038b'/>
<var-decl name='libshare_nfs_type' type-id='d19dbca9' visibility='default'/>
+ <function-decl name='nfs_escape_mountpoint' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9b23c9ad'/>
+ <parameter type-id='37e3bd22'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nfs_is_shared_impl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a48b47d0'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nfs_toggle_share' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a48b47d0'/>
+ <parameter type-id='1d99e49c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nfs_reset_shares' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-type size-in-bits='64' id='276427e1'>
<return type-id='95e97e5e'/>
</function-type>
@@ -829,47 +753,44 @@
<parameter type-id='a48b47d0'/>
<return type-id='95e97e5e'/>
</function-type>
+ <function-type size-in-bits='64' id='723e6cf2'>
+ <parameter type-id='a48b47d0'/>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
<function-type size-in-bits='64' id='86373eb1'>
<parameter type-id='a48b47d0'/>
<return type-id='c19b74c3'/>
</function-type>
+ <function-type size-in-bits='64' id='ee076206'>
+ <return type-id='48b5725f'/>
+ </function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libshare/os/linux/smb.c' language='LANG_C99'>
<var-decl name='libshare_smb_type' type-id='d19dbca9' visibility='default'/>
+ <function-decl name='__fgets_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='e75a27e9'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
- <parameter type-id='80f4b756' name='file'/>
- <parameter type-id='80f4b756' name='func'/>
- <parameter type-id='95e97e5e' name='line'/>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
- <return type-id='48b5725f'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/atomic.c' language='LANG_C99'>
- <type-decl name='signed char' size-in-bits='8' id='28577a57'/>
- <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
<typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
- <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
- <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
<typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
- <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
- <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
<qualified-type-def type-id='149c6638' volatile='yes' id='5120c5f7'/>
<pointer-type-def type-id='5120c5f7' size-in-bits='64' id='93977ae7'/>
- <qualified-type-def type-id='8f92235e' volatile='yes' id='430e0681'/>
- <pointer-type-def type-id='430e0681' size-in-bits='64' id='3a147f31'/>
<qualified-type-def type-id='b96825af' volatile='yes' id='84ff7d66'/>
<pointer-type-def type-id='84ff7d66' size-in-bits='64' id='aa323ea4'/>
<qualified-type-def type-id='ee1f298e' volatile='yes' id='6f7e09cb'/>
<pointer-type-def type-id='6f7e09cb' size-in-bits='64' id='64698d33'/>
- <qualified-type-def type-id='48b5725f' volatile='yes' id='b0b3cbf9'/>
- <pointer-type-def type-id='b0b3cbf9' size-in-bits='64' id='fe09dd29'/>
<function-decl name='atomic_inc_8' mangled-name='atomic_inc_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_inc_8'>
<parameter type-id='aa323ea4' name='target'/>
<return type-id='48b5725f'/>
@@ -922,11 +843,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_add_long' mangled-name='atomic_add_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'>
<parameter type-id='fe09dd29' name='target'/>
<parameter type-id='79a0948f' name='bits'/>
@@ -947,11 +863,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_sub_long' mangled-name='atomic_sub_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_or_8' mangled-name='atomic_or_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8'>
<parameter type-id='aa323ea4' name='target'/>
<parameter type-id='b96825af' name='bits'/>
@@ -1154,11 +1065,6 @@
<parameter type-id='149c6638' name='bits'/>
<return type-id='149c6638'/>
</function-decl>
- <function-decl name='atomic_swap_32' mangled-name='atomic_swap_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_32'>
- <parameter type-id='3a147f31' name='target'/>
- <parameter type-id='8f92235e' name='bits'/>
- <return type-id='8f92235e'/>
- </function-decl>
<function-decl name='atomic_swap_ulong' mangled-name='atomic_swap_ulong' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_ulong'>
<parameter type-id='64698d33' name='target'/>
<parameter type-id='ee1f298e' name='bits'/>
@@ -1182,9 +1088,6 @@
<function-decl name='membar_enter' mangled-name='membar_enter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_enter'>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='membar_producer' mangled-name='membar_producer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_producer'>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='membar_consumer' mangled-name='membar_consumer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_consumer'>
<return type-id='48b5725f'/>
</function-decl>
@@ -1193,6 +1096,10 @@
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
</function-decl>
+ <function-decl name='getexecname_impl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/list.c' language='LANG_C99'>
<typedef-decl name='list_node_t' type-id='b0b5e45e' id='b21843b2'/>
@@ -1205,14 +1112,11 @@
<var-decl name='prev' type-id='b03eadb4' visibility='default'/>
</data-member>
</class-decl>
- <class-decl name='list' size-in-bits='256' is-struct='yes' visibility='default' id='e824dae9'>
+ <class-decl name='list' size-in-bits='192' is-struct='yes' visibility='default' id='e824dae9'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='list_size' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_offset' type-id='b59d7dce' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='128'>
+ <data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_head' type-id='b0b5e45e' visibility='default'/>
</data-member>
</class-decl>
@@ -1306,292 +1210,96 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/mkdirp.c' language='LANG_C99'>
- <typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
- <function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'>
- <parameter type-id='80f4b756' name='d'/>
- <parameter type-id='d50d396c' name='mode'/>
- <return type-id='95e97e5e'/>
+ <typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/>
+ <qualified-type-def type-id='928221d2' const='yes' id='effb3702'/>
+ <pointer-type-def type-id='effb3702' size-in-bits='64' id='f077d3f8'/>
+ <qualified-type-def type-id='f077d3f8' restrict='yes' id='598aab80'/>
+ <pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/>
+ <qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/>
+ <function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f1358bc3'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
</function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
- <function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
- <return type-id='7359adad'/>
+ <function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='598aab80'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
- <subrange length='3' type-id='7359adad' id='56f209d2'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
- <subrange length='1' type-id='7359adad' id='52f813b4'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
- <subrange length='20' type-id='7359adad' id='fdca39cf'/>
- </array-type-def>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
- <class-decl name='extmnttab' size-in-bits='320' is-struct='yes' visibility='default' id='0c544dc0'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='mnt_major' type-id='3502e3ff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='288'>
- <var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
- </data-member>
- </class-decl>
- <class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='st_ino' type-id='71288a47' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='224'>
- <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='288'>
- <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='st_size' type-id='79989e9c' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='st_blocks' type-id='4e711bf1' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='832'>
- <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
- <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
- <typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
- <typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
- <typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
- <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
- <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
- <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
- <typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
- <typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
- <typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
- <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
- <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
- <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='640'>
- <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='768'>
- <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='832'>
- <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='896'>
- <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='928'>
- <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1024'>
- <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1040'>
- <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1048'>
- <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1088'>
- <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1152'>
- <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1216'>
- <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1280'>
- <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1344'>
- <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1408'>
- <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1472'>
- <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1536'>
- <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1568'>
- <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
- </data-member>
- </class-decl>
- <class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
- </data-member>
- </class-decl>
- <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
- <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
- <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
- <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
- <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
- <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
- <pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
- <pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
- <function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'>
- <parameter type-id='822cd80b' name='fp'/>
- <parameter type-id='9d424d31' name='mgetp'/>
- <parameter type-id='9d424d31' name='mrefp'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'>
- <parameter type-id='822cd80b' name='fp'/>
- <parameter type-id='9d424d31' name='mgetp'/>
- <return type-id='95e97e5e'/>
+ <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
+ <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
+ <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='3cad23cd'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='b6b61d2f'/>
</function-decl>
- <function-decl name='getextmntent' mangled-name='getextmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getextmntent'>
- <parameter type-id='80f4b756' name='path'/>
- <parameter type-id='394fc496' name='entry'/>
- <parameter type-id='62f7a03d' name='statbuf'/>
+ <function-decl name='feof' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='lib/libspl/os/linux/zone.c' language='LANG_C99'>
- <typedef-decl name='zoneid_t' type-id='3502e3ff' id='4da03624'/>
- <function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'>
- <return type-id='4da03624'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libspl/page.c' language='LANG_C99'>
- <function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
- <return type-id='b59d7dce'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libspl/strlcat.c' language='LANG_C99'>
- <function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'>
- <parameter type-id='26a90f95' name='dst'/>
- <parameter type-id='80f4b756' name='src'/>
- <parameter type-id='b59d7dce' name='dstsize'/>
- <return type-id='b59d7dce'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libspl/strlcpy.c' language='LANG_C99'>
- <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
- <parameter type-id='26a90f95' name='dst'/>
- <parameter type-id='80f4b756' name='src'/>
- <parameter type-id='b59d7dce' name='len'/>
- <return type-id='b59d7dce'/>
- </function-decl>
- </abi-instr>
<abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
+ <typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
+ <function-decl name='nl_langinfo' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='03b79a94'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
<function-decl name='print_timestamp' mangled-name='print_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='print_timestamp'>
<parameter type-id='3502e3ff' name='timestamp_fmt'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libtpool/thread_pool.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='49ef3ffd' size-in-bits='1024' id='a14403f5'>
+ <subrange length='16' type-id='7359adad' id='848d0938'/>
+ </array-type-def>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='384' id='36d7f119'>
<subrange length='48' type-id='7359adad' id='8f6d2a81'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'>
- <subrange length='56' type-id='7359adad' id='f8137894'/>
- </array-type-def>
- <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
<array-type-def dimensions='1' type-id='f0981eeb' size-in-bits='64' id='0d532ec1'>
<subrange length='2' type-id='7359adad' id='52efc4ef'/>
</array-type-def>
- <typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/>
- <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/>
- <union-decl name='pthread_attr_t' size-in-bits='448' visibility='default' id='b63afacd'>
+ <union-decl name='__atomic_wide_counter' size-in-bits='64' naming-typedef-id='f3b40860' visibility='default' id='613ce450'>
<data-member access='public'>
- <var-decl name='__size' type-id='6093ff7c' visibility='default'/>
+ <var-decl name='__value64' type-id='3a47d82b' visibility='default'/>
</data-member>
<data-member access='public'>
- <var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
+ <var-decl name='__value32' type-id='e7f43f72' visibility='default'/>
</data-member>
</union-decl>
- <typedef-decl name='pthread_attr_t' type-id='b63afacd' id='7d8569fd'/>
+ <class-decl name='__anonymous_struct__' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__low' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='__high' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__atomic_wide_counter' type-id='613ce450' id='f3b40860'/>
+ <typedef-decl name='__cpu_mask' type-id='7359adad' id='49ef3ffd'/>
+ <class-decl name='cpu_set_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='8037c762' visibility='default' id='1f20d231'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__bits' type-id='a14403f5' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='cpu_set_t' type-id='1f20d231' id='8037c762'/>
+ <union-decl name='pthread_condattr_t' size-in-bits='32' naming-typedef-id='836265dd' visibility='default' id='33dd3aad'>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='8e0573fd' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_condattr_t' type-id='33dd3aad' id='836265dd'/>
<union-decl name='pthread_cond_t' size-in-bits='384' naming-typedef-id='62fab762' visibility='default' id='cbb12c12'>
<data-member access='public'>
<var-decl name='__data' type-id='c987b47c' visibility='default'/>
@@ -1606,10 +1314,10 @@
<typedef-decl name='pthread_cond_t' type-id='cbb12c12' id='62fab762'/>
<class-decl name='__pthread_cond_s' size-in-bits='384' is-struct='yes' visibility='default' id='c987b47c'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='' type-id='ac5ab595' visibility='default'/>
+ <var-decl name='__wseq' type-id='f3b40860' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='' type-id='ac5ab596' visibility='default'/>
+ <var-decl name='__g1_start' type-id='f3b40860' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='__g_refs' type-id='0d532ec1' visibility='default'/>
@@ -1627,30 +1335,11 @@
<var-decl name='__g_signals' type-id='0d532ec1' visibility='default'/>
</data-member>
</class-decl>
- <union-decl name='__anonymous_union__1' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab595'>
- <data-member access='public'>
- <var-decl name='__wseq' type-id='3a47d82b' visibility='default'/>
- </data-member>
- <data-member access='public'>
- <var-decl name='__wseq32' type-id='e7f43f72' visibility='default'/>
- </data-member>
- </union-decl>
- <class-decl name='__anonymous_struct__' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
+ <class-decl name='sched_param' size-in-bits='32' is-struct='yes' visibility='default' id='0897719a'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='__low' type-id='f0981eeb' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32'>
- <var-decl name='__high' type-id='f0981eeb' visibility='default'/>
+ <var-decl name='sched_priority' type-id='95e97e5e' visibility='default'/>
</data-member>
</class-decl>
- <union-decl name='__anonymous_union__2' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab596'>
- <data-member access='public'>
- <var-decl name='__g1_start' type-id='3a47d82b' visibility='default'/>
- </data-member>
- <data-member access='public'>
- <var-decl name='__g1_start32' type-id='e7f43f72' visibility='default'/>
- </data-member>
- </union-decl>
<typedef-decl name='tpool_job_t' type-id='3b8579e5' id='66a0afc9'/>
<class-decl name='tpool_job' size-in-bits='192' is-struct='yes' visibility='default' id='3b8579e5'>
<data-member access='public' layout-offset-in-bits='0'>
@@ -1672,6 +1361,185 @@
<var-decl name='tpa_tid' type-id='4051f5e7' visibility='default'/>
</data-member>
</class-decl>
+ <qualified-type-def type-id='8037c762' const='yes' id='f50ea9b2'/>
+ <pointer-type-def type-id='f50ea9b2' size-in-bits='64' id='5e14fa48'/>
+ <qualified-type-def type-id='836265dd' const='yes' id='7d24c58d'/>
+ <pointer-type-def type-id='7d24c58d' size-in-bits='64' id='a7e325e5'/>
+ <qualified-type-def type-id='a7e325e5' restrict='yes' id='4c428e67'/>
+ <qualified-type-def type-id='0897719a' const='yes' id='c4a7b189'/>
+ <pointer-type-def type-id='c4a7b189' size-in-bits='64' id='36fca399'/>
+ <qualified-type-def type-id='36fca399' restrict='yes' id='37e4897b'/>
+ <qualified-type-def type-id='e05e8614' restrict='yes' id='0be2e71c'/>
+ <pointer-type-def type-id='8037c762' size-in-bits='64' id='d74a6869'/>
+ <qualified-type-def type-id='7292109c' restrict='yes' id='6942f6a4'/>
+ <qualified-type-def type-id='7347a39e' restrict='yes' id='578ba182'/>
+ <pointer-type-def type-id='62fab762' size-in-bits='64' id='db285b03'/>
+ <qualified-type-def type-id='db285b03' restrict='yes' id='2a468b41'/>
+ <qualified-type-def type-id='18c91f9e' restrict='yes' id='6e745582'/>
+ <pointer-type-def type-id='0897719a' size-in-bits='64' id='23cbcb08'/>
+ <qualified-type-def type-id='23cbcb08' restrict='yes' id='b09b2050'/>
+ <pointer-type-def type-id='6fcda10e' size-in-bits='64' id='ad33e5e7'/>
+ <pointer-type-def type-id='66a0afc9' size-in-bits='64' id='f32b30e4'/>
+ <qualified-type-def type-id='63e171df' restrict='yes' id='9e7a3a7d'/>
+ <function-decl name='pthread_self' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='4051f5e7'/>
+ </function-decl>
+ <function-decl name='pthread_attr_init' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getdetachstate' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='540db505'/>
+ <parameter type-id='7292109c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setdetachstate' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getguardsize' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='540db505'/>
+ <parameter type-id='78c01427'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setguardsize' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getschedparam' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='b09b2050'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setschedparam' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='578ba182'/>
+ <parameter type-id='37e4897b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getschedpolicy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='6942f6a4'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setschedpolicy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getinheritsched' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='6942f6a4'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setinheritsched' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getscope' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='6942f6a4'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setscope' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getstack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='9e7a3a7d'/>
+ <parameter type-id='d19b2c25'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setstack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_setaffinity_np' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7347a39e'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='5e14fa48'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_attr_getaffinity_np' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='540db505'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='d74a6869'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_setcancelstate' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7292109c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_setcanceltype' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7292109c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__pthread_unregister_cancel' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='ba7c727c'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='pthread_cond_init' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2a468b41'/>
+ <parameter type-id='4c428e67'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_cond_signal' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='db285b03'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_cond_broadcast' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='db285b03'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_cond_wait' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2a468b41'/>
+ <parameter type-id='6e745582'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_cond_timedwait' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2a468b41'/>
+ <parameter type-id='6e745582'/>
+ <parameter type-id='0be2e71c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__sysconf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
+ <function-decl name='tpool_abandon' mangled-name='tpool_abandon' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_abandon'>
+ <parameter type-id='9cf59a50' name='tpool'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='tpool_suspend' mangled-name='tpool_suspend' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspend'>
+ <parameter type-id='9cf59a50' name='tpool'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='tpool_suspended' mangled-name='tpool_suspended' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspended'>
+ <parameter type-id='9cf59a50' name='tpool'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='tpool_resume' mangled-name='tpool_resume' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_resume'>
+ <parameter type-id='9cf59a50' name='tpool'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='tpool_member' mangled-name='tpool_member' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_member'>
+ <parameter type-id='9cf59a50' name='tpool'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <pointer-type-def type-id='b1bbf10d' size-in-bits='64' id='9cf59a50'/>
+ <typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/>
<class-decl name='tpool' size-in-bits='2496' is-struct='yes' visibility='default' id='88d1b7f9'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tp_forw' type-id='9cf59a50' visibility='default'/>
@@ -1725,61 +1593,12 @@
<var-decl name='tp_idle' type-id='95e97e5e' visibility='default'/>
</data-member>
</class-decl>
- <pointer-type-def type-id='7d8569fd' size-in-bits='64' id='7347a39e'/>
- <pointer-type-def type-id='6fcda10e' size-in-bits='64' id='ad33e5e7'/>
- <pointer-type-def type-id='66a0afc9' size-in-bits='64' id='f32b30e4'/>
- <pointer-type-def type-id='b1bbf10d' size-in-bits='64' id='9cf59a50'/>
- <pointer-type-def type-id='c5c76c9c' size-in-bits='64' id='b7f9d8e6'/>
- <function-decl name='tpool_create' mangled-name='tpool_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_create'>
- <parameter type-id='3502e3ff' name='min_threads'/>
- <parameter type-id='3502e3ff' name='max_threads'/>
- <parameter type-id='3502e3ff' name='linger'/>
- <parameter type-id='7347a39e' name='attr'/>
- <return type-id='9cf59a50'/>
- </function-decl>
- <function-decl name='tpool_dispatch' mangled-name='tpool_dispatch' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_dispatch'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <parameter type-id='b7f9d8e6' name='func'/>
- <parameter type-id='eaa32e2f' name='arg'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='tpool_destroy' mangled-name='tpool_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_destroy'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='tpool_abandon' mangled-name='tpool_abandon' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_abandon'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='tpool_wait' mangled-name='tpool_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_wait'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='tpool_suspend' mangled-name='tpool_suspend' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspend'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='tpool_suspended' mangled-name='tpool_suspended' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_suspended'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='tpool_resume' mangled-name='tpool_resume' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_resume'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='tpool_member' mangled-name='tpool_member' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_member'>
- <parameter type-id='9cf59a50' name='tpool'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-type size-in-bits='64' id='c5c76c9c'>
<parameter type-id='eaa32e2f'/>
<return type-id='48b5725f'/>
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_changelist.c' language='LANG_C99'>
- <type-decl name='void' id='48b5725f'/>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libzfs/libzfs_config.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='bf311473' size-in-bits='128' id='f0f65199'>
<subrange length='2' type-id='7359adad' id='52efc4ef'/>
</array-type-def>
@@ -1796,20 +1615,33 @@
<class-decl name='re_dfa_t' is-struct='yes' visibility='default' is-declaration-only='yes' id='b48d2441'/>
<class-decl name='uu_avl' is-struct='yes' visibility='default' is-declaration-only='yes' id='4af029d1'/>
<class-decl name='uu_avl_pool' is-struct='yes' visibility='default' is-declaration-only='yes' id='12a530a8'/>
+ <class-decl name='uu_avl_walk' is-struct='yes' visibility='default' is-declaration-only='yes' id='e70a39e3'/>
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
<type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
<type-decl name='short int' size-in-bits='16' id='a2185560'/>
+ <array-type-def dimensions='1' type-id='e475ab95' size-in-bits='192' id='0ce65a8b'>
+ <subrange length='3' type-id='7359adad' id='56f209d2'/>
+ </array-type-def>
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
<type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
+ <type-decl name='void' id='48b5725f'/>
+ <typedef-decl name='uu_compare_fn_t' type-id='add6e811' id='40f93560'/>
<typedef-decl name='uu_avl_pool_t' type-id='12a530a8' id='7f84e390'/>
<typedef-decl name='uu_avl_t' type-id='4af029d1' id='bb7f0973'/>
+ <class-decl name='uu_avl_node' size-in-bits='192' is-struct='yes' visibility='default' id='f65f4326'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='uan_opaque' type-id='0ce65a8b' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='uu_avl_node_t' type-id='f65f4326' id='73a65116'/>
+ <typedef-decl name='uu_avl_walk_t' type-id='e70a39e3' id='edd8457b'/>
+ <typedef-decl name='uu_avl_index_t' type-id='e475ab95' id='5d7f5fc8'/>
<typedef-decl name='zfs_handle_t' type-id='f6ee4445' id='775509eb'/>
<typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/>
<typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/>
- <typedef-decl name='zpool_iter_f' type-id='3aebb66f' id='fa476e62'/>
<typedef-decl name='zfs_iter_f' type-id='5571cde4' id='d8e49ab9'/>
<typedef-decl name='avl_tree_t' type-id='b351119f' id='f20fbd51'/>
<class-decl name='avl_node' size-in-bits='192' is-struct='yes' visibility='default' id='428b67b3'>
@@ -1886,6 +1718,122 @@
<enumerator name='DMU_OST_NUMTYPES' value='6'/>
</enum-decl>
<typedef-decl name='dmu_objset_type_t' type-id='6b1b19f9' id='230f1e16'/>
+ <enum-decl name='zfs_prop_t' naming-typedef-id='58603c44' id='4b000d60'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZPROP_CONT' value='-2'/>
+ <enumerator name='ZPROP_INVAL' value='-1'/>
+ <enumerator name='ZPROP_USERPROP' value='-1'/>
+ <enumerator name='ZFS_PROP_TYPE' value='0'/>
+ <enumerator name='ZFS_PROP_CREATION' value='1'/>
+ <enumerator name='ZFS_PROP_USED' value='2'/>
+ <enumerator name='ZFS_PROP_AVAILABLE' value='3'/>
+ <enumerator name='ZFS_PROP_REFERENCED' value='4'/>
+ <enumerator name='ZFS_PROP_COMPRESSRATIO' value='5'/>
+ <enumerator name='ZFS_PROP_MOUNTED' value='6'/>
+ <enumerator name='ZFS_PROP_ORIGIN' value='7'/>
+ <enumerator name='ZFS_PROP_QUOTA' value='8'/>
+ <enumerator name='ZFS_PROP_RESERVATION' value='9'/>
+ <enumerator name='ZFS_PROP_VOLSIZE' value='10'/>
+ <enumerator name='ZFS_PROP_VOLBLOCKSIZE' value='11'/>
+ <enumerator name='ZFS_PROP_RECORDSIZE' value='12'/>
+ <enumerator name='ZFS_PROP_MOUNTPOINT' value='13'/>
+ <enumerator name='ZFS_PROP_SHARENFS' value='14'/>
+ <enumerator name='ZFS_PROP_CHECKSUM' value='15'/>
+ <enumerator name='ZFS_PROP_COMPRESSION' value='16'/>
+ <enumerator name='ZFS_PROP_ATIME' value='17'/>
+ <enumerator name='ZFS_PROP_DEVICES' value='18'/>
+ <enumerator name='ZFS_PROP_EXEC' value='19'/>
+ <enumerator name='ZFS_PROP_SETUID' value='20'/>
+ <enumerator name='ZFS_PROP_READONLY' value='21'/>
+ <enumerator name='ZFS_PROP_ZONED' value='22'/>
+ <enumerator name='ZFS_PROP_SNAPDIR' value='23'/>
+ <enumerator name='ZFS_PROP_ACLMODE' value='24'/>
+ <enumerator name='ZFS_PROP_ACLINHERIT' value='25'/>
+ <enumerator name='ZFS_PROP_CREATETXG' value='26'/>
+ <enumerator name='ZFS_PROP_NAME' value='27'/>
+ <enumerator name='ZFS_PROP_CANMOUNT' value='28'/>
+ <enumerator name='ZFS_PROP_ISCSIOPTIONS' value='29'/>
+ <enumerator name='ZFS_PROP_XATTR' value='30'/>
+ <enumerator name='ZFS_PROP_NUMCLONES' value='31'/>
+ <enumerator name='ZFS_PROP_COPIES' value='32'/>
+ <enumerator name='ZFS_PROP_VERSION' value='33'/>
+ <enumerator name='ZFS_PROP_UTF8ONLY' value='34'/>
+ <enumerator name='ZFS_PROP_NORMALIZE' value='35'/>
+ <enumerator name='ZFS_PROP_CASE' value='36'/>
+ <enumerator name='ZFS_PROP_VSCAN' value='37'/>
+ <enumerator name='ZFS_PROP_NBMAND' value='38'/>
+ <enumerator name='ZFS_PROP_SHARESMB' value='39'/>
+ <enumerator name='ZFS_PROP_REFQUOTA' value='40'/>
+ <enumerator name='ZFS_PROP_REFRESERVATION' value='41'/>
+ <enumerator name='ZFS_PROP_GUID' value='42'/>
+ <enumerator name='ZFS_PROP_PRIMARYCACHE' value='43'/>
+ <enumerator name='ZFS_PROP_SECONDARYCACHE' value='44'/>
+ <enumerator name='ZFS_PROP_USEDSNAP' value='45'/>
+ <enumerator name='ZFS_PROP_USEDDS' value='46'/>
+ <enumerator name='ZFS_PROP_USEDCHILD' value='47'/>
+ <enumerator name='ZFS_PROP_USEDREFRESERV' value='48'/>
+ <enumerator name='ZFS_PROP_USERACCOUNTING' value='49'/>
+ <enumerator name='ZFS_PROP_STMF_SHAREINFO' value='50'/>
+ <enumerator name='ZFS_PROP_DEFER_DESTROY' value='51'/>
+ <enumerator name='ZFS_PROP_USERREFS' value='52'/>
+ <enumerator name='ZFS_PROP_LOGBIAS' value='53'/>
+ <enumerator name='ZFS_PROP_UNIQUE' value='54'/>
+ <enumerator name='ZFS_PROP_OBJSETID' value='55'/>
+ <enumerator name='ZFS_PROP_DEDUP' value='56'/>
+ <enumerator name='ZFS_PROP_MLSLABEL' value='57'/>
+ <enumerator name='ZFS_PROP_SYNC' value='58'/>
+ <enumerator name='ZFS_PROP_DNODESIZE' value='59'/>
+ <enumerator name='ZFS_PROP_REFRATIO' value='60'/>
+ <enumerator name='ZFS_PROP_WRITTEN' value='61'/>
+ <enumerator name='ZFS_PROP_CLONES' value='62'/>
+ <enumerator name='ZFS_PROP_LOGICALUSED' value='63'/>
+ <enumerator name='ZFS_PROP_LOGICALREFERENCED' value='64'/>
+ <enumerator name='ZFS_PROP_INCONSISTENT' value='65'/>
+ <enumerator name='ZFS_PROP_VOLMODE' value='66'/>
+ <enumerator name='ZFS_PROP_FILESYSTEM_LIMIT' value='67'/>
+ <enumerator name='ZFS_PROP_SNAPSHOT_LIMIT' value='68'/>
+ <enumerator name='ZFS_PROP_FILESYSTEM_COUNT' value='69'/>
+ <enumerator name='ZFS_PROP_SNAPSHOT_COUNT' value='70'/>
+ <enumerator name='ZFS_PROP_SNAPDEV' value='71'/>
+ <enumerator name='ZFS_PROP_ACLTYPE' value='72'/>
+ <enumerator name='ZFS_PROP_SELINUX_CONTEXT' value='73'/>
+ <enumerator name='ZFS_PROP_SELINUX_FSCONTEXT' value='74'/>
+ <enumerator name='ZFS_PROP_SELINUX_DEFCONTEXT' value='75'/>
+ <enumerator name='ZFS_PROP_SELINUX_ROOTCONTEXT' value='76'/>
+ <enumerator name='ZFS_PROP_RELATIME' value='77'/>
+ <enumerator name='ZFS_PROP_REDUNDANT_METADATA' value='78'/>
+ <enumerator name='ZFS_PROP_OVERLAY' value='79'/>
+ <enumerator name='ZFS_PROP_PREV_SNAP' value='80'/>
+ <enumerator name='ZFS_PROP_RECEIVE_RESUME_TOKEN' value='81'/>
+ <enumerator name='ZFS_PROP_ENCRYPTION' value='82'/>
+ <enumerator name='ZFS_PROP_KEYLOCATION' value='83'/>
+ <enumerator name='ZFS_PROP_KEYFORMAT' value='84'/>
+ <enumerator name='ZFS_PROP_PBKDF2_SALT' value='85'/>
+ <enumerator name='ZFS_PROP_PBKDF2_ITERS' value='86'/>
+ <enumerator name='ZFS_PROP_ENCRYPTION_ROOT' value='87'/>
+ <enumerator name='ZFS_PROP_KEY_GUID' value='88'/>
+ <enumerator name='ZFS_PROP_KEYSTATUS' value='89'/>
+ <enumerator name='ZFS_PROP_REMAPTXG' value='90'/>
+ <enumerator name='ZFS_PROP_SPECIAL_SMALL_BLOCKS' value='91'/>
+ <enumerator name='ZFS_PROP_IVSET_GUID' value='92'/>
+ <enumerator name='ZFS_PROP_REDACTED' value='93'/>
+ <enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/>
+ <enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED' value='95'/>
+ <enumerator name='ZFS_PROP_PREFETCH' value='96'/>
+ <enumerator name='ZFS_PROP_VOLTHREADING' value='97'/>
+ <enumerator name='ZFS_NUM_PROPS' value='98'/>
+ </enum-decl>
+ <typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
+ <enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZPROP_SRC_NONE' value='1'/>
+ <enumerator name='ZPROP_SRC_DEFAULT' value='2'/>
+ <enumerator name='ZPROP_SRC_TEMPORARY' value='4'/>
+ <enumerator name='ZPROP_SRC_LOCAL' value='8'/>
+ <enumerator name='ZPROP_SRC_INHERITED' value='16'/>
+ <enumerator name='ZPROP_SRC_RECEIVED' value='32'/>
+ </enum-decl>
+ <typedef-decl name='zprop_source_t' type-id='5903f80e' id='a2256d42'/>
<class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='nvl_version' type-id='3ff5601b' visibility='default'/>
@@ -1904,15 +1852,23 @@
</data-member>
</class-decl>
<typedef-decl name='nvlist_t' type-id='ac266fd9' id='8e8d4be3'/>
+ <enum-decl name='sa_protocol' id='9155d4b5'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='SA_PROTOCOL_NFS' value='0'/>
+ <enumerator name='SA_PROTOCOL_SMB' value='1'/>
+ <enumerator name='SA_PROTOCOL_COUNT' value='2'/>
+ </enum-decl>
<enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='B_FALSE' value='0'/>
<enumerator name='B_TRUE' value='1'/>
</enum-decl>
<typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/>
+ <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
<typedef-decl name='ulong_t' type-id='7359adad' id='ee1f298e'/>
<typedef-decl name='longlong_t' type-id='1eb56b1e' id='9b3ff54f'/>
<typedef-decl name='diskaddr_t' type-id='9b3ff54f' id='804dc465'/>
+ <typedef-decl name='zoneid_t' type-id='3502e3ff' id='4da03624'/>
<typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
<typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
<class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
@@ -2145,27 +2101,656 @@
</class-decl>
<pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
<pointer-type-def type-id='428b67b3' size-in-bits='64' id='bf311473'/>
- <pointer-type-def type-id='c19b74c3' size-in-bits='64' id='37e3bd22'/>
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
+ <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
+ <qualified-type-def type-id='9155d4b5' const='yes' id='9f2c1699'/>
+ <pointer-type-def type-id='9f2c1699' size-in-bits='64' id='4567bbc9'/>
+ <qualified-type-def type-id='775509eb' const='yes' id='5eadf2db'/>
+ <pointer-type-def type-id='5eadf2db' size-in-bits='64' id='fcd57163'/>
<pointer-type-def type-id='96ee24a5' size-in-bits='64' id='585e1de9'/>
<pointer-type-def type-id='cb9628fa' size-in-bits='64' id='5571cde4'/>
- <pointer-type-def type-id='2bce87e3' size-in-bits='64' id='3aebb66f'/>
<pointer-type-def type-id='95942d0c' size-in-bits='64' id='b0382bb3'/>
<pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
- <pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
<pointer-type-def type-id='b48d2441' size-in-bits='64' id='33976309'/>
<pointer-type-def type-id='b96825af' size-in-bits='64' id='ae3e8ca6'/>
<pointer-type-def type-id='002ac4a6' size-in-bits='64' id='cf536864'/>
+ <pointer-type-def type-id='5d7f5fc8' size-in-bits='64' id='813a2225'/>
+ <pointer-type-def type-id='73a65116' size-in-bits='64' id='2dc35b9d'/>
<pointer-type-def type-id='7f84e390' size-in-bits='64' id='de82c773'/>
<pointer-type-def type-id='bb7f0973' size-in-bits='64' id='a5c21a38'/>
+ <pointer-type-def type-id='edd8457b' size-in-bits='64' id='5842d146'/>
+ <pointer-type-def type-id='40f93560' size-in-bits='64' id='d502b39f'/>
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
<pointer-type-def type-id='775509eb' size-in-bits='64' id='9200a744'/>
<pointer-type-def type-id='b1efc708' size-in-bits='64' id='4c81de99'/>
+ <pointer-type-def type-id='a2256d42' size-in-bits='64' id='debc6aa3'/>
<class-decl name='re_dfa_t' is-struct='yes' visibility='default' is-declaration-only='yes' id='b48d2441'/>
<class-decl name='uu_avl' is-struct='yes' visibility='default' is-declaration-only='yes' id='4af029d1'/>
<class-decl name='uu_avl_pool' is-struct='yes' visibility='default' is-declaration-only='yes' id='12a530a8'/>
+ <class-decl name='uu_avl_walk' is-struct='yes' visibility='default' is-declaration-only='yes' id='e70a39e3'/>
+ <function-decl name='uu_avl_pool_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='d502b39f'/>
+ <parameter type-id='8f92235e'/>
+ <return type-id='de82c773'/>
+ </function-decl>
+ <function-decl name='uu_avl_pool_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='de82c773'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='uu_avl_node_init' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='2dc35b9d'/>
+ <parameter type-id='de82c773'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='uu_avl_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='de82c773'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='8f92235e'/>
+ <return type-id='a5c21a38'/>
+ </function-decl>
+ <function-decl name='uu_avl_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='uu_avl_last' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='uu_avl_walk_start' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='8f92235e'/>
+ <return type-id='5842d146'/>
+ </function-decl>
+ <function-decl name='uu_avl_walk_next' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5842d146'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='uu_avl_walk_end' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5842d146'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='uu_avl_find' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='813a2225'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='uu_avl_insert' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='5d7f5fc8'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='uu_avl_remove' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_get_handle' mangled-name='zfs_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_handle'>
+ <parameter type-id='9200a744'/>
+ <return type-id='b0382bb3'/>
+ </function-decl>
+ <function-decl name='zfs_open' mangled-name='zfs_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_open'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='9200a744'/>
+ </function-decl>
+ <function-decl name='zfs_close' mangled-name='zfs_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_close'>
+ <parameter type-id='9200a744'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_get_name' mangled-name='zfs_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_name'>
+ <parameter type-id='fcd57163'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zfs_prop_get' mangled-name='zfs_prop_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='58603c44'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='debc6aa3'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_prop_get_int' mangled-name='zfs_prop_get_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_int'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='58603c44'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='zfs_iter_children_v2' mangled-name='zfs_iter_children_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children_v2'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_iter_dependents_v2' mangled-name='zfs_iter_dependents_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents_v2'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_iter_mounted' mangled-name='zfs_iter_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_mounted'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_refresh_properties' mangled-name='zfs_refresh_properties' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_refresh_properties'>
+ <parameter type-id='9200a744'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_is_mounted' mangled-name='zfs_is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_mounted'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='9b23c9ad'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_mount' mangled-name='zfs_mount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_unmount' mangled-name='zfs_unmount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unmount'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_is_shared' mangled-name='zfs_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_shared'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='9b23c9ad'/>
+ <parameter type-id='4567bbc9'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_share' mangled-name='zfs_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_share'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='4567bbc9'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_unshare' mangled-name='zfs_unshare' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unshare'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='4567bbc9'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_commit_shares' mangled-name='zfs_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_commit_shares'>
+ <parameter type-id='4567bbc9'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'>
+ <return type-id='4da03624'/>
+ </function-decl>
+ <function-decl name='sa_commit_shares' mangled-name='sa_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_commit_shares'>
+ <parameter type-id='9155d4b5'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='zfs_error' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='remove_mountpoint' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-type size-in-bits='64' id='96ee24a5'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
+ <function-type size-in-bits='64' id='add6e811'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
+ <function-type size-in-bits='64' id='cb9628fa'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libzfs/libzfs_config.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
+ <subrange length='4096' type-id='7359adad' id='bc1b5ddc'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='65536' id='163f6aa5'>
+ <subrange length='8192' type-id='7359adad' id='c88f397d'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='infinite' id='e84913bd'>
+ <subrange length='infinite' type-id='7359adad' id='031f2035'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='128' id='c1c22e6c'>
+ <subrange length='2' type-id='7359adad' id='52efc4ef'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='24' id='d3490169'>
+ <subrange length='3' type-id='7359adad' id='56f209d2'/>
+ </array-type-def>
+ <type-decl name='variadic parameter type' id='2c1145c5'/>
+ <typedef-decl name='zpool_iter_f' type-id='3aebb66f' id='fa476e62'/>
+ <enum-decl name='data_type_t' naming-typedef-id='8d0687d2' id='aeeae136'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='DATA_TYPE_DONTCARE' value='-1'/>
+ <enumerator name='DATA_TYPE_UNKNOWN' value='0'/>
+ <enumerator name='DATA_TYPE_BOOLEAN' value='1'/>
+ <enumerator name='DATA_TYPE_BYTE' value='2'/>
+ <enumerator name='DATA_TYPE_INT16' value='3'/>
+ <enumerator name='DATA_TYPE_UINT16' value='4'/>
+ <enumerator name='DATA_TYPE_INT32' value='5'/>
+ <enumerator name='DATA_TYPE_UINT32' value='6'/>
+ <enumerator name='DATA_TYPE_INT64' value='7'/>
+ <enumerator name='DATA_TYPE_UINT64' value='8'/>
+ <enumerator name='DATA_TYPE_STRING' value='9'/>
+ <enumerator name='DATA_TYPE_BYTE_ARRAY' value='10'/>
+ <enumerator name='DATA_TYPE_INT16_ARRAY' value='11'/>
+ <enumerator name='DATA_TYPE_UINT16_ARRAY' value='12'/>
+ <enumerator name='DATA_TYPE_INT32_ARRAY' value='13'/>
+ <enumerator name='DATA_TYPE_UINT32_ARRAY' value='14'/>
+ <enumerator name='DATA_TYPE_INT64_ARRAY' value='15'/>
+ <enumerator name='DATA_TYPE_UINT64_ARRAY' value='16'/>
+ <enumerator name='DATA_TYPE_STRING_ARRAY' value='17'/>
+ <enumerator name='DATA_TYPE_HRTIME' value='18'/>
+ <enumerator name='DATA_TYPE_NVLIST' value='19'/>
+ <enumerator name='DATA_TYPE_NVLIST_ARRAY' value='20'/>
+ <enumerator name='DATA_TYPE_BOOLEAN_VALUE' value='21'/>
+ <enumerator name='DATA_TYPE_INT8' value='22'/>
+ <enumerator name='DATA_TYPE_UINT8' value='23'/>
+ <enumerator name='DATA_TYPE_BOOLEAN_ARRAY' value='24'/>
+ <enumerator name='DATA_TYPE_INT8_ARRAY' value='25'/>
+ <enumerator name='DATA_TYPE_UINT8_ARRAY' value='26'/>
+ <enumerator name='DATA_TYPE_DOUBLE' value='27'/>
+ </enum-decl>
+ <typedef-decl name='data_type_t' type-id='aeeae136' id='8d0687d2'/>
+ <class-decl name='nvpair' size-in-bits='128' is-struct='yes' visibility='default' id='1c34e459'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='nvp_size' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='nvp_name_sz' type-id='23bd8cb5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='48'>
+ <var-decl name='nvp_reserve' type-id='23bd8cb5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='nvp_value_elem' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='nvp_type' type-id='8d0687d2' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='nvp_name' type-id='e84913bd' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='nvpair_t' type-id='1c34e459' id='57928edf'/>
+ <class-decl name='drr_begin' size-in-bits='2432' is-struct='yes' visibility='default' id='09fcdc01'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_magic' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_versioninfo' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_creation_time' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_type' type-id='230f1e16' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='drr_flags' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_fromguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='drr_toname' type-id='d1617432' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='zinject_record' size-in-bits='2816' is-struct='yes' visibility='default' id='3216f820'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zi_objset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='zi_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='zi_start' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='zi_end' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='zi_guid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='zi_level' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='352'>
+ <var-decl name='zi_error' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='zi_type' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='zi_freq' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='480'>
+ <var-decl name='zi_failfast' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='zi_func' type-id='d1617432' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2560'>
+ <var-decl name='zi_iotype' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2592'>
+ <var-decl name='zi_duration' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2624'>
+ <var-decl name='zi_timer' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2688'>
+ <var-decl name='zi_nlanes' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2752'>
+ <var-decl name='zi_cmd' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2784'>
+ <var-decl name='zi_dvas' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zinject_record_t' type-id='3216f820' id='a4301ca6'/>
+ <class-decl name='zfs_share' size-in-bits='256' is-struct='yes' visibility='default' id='feb6f2da'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='z_exportdata' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='z_sharedata' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='z_sharetype' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='z_sharemax' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zfs_share_t' type-id='feb6f2da' id='ee5cec36'/>
+ <class-decl name='zfs_cmd' size-in-bits='109952' is-struct='yes' visibility='default' id='3522cd69'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zc_name' type-id='d16c6df4' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32768'>
+ <var-decl name='zc_nvlist_src' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32832'>
+ <var-decl name='zc_nvlist_src_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32896'>
+ <var-decl name='zc_nvlist_dst' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32960'>
+ <var-decl name='zc_nvlist_dst_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33024'>
+ <var-decl name='zc_nvlist_dst_filled' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33056'>
+ <var-decl name='zc_pad2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33088'>
+ <var-decl name='zc_history' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33152'>
+ <var-decl name='zc_value' type-id='163f6aa5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='98688'>
+ <var-decl name='zc_string' type-id='d1617432' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100736'>
+ <var-decl name='zc_guid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100800'>
+ <var-decl name='zc_nvlist_conf' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100864'>
+ <var-decl name='zc_nvlist_conf_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100928'>
+ <var-decl name='zc_cookie' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100992'>
+ <var-decl name='zc_objset_type' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101056'>
+ <var-decl name='zc_perm_action' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101120'>
+ <var-decl name='zc_history_len' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101184'>
+ <var-decl name='zc_history_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101248'>
+ <var-decl name='zc_obj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101312'>
+ <var-decl name='zc_iflags' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101376'>
+ <var-decl name='zc_share' type-id='ee5cec36' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101632'>
+ <var-decl name='zc_objset_stats' type-id='b2c14f17' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='103936'>
+ <var-decl name='zc_begin_record' type-id='09fcdc01' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='106368'>
+ <var-decl name='zc_inject_record' type-id='a4301ca6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109184'>
+ <var-decl name='zc_defer_destroy' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109216'>
+ <var-decl name='zc_flags' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109248'>
+ <var-decl name='zc_action_handle' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109312'>
+ <var-decl name='zc_cleanup_fd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109344'>
+ <var-decl name='zc_simple' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109352'>
+ <var-decl name='zc_pad' type-id='d3490169' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109376'>
+ <var-decl name='zc_sendobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109440'>
+ <var-decl name='zc_fromobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109504'>
+ <var-decl name='zc_createtxg' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109568'>
+ <var-decl name='zc_stat' type-id='0371a9c7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109888'>
+ <var-decl name='zc_zoneid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zfs_cmd_t' type-id='3522cd69' id='a5559cdd'/>
+ <class-decl name='zfs_stat' size-in-bits='320' is-struct='yes' visibility='default' id='6417f0b9'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zs_gen' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='zs_mode' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='zs_links' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='zs_ctime' type-id='c1c22e6c' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zfs_stat_t' type-id='6417f0b9' id='0371a9c7'/>
+ <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
+ <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
+ <pointer-type-def type-id='c19b74c3' size-in-bits='64' id='37e3bd22'/>
+ <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
+ <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
+ <qualified-type-def type-id='57928edf' const='yes' id='642ee20f'/>
+ <pointer-type-def type-id='642ee20f' size-in-bits='64' id='dace003f'/>
+ <pointer-type-def type-id='2bce87e3' size-in-bits='64' id='3aebb66f'/>
+ <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
+ <pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
+ <pointer-type-def type-id='57928edf' size-in-bits='64' id='3fa542f0'/>
+ <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
+ <pointer-type-def type-id='3522cd69' size-in-bits='64' id='b65f7fd1'/>
+ <pointer-type-def type-id='a5559cdd' size-in-bits='64' id='e4ec4540'/>
+ <pointer-type-def type-id='4c81de99' size-in-bits='64' id='237193c9'/>
+ <function-decl name='uu_avl_first' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='uu_avl_next' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='uu_avl_teardown' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a5c21a38'/>
+ <parameter type-id='63e171df'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='zfs_standard_error' mangled-name='zfs_standard_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_standard_error'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_ioctl' mangled-name='zfs_ioctl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_ioctl'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='b65f7fd1'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nvlist_dup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_exists' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvlist_next_nvpair' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='dace003f'/>
+ <return type-id='3fa542f0'/>
+ </function-decl>
+ <function-decl name='nvpair_name' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='3fa542f0'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__errno_location' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='7292109c'/>
+ </function-decl>
+ <function-decl name='dcgettext' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='getenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
<function-decl name='zpool_get_config' mangled-name='zpool_get_config' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_config'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='857bb57e' name='oldconfig'/>
@@ -2196,16 +2781,47 @@
<parameter type-id='eaa32e2f' name='data'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-type size-in-bits='64' id='96ee24a5'>
- <parameter type-id='eaa32e2f'/>
- <parameter type-id='eaa32e2f'/>
+ <function-decl name='zfs_strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='no_memory' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
<return type-id='95e97e5e'/>
- </function-type>
- <function-type size-in-bits='64' id='cb9628fa'>
- <parameter type-id='9200a744'/>
- <parameter type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='zcmd_alloc_dst_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zcmd_expand_dst_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zcmd_read_dst_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <parameter type-id='857bb57e'/>
<return type-id='95e97e5e'/>
- </function-type>
+ </function-decl>
+ <function-decl name='zcmd_free_nvlists' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e4ec4540'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='make_dataset_handle' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='9200a744'/>
+ </function-decl>
+ <function-decl name='zpool_open_silent' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='237193c9'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-type size-in-bits='64' id='2bce87e3'>
<parameter type-id='4c81de99'/>
<parameter type-id='eaa32e2f'/>
@@ -2213,9 +2829,710 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_crypto.c' language='LANG_C99'>
- <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
+ <array-type-def dimensions='1' type-id='38b51b3c' size-in-bits='832' id='02b72c00'>
+ <subrange length='13' type-id='7359adad' id='487fded1'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='fb7c6451' size-in-bits='256' id='64177143'>
+ <subrange length='32' type-id='7359adad' id='ae5bde82'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
+ <subrange length='1' type-id='7359adad' id='52f813b4'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
+ <subrange length='20' type-id='7359adad' id='fdca39cf'/>
+ </array-type-def>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
+ <array-type-def dimensions='1' type-id='80f4b756' size-in-bits='832' id='39e6f84a'>
+ <subrange length='13' type-id='7359adad' id='487fded1'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='896' id='47394ee0'>
+ <subrange length='28' type-id='7359adad' id='3db583d7'/>
+ </array-type-def>
+ <type-decl name='signed char' size-in-bits='8' id='28577a57'/>
+ <array-type-def dimensions='1' type-id='7359adad' size-in-bits='1024' id='d2baa450'>
+ <subrange length='16' type-id='7359adad' id='848d0938'/>
+ </array-type-def>
+ <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <enum-decl name='zpool_prop_t' naming-typedef-id='5d0c23fb' id='af1ba157'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZPOOL_PROP_INVAL' value='-1'/>
+ <enumerator name='ZPOOL_PROP_NAME' value='0'/>
+ <enumerator name='ZPOOL_PROP_SIZE' value='1'/>
+ <enumerator name='ZPOOL_PROP_CAPACITY' value='2'/>
+ <enumerator name='ZPOOL_PROP_ALTROOT' value='3'/>
+ <enumerator name='ZPOOL_PROP_HEALTH' value='4'/>
+ <enumerator name='ZPOOL_PROP_GUID' value='5'/>
+ <enumerator name='ZPOOL_PROP_VERSION' value='6'/>
+ <enumerator name='ZPOOL_PROP_BOOTFS' value='7'/>
+ <enumerator name='ZPOOL_PROP_DELEGATION' value='8'/>
+ <enumerator name='ZPOOL_PROP_AUTOREPLACE' value='9'/>
+ <enumerator name='ZPOOL_PROP_CACHEFILE' value='10'/>
+ <enumerator name='ZPOOL_PROP_FAILUREMODE' value='11'/>
+ <enumerator name='ZPOOL_PROP_LISTSNAPS' value='12'/>
+ <enumerator name='ZPOOL_PROP_AUTOEXPAND' value='13'/>
+ <enumerator name='ZPOOL_PROP_DEDUPDITTO' value='14'/>
+ <enumerator name='ZPOOL_PROP_DEDUPRATIO' value='15'/>
+ <enumerator name='ZPOOL_PROP_FREE' value='16'/>
+ <enumerator name='ZPOOL_PROP_ALLOCATED' value='17'/>
+ <enumerator name='ZPOOL_PROP_READONLY' value='18'/>
+ <enumerator name='ZPOOL_PROP_ASHIFT' value='19'/>
+ <enumerator name='ZPOOL_PROP_COMMENT' value='20'/>
+ <enumerator name='ZPOOL_PROP_EXPANDSZ' value='21'/>
+ <enumerator name='ZPOOL_PROP_FREEING' value='22'/>
+ <enumerator name='ZPOOL_PROP_FRAGMENTATION' value='23'/>
+ <enumerator name='ZPOOL_PROP_LEAKED' value='24'/>
+ <enumerator name='ZPOOL_PROP_MAXBLOCKSIZE' value='25'/>
+ <enumerator name='ZPOOL_PROP_TNAME' value='26'/>
+ <enumerator name='ZPOOL_PROP_MAXDNODESIZE' value='27'/>
+ <enumerator name='ZPOOL_PROP_MULTIHOST' value='28'/>
+ <enumerator name='ZPOOL_PROP_CHECKPOINT' value='29'/>
+ <enumerator name='ZPOOL_PROP_LOAD_GUID' value='30'/>
+ <enumerator name='ZPOOL_PROP_AUTOTRIM' value='31'/>
+ <enumerator name='ZPOOL_PROP_COMPATIBILITY' value='32'/>
+ <enumerator name='ZPOOL_PROP_BCLONEUSED' value='33'/>
+ <enumerator name='ZPOOL_PROP_BCLONESAVED' value='34'/>
+ <enumerator name='ZPOOL_PROP_BCLONERATIO' value='35'/>
+ <enumerator name='ZPOOL_NUM_PROPS' value='36'/>
+ </enum-decl>
+ <typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
+ <typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
+ <class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
+ <typedef-decl name='__sighandler_t' type-id='03347643' id='8cdd9566'/>
+ <typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
+ <class-decl name='sigaction' size-in-bits='1216' is-struct='yes' visibility='default' id='fe391c48'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__sigaction_handler' type-id='ac5ab595' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='sa_mask' type-id='b9c97942' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='sa_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1152'>
+ <var-decl name='sa_restorer' type-id='953b12f8' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='__anonymous_union__' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab595'>
+ <data-member access='public'>
+ <var-decl name='sa_handler' type-id='8cdd9566' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='sa_sigaction' type-id='6e756877' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <class-decl name='termios' size-in-bits='480' is-struct='yes' visibility='default' id='ad55d2bc'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='c_iflag' type-id='241ce6f8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='c_oflag' type-id='241ce6f8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='c_cflag' type-id='241ce6f8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='c_lflag' type-id='241ce6f8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='c_line' type-id='fb7c6451' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='136'>
+ <var-decl name='c_cc' type-id='64177143' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='416'>
+ <var-decl name='c_ispeed' type-id='6a8e8a14' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='c_ospeed' type-id='6a8e8a14' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='cc_t' type-id='002ac4a6' id='fb7c6451'/>
+ <typedef-decl name='speed_t' type-id='f0981eeb' id='6a8e8a14'/>
+ <typedef-decl name='tcflag_t' type-id='f0981eeb' id='241ce6f8'/>
+ <typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
+ <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
+ <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
+ <typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
+ <typedef-decl name='__clock_t' type-id='bd54fe1a' id='4d66c6d7'/>
+ <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
+ <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
+ <class-decl name='__locale_struct' size-in-bits='1856' is-struct='yes' visibility='default' id='90cc1ce3'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__locales' type-id='02b72c00' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='__ctype_b' type-id='31347b7a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='__ctype_tolower' type-id='6d60f45d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='__ctype_toupper' type-id='6d60f45d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='__names' type-id='39e6f84a' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__locale_t' type-id='f01e1813' id='b7ac9b5f'/>
+ <class-decl name='__sigset_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='b9c97942' visibility='default' id='2616147f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__val' type-id='d2baa450' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__sigset_t' type-id='2616147f' id='b9c97942'/>
+ <union-decl name='sigval' size-in-bits='64' visibility='default' id='a094b870'>
+ <data-member access='public'>
+ <var-decl name='sival_int' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='sival_ptr' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='__sigval_t' type-id='a094b870' id='eabacd01'/>
+ <typedef-decl name='locale_t' type-id='b7ac9b5f' id='973a4f8d'/>
+ <class-decl name='siginfo_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='cb681f62' visibility='default' id='d8149419'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_signo' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='si_errno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_code' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_sifields' type-id='ac5ab596' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='__anonymous_union__1' size-in-bits='896' is-anonymous='yes' visibility='default' id='ac5ab596'>
+ <data-member access='public'>
+ <var-decl name='_pad' type-id='47394ee0' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_kill' type-id='e7f43f73' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_timer' type-id='e7f43f74' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_rt' type-id='e7f43f75' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_sigchld' type-id='e7f43f76' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_sigfault' type-id='e7f43f77' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_sigpoll' type-id='e7f43f78' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_sigsys' type-id='e7f43f79' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <class-decl name='__anonymous_struct__1' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f73'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_pid' type-id='3629bad8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__2' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f74'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_tid' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='si_overrun' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_sigval' type-id='eabacd01' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__3' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f75'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_pid' type-id='3629bad8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_sigval' type-id='eabacd01' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__4' size-in-bits='256' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f76'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_pid' type-id='3629bad8' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='si_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_status' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='si_utime' type-id='4d66c6d7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='si_stime' type-id='4d66c6d7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__5' size-in-bits='256' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f77'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_addr' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_addr_lsb' type-id='a2185560' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_bounds' type-id='ac5ab597' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='__anonymous_union__2' size-in-bits='128' is-anonymous='yes' visibility='default' id='ac5ab597'>
+ <data-member access='public'>
+ <var-decl name='_addr_bnd' type-id='e7f43f7a' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_pkey' type-id='62f1140c' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <class-decl name='__anonymous_struct__6' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7a'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_lower' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_upper' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__7' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f78'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='si_band' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='si_fd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__anonymous_struct__8' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f79'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_call_addr' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_syscall' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='_arch' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='siginfo_t' type-id='d8149419' id='cb681f62'/>
+ <typedef-decl name='sigset_t' type-id='b9c97942' id='daf33c64'/>
+ <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
+ <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='928'>
+ <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1040'>
+ <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1048'>
+ <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1152'>
+ <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1216'>
+ <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1280'>
+ <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1344'>
+ <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1408'>
+ <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1472'>
+ <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1536'>
+ <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1568'>
+ <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
+ <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
+ <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
+ <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
+ <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
+ <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
+ <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
+ <pointer-type-def type-id='23de8b96' size-in-bits='64' id='38b51b3c'/>
+ <pointer-type-def type-id='90cc1ce3' size-in-bits='64' id='f01e1813'/>
+ <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
+ <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
+ <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/>
+ <qualified-type-def type-id='95e97e5e' const='yes' id='2448a865'/>
+ <pointer-type-def type-id='2448a865' size-in-bits='64' id='6d60f45d'/>
+ <qualified-type-def type-id='aca3bac8' const='yes' id='2498fd78'/>
+ <pointer-type-def type-id='2498fd78' size-in-bits='64' id='eed6c816'/>
+ <qualified-type-def type-id='eed6c816' restrict='yes' id='a431a9da'/>
+ <qualified-type-def type-id='fe391c48' const='yes' id='14a93b33'/>
+ <pointer-type-def type-id='14a93b33' size-in-bits='64' id='9f68085b'/>
+ <qualified-type-def type-id='9f68085b' restrict='yes' id='e2a5e6f9'/>
+ <qualified-type-def type-id='ad55d2bc' const='yes' id='a46bf13f'/>
+ <pointer-type-def type-id='a46bf13f' size-in-bits='64' id='eaec840f'/>
+ <qualified-type-def type-id='002ac4a6' const='yes' id='ea86de29'/>
+ <pointer-type-def type-id='ea86de29' size-in-bits='64' id='354f7eb9'/>
+ <qualified-type-def type-id='8efea9e5' const='yes' id='3beb2af4'/>
+ <pointer-type-def type-id='3beb2af4' size-in-bits='64' id='31347b7a'/>
+ <pointer-type-def type-id='31347b7a' size-in-bits='64' id='c59e1ef0'/>
+ <pointer-type-def type-id='1b941664' size-in-bits='64' id='7e2979d5'/>
+ <qualified-type-def type-id='7e2979d5' restrict='yes' id='fc212857'/>
+ <pointer-type-def type-id='fe391c48' size-in-bits='64' id='568dd84e'/>
+ <qualified-type-def type-id='568dd84e' restrict='yes' id='3d8ee6f2'/>
+ <pointer-type-def type-id='cb681f62' size-in-bits='64' id='185869c1'/>
+ <pointer-type-def type-id='daf33c64' size-in-bits='64' id='9e80f729'/>
+ <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/>
+ <qualified-type-def type-id='78c01427' restrict='yes' id='d19b2c25'/>
+ <pointer-type-def type-id='ad55d2bc' size-in-bits='64' id='665a4eda'/>
+ <pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
<pointer-type-def type-id='ae3e8ca6' size-in-bits='64' id='d8774064'/>
<pointer-type-def type-id='3502e3ff' size-in-bits='64' id='4dd26a40'/>
+ <pointer-type-def type-id='ee076206' size-in-bits='64' id='953b12f8'/>
+ <pointer-type-def type-id='f712e2b7' size-in-bits='64' id='03347643'/>
+ <pointer-type-def type-id='ef70d893' size-in-bits='64' id='6e756877'/>
+ <qualified-type-def type-id='eaa32e2f' restrict='yes' id='1b7446cd'/>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
+ <function-decl name='zpool_get_prop_int' mangled-name='zpool_get_prop_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop_int'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='5d0c23fb'/>
+ <parameter type-id='debc6aa3'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='zfs_handle_dup' mangled-name='zfs_handle_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_handle_dup'>
+ <parameter type-id='9200a744'/>
+ <return type-id='9200a744'/>
+ </function-decl>
+ <function-decl name='zfs_valid_proplist' mangled-name='zfs_valid_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valid_proplist'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='2e45de5d'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='zfs_prop_to_name' mangled-name='zfs_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_to_name'>
+ <parameter type-id='58603c44'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zfs_iter_filesystems_v2' mangled-name='zfs_iter_filesystems_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems_v2'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_parent_name' mangled-name='zfs_parent_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parent_name'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_load_key' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='ae3e8ca6'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_unload_key' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_change_key' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='ae3e8ca6'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_name_to_prop' mangled-name='zfs_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_name_to_prop'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='58603c44'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='c59e1ef0'/>
+ </function-decl>
+ <function-decl name='dlopen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='dlsym' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='1b7446cd'/>
+ <parameter type-id='9d26089a'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='dlerror' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='uselocale' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='973a4f8d'/>
+ <return type-id='973a4f8d'/>
+ </function-decl>
+ <function-decl name='PKCS5_PBKDF2_HMAC_SHA1' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='354f7eb9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='cf536864'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='regexec' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a431a9da'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='fc212857'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='kill' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='3629bad8'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='sigemptyset' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9e80f729'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='sigaction' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='e2a5e6f9'/>
+ <parameter type-id='3d8ee6f2'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fflush' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fdopen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='822cd80b'/>
+ </function-decl>
+ <function-decl name='fputc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__getdelim' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='d19b2c25'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='e75a27e9'/>
+ <return type-id='41060289'/>
+ </function-decl>
+ <function-decl name='rewind' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='ferror' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fileno' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='calloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strerror_l' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='973a4f8d'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='tcgetattr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='665a4eda'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='tcsetattr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaec840f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='close' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='3629bad8'/>
+ </function-decl>
+ <function-decl name='isatty' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='unlink' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__fread_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='1b7446cd'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='e75a27e9'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
<function-decl name='zfs_crypto_get_encryption_root' mangled-name='zfs_crypto_get_encryption_root' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_crypto_get_encryption_root'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='37e3bd22' name='is_encroot'/>
@@ -2260,8 +3577,28 @@
<parameter type-id='c19b74c3' name='inheritkey'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zfs_error_aux' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-type size-in-bits='64' id='f712e2b7'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='48b5725f'/>
+ </function-type>
+ <function-type size-in-bits='64' id='ef70d893'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='185869c1'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_dataset.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
+ <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/>
<class-decl name='zprop_list' size-in-bits='448' is-struct='yes' visibility='default' id='bd9b4291'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='pl_prop' type-id='95e97e5e' visibility='default'/>
@@ -2288,119 +3625,23 @@
<typedef-decl name='zprop_list_t' type-id='bd9b4291' id='bdb8ac4f'/>
<class-decl name='renameflags' size-in-bits='32' is-struct='yes' visibility='default' id='7aee5792'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='recursive' type-id='95e97e5e' visibility='default'/>
+ <var-decl name='recursive' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1'>
- <var-decl name='nounmount' type-id='95e97e5e' visibility='default'/>
+ <var-decl name='nounmount' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='2'>
- <var-decl name='forceunmount' type-id='95e97e5e' visibility='default'/>
+ <var-decl name='forceunmount' type-id='f0981eeb' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='renameflags_t' type-id='7aee5792' id='067170c2'/>
<typedef-decl name='zfs_userspace_cb_t' type-id='ca64ff60' id='16c5f410'/>
- <enum-decl name='zfs_prop_t' naming-typedef-id='58603c44' id='4b000d60'>
+ <enum-decl name='lzc_dataset_type' id='bc9887f1'>
<underlying-type type-id='9cac1fee'/>
- <enumerator name='ZPROP_CONT' value='-2'/>
- <enumerator name='ZPROP_INVAL' value='-1'/>
- <enumerator name='ZFS_PROP_TYPE' value='0'/>
- <enumerator name='ZFS_PROP_CREATION' value='1'/>
- <enumerator name='ZFS_PROP_USED' value='2'/>
- <enumerator name='ZFS_PROP_AVAILABLE' value='3'/>
- <enumerator name='ZFS_PROP_REFERENCED' value='4'/>
- <enumerator name='ZFS_PROP_COMPRESSRATIO' value='5'/>
- <enumerator name='ZFS_PROP_MOUNTED' value='6'/>
- <enumerator name='ZFS_PROP_ORIGIN' value='7'/>
- <enumerator name='ZFS_PROP_QUOTA' value='8'/>
- <enumerator name='ZFS_PROP_RESERVATION' value='9'/>
- <enumerator name='ZFS_PROP_VOLSIZE' value='10'/>
- <enumerator name='ZFS_PROP_VOLBLOCKSIZE' value='11'/>
- <enumerator name='ZFS_PROP_RECORDSIZE' value='12'/>
- <enumerator name='ZFS_PROP_MOUNTPOINT' value='13'/>
- <enumerator name='ZFS_PROP_SHARENFS' value='14'/>
- <enumerator name='ZFS_PROP_CHECKSUM' value='15'/>
- <enumerator name='ZFS_PROP_COMPRESSION' value='16'/>
- <enumerator name='ZFS_PROP_ATIME' value='17'/>
- <enumerator name='ZFS_PROP_DEVICES' value='18'/>
- <enumerator name='ZFS_PROP_EXEC' value='19'/>
- <enumerator name='ZFS_PROP_SETUID' value='20'/>
- <enumerator name='ZFS_PROP_READONLY' value='21'/>
- <enumerator name='ZFS_PROP_ZONED' value='22'/>
- <enumerator name='ZFS_PROP_SNAPDIR' value='23'/>
- <enumerator name='ZFS_PROP_ACLMODE' value='24'/>
- <enumerator name='ZFS_PROP_ACLINHERIT' value='25'/>
- <enumerator name='ZFS_PROP_CREATETXG' value='26'/>
- <enumerator name='ZFS_PROP_NAME' value='27'/>
- <enumerator name='ZFS_PROP_CANMOUNT' value='28'/>
- <enumerator name='ZFS_PROP_ISCSIOPTIONS' value='29'/>
- <enumerator name='ZFS_PROP_XATTR' value='30'/>
- <enumerator name='ZFS_PROP_NUMCLONES' value='31'/>
- <enumerator name='ZFS_PROP_COPIES' value='32'/>
- <enumerator name='ZFS_PROP_VERSION' value='33'/>
- <enumerator name='ZFS_PROP_UTF8ONLY' value='34'/>
- <enumerator name='ZFS_PROP_NORMALIZE' value='35'/>
- <enumerator name='ZFS_PROP_CASE' value='36'/>
- <enumerator name='ZFS_PROP_VSCAN' value='37'/>
- <enumerator name='ZFS_PROP_NBMAND' value='38'/>
- <enumerator name='ZFS_PROP_SHARESMB' value='39'/>
- <enumerator name='ZFS_PROP_REFQUOTA' value='40'/>
- <enumerator name='ZFS_PROP_REFRESERVATION' value='41'/>
- <enumerator name='ZFS_PROP_GUID' value='42'/>
- <enumerator name='ZFS_PROP_PRIMARYCACHE' value='43'/>
- <enumerator name='ZFS_PROP_SECONDARYCACHE' value='44'/>
- <enumerator name='ZFS_PROP_USEDSNAP' value='45'/>
- <enumerator name='ZFS_PROP_USEDDS' value='46'/>
- <enumerator name='ZFS_PROP_USEDCHILD' value='47'/>
- <enumerator name='ZFS_PROP_USEDREFRESERV' value='48'/>
- <enumerator name='ZFS_PROP_USERACCOUNTING' value='49'/>
- <enumerator name='ZFS_PROP_STMF_SHAREINFO' value='50'/>
- <enumerator name='ZFS_PROP_DEFER_DESTROY' value='51'/>
- <enumerator name='ZFS_PROP_USERREFS' value='52'/>
- <enumerator name='ZFS_PROP_LOGBIAS' value='53'/>
- <enumerator name='ZFS_PROP_UNIQUE' value='54'/>
- <enumerator name='ZFS_PROP_OBJSETID' value='55'/>
- <enumerator name='ZFS_PROP_DEDUP' value='56'/>
- <enumerator name='ZFS_PROP_MLSLABEL' value='57'/>
- <enumerator name='ZFS_PROP_SYNC' value='58'/>
- <enumerator name='ZFS_PROP_DNODESIZE' value='59'/>
- <enumerator name='ZFS_PROP_REFRATIO' value='60'/>
- <enumerator name='ZFS_PROP_WRITTEN' value='61'/>
- <enumerator name='ZFS_PROP_CLONES' value='62'/>
- <enumerator name='ZFS_PROP_LOGICALUSED' value='63'/>
- <enumerator name='ZFS_PROP_LOGICALREFERENCED' value='64'/>
- <enumerator name='ZFS_PROP_INCONSISTENT' value='65'/>
- <enumerator name='ZFS_PROP_VOLMODE' value='66'/>
- <enumerator name='ZFS_PROP_FILESYSTEM_LIMIT' value='67'/>
- <enumerator name='ZFS_PROP_SNAPSHOT_LIMIT' value='68'/>
- <enumerator name='ZFS_PROP_FILESYSTEM_COUNT' value='69'/>
- <enumerator name='ZFS_PROP_SNAPSHOT_COUNT' value='70'/>
- <enumerator name='ZFS_PROP_SNAPDEV' value='71'/>
- <enumerator name='ZFS_PROP_ACLTYPE' value='72'/>
- <enumerator name='ZFS_PROP_SELINUX_CONTEXT' value='73'/>
- <enumerator name='ZFS_PROP_SELINUX_FSCONTEXT' value='74'/>
- <enumerator name='ZFS_PROP_SELINUX_DEFCONTEXT' value='75'/>
- <enumerator name='ZFS_PROP_SELINUX_ROOTCONTEXT' value='76'/>
- <enumerator name='ZFS_PROP_RELATIME' value='77'/>
- <enumerator name='ZFS_PROP_REDUNDANT_METADATA' value='78'/>
- <enumerator name='ZFS_PROP_OVERLAY' value='79'/>
- <enumerator name='ZFS_PROP_PREV_SNAP' value='80'/>
- <enumerator name='ZFS_PROP_RECEIVE_RESUME_TOKEN' value='81'/>
- <enumerator name='ZFS_PROP_ENCRYPTION' value='82'/>
- <enumerator name='ZFS_PROP_KEYLOCATION' value='83'/>
- <enumerator name='ZFS_PROP_KEYFORMAT' value='84'/>
- <enumerator name='ZFS_PROP_PBKDF2_SALT' value='85'/>
- <enumerator name='ZFS_PROP_PBKDF2_ITERS' value='86'/>
- <enumerator name='ZFS_PROP_ENCRYPTION_ROOT' value='87'/>
- <enumerator name='ZFS_PROP_KEY_GUID' value='88'/>
- <enumerator name='ZFS_PROP_KEYSTATUS' value='89'/>
- <enumerator name='ZFS_PROP_REMAPTXG' value='90'/>
- <enumerator name='ZFS_PROP_SPECIAL_SMALL_BLOCKS' value='91'/>
- <enumerator name='ZFS_PROP_IVSET_GUID' value='92'/>
- <enumerator name='ZFS_PROP_REDACTED' value='93'/>
- <enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/>
- <enumerator name='ZFS_NUM_PROPS' value='95'/>
+ <enumerator name='LZC_DATSET_TYPE_ZFS' value='2'/>
+ <enumerator name='LZC_DATSET_TYPE_ZVOL' value='3'/>
</enum-decl>
- <typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
+ <typedef-decl name='avl_index_t' type-id='e475ab95' id='fba6cb51'/>
<enum-decl name='zfs_userquota_prop_t' naming-typedef-id='279fde6a' id='5258d2f6'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_PROP_USERUSED' value='0'/>
@@ -2418,22 +3659,36 @@
<enumerator name='ZFS_NUM_USERQUOTA_PROPS' value='12'/>
</enum-decl>
<typedef-decl name='zfs_userquota_prop_t' type-id='5258d2f6' id='279fde6a'/>
- <enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='ZPROP_SRC_NONE' value='1'/>
- <enumerator name='ZPROP_SRC_DEFAULT' value='2'/>
- <enumerator name='ZPROP_SRC_TEMPORARY' value='4'/>
- <enumerator name='ZPROP_SRC_LOCAL' value='8'/>
- <enumerator name='ZPROP_SRC_INHERITED' value='16'/>
- <enumerator name='ZPROP_SRC_RECEIVED' value='32'/>
- </enum-decl>
- <typedef-decl name='zprop_source_t' type-id='5903f80e' id='a2256d42'/>
<enum-decl name='zfs_wait_activity_t' naming-typedef-id='3024501a' id='527d5dc6'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_WAIT_DELETEQ' value='0'/>
<enumerator name='ZFS_WAIT_NUM_ACTIVITIES' value='1'/>
</enum-decl>
<typedef-decl name='zfs_wait_activity_t' type-id='527d5dc6' id='3024501a'/>
+ <enum-decl name='namecheck_err_t' naming-typedef-id='8e0af06e' id='f43bbcda'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='NAME_ERR_LEADING_SLASH' value='0'/>
+ <enumerator name='NAME_ERR_EMPTY_COMPONENT' value='1'/>
+ <enumerator name='NAME_ERR_TRAILING_SLASH' value='2'/>
+ <enumerator name='NAME_ERR_INVALCHAR' value='3'/>
+ <enumerator name='NAME_ERR_MULTIPLE_DELIMITERS' value='4'/>
+ <enumerator name='NAME_ERR_NOLETTER' value='5'/>
+ <enumerator name='NAME_ERR_RESERVED' value='6'/>
+ <enumerator name='NAME_ERR_DISKLIKE' value='7'/>
+ <enumerator name='NAME_ERR_TOOLONG' value='8'/>
+ <enumerator name='NAME_ERR_SELF_REF' value='9'/>
+ <enumerator name='NAME_ERR_PARENT_REF' value='10'/>
+ <enumerator name='NAME_ERR_NO_AT' value='11'/>
+ <enumerator name='NAME_ERR_NO_POUND' value='12'/>
+ </enum-decl>
+ <typedef-decl name='namecheck_err_t' type-id='f43bbcda' id='8e0af06e'/>
+ <enum-decl name='zprop_type_t' naming-typedef-id='31429eff' id='87676253'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='PROP_TYPE_NUMBER' value='0'/>
+ <enumerator name='PROP_TYPE_STRING' value='1'/>
+ <enumerator name='PROP_TYPE_INDEX' value='2'/>
+ </enum-decl>
+ <typedef-decl name='zprop_type_t' type-id='87676253' id='31429eff'/>
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
@@ -2448,19 +3703,672 @@
<var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
+ <class-decl name='group' size-in-bits='256' is-struct='yes' visibility='default' id='01a1b934'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='gr_name' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='gr_passwd' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='gr_gid' type-id='d94ec6d9' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='gr_mem' type-id='9b23c9ad' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='mnt_type' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='passwd' size-in-bits='384' is-struct='yes' visibility='default' id='a63d15a3'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='pw_name' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='pw_passwd' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='pw_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='pw_gid' type-id='d94ec6d9' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='pw_gecos' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='pw_dir' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='pw_shell' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='8e0573fd' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/>
+ <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
+ <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
+ <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
+ <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
+ <class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='tm_min' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='tm_year' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='tm_zone' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
<typedef-decl name='uid_t' type-id='cc5fcceb' id='354978ed'/>
- <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
- <qualified-type-def type-id='775509eb' const='yes' id='5eadf2db'/>
- <pointer-type-def type-id='5eadf2db' size-in-bits='64' id='fcd57163'/>
+ <typedef-decl name='prop_changelist_t' type-id='d86edc51' id='eae6431d'/>
+ <pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
+ <pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/>
+ <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
+ <qualified-type-def type-id='56fe4a37' const='yes' id='a75125ce'/>
+ <pointer-type-def type-id='a75125ce' size-in-bits='64' id='48bea5ec'/>
+ <qualified-type-def type-id='8afd6070' const='yes' id='1d853360'/>
+ <pointer-type-def type-id='1d853360' size-in-bits='64' id='c2afbd7e'/>
+ <qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/>
+ <pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/>
+ <qualified-type-def type-id='9f201474' restrict='yes' id='d6e2847c'/>
+ <qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/>
+ <pointer-type-def type-id='e824a34f' size-in-bits='64' id='d6ad37ff'/>
+ <qualified-type-def type-id='d6ad37ff' restrict='yes' id='f8c6051d'/>
+ <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/>
+ <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/>
+ <pointer-type-def type-id='01a1b934' size-in-bits='64' id='566b3f52'/>
+ <qualified-type-def type-id='566b3f52' restrict='yes' id='c878edd6'/>
+ <pointer-type-def type-id='566b3f52' size-in-bits='64' id='82d4e9e8'/>
+ <qualified-type-def type-id='82d4e9e8' restrict='yes' id='aa19c230'/>
<pointer-type-def type-id='7e291ce6' size-in-bits='64' id='ca64ff60'/>
- <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
+ <pointer-type-def type-id='9da381c4' size-in-bits='64' id='cb785ebf'/>
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
- <pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
+ <pointer-type-def type-id='8e0af06e' size-in-bits='64' id='053457bd'/>
+ <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/>
+ <pointer-type-def type-id='a63d15a3' size-in-bits='64' id='a195f4a3'/>
+ <qualified-type-def type-id='a195f4a3' restrict='yes' id='33518961'/>
+ <pointer-type-def type-id='a195f4a3' size-in-bits='64' id='e80ff3ab'/>
+ <qualified-type-def type-id='e80ff3ab' restrict='yes' id='8f2c7109'/>
+ <pointer-type-def type-id='eae6431d' size-in-bits='64' id='0d41d328'/>
+ <pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/>
+ <pointer-type-def type-id='dddf6ca2' size-in-bits='64' id='d915a820'/>
+ <qualified-type-def type-id='d915a820' restrict='yes' id='f099ad08'/>
+ <pointer-type-def type-id='5d6479ae' size-in-bits='64' id='892b4acc'/>
<pointer-type-def type-id='bd9b4291' size-in-bits='64' id='9f1a1109'/>
<pointer-type-def type-id='bdb8ac4f' size-in-bits='64' id='3a9b2288'/>
<pointer-type-def type-id='3a9b2288' size-in-bits='64' id='e4378506'/>
- <pointer-type-def type-id='a2256d42' size-in-bits='64' id='debc6aa3'/>
+ <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/>
+ <function-decl name='zpool_open' mangled-name='zpool_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='4c81de99'/>
+ </function-decl>
+ <function-decl name='zpool_open_canfail' mangled-name='zpool_open_canfail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open_canfail'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='4c81de99'/>
+ </function-decl>
+ <function-decl name='zpool_close' mangled-name='zpool_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_close'>
+ <parameter type-id='4c81de99'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zpool_get_name' mangled-name='zpool_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_name'>
+ <parameter type-id='4c81de99'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zpool_get_prop' mangled-name='zpool_get_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='5d0c23fb'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='debc6aa3'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_prop_default_string' mangled-name='zfs_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_string'>
+ <parameter type-id='58603c44'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zfs_prop_default_numeric' mangled-name='zfs_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_numeric'>
+ <parameter type-id='58603c44'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_iter_snapshots_v2' mangled-name='zfs_iter_snapshots_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_v2'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_iter_bookmarks_v2' mangled-name='zfs_iter_bookmarks_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks_v2'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='d8e49ab9'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_destroy_snaps_nvl_os' mangled-name='zfs_destroy_snaps_nvl_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps_nvl_os'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_nicestrtonum' mangled-name='zfs_nicestrtonum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicestrtonum'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_snapshot' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='bc9887f1'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='ae3e8ca6'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_clone' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_promote' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_destroy_snaps' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_get_bookmarks' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_destroy_bookmarks' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_hold' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_release' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_get_holds' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_exists' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='lzc_rollback_to' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_channel_program_nosync' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_wait_fs' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3024501a'/>
+ <parameter type-id='37e3bd22'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_nicebytes' mangled-name='zfs_nicebytes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicebytes'>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_nicenum' mangled-name='zfs_nicenum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicenum'>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_create' mangled-name='avl_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_create'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='585e1de9'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_find' mangled-name='avl_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_find'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='32adbf30'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_remove' mangled-name='avl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_remove'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='ee1f298e'/>
+ </function-decl>
+ <function-decl name='avl_destroy_nodes' mangled-name='avl_destroy_nodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy_nodes'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='63e171df'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_destroy' mangled-name='avl_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_prop_readonly' mangled-name='zfs_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_readonly'>
+ <parameter type-id='58603c44'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_inheritable' mangled-name='zfs_prop_inheritable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inheritable'>
+ <parameter type-id='58603c44'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_setonce' mangled-name='zfs_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_setonce'>
+ <parameter type-id='58603c44'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_encryption_key_param' mangled-name='zfs_prop_encryption_key_param' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_encryption_key_param'>
+ <parameter type-id='58603c44'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_valid_keylocation' mangled-name='zfs_prop_valid_keylocation' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_keylocation'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_user' mangled-name='zfs_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_user'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_userquota' mangled-name='zfs_prop_userquota' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_userquota'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_written' mangled-name='zfs_prop_written' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_written'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfs_prop_index_to_string' mangled-name='zfs_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_index_to_string'>
+ <parameter type-id='58603c44'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_prop_valid_for_type' mangled-name='zfs_prop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_for_type'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='2e45de5d'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_size' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='78c01427'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_pack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='9b23c9ad'/>
+ <parameter type-id='78c01427'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_unpack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='22cce67b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='713a56f5'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='8d0687d2'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_int64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='cb785ebf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='892b4acc'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='75be733c'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_empty' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvpair_type' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='8d0687d2'/>
+ </function-decl>
+ <function-decl name='nvpair_value_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='3ff5601b'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='entity_namecheck' mangled-name='entity_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='entity_namecheck'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='053457bd'/>
+ <parameter type-id='26a90f95'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='dataset_nestcheck' mangled-name='dataset_nestcheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='dataset_nestcheck'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='mountpoint_namecheck' mangled-name='mountpoint_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mountpoint_namecheck'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='053457bd'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_prop_get_type' mangled-name='zfs_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_type'>
+ <parameter type-id='58603c44'/>
+ <return type-id='31429eff'/>
+ </function-decl>
+ <function-decl name='sa_validate_shareopts' mangled-name='sa_validate_shareopts' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_validate_shareopts'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9155d4b5'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'>
+ <parameter type-id='822cd80b'/>
+ <parameter type-id='9d424d31'/>
+ <parameter type-id='9d424d31'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'>
+ <parameter type-id='822cd80b'/>
+ <parameter type-id='9d424d31'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='getgrnam_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='c878edd6'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='aa19c230'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='hasmntopt' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='48bea5ec'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_init' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <parameter type-id='c2afbd7e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_destroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='getpwnam_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='33518961'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='8f2c7109'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
+ <function-decl name='strtoul' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='7359adad'/>
+ </function-decl>
+ <function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='strstr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strsep' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='9d26089a'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strftime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f8c6051d'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='localtime_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='d6e2847c'/>
+ <parameter type-id='f099ad08'/>
+ <return type-id='d915a820'/>
+ </function-decl>
+ <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7359adad'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_type_to_name' mangled-name='zfs_type_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_type_to_name'>
<parameter type-id='2e45de5d' name='type'/>
<return type-id='80f4b756'/>
@@ -2474,28 +4382,10 @@
<parameter type-id='b0382bb3' name='hdl'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_refresh_properties' mangled-name='zfs_refresh_properties' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_refresh_properties'>
- <parameter type-id='9200a744' name='zhp'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zfs_handle_dup' mangled-name='zfs_handle_dup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_handle_dup'>
- <parameter type-id='9200a744' name='zhp_orig'/>
- <return type-id='9200a744'/>
- </function-decl>
<function-decl name='zfs_bookmark_exists' mangled-name='zfs_bookmark_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_bookmark_exists'>
<parameter type-id='80f4b756' name='path'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zfs_open' mangled-name='zfs_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_open'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='80f4b756' name='path'/>
- <parameter type-id='95e97e5e' name='types'/>
- <return type-id='9200a744'/>
- </function-decl>
- <function-decl name='zfs_close' mangled-name='zfs_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_close'>
- <parameter type-id='9200a744' name='zhp'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='libzfs_mnttab_init' mangled-name='libzfs_mnttab_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_init'>
<parameter type-id='b0382bb3' name='hdl'/>
<return type-id='48b5725f'/>
@@ -2532,17 +4422,6 @@
<parameter type-id='7292109c' name='spa_version'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_valid_proplist' mangled-name='zfs_valid_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_valid_proplist'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='2e45de5d' name='type'/>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='9c313c2d' name='zoned'/>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='4c81de99' name='zpool_hdl'/>
- <parameter type-id='c19b74c3' name='key_params_ok'/>
- <parameter type-id='80f4b756' name='errbuf'/>
- <return type-id='5ce45b60'/>
- </function-decl>
<function-decl name='zfs_prop_set' mangled-name='zfs_prop_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='80f4b756' name='propname'/>
@@ -2554,6 +4433,12 @@
<parameter type-id='5ce45b60' name='props'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zfs_prop_set_list_flags' mangled-name='zfs_prop_set_list_flags' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set_list_flags'>
+ <parameter type-id='9200a744' name='zhp'/>
+ <parameter type-id='5ce45b60' name='props'/>
+ <parameter type-id='95e97e5e' name='flags'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_prop_inherit' mangled-name='zfs_prop_inherit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inherit'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='80f4b756' name='propname'/>
@@ -2563,7 +4448,7 @@
<function-decl name='getprop_uint64' mangled-name='getprop_uint64' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getprop_uint64'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='58603c44' name='prop'/>
- <parameter type-id='9b23c9ad' name='source'/>
+ <parameter type-id='7d3cd834' name='source'/>
<return type-id='9c313c2d'/>
</function-decl>
<function-decl name='zfs_prop_get_recvd' mangled-name='zfs_prop_get_recvd' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_recvd'>
@@ -2578,22 +4463,6 @@
<parameter type-id='9200a744' name='zhp'/>
<return type-id='5ce45b60'/>
</function-decl>
- <function-decl name='zfs_prop_get' mangled-name='zfs_prop_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='58603c44' name='prop'/>
- <parameter type-id='26a90f95' name='propbuf'/>
- <parameter type-id='b59d7dce' name='proplen'/>
- <parameter type-id='debc6aa3' name='src'/>
- <parameter type-id='26a90f95' name='statbuf'/>
- <parameter type-id='b59d7dce' name='statlen'/>
- <parameter type-id='c19b74c3' name='literal'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zfs_prop_get_int' mangled-name='zfs_prop_get_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_int'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='9c313c2d'/>
- </function-decl>
<function-decl name='zfs_prop_get_numeric' mangled-name='zfs_prop_get_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_numeric'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='58603c44' name='prop'/>
@@ -2631,10 +4500,6 @@
<parameter type-id='c19b74c3' name='literal'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_get_name' mangled-name='zfs_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_name'>
- <parameter type-id='fcd57163' name='zhp'/>
- <return type-id='80f4b756'/>
- </function-decl>
<function-decl name='zfs_get_pool_name' mangled-name='zfs_get_pool_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_pool_name'>
<parameter type-id='fcd57163' name='zhp'/>
<return type-id='80f4b756'/>
@@ -2647,12 +4512,6 @@
<parameter type-id='fcd57163' name='zhp'/>
<return type-id='2e45de5d'/>
</function-decl>
- <function-decl name='zfs_parent_name' mangled-name='zfs_parent_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parent_name'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zfs_dataset_exists' mangled-name='zfs_dataset_exists' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dataset_exists'>
<parameter type-id='b0382bb3' name='hdl'/>
<parameter type-id='80f4b756' name='path'/>
@@ -2832,6 +4691,90 @@
<parameter type-id='37e3bd22' name='waited'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zfs_error_fmt' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_standard_error_fmt' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_setprop_error' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='58603c44'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='26a90f95'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zprop_parse_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='2e45de5d'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='7d3cd834'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zprop_expand_list' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4378506'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zcmd_write_src_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='changelist_prefix' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='changelist_postfix' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='changelist_rename' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='changelist_remove' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='changelist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='changelist_gather' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='58603c44'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='0d41d328'/>
+ </function-decl>
+ <function-decl name='changelist_haszonedchild' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_name_valid' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
<function-type size-in-bits='64' id='7e291ce6'>
<parameter type-id='eaa32e2f'/>
<parameter type-id='80f4b756'/>
@@ -2841,6 +4784,125 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_diff.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'>
+ <subrange length='56' type-id='7359adad' id='f8137894'/>
+ </array-type-def>
+ <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/>
+ <union-decl name='pthread_attr_t' size-in-bits='448' visibility='default' id='b63afacd'>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='6093ff7c' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_attr_t' type-id='b63afacd' id='7d8569fd'/>
+ <class-decl name='differ_info' size-in-bits='9088' is-struct='yes' visibility='default' id='d41965ee'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zhp' type-id='9200a744' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='fromsnap' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='frommnt' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='tosnap' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='tomnt' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='ds' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='dsmnt' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='tmpsnap' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='errbuf' type-id='b54ce520' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8704'>
+ <var-decl name='isclone' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8736'>
+ <var-decl name='scripted' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8768'>
+ <var-decl name='classify' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8800'>
+ <var-decl name='timestamped' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8832'>
+ <var-decl name='no_mangle' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8896'>
+ <var-decl name='shares' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8960'>
+ <var-decl name='zerr' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8992'>
+ <var-decl name='cleanupfd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='9024'>
+ <var-decl name='outputfd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='9056'>
+ <var-decl name='datafd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='differ_info_t' type-id='d41965ee' id='e8525f0e'/>
+ <qualified-type-def type-id='7d8569fd' const='yes' id='e06dee2d'/>
+ <pointer-type-def type-id='e06dee2d' size-in-bits='64' id='540db505'/>
+ <qualified-type-def type-id='540db505' restrict='yes' id='e1815e87'/>
+ <pointer-type-def type-id='e8525f0e' size-in-bits='64' id='ee78f675'/>
+ <pointer-type-def type-id='4051f5e7' size-in-bits='64' id='e01b5462'/>
+ <qualified-type-def type-id='e01b5462' restrict='yes' id='cc338b26'/>
+ <pointer-type-def type-id='cd5d79f4' size-in-bits='64' id='5ad9edb6'/>
+ <function-decl name='is_mounted' mangled-name='is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='is_mounted'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9b23c9ad'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='color_start' mangled-name='color_start' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_start'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='color_end' mangled-name='color_end' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_end'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='pthread_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='cc338b26'/>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='5ad9edb6'/>
+ <parameter type-id='1b7446cd'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_join' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4051f5e7'/>
+ <parameter type-id='63e171df'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_cancel' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4051f5e7'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fputs' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='e75a27e9'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pipe2' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7292109c'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_show_diffs' mangled-name='zfs_show_diffs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_show_diffs'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='95e97e5e' name='outfd'/>
@@ -2849,8 +4911,32 @@
<parameter type-id='95e97e5e' name='flags'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zfs_asprintf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='zfs_validate_name' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='find_shares_object' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='ee78f675'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-type size-in-bits='64' id='cd5d79f4'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='eaa32e2f'/>
+ </function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_import.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
+ <subrange length='3' type-id='7359adad' id='56f209d2'/>
+ </array-type-def>
<typedef-decl name='refresh_config_func_t' type-id='29f040d2' id='b7c58eaa'/>
<typedef-decl name='pool_active_func_t' type-id='baa42fef' id='de5d1d8f'/>
<class-decl name='pool_config_ops' size-in-bits='128' is-struct='yes' visibility='default' id='8b092c69'>
@@ -2874,11 +4960,106 @@
<enumerator name='POOL_STATE_POTENTIALLY_ACTIVE' value='7'/>
</enum-decl>
<typedef-decl name='pool_state_t' type-id='4871ac24' id='084a08a3'/>
+ <class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='st_ino' type-id='71288a47' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='st_size' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='st_blocks' type-id='4e711bf1' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
+ <typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
+ <typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
+ <typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
+ <typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
+ <typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
+ <typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
+ <class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
+ </data-member>
+ </class-decl>
<qualified-type-def type-id='8b092c69' const='yes' id='1a21babe'/>
<pointer-type-def type-id='de5d1d8f' size-in-bits='64' id='9eadf5e0'/>
<pointer-type-def type-id='084a08a3' size-in-bits='64' id='b9ea57b8'/>
<pointer-type-def type-id='b7c58eaa' size-in-bits='64' id='e7c00489'/>
+ <pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
<var-decl name='libzfs_config_ops' type-id='b1e62775' mangled-name='libzfs_config_ops' visibility='default' elf-symbol-id='libzfs_config_ops'/>
+ <function-decl name='zpool_read_label' mangled-name='zpool_read_label' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_read_label'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='7292109c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pwrite64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='724e4de6'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
+ <function-decl name='__pread64_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='724e4de6'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
+ <function-decl name='fstat64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='62f7a03d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zcmd_write_conf_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='zpool_clear_label' mangled-name='zpool_clear_label' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_clear_label'>
<parameter type-id='95e97e5e' name='fd'/>
<return type-id='95e97e5e'/>
@@ -2905,6 +5086,33 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_iter.c' language='LANG_C99'>
+ <pointer-type-def type-id='b351119f' size-in-bits='64' id='716943c7'/>
+ <function-decl name='avl_first' mangled-name='avl_first' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_first'>
+ <parameter type-id='a3681dea'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='avl_walk' mangled-name='avl_walk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_walk'>
+ <parameter type-id='716943c7'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='make_dataset_handle_zc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='e4ec4540'/>
+ <return type-id='9200a744'/>
+ </function-decl>
+ <function-decl name='make_dataset_simple_handle_zc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='e4ec4540'/>
+ <return type-id='9200a744'/>
+ </function-decl>
+ <function-decl name='make_bookmark_handle' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='9200a744'/>
+ </function-decl>
<function-decl name='zfs_iter_filesystems' mangled-name='zfs_iter_filesystems' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='d8e49ab9' name='func'/>
@@ -2934,6 +5142,15 @@
<parameter type-id='9c313c2d' name='max_txg'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zfs_iter_snapshots_sorted_v2' mangled-name='zfs_iter_snapshots_sorted_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_sorted_v2'>
+ <parameter type-id='9200a744' name='zhp'/>
+ <parameter type-id='95e97e5e' name='flags'/>
+ <parameter type-id='d8e49ab9' name='callback'/>
+ <parameter type-id='eaa32e2f' name='data'/>
+ <parameter type-id='9c313c2d' name='min_txg'/>
+ <parameter type-id='9c313c2d' name='max_txg'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_iter_snapspec' mangled-name='zfs_iter_snapspec' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapspec'>
<parameter type-id='9200a744' name='fs_zhp'/>
<parameter type-id='80f4b756' name='spec_orig'/>
@@ -2941,27 +5158,89 @@
<parameter type-id='eaa32e2f' name='arg'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_iter_children' mangled-name='zfs_iter_children' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children'>
- <parameter type-id='9200a744' name='zhp'/>
+ <function-decl name='zfs_iter_snapspec_v2' mangled-name='zfs_iter_snapspec_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapspec_v2'>
+ <parameter type-id='9200a744' name='fs_zhp'/>
+ <parameter type-id='95e97e5e' name='flags'/>
+ <parameter type-id='80f4b756' name='spec_orig'/>
<parameter type-id='d8e49ab9' name='func'/>
- <parameter type-id='eaa32e2f' name='data'/>
+ <parameter type-id='eaa32e2f' name='arg'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_iter_dependents' mangled-name='zfs_iter_dependents' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents'>
+ <function-decl name='zfs_iter_children' mangled-name='zfs_iter_children' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children'>
<parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='c19b74c3' name='allowrecursion'/>
<parameter type-id='d8e49ab9' name='func'/>
<parameter type-id='eaa32e2f' name='data'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_iter_mounted' mangled-name='zfs_iter_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_mounted'>
+ <function-decl name='zfs_iter_dependents' mangled-name='zfs_iter_dependents' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents'>
<parameter type-id='9200a744' name='zhp'/>
+ <parameter type-id='c19b74c3' name='allowrecursion'/>
<parameter type-id='d8e49ab9' name='func'/>
<parameter type-id='eaa32e2f' name='data'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_mount.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='6028cbfe' size-in-bits='256' id='b39b9aa7'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
+ <class-decl name='__dirstream' is-struct='yes' visibility='default' is-declaration-only='yes' id='20cd73f2'/>
+ <class-decl name='tpool' size-in-bits='2496' is-struct='yes' visibility='default' id='88d1b7f9'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tp_forw' type-id='9cf59a50' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tp_back' type-id='9cf59a50' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='tp_mutex' type-id='7a6844eb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='tp_busycv' type-id='62fab762' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='tp_workcv' type-id='62fab762' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1216'>
+ <var-decl name='tp_waitcv' type-id='62fab762' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1600'>
+ <var-decl name='tp_active' type-id='ad33e5e7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1664'>
+ <var-decl name='tp_head' type-id='f32b30e4' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1728'>
+ <var-decl name='tp_tail' type-id='f32b30e4' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1792'>
+ <var-decl name='tp_attr' type-id='7d8569fd' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2240'>
+ <var-decl name='tp_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2272'>
+ <var-decl name='tp_linger' type-id='3502e3ff' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2304'>
+ <var-decl name='tp_njobs' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2336'>
+ <var-decl name='tp_minimum' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2368'>
+ <var-decl name='tp_maximum' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2400'>
+ <var-decl name='tp_current' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2432'>
+ <var-decl name='tp_idle' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='64' id='e4266c7e'>
+ <subrange length='2' type-id='7359adad' id='52efc4ef'/>
+ </array-type-def>
<class-decl name='get_all_cb' size-in-bits='192' is-struct='yes' visibility='default' id='803dac95'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='cb_handles' type-id='4507922a' visibility='default'/>
@@ -2974,31 +5253,251 @@
</data-member>
</class-decl>
<typedef-decl name='get_all_cb_t' type-id='803dac95' id='9b293607'/>
- <enum-decl name='sa_protocol' id='9155d4b5'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='SA_PROTOCOL_NFS' value='0'/>
- <enumerator name='SA_PROTOCOL_SMB' value='1'/>
- <enumerator name='SA_PROTOCOL_COUNT' value='2'/>
- </enum-decl>
- <qualified-type-def type-id='9155d4b5' const='yes' id='9f2c1699'/>
- <pointer-type-def type-id='9f2c1699' size-in-bits='64' id='4567bbc9'/>
+ <typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/>
+ <typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/>
+ <typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
+ <typedef-decl name='__compar_fn_t' type-id='585e1de9' id='aba7edd8'/>
+ <class-decl name='dirent64' size-in-bits='2240' is-struct='yes' visibility='default' id='5725d813'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='d_ino' type-id='71288a47' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='d_off' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='d_reclen' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='144'>
+ <var-decl name='d_type' type-id='002ac4a6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='152'>
+ <var-decl name='d_name' type-id='d1617432' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='statfs64' size-in-bits='960' is-struct='yes' visibility='default' id='a2a6be1a'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='f_type' type-id='6028cbfe' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='f_bsize' type-id='6028cbfe' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='f_blocks' type-id='95fe1a02' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='f_bfree' type-id='95fe1a02' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='f_bavail' type-id='95fe1a02' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='f_files' type-id='0c3a4dde' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='f_ffree' type-id='0c3a4dde' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='f_fsid' type-id='0f35d263' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='f_namelen' type-id='6028cbfe' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='f_frsize' type-id='6028cbfe' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='f_flags' type-id='6028cbfe' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='f_spare' type-id='b39b9aa7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='stat' size-in-bits='1152' is-struct='yes' visibility='default' id='aafc373f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='st_ino' type-id='e43e523d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='st_size' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='st_blocks' type-id='dbc43803' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__ino_t' type-id='7359adad' id='e43e523d'/>
+ <class-decl name='__fsid_t' size-in-bits='64' is-struct='yes' naming-typedef-id='0f35d263' visibility='default' id='ea35c84a'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__val' type-id='e4266c7e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__fsid_t' type-id='ea35c84a' id='0f35d263'/>
+ <typedef-decl name='__blkcnt_t' type-id='bd54fe1a' id='dbc43803'/>
+ <typedef-decl name='__fsblkcnt64_t' type-id='7359adad' id='95fe1a02'/>
+ <typedef-decl name='__fsfilcnt64_t' type-id='7359adad' id='0c3a4dde'/>
+ <typedef-decl name='__fsword_t' type-id='bd54fe1a' id='6028cbfe'/>
+ <pointer-type-def type-id='54a5d683' size-in-bits='64' id='f09217ba'/>
+ <pointer-type-def type-id='5725d813' size-in-bits='64' id='07b96073'/>
<pointer-type-def type-id='9b293607' size-in-bits='64' id='77bf1784'/>
+ <pointer-type-def type-id='7d8569fd' size-in-bits='64' id='7347a39e'/>
+ <pointer-type-def type-id='aafc373f' size-in-bits='64' id='4330df87'/>
+ <qualified-type-def type-id='4330df87' restrict='yes' id='73665405'/>
+ <pointer-type-def type-id='a2a6be1a' size-in-bits='64' id='7fd094c8'/>
+ <pointer-type-def type-id='b1bbf10d' size-in-bits='64' id='9cf59a50'/>
+ <pointer-type-def type-id='c5c76c9c' size-in-bits='64' id='b7f9d8e6'/>
<pointer-type-def type-id='9200a744' size-in-bits='64' id='4507922a'/>
- <function-decl name='is_mounted' mangled-name='is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='is_mounted'>
- <parameter type-id='b0382bb3' name='zfs_hdl'/>
- <parameter type-id='80f4b756' name='special'/>
- <parameter type-id='9b23c9ad' name='where'/>
- <return type-id='c19b74c3'/>
+ <class-decl name='__dirstream' is-struct='yes' visibility='default' is-declaration-only='yes' id='20cd73f2'/>
+ <function-decl name='zpool_disable_datasets_os' mangled-name='zpool_disable_datasets_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_datasets_os'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_is_mounted' mangled-name='zfs_is_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_mounted'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='9b23c9ad' name='where'/>
+ <function-decl name='zpool_disable_volume_os' mangled-name='zpool_disable_volume_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_volume_os'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='tpool_create' mangled-name='tpool_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_create'>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='7347a39e'/>
+ <return type-id='9cf59a50'/>
+ </function-decl>
+ <function-decl name='tpool_dispatch' mangled-name='tpool_dispatch' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_dispatch'>
+ <parameter type-id='9cf59a50'/>
+ <parameter type-id='b7f9d8e6'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='tpool_destroy' mangled-name='tpool_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_destroy'>
+ <parameter type-id='9cf59a50'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='tpool_wait' mangled-name='tpool_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='tpool_wait'>
+ <parameter type-id='9cf59a50'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='d50d396c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='sa_errorstr' mangled-name='sa_errorstr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_errorstr'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='sa_enable_share' mangled-name='sa_enable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_enable_share'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9155d4b5'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='sa_disable_share' mangled-name='sa_disable_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_disable_share'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9155d4b5'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='sa_is_shared' mangled-name='sa_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_is_shared'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9155d4b5'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zfs_mount' mangled-name='zfs_mount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='80f4b756' name='options'/>
- <parameter type-id='95e97e5e' name='flags'/>
+ <function-decl name='sa_truncate_shares' mangled-name='sa_truncate_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='sa_truncate_shares'>
+ <parameter type-id='9155d4b5'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fdopendir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='f09217ba'/>
+ </function-decl>
+ <function-decl name='closedir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f09217ba'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='readdir64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f09217ba'/>
+ <return type-id='07b96073'/>
+ </function-decl>
+ <function-decl name='qsort' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='aba7edd8'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='rmdir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__openat_too_many_args' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__openat_missing_mode' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='statfs64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='7fd094c8'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_realloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='changelist_unshare' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0d41d328'/>
+ <parameter type-id='4567bbc9'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='do_mount' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='do_unmount' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9200a744'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_mount_at' mangled-name='zfs_mount_at' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount_at'>
@@ -3008,38 +5507,15 @@
<parameter type-id='80f4b756' name='mountpoint'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_unmount' mangled-name='zfs_unmount' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unmount'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='80f4b756' name='mountpoint'/>
- <parameter type-id='95e97e5e' name='flags'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zfs_unmountall' mangled-name='zfs_unmountall' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unmountall'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='95e97e5e' name='flags'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_share' mangled-name='zfs_share' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_share'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='4567bbc9' name='proto'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zfs_is_shared' mangled-name='zfs_is_shared' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_is_shared'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='9b23c9ad' name='where'/>
- <parameter type-id='4567bbc9' name='proto'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zfs_commit_shares' mangled-name='zfs_commit_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_commit_shares'>
+ <function-decl name='zfs_truncate_shares' mangled-name='zfs_truncate_shares' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_truncate_shares'>
<parameter type-id='4567bbc9' name='proto'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_unshare' mangled-name='zfs_unshare' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unshare'>
- <parameter type-id='9200a744' name='zhp'/>
- <parameter type-id='80f4b756' name='mountpoint'/>
- <parameter type-id='4567bbc9' name='proto'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zfs_unshareall' mangled-name='zfs_unshareall' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_unshareall'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='4567bbc9' name='proto'/>
@@ -3072,12 +5548,13 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_pool.c' language='LANG_C99'>
+ <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
<class-decl name='splitflags' size-in-bits='64' is-struct='yes' visibility='default' id='dc01bf52'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='dryrun' type-id='95e97e5e' visibility='default'/>
+ <var-decl name='dryrun' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1'>
- <var-decl name='import' type-id='95e97e5e' visibility='default'/>
+ <var-decl name='import' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='name_flags' type-id='95e97e5e' visibility='default'/>
@@ -3099,6 +5576,43 @@
</data-member>
</class-decl>
<typedef-decl name='trimflags_t' type-id='8ef58008' id='a093cbb8'/>
+ <enum-decl name='zpool_status_t' naming-typedef-id='d3dd6294' id='5e770b40'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZPOOL_STATUS_CORRUPT_CACHE' value='0'/>
+ <enumerator name='ZPOOL_STATUS_MISSING_DEV_R' value='1'/>
+ <enumerator name='ZPOOL_STATUS_MISSING_DEV_NR' value='2'/>
+ <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_R' value='3'/>
+ <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_NR' value='4'/>
+ <enumerator name='ZPOOL_STATUS_BAD_GUID_SUM' value='5'/>
+ <enumerator name='ZPOOL_STATUS_CORRUPT_POOL' value='6'/>
+ <enumerator name='ZPOOL_STATUS_CORRUPT_DATA' value='7'/>
+ <enumerator name='ZPOOL_STATUS_FAILING_DEV' value='8'/>
+ <enumerator name='ZPOOL_STATUS_VERSION_NEWER' value='9'/>
+ <enumerator name='ZPOOL_STATUS_HOSTID_MISMATCH' value='10'/>
+ <enumerator name='ZPOOL_STATUS_HOSTID_ACTIVE' value='11'/>
+ <enumerator name='ZPOOL_STATUS_HOSTID_REQUIRED' value='12'/>
+ <enumerator name='ZPOOL_STATUS_IO_FAILURE_WAIT' value='13'/>
+ <enumerator name='ZPOOL_STATUS_IO_FAILURE_CONTINUE' value='14'/>
+ <enumerator name='ZPOOL_STATUS_IO_FAILURE_MMP' value='15'/>
+ <enumerator name='ZPOOL_STATUS_BAD_LOG' value='16'/>
+ <enumerator name='ZPOOL_STATUS_ERRATA' value='17'/>
+ <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_READ' value='18'/>
+ <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_WRITE' value='19'/>
+ <enumerator name='ZPOOL_STATUS_FAULTED_DEV_R' value='20'/>
+ <enumerator name='ZPOOL_STATUS_FAULTED_DEV_NR' value='21'/>
+ <enumerator name='ZPOOL_STATUS_VERSION_OLDER' value='22'/>
+ <enumerator name='ZPOOL_STATUS_FEAT_DISABLED' value='23'/>
+ <enumerator name='ZPOOL_STATUS_RESILVERING' value='24'/>
+ <enumerator name='ZPOOL_STATUS_OFFLINE_DEV' value='25'/>
+ <enumerator name='ZPOOL_STATUS_REMOVED_DEV' value='26'/>
+ <enumerator name='ZPOOL_STATUS_REBUILDING' value='27'/>
+ <enumerator name='ZPOOL_STATUS_REBUILD_SCRUB' value='28'/>
+ <enumerator name='ZPOOL_STATUS_NON_NATIVE_ASHIFT' value='29'/>
+ <enumerator name='ZPOOL_STATUS_COMPATIBILITY_ERR' value='30'/>
+ <enumerator name='ZPOOL_STATUS_INCOMPATIBLE_FEAT' value='31'/>
+ <enumerator name='ZPOOL_STATUS_OK' value='32'/>
+ </enum-decl>
+ <typedef-decl name='zpool_status_t' type-id='5e770b40' id='d3dd6294'/>
<enum-decl name='zpool_compat_status_t' naming-typedef-id='901b78d1' id='20676925'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZPOOL_COMPATIBILITY_OK' value='0'/>
@@ -3108,48 +5622,10 @@
<enumerator name='ZPOOL_COMPATIBILITY_NOFILES' value='4'/>
</enum-decl>
<typedef-decl name='zpool_compat_status_t' type-id='20676925' id='901b78d1'/>
- <enum-decl name='zpool_prop_t' naming-typedef-id='5d0c23fb' id='af1ba157'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='ZPOOL_PROP_INVAL' value='-1'/>
- <enumerator name='ZPOOL_PROP_NAME' value='0'/>
- <enumerator name='ZPOOL_PROP_SIZE' value='1'/>
- <enumerator name='ZPOOL_PROP_CAPACITY' value='2'/>
- <enumerator name='ZPOOL_PROP_ALTROOT' value='3'/>
- <enumerator name='ZPOOL_PROP_HEALTH' value='4'/>
- <enumerator name='ZPOOL_PROP_GUID' value='5'/>
- <enumerator name='ZPOOL_PROP_VERSION' value='6'/>
- <enumerator name='ZPOOL_PROP_BOOTFS' value='7'/>
- <enumerator name='ZPOOL_PROP_DELEGATION' value='8'/>
- <enumerator name='ZPOOL_PROP_AUTOREPLACE' value='9'/>
- <enumerator name='ZPOOL_PROP_CACHEFILE' value='10'/>
- <enumerator name='ZPOOL_PROP_FAILUREMODE' value='11'/>
- <enumerator name='ZPOOL_PROP_LISTSNAPS' value='12'/>
- <enumerator name='ZPOOL_PROP_AUTOEXPAND' value='13'/>
- <enumerator name='ZPOOL_PROP_DEDUPDITTO' value='14'/>
- <enumerator name='ZPOOL_PROP_DEDUPRATIO' value='15'/>
- <enumerator name='ZPOOL_PROP_FREE' value='16'/>
- <enumerator name='ZPOOL_PROP_ALLOCATED' value='17'/>
- <enumerator name='ZPOOL_PROP_READONLY' value='18'/>
- <enumerator name='ZPOOL_PROP_ASHIFT' value='19'/>
- <enumerator name='ZPOOL_PROP_COMMENT' value='20'/>
- <enumerator name='ZPOOL_PROP_EXPANDSZ' value='21'/>
- <enumerator name='ZPOOL_PROP_FREEING' value='22'/>
- <enumerator name='ZPOOL_PROP_FRAGMENTATION' value='23'/>
- <enumerator name='ZPOOL_PROP_LEAKED' value='24'/>
- <enumerator name='ZPOOL_PROP_MAXBLOCKSIZE' value='25'/>
- <enumerator name='ZPOOL_PROP_TNAME' value='26'/>
- <enumerator name='ZPOOL_PROP_MAXDNODESIZE' value='27'/>
- <enumerator name='ZPOOL_PROP_MULTIHOST' value='28'/>
- <enumerator name='ZPOOL_PROP_CHECKPOINT' value='29'/>
- <enumerator name='ZPOOL_PROP_LOAD_GUID' value='30'/>
- <enumerator name='ZPOOL_PROP_AUTOTRIM' value='31'/>
- <enumerator name='ZPOOL_PROP_COMPATIBILITY' value='32'/>
- <enumerator name='ZPOOL_NUM_PROPS' value='33'/>
- </enum-decl>
- <typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
<enum-decl name='vdev_prop_t' naming-typedef-id='5aa5c90c' id='1573bec8'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='VDEV_PROP_INVAL' value='-1'/>
+ <enumerator name='VDEV_PROP_USERPROP' value='-1'/>
<enumerator name='VDEV_PROP_NAME' value='0'/>
<enumerator name='VDEV_PROP_CAPACITY' value='1'/>
<enumerator name='VDEV_PROP_STATE' value='2'/>
@@ -3191,9 +5667,32 @@
<enumerator name='VDEV_PROP_BYTES_TRIM' value='38'/>
<enumerator name='VDEV_PROP_REMOVING' value='39'/>
<enumerator name='VDEV_PROP_ALLOCATING' value='40'/>
- <enumerator name='VDEV_NUM_PROPS' value='41'/>
+ <enumerator name='VDEV_PROP_FAILFAST' value='41'/>
+ <enumerator name='VDEV_PROP_CHECKSUM_N' value='42'/>
+ <enumerator name='VDEV_PROP_CHECKSUM_T' value='43'/>
+ <enumerator name='VDEV_PROP_IO_N' value='44'/>
+ <enumerator name='VDEV_PROP_IO_T' value='45'/>
+ <enumerator name='VDEV_PROP_RAIDZ_EXPANDING' value='46'/>
+ <enumerator name='VDEV_PROP_SLOW_IO_N' value='47'/>
+ <enumerator name='VDEV_PROP_SLOW_IO_T' value='48'/>
+ <enumerator name='VDEV_NUM_PROPS' value='49'/>
</enum-decl>
<typedef-decl name='vdev_prop_t' type-id='1573bec8' id='5aa5c90c'/>
+ <class-decl name='zpool_load_policy' size-in-bits='256' is-struct='yes' visibility='default' id='2f65b36f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zlp_rewind' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='zlp_maxmeta' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='zlp_maxdata' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='zlp_txg' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zpool_load_policy_t' type-id='2f65b36f' id='d11b7617'/>
<enum-decl name='vdev_state' id='21566197'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='VDEV_STATE_UNKNOWN' value='0'/>
@@ -3236,7 +5735,8 @@
<enumerator name='POOL_SCAN_NONE' value='0'/>
<enumerator name='POOL_SCAN_SCRUB' value='1'/>
<enumerator name='POOL_SCAN_RESILVER' value='2'/>
- <enumerator name='POOL_SCAN_FUNCS' value='3'/>
+ <enumerator name='POOL_SCAN_ERRORSCRUB' value='3'/>
+ <enumerator name='POOL_SCAN_FUNCS' value='4'/>
</enum-decl>
<typedef-decl name='pool_scan_func_t' type-id='1b092565' id='7313fbe2'/>
<enum-decl name='pool_scrub_cmd' id='a1474cbd'>
@@ -3246,12 +5746,22 @@
<enumerator name='POOL_SCRUB_FLAGS_END' value='2'/>
</enum-decl>
<typedef-decl name='pool_scrub_cmd_t' type-id='a1474cbd' id='b51cf3c2'/>
+ <enum-decl name='zpool_errata' id='d9abbf54'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZPOOL_ERRATA_NONE' value='0'/>
+ <enumerator name='ZPOOL_ERRATA_ZOL_2094_SCRUB' value='1'/>
+ <enumerator name='ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY' value='2'/>
+ <enumerator name='ZPOOL_ERRATA_ZOL_6845_ENCRYPTION' value='3'/>
+ <enumerator name='ZPOOL_ERRATA_ZOL_8308_ENCRYPTION' value='4'/>
+ </enum-decl>
+ <typedef-decl name='zpool_errata_t' type-id='d9abbf54' id='688c495b'/>
<enum-decl name='pool_initialize_func' id='5c246ad4'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='POOL_INITIALIZE_START' value='0'/>
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
- <enumerator name='POOL_INITIALIZE_FUNCS' value='3'/>
+ <enumerator name='POOL_INITIALIZE_UNINIT' value='3'/>
+ <enumerator name='POOL_INITIALIZE_FUNCS' value='4'/>
</enum-decl>
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
<enum-decl name='pool_trim_func' id='54ed608a'>
@@ -3262,6 +5772,112 @@
<enumerator name='POOL_TRIM_FUNCS' value='3'/>
</enum-decl>
<typedef-decl name='pool_trim_func_t' type-id='54ed608a' id='b1146b8d'/>
+ <enum-decl name='zfs_ioc' id='12033f13'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZFS_IOC_FIRST' value='23040'/>
+ <enumerator name='ZFS_IOC' value='23040'/>
+ <enumerator name='ZFS_IOC_POOL_CREATE' value='23040'/>
+ <enumerator name='ZFS_IOC_POOL_DESTROY' value='23041'/>
+ <enumerator name='ZFS_IOC_POOL_IMPORT' value='23042'/>
+ <enumerator name='ZFS_IOC_POOL_EXPORT' value='23043'/>
+ <enumerator name='ZFS_IOC_POOL_CONFIGS' value='23044'/>
+ <enumerator name='ZFS_IOC_POOL_STATS' value='23045'/>
+ <enumerator name='ZFS_IOC_POOL_TRYIMPORT' value='23046'/>
+ <enumerator name='ZFS_IOC_POOL_SCAN' value='23047'/>
+ <enumerator name='ZFS_IOC_POOL_FREEZE' value='23048'/>
+ <enumerator name='ZFS_IOC_POOL_UPGRADE' value='23049'/>
+ <enumerator name='ZFS_IOC_POOL_GET_HISTORY' value='23050'/>
+ <enumerator name='ZFS_IOC_VDEV_ADD' value='23051'/>
+ <enumerator name='ZFS_IOC_VDEV_REMOVE' value='23052'/>
+ <enumerator name='ZFS_IOC_VDEV_SET_STATE' value='23053'/>
+ <enumerator name='ZFS_IOC_VDEV_ATTACH' value='23054'/>
+ <enumerator name='ZFS_IOC_VDEV_DETACH' value='23055'/>
+ <enumerator name='ZFS_IOC_VDEV_SETPATH' value='23056'/>
+ <enumerator name='ZFS_IOC_VDEV_SETFRU' value='23057'/>
+ <enumerator name='ZFS_IOC_OBJSET_STATS' value='23058'/>
+ <enumerator name='ZFS_IOC_OBJSET_ZPLPROPS' value='23059'/>
+ <enumerator name='ZFS_IOC_DATASET_LIST_NEXT' value='23060'/>
+ <enumerator name='ZFS_IOC_SNAPSHOT_LIST_NEXT' value='23061'/>
+ <enumerator name='ZFS_IOC_SET_PROP' value='23062'/>
+ <enumerator name='ZFS_IOC_CREATE' value='23063'/>
+ <enumerator name='ZFS_IOC_DESTROY' value='23064'/>
+ <enumerator name='ZFS_IOC_ROLLBACK' value='23065'/>
+ <enumerator name='ZFS_IOC_RENAME' value='23066'/>
+ <enumerator name='ZFS_IOC_RECV' value='23067'/>
+ <enumerator name='ZFS_IOC_SEND' value='23068'/>
+ <enumerator name='ZFS_IOC_INJECT_FAULT' value='23069'/>
+ <enumerator name='ZFS_IOC_CLEAR_FAULT' value='23070'/>
+ <enumerator name='ZFS_IOC_INJECT_LIST_NEXT' value='23071'/>
+ <enumerator name='ZFS_IOC_ERROR_LOG' value='23072'/>
+ <enumerator name='ZFS_IOC_CLEAR' value='23073'/>
+ <enumerator name='ZFS_IOC_PROMOTE' value='23074'/>
+ <enumerator name='ZFS_IOC_SNAPSHOT' value='23075'/>
+ <enumerator name='ZFS_IOC_DSOBJ_TO_DSNAME' value='23076'/>
+ <enumerator name='ZFS_IOC_OBJ_TO_PATH' value='23077'/>
+ <enumerator name='ZFS_IOC_POOL_SET_PROPS' value='23078'/>
+ <enumerator name='ZFS_IOC_POOL_GET_PROPS' value='23079'/>
+ <enumerator name='ZFS_IOC_SET_FSACL' value='23080'/>
+ <enumerator name='ZFS_IOC_GET_FSACL' value='23081'/>
+ <enumerator name='ZFS_IOC_SHARE' value='23082'/>
+ <enumerator name='ZFS_IOC_INHERIT_PROP' value='23083'/>
+ <enumerator name='ZFS_IOC_SMB_ACL' value='23084'/>
+ <enumerator name='ZFS_IOC_USERSPACE_ONE' value='23085'/>
+ <enumerator name='ZFS_IOC_USERSPACE_MANY' value='23086'/>
+ <enumerator name='ZFS_IOC_USERSPACE_UPGRADE' value='23087'/>
+ <enumerator name='ZFS_IOC_HOLD' value='23088'/>
+ <enumerator name='ZFS_IOC_RELEASE' value='23089'/>
+ <enumerator name='ZFS_IOC_GET_HOLDS' value='23090'/>
+ <enumerator name='ZFS_IOC_OBJSET_RECVD_PROPS' value='23091'/>
+ <enumerator name='ZFS_IOC_VDEV_SPLIT' value='23092'/>
+ <enumerator name='ZFS_IOC_NEXT_OBJ' value='23093'/>
+ <enumerator name='ZFS_IOC_DIFF' value='23094'/>
+ <enumerator name='ZFS_IOC_TMP_SNAPSHOT' value='23095'/>
+ <enumerator name='ZFS_IOC_OBJ_TO_STATS' value='23096'/>
+ <enumerator name='ZFS_IOC_SPACE_WRITTEN' value='23097'/>
+ <enumerator name='ZFS_IOC_SPACE_SNAPS' value='23098'/>
+ <enumerator name='ZFS_IOC_DESTROY_SNAPS' value='23099'/>
+ <enumerator name='ZFS_IOC_POOL_REGUID' value='23100'/>
+ <enumerator name='ZFS_IOC_POOL_REOPEN' value='23101'/>
+ <enumerator name='ZFS_IOC_SEND_PROGRESS' value='23102'/>
+ <enumerator name='ZFS_IOC_LOG_HISTORY' value='23103'/>
+ <enumerator name='ZFS_IOC_SEND_NEW' value='23104'/>
+ <enumerator name='ZFS_IOC_SEND_SPACE' value='23105'/>
+ <enumerator name='ZFS_IOC_CLONE' value='23106'/>
+ <enumerator name='ZFS_IOC_BOOKMARK' value='23107'/>
+ <enumerator name='ZFS_IOC_GET_BOOKMARKS' value='23108'/>
+ <enumerator name='ZFS_IOC_DESTROY_BOOKMARKS' value='23109'/>
+ <enumerator name='ZFS_IOC_RECV_NEW' value='23110'/>
+ <enumerator name='ZFS_IOC_POOL_SYNC' value='23111'/>
+ <enumerator name='ZFS_IOC_CHANNEL_PROGRAM' value='23112'/>
+ <enumerator name='ZFS_IOC_LOAD_KEY' value='23113'/>
+ <enumerator name='ZFS_IOC_UNLOAD_KEY' value='23114'/>
+ <enumerator name='ZFS_IOC_CHANGE_KEY' value='23115'/>
+ <enumerator name='ZFS_IOC_REMAP' value='23116'/>
+ <enumerator name='ZFS_IOC_POOL_CHECKPOINT' value='23117'/>
+ <enumerator name='ZFS_IOC_POOL_DISCARD_CHECKPOINT' value='23118'/>
+ <enumerator name='ZFS_IOC_POOL_INITIALIZE' value='23119'/>
+ <enumerator name='ZFS_IOC_POOL_TRIM' value='23120'/>
+ <enumerator name='ZFS_IOC_REDACT' value='23121'/>
+ <enumerator name='ZFS_IOC_GET_BOOKMARK_PROPS' value='23122'/>
+ <enumerator name='ZFS_IOC_WAIT' value='23123'/>
+ <enumerator name='ZFS_IOC_WAIT_FS' value='23124'/>
+ <enumerator name='ZFS_IOC_VDEV_GET_PROPS' value='23125'/>
+ <enumerator name='ZFS_IOC_VDEV_SET_PROPS' value='23126'/>
+ <enumerator name='ZFS_IOC_POOL_SCRUB' value='23127'/>
+ <enumerator name='ZFS_IOC_PLATFORM' value='23168'/>
+ <enumerator name='ZFS_IOC_EVENTS_NEXT' value='23169'/>
+ <enumerator name='ZFS_IOC_EVENTS_CLEAR' value='23170'/>
+ <enumerator name='ZFS_IOC_EVENTS_SEEK' value='23171'/>
+ <enumerator name='ZFS_IOC_NEXTBOOT' value='23172'/>
+ <enumerator name='ZFS_IOC_JAIL' value='23173'/>
+ <enumerator name='ZFS_IOC_USERNS_ATTACH' value='23173'/>
+ <enumerator name='ZFS_IOC_UNJAIL' value='23174'/>
+ <enumerator name='ZFS_IOC_USERNS_DETACH' value='23174'/>
+ <enumerator name='ZFS_IOC_SET_BOOTENV' value='23175'/>
+ <enumerator name='ZFS_IOC_GET_BOOTENV' value='23176'/>
+ <enumerator name='ZFS_IOC_LAST' value='23177'/>
+ </enum-decl>
+ <typedef-decl name='zfs_ioc_t' type-id='12033f13' id='5b35941c'/>
<enum-decl name='zpool_wait_activity_t' naming-typedef-id='73446457' id='849338e3'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZPOOL_WAIT_CKPT_DISCARD' value='0'/>
@@ -3272,23 +5888,408 @@
<enumerator name='ZPOOL_WAIT_RESILVER' value='5'/>
<enumerator name='ZPOOL_WAIT_SCRUB' value='6'/>
<enumerator name='ZPOOL_WAIT_TRIM' value='7'/>
- <enumerator name='ZPOOL_WAIT_NUM_ACTIVITIES' value='8'/>
+ <enumerator name='ZPOOL_WAIT_RAIDZ_EXPAND' value='8'/>
+ <enumerator name='ZPOOL_WAIT_NUM_ACTIVITIES' value='9'/>
</enum-decl>
<typedef-decl name='zpool_wait_activity_t' type-id='849338e3' id='73446457'/>
- <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
- <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
+ <enum-decl name='spa_feature' id='33ecb627'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='SPA_FEATURE_NONE' value='-1'/>
+ <enumerator name='SPA_FEATURE_ASYNC_DESTROY' value='0'/>
+ <enumerator name='SPA_FEATURE_EMPTY_BPOBJ' value='1'/>
+ <enumerator name='SPA_FEATURE_LZ4_COMPRESS' value='2'/>
+ <enumerator name='SPA_FEATURE_MULTI_VDEV_CRASH_DUMP' value='3'/>
+ <enumerator name='SPA_FEATURE_SPACEMAP_HISTOGRAM' value='4'/>
+ <enumerator name='SPA_FEATURE_ENABLED_TXG' value='5'/>
+ <enumerator name='SPA_FEATURE_HOLE_BIRTH' value='6'/>
+ <enumerator name='SPA_FEATURE_EXTENSIBLE_DATASET' value='7'/>
+ <enumerator name='SPA_FEATURE_EMBEDDED_DATA' value='8'/>
+ <enumerator name='SPA_FEATURE_BOOKMARKS' value='9'/>
+ <enumerator name='SPA_FEATURE_FS_SS_LIMIT' value='10'/>
+ <enumerator name='SPA_FEATURE_LARGE_BLOCKS' value='11'/>
+ <enumerator name='SPA_FEATURE_LARGE_DNODE' value='12'/>
+ <enumerator name='SPA_FEATURE_SHA512' value='13'/>
+ <enumerator name='SPA_FEATURE_SKEIN' value='14'/>
+ <enumerator name='SPA_FEATURE_EDONR' value='15'/>
+ <enumerator name='SPA_FEATURE_USEROBJ_ACCOUNTING' value='16'/>
+ <enumerator name='SPA_FEATURE_ENCRYPTION' value='17'/>
+ <enumerator name='SPA_FEATURE_PROJECT_QUOTA' value='18'/>
+ <enumerator name='SPA_FEATURE_DEVICE_REMOVAL' value='19'/>
+ <enumerator name='SPA_FEATURE_OBSOLETE_COUNTS' value='20'/>
+ <enumerator name='SPA_FEATURE_POOL_CHECKPOINT' value='21'/>
+ <enumerator name='SPA_FEATURE_SPACEMAP_V2' value='22'/>
+ <enumerator name='SPA_FEATURE_ALLOCATION_CLASSES' value='23'/>
+ <enumerator name='SPA_FEATURE_RESILVER_DEFER' value='24'/>
+ <enumerator name='SPA_FEATURE_BOOKMARK_V2' value='25'/>
+ <enumerator name='SPA_FEATURE_REDACTION_BOOKMARKS' value='26'/>
+ <enumerator name='SPA_FEATURE_REDACTED_DATASETS' value='27'/>
+ <enumerator name='SPA_FEATURE_BOOKMARK_WRITTEN' value='28'/>
+ <enumerator name='SPA_FEATURE_LOG_SPACEMAP' value='29'/>
+ <enumerator name='SPA_FEATURE_LIVELIST' value='30'/>
+ <enumerator name='SPA_FEATURE_DEVICE_REBUILD' value='31'/>
+ <enumerator name='SPA_FEATURE_ZSTD_COMPRESS' value='32'/>
+ <enumerator name='SPA_FEATURE_DRAID' value='33'/>
+ <enumerator name='SPA_FEATURE_ZILSAXATTR' value='34'/>
+ <enumerator name='SPA_FEATURE_HEAD_ERRLOG' value='35'/>
+ <enumerator name='SPA_FEATURE_BLAKE3' value='36'/>
+ <enumerator name='SPA_FEATURE_BLOCK_CLONING' value='37'/>
+ <enumerator name='SPA_FEATURE_AVZ_V2' value='38'/>
+ <enumerator name='SPA_FEATURE_REDACTION_LIST_SPILL' value='39'/>
+ <enumerator name='SPA_FEATURE_RAIDZ_EXPANSION' value='40'/>
+ <enumerator name='SPA_FEATURES' value='41'/>
+ </enum-decl>
+ <typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/>
+ <qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/>
+ <pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/>
+ <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
+ <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
+ <pointer-type-def type-id='d6618c78' size-in-bits='64' id='a8425263'/>
+ <qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
<pointer-type-def type-id='a093cbb8' size-in-bits='64' id='b13f38c3'/>
<pointer-type-def type-id='35acf840' size-in-bits='64' id='17f3480d'/>
- <function-decl name='zpool_props_refresh' mangled-name='zpool_props_refresh' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_props_refresh'>
- <parameter type-id='4c81de99' name='zhp'/>
+ <pointer-type-def type-id='688c495b' size-in-bits='64' id='cec6f2e4'/>
+ <pointer-type-def type-id='d11b7617' size-in-bits='64' id='23432aaa'/>
+ <function-decl name='zpool_get_handle' mangled-name='zpool_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_handle'>
+ <parameter type-id='4c81de99'/>
+ <return type-id='b0382bb3'/>
+ </function-decl>
+ <function-decl name='zpool_prop_to_name' mangled-name='zpool_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_to_name'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_to_name' mangled-name='vdev_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_to_name'>
+ <parameter type-id='5aa5c90c'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_user' mangled-name='vdev_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_user'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zpool_get_status' mangled-name='zpool_get_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_status'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='7d3cd834'/>
+ <parameter type-id='cec6f2e4'/>
+ <return type-id='d3dd6294'/>
+ </function-decl>
+ <function-decl name='zpool_prop_default_string' mangled-name='zpool_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_string'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zpool_prop_default_numeric' mangled-name='zpool_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_numeric'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='libzfs_envvar_is_set' mangled-name='libzfs_envvar_is_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_envvar_is_set'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='lzc_initialize' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='7063e1ab'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_get_prop_int' mangled-name='zpool_get_prop_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop_int'>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='5d0c23fb' name='prop'/>
- <parameter type-id='debc6aa3' name='src'/>
+ <function-decl name='lzc_trim' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b1146b8d'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_sync' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_reopen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_pool_checkpoint' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_pool_checkpoint_discard' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_wait' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='73446457'/>
+ <parameter type-id='37e3bd22'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_wait_tag' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='73446457'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='37e3bd22'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_set_bootenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='22cce67b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_get_bootenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_get_vdev_prop' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_set_vdev_prop' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_scrub' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5b35941c'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_resolve_shortname' mangled-name='zfs_resolve_shortname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_resolve_shortname'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_strip_partition' mangled-name='zfs_strip_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_partition'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='zfs_strip_path' mangled-name='zfs_strip_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_path'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zfs_strcmp_pathname' mangled-name='zfs_strcmp_pathname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strcmp_pathname'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_history_unpack' mangled-name='zpool_history_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_history_unpack'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='75be733c'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_basename' mangled-name='zfs_basename' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_basename'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zpool_name_to_prop' mangled-name='zpool_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_name_to_prop'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='5d0c23fb'/>
+ </function-decl>
+ <function-decl name='zpool_prop_readonly' mangled-name='zpool_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_readonly'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zpool_prop_setonce' mangled-name='zpool_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_setonce'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zpool_prop_feature' mangled-name='zpool_prop_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_feature'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zpool_prop_index_to_string' mangled-name='zpool_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_index_to_string'>
+ <parameter type-id='5d0c23fb'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='vdev_name_to_prop' mangled-name='vdev_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_name_to_prop'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='5aa5c90c'/>
+ </function-decl>
+ <function-decl name='vdev_prop_default_string' mangled-name='vdev_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_string'>
+ <parameter type-id='5aa5c90c'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_default_numeric' mangled-name='vdev_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_numeric'>
+ <parameter type-id='5aa5c90c'/>
<return type-id='9c313c2d'/>
</function-decl>
+ <function-decl name='vdev_prop_readonly' mangled-name='vdev_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_readonly'>
+ <parameter type-id='5aa5c90c'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='vdev_prop_index_to_string' mangled-name='vdev_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_index_to_string'>
+ <parameter type-id='5aa5c90c'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_prop_vdev' mangled-name='zpool_prop_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_vdev'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvpair' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='3fa542f0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9f7200cf'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3bbfee2e'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='3fa542f0'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9da381c4'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3bbfee2e'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint64_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='4dd26a40'/>
+ <return type-id='5d6479ae'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_int64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='9da381c4'/>
+ </function-decl>
+ <function-decl name='fnvpair_value_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zfeature_is_supported' mangled-name='zfeature_is_supported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_supported'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zfeature_lookup_guid' mangled-name='zfeature_lookup_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_guid'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a8425263'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfeature_lookup_name' mangled-name='zfeature_lookup_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_name'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a8425263'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_get_load_policy' mangled-name='zpool_get_load_policy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_load_policy'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='23432aaa'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='pool_namecheck' mangled-name='pool_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='pool_namecheck'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='053457bd'/>
+ <parameter type-id='26a90f95'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_prop_get_type' mangled-name='zpool_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_type'>
+ <parameter type-id='5d0c23fb'/>
+ <return type-id='31429eff'/>
+ </function-decl>
+ <function-decl name='vdev_prop_get_type' mangled-name='vdev_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_type'>
+ <parameter type-id='5aa5c90c'/>
+ <return type-id='31429eff'/>
+ </function-decl>
+ <function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
+ <return type-id='7359adad'/>
+ </function-decl>
+ <function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='3a47d82b'/>
+ </function-decl>
+ <function-decl name='memcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strtok_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='__realpath_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='munmap' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f1cadedf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_standard_error' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_standard_error_fmt' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_relabel_disk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_props_refresh' mangled-name='zpool_props_refresh' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_props_refresh'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_state_to_name' mangled-name='zpool_state_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_state_to_name'>
<parameter type-id='35acf840' name='state'/>
<parameter type-id='9d774e0b' name='aux'/>
@@ -3302,13 +6303,12 @@
<parameter type-id='4c81de99' name='zhp'/>
<return type-id='80f4b756'/>
</function-decl>
- <function-decl name='zpool_get_prop' mangled-name='zpool_get_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_prop'>
+ <function-decl name='zpool_get_userprop' mangled-name='zpool_get_userprop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_userprop'>
<parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='5d0c23fb' name='prop'/>
+ <parameter type-id='80f4b756' name='propname'/>
<parameter type-id='26a90f95' name='buf'/>
<parameter type-id='b59d7dce' name='len'/>
<parameter type-id='debc6aa3' name='srctype'/>
- <parameter type-id='c19b74c3' name='literal'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_set_prop' mangled-name='zpool_set_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_prop'>
@@ -3330,31 +6330,6 @@
<parameter type-id='e4378506' name='plp'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='80f4b756' name='propname'/>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='len'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zpool_open_canfail' mangled-name='zpool_open_canfail' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open_canfail'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='80f4b756' name='pool'/>
- <return type-id='4c81de99'/>
- </function-decl>
- <function-decl name='zpool_open' mangled-name='zpool_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='80f4b756' name='pool'/>
- <return type-id='4c81de99'/>
- </function-decl>
- <function-decl name='zpool_close' mangled-name='zpool_close' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_close'>
- <parameter type-id='4c81de99' name='zhp'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zpool_get_name' mangled-name='zpool_get_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_name'>
- <parameter type-id='4c81de99' name='zhp'/>
- <return type-id='80f4b756'/>
- </function-decl>
<function-decl name='zpool_get_state' mangled-name='zpool_get_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_state'>
<parameter type-id='4c81de99' name='zhp'/>
<return type-id='95e97e5e'/>
@@ -3387,6 +6362,7 @@
<function-decl name='zpool_add' mangled-name='zpool_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_add'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='5ce45b60' name='nvroot'/>
+ <parameter type-id='c19b74c3' name='ashift_check'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_export' mangled-name='zpool_export' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_export'>
@@ -3467,12 +6443,6 @@
<parameter type-id='37e3bd22' name='log'/>
<return type-id='5ce45b60'/>
</function-decl>
- <function-decl name='zpool_get_physpath' mangled-name='zpool_get_physpath' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_physpath'>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='26a90f95' name='physpath'/>
- <parameter type-id='b59d7dce' name='phypath_size'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zpool_vdev_path_to_guid' mangled-name='zpool_vdev_path_to_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_path_to_guid'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='path'/>
@@ -3491,6 +6461,11 @@
<parameter type-id='c19b74c3' name='istmp'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zpool_vdev_remove_wanted' mangled-name='zpool_vdev_remove_wanted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_remove_wanted'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='path'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_vdev_fault' mangled-name='zpool_vdev_fault' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_fault'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='9c313c2d' name='guid'/>
@@ -3503,6 +6478,12 @@
<parameter type-id='9d774e0b' name='aux'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zpool_vdev_set_removed_state' mangled-name='zpool_vdev_set_removed_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_set_removed_state'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='9c313c2d' name='guid'/>
+ <parameter type-id='9d774e0b' name='aux'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_vdev_attach' mangled-name='zpool_vdev_attach' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_attach'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='old_disk'/>
@@ -3701,7 +6682,40 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_sendrecv.c' language='LANG_C99'>
- <class-decl name='sendflags' size-in-bits='544' is-struct='yes' visibility='default' id='f6aa15be'>
+ <array-type-def dimensions='1' type-id='8901473c' size-in-bits='576' id='f5da478b'>
+ <subrange length='1' type-id='7359adad' id='52f813b4'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='384' id='73b82f0f'>
+ <subrange length='12' type-id='7359adad' id='84827bdc'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='bd54fe1a' size-in-bits='512' id='5d4efd44'>
+ <subrange length='8' type-id='7359adad' id='56e0c0b1'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='2176' id='8c2bcad1'>
+ <subrange length='34' type-id='7359adad' id='6a6a7e00'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='256' id='85c64d26'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='96' id='fa8ef949'>
+ <subrange length='12' type-id='7359adad' id='84827bdc'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='128' id='fa9986a5'>
+ <subrange length='16' type-id='7359adad' id='848d0938'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='40' id='0f4ddd0b'>
+ <subrange length='5' type-id='7359adad' id='53010e10'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='48' id='0f562bd0'>
+ <subrange length='6' type-id='7359adad' id='52fa524b'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='b96825af' size-in-bits='64' id='13339fda'>
+ <subrange length='8' type-id='7359adad' id='56e0c0b1'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='eaa32e2f' size-in-bits='256' id='209ef23f'>
+ <subrange length='4' type-id='7359adad' id='16fe7105'/>
+ </array-type-def>
+ <class-decl name='sendflags' size-in-bits='576' is-struct='yes' visibility='default' id='f6aa15be'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='verbosity' type-id='95e97e5e' visibility='default'/>
</data-member>
@@ -3733,30 +6747,33 @@
<var-decl name='progress' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='progressastitle' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='352'>
- <var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='largeblock' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='compress' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='embed_data' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='416'>
- <var-decl name='raw' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='compress' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='backup' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='raw' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='480'>
- <var-decl name='holds' type-id='c19b74c3' visibility='default'/>
+ <var-decl name='backup' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='holds' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='544'>
<var-decl name='saved' type-id='c19b74c3' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='sendflags_t' type-id='f6aa15be' id='945467e6'/>
<typedef-decl name='snapfilter_cb_t' type-id='d2a5e211' id='3d3ffb69'/>
- <class-decl name='recvflags' size-in-bits='416' is-struct='yes' visibility='default' id='34a384dc'>
+ <class-decl name='recvflags' size-in-bits='448' is-struct='yes' visibility='default' id='34a384dc'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='verbose' type-id='c19b74c3' visibility='default'/>
</data-member>
@@ -3796,12 +6813,791 @@
<data-member access='public' layout-offset-in-bits='384'>
<var-decl name='forceunmount' type-id='c19b74c3' visibility='default'/>
</data-member>
+ <data-member access='public' layout-offset-in-bits='416'>
+ <var-decl name='heal' type-id='c19b74c3' visibility='default'/>
+ </data-member>
</class-decl>
<typedef-decl name='recvflags_t' type-id='34a384dc' id='9e59d1d4'/>
- <pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/>
+ <enum-decl name='lzc_send_flags' id='bfbd3c8e'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='LZC_SEND_FLAG_EMBED_DATA' value='1'/>
+ <enumerator name='LZC_SEND_FLAG_LARGE_BLOCK' value='2'/>
+ <enumerator name='LZC_SEND_FLAG_COMPRESS' value='4'/>
+ <enumerator name='LZC_SEND_FLAG_RAW' value='8'/>
+ <enumerator name='LZC_SEND_FLAG_SAVED' value='16'/>
+ </enum-decl>
+ <class-decl name='ddt_key_t' size-in-bits='320' is-struct='yes' naming-typedef-id='67f6d2cf' visibility='default' id='5fae1718'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='ddk_cksum' type-id='39730d0b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='ddk_prop' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='ddt_key_t' type-id='5fae1718' id='67f6d2cf'/>
+ <enum-decl name='dmu_object_type' id='04b3b0b9'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='DMU_OT_NONE' value='0'/>
+ <enumerator name='DMU_OT_OBJECT_DIRECTORY' value='1'/>
+ <enumerator name='DMU_OT_OBJECT_ARRAY' value='2'/>
+ <enumerator name='DMU_OT_PACKED_NVLIST' value='3'/>
+ <enumerator name='DMU_OT_PACKED_NVLIST_SIZE' value='4'/>
+ <enumerator name='DMU_OT_BPOBJ' value='5'/>
+ <enumerator name='DMU_OT_BPOBJ_HDR' value='6'/>
+ <enumerator name='DMU_OT_SPACE_MAP_HEADER' value='7'/>
+ <enumerator name='DMU_OT_SPACE_MAP' value='8'/>
+ <enumerator name='DMU_OT_INTENT_LOG' value='9'/>
+ <enumerator name='DMU_OT_DNODE' value='10'/>
+ <enumerator name='DMU_OT_OBJSET' value='11'/>
+ <enumerator name='DMU_OT_DSL_DIR' value='12'/>
+ <enumerator name='DMU_OT_DSL_DIR_CHILD_MAP' value='13'/>
+ <enumerator name='DMU_OT_DSL_DS_SNAP_MAP' value='14'/>
+ <enumerator name='DMU_OT_DSL_PROPS' value='15'/>
+ <enumerator name='DMU_OT_DSL_DATASET' value='16'/>
+ <enumerator name='DMU_OT_ZNODE' value='17'/>
+ <enumerator name='DMU_OT_OLDACL' value='18'/>
+ <enumerator name='DMU_OT_PLAIN_FILE_CONTENTS' value='19'/>
+ <enumerator name='DMU_OT_DIRECTORY_CONTENTS' value='20'/>
+ <enumerator name='DMU_OT_MASTER_NODE' value='21'/>
+ <enumerator name='DMU_OT_UNLINKED_SET' value='22'/>
+ <enumerator name='DMU_OT_ZVOL' value='23'/>
+ <enumerator name='DMU_OT_ZVOL_PROP' value='24'/>
+ <enumerator name='DMU_OT_PLAIN_OTHER' value='25'/>
+ <enumerator name='DMU_OT_UINT64_OTHER' value='26'/>
+ <enumerator name='DMU_OT_ZAP_OTHER' value='27'/>
+ <enumerator name='DMU_OT_ERROR_LOG' value='28'/>
+ <enumerator name='DMU_OT_SPA_HISTORY' value='29'/>
+ <enumerator name='DMU_OT_SPA_HISTORY_OFFSETS' value='30'/>
+ <enumerator name='DMU_OT_POOL_PROPS' value='31'/>
+ <enumerator name='DMU_OT_DSL_PERMS' value='32'/>
+ <enumerator name='DMU_OT_ACL' value='33'/>
+ <enumerator name='DMU_OT_SYSACL' value='34'/>
+ <enumerator name='DMU_OT_FUID' value='35'/>
+ <enumerator name='DMU_OT_FUID_SIZE' value='36'/>
+ <enumerator name='DMU_OT_NEXT_CLONES' value='37'/>
+ <enumerator name='DMU_OT_SCAN_QUEUE' value='38'/>
+ <enumerator name='DMU_OT_USERGROUP_USED' value='39'/>
+ <enumerator name='DMU_OT_USERGROUP_QUOTA' value='40'/>
+ <enumerator name='DMU_OT_USERREFS' value='41'/>
+ <enumerator name='DMU_OT_DDT_ZAP' value='42'/>
+ <enumerator name='DMU_OT_DDT_STATS' value='43'/>
+ <enumerator name='DMU_OT_SA' value='44'/>
+ <enumerator name='DMU_OT_SA_MASTER_NODE' value='45'/>
+ <enumerator name='DMU_OT_SA_ATTR_REGISTRATION' value='46'/>
+ <enumerator name='DMU_OT_SA_ATTR_LAYOUTS' value='47'/>
+ <enumerator name='DMU_OT_SCAN_XLATE' value='48'/>
+ <enumerator name='DMU_OT_DEDUP' value='49'/>
+ <enumerator name='DMU_OT_DEADLIST' value='50'/>
+ <enumerator name='DMU_OT_DEADLIST_HDR' value='51'/>
+ <enumerator name='DMU_OT_DSL_CLONES' value='52'/>
+ <enumerator name='DMU_OT_BPOBJ_SUBOBJ' value='53'/>
+ <enumerator name='DMU_OT_NUMTYPES' value='54'/>
+ <enumerator name='DMU_OTN_UINT8_DATA' value='128'/>
+ <enumerator name='DMU_OTN_UINT8_METADATA' value='192'/>
+ <enumerator name='DMU_OTN_UINT16_DATA' value='129'/>
+ <enumerator name='DMU_OTN_UINT16_METADATA' value='193'/>
+ <enumerator name='DMU_OTN_UINT32_DATA' value='130'/>
+ <enumerator name='DMU_OTN_UINT32_METADATA' value='194'/>
+ <enumerator name='DMU_OTN_UINT64_DATA' value='131'/>
+ <enumerator name='DMU_OTN_UINT64_METADATA' value='195'/>
+ <enumerator name='DMU_OTN_ZAP_DATA' value='132'/>
+ <enumerator name='DMU_OTN_ZAP_METADATA' value='196'/>
+ <enumerator name='DMU_OTN_UINT8_ENC_DATA' value='160'/>
+ <enumerator name='DMU_OTN_UINT8_ENC_METADATA' value='224'/>
+ <enumerator name='DMU_OTN_UINT16_ENC_DATA' value='161'/>
+ <enumerator name='DMU_OTN_UINT16_ENC_METADATA' value='225'/>
+ <enumerator name='DMU_OTN_UINT32_ENC_DATA' value='162'/>
+ <enumerator name='DMU_OTN_UINT32_ENC_METADATA' value='226'/>
+ <enumerator name='DMU_OTN_UINT64_ENC_DATA' value='163'/>
+ <enumerator name='DMU_OTN_UINT64_ENC_METADATA' value='227'/>
+ <enumerator name='DMU_OTN_ZAP_ENC_DATA' value='164'/>
+ <enumerator name='DMU_OTN_ZAP_ENC_METADATA' value='228'/>
+ </enum-decl>
+ <typedef-decl name='dmu_object_type_t' type-id='04b3b0b9' id='5c9d8906'/>
+ <class-decl name='zio_cksum' size-in-bits='256' is-struct='yes' visibility='default' id='1d53e28b'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zc_word' type-id='85c64d26' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zio_cksum_t' type-id='1d53e28b' id='39730d0b'/>
+ <class-decl name='dmu_replay_record' size-in-bits='2496' is-struct='yes' visibility='default' id='781a52d7'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_type' type-id='08f5ca17' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='drr_payloadlen' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_u' type-id='ac5ab598' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <enum-decl name='__anonymous_enum__' is-anonymous='yes' id='08f5ca17'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='DRR_BEGIN' value='0'/>
+ <enumerator name='DRR_OBJECT' value='1'/>
+ <enumerator name='DRR_FREEOBJECTS' value='2'/>
+ <enumerator name='DRR_WRITE' value='3'/>
+ <enumerator name='DRR_FREE' value='4'/>
+ <enumerator name='DRR_END' value='5'/>
+ <enumerator name='DRR_WRITE_BYREF' value='6'/>
+ <enumerator name='DRR_SPILL' value='7'/>
+ <enumerator name='DRR_WRITE_EMBEDDED' value='8'/>
+ <enumerator name='DRR_OBJECT_RANGE' value='9'/>
+ <enumerator name='DRR_REDACT' value='10'/>
+ <enumerator name='DRR_NUMTYPES' value='11'/>
+ </enum-decl>
+ <union-decl name='__anonymous_union__' size-in-bits='2432' is-anonymous='yes' visibility='default' id='ac5ab598'>
+ <data-member access='public'>
+ <var-decl name='drr_begin' type-id='09fcdc01' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_end' type-id='6ee25631' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_object' type-id='f9ad530b' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_freeobjects' type-id='a27d958e' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_write' type-id='4cc69e4b' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_free' type-id='c836cfd2' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_write_byref' type-id='e511cdce' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_spill' type-id='1e69a80a' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_write_embedded' type-id='98b1345e' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_object_range' type-id='aba1f9e1' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_redact' type-id='50389039' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='drr_checksum' type-id='a5fe3647' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <class-decl name='drr_end' size-in-bits='320' is-struct='yes' visibility='default' id='6ee25631'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_checksum' type-id='39730d0b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_object' size-in-bits='448' is-struct='yes' visibility='default' id='f9ad530b'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='drr_bonustype' type-id='5c9d8906' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_blksz' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='drr_bonuslen' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='200'>
+ <var-decl name='drr_compress' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='208'>
+ <var-decl name='drr_dn_slots' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='216'>
+ <var-decl name='drr_flags' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='drr_raw_bonuslen' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_indblkshift' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='328'>
+ <var-decl name='drr_nlevels' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='336'>
+ <var-decl name='drr_nblkptr' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='344'>
+ <var-decl name='drr_pad' type-id='0f4ddd0b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='drr_maxblkid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_freeobjects' size-in-bits='192' is-struct='yes' visibility='default' id='a27d958e'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_firstobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_numobjs' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_write' size-in-bits='1088' is-struct='yes' visibility='default' id='4cc69e4b'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='drr_pad' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_logical_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='328'>
+ <var-decl name='drr_flags' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='336'>
+ <var-decl name='drr_compressiontype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='344'>
+ <var-decl name='drr_pad2' type-id='0f4ddd0b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='drr_key' type-id='67f6d2cf' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='drr_compressed_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='drr_salt' type-id='13339fda' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='928'>
+ <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_free' size-in-bits='256' is-struct='yes' visibility='default' id='c836cfd2'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_write_byref' size-in-bits='832' is-struct='yes' visibility='default' id='e511cdce'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_refguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_refobject' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='drr_refoffset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='drr_checksumtype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='456'>
+ <var-decl name='drr_flags' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='464'>
+ <var-decl name='drr_pad2' type-id='0f562bd0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='drr_key' type-id='67f6d2cf' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_spill' size-in-bits='640' is-struct='yes' visibility='default' id='1e69a80a'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_flags' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='200'>
+ <var-decl name='drr_compressiontype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='208'>
+ <var-decl name='drr_pad' type-id='0f562bd0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_compressed_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_salt' type-id='13339fda' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='480'>
+ <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='608'>
+ <var-decl name='drr_type' type-id='5c9d8906' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_write_embedded' size-in-bits='384' is-struct='yes' visibility='default' id='98b1345e'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_compression' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='264'>
+ <var-decl name='drr_etype' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='272'>
+ <var-decl name='drr_pad' type-id='0f562bd0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='drr_lsize' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='352'>
+ <var-decl name='drr_psize' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_object_range' size-in-bits='512' is-struct='yes' visibility='default' id='aba1f9e1'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_firstobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_numslots' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_salt' type-id='13339fda' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='drr_iv' type-id='fa8ef949' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='352'>
+ <var-decl name='drr_mac' type-id='fa9986a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='480'>
+ <var-decl name='drr_flags' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='488'>
+ <var-decl name='drr_pad' type-id='d3490169' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_redact' size-in-bits='256' is-struct='yes' visibility='default' id='50389039'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='drr_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='drr_length' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='drr_checksum' size-in-bits='2432' is-struct='yes' visibility='default' id='a5fe3647'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='drr_pad' type-id='8c2bcad1' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2176'>
+ <var-decl name='drr_checksum' type-id='39730d0b' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__cancel_jmp_buf_tag' size-in-bits='576' is-struct='yes' visibility='default' id='8901473c'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__cancel_jmp_buf' type-id='379a1ab7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='__mask_was_saved' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__pthread_unwind_buf_t' size-in-bits='832' is-struct='yes' naming-typedef-id='4423cf7f' visibility='default' id='a0abc656'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__cancel_jmp_buf' type-id='f5da478b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='__pad' type-id='209ef23f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__pthread_unwind_buf_t' type-id='a0abc656' id='4423cf7f'/>
+ <typedef-decl name='__jmp_buf' type-id='5d4efd44' id='379a1ab7'/>
+ <typedef-decl name='__clockid_t' type-id='95e97e5e' id='08f9a87a'/>
+ <typedef-decl name='__timer_t' type-id='eaa32e2f' id='df209b60'/>
+ <typedef-decl name='clockid_t' type-id='08f9a87a' id='a1c3b834'/>
+ <class-decl name='sigevent' size-in-bits='512' is-struct='yes' visibility='default' id='519bc206'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='sigev_value' type-id='eabacd01' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='sigev_signo' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='sigev_notify' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_sigev_un' type-id='ac5ab599' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <union-decl name='__anonymous_union__1' size-in-bits='384' is-anonymous='yes' visibility='default' id='ac5ab599'>
+ <data-member access='public'>
+ <var-decl name='_pad' type-id='73b82f0f' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_tid' type-id='3629bad8' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='_sigev_thread' type-id='e7f43f7b' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <class-decl name='__anonymous_struct__' size-in-bits='128' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f7b'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_function' type-id='5f147c28' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_attribute' type-id='7347a39e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='itimerspec' size-in-bits='256' is-struct='yes' visibility='default' id='acbdbcc6'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='it_interval' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='it_value' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='timer_t' type-id='df209b60' id='b07ae406'/>
+ <typedef-decl name='Byte' type-id='002ac4a6' id='efb9ba06'/>
+ <typedef-decl name='uLong' type-id='7359adad' id='5bbcce85'/>
+ <typedef-decl name='Bytef' type-id='efb9ba06' id='c1606520'/>
+ <typedef-decl name='uLongf' type-id='5bbcce85' id='4d39af59'/>
+ <pointer-type-def type-id='c1606520' size-in-bits='64' id='4c667223'/>
+ <pointer-type-def type-id='8901473c' size-in-bits='64' id='eb91b7ea'/>
+ <pointer-type-def type-id='4423cf7f' size-in-bits='64' id='ba7c727c'/>
+ <pointer-type-def type-id='b9c97942' size-in-bits='64' id='bbf06c47'/>
+ <qualified-type-def type-id='bbf06c47' restrict='yes' id='65e6ec45'/>
+ <qualified-type-def type-id='c1606520' const='yes' id='a6124a50'/>
+ <pointer-type-def type-id='a6124a50' size-in-bits='64' id='e8cb3e0e'/>
+ <qualified-type-def type-id='b9c97942' const='yes' id='191f6b72'/>
+ <pointer-type-def type-id='191f6b72' size-in-bits='64' id='e475fb88'/>
+ <qualified-type-def type-id='e475fb88' restrict='yes' id='5a8729d0'/>
+ <qualified-type-def type-id='781a52d7' const='yes' id='413ab2b8'/>
+ <pointer-type-def type-id='413ab2b8' size-in-bits='64' id='41671bd6'/>
+ <qualified-type-def type-id='acbdbcc6' const='yes' id='4ba62af7'/>
+ <pointer-type-def type-id='4ba62af7' size-in-bits='64' id='f39579e7'/>
+ <qualified-type-def type-id='f39579e7' restrict='yes' id='9b23e165'/>
+ <pointer-type-def type-id='c70fa2e8' size-in-bits='64' id='2e711a2a'/>
+ <pointer-type-def type-id='3ff5601b' size-in-bits='64' id='4aafb922'/>
+ <pointer-type-def type-id='acbdbcc6' size-in-bits='64' id='116842ac'/>
+ <qualified-type-def type-id='116842ac' restrict='yes' id='3d3c4cf4'/>
<pointer-type-def type-id='9e59d1d4' size-in-bits='64' id='4ea84b4f'/>
<pointer-type-def type-id='945467e6' size-in-bits='64' id='8def7735'/>
+ <pointer-type-def type-id='519bc206' size-in-bits='64' id='ef2f159c'/>
+ <qualified-type-def type-id='ef2f159c' restrict='yes' id='de0eb5a4'/>
<pointer-type-def type-id='3d3ffb69' size-in-bits='64' id='72a26210'/>
+ <pointer-type-def type-id='c9d12d66' size-in-bits='64' id='b2eb2c3f'/>
+ <pointer-type-def type-id='b07ae406' size-in-bits='64' id='36e89359'/>
+ <qualified-type-def type-id='36e89359' restrict='yes' id='de98c2bb'/>
+ <pointer-type-def type-id='a9c79a1f' size-in-bits='64' id='3d83ba87'/>
+ <pointer-type-def type-id='4d39af59' size-in-bits='64' id='60db3356'/>
+ <pointer-type-def type-id='f1abb096' size-in-bits='64' id='5f147c28'/>
+ <pointer-type-def type-id='39730d0b' size-in-bits='64' id='c24fc2ee'/>
+ <function-decl name='nvlist_print' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_get_pool_handle' mangled-name='zfs_get_pool_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_pool_handle'>
+ <parameter type-id='fcd57163'/>
+ <return type-id='4c81de99'/>
+ </function-decl>
+ <function-decl name='lzc_send_wrapper' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2e711a2a'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_send_redacted' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='bfbd3c8e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_send_resume_redacted' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='bfbd3c8e'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_receive_with_cmdprops' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='ae3e8ca6'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='41671bd6'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_receive_with_heal' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='ae3e8ca6'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='41671bd6'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_send_space' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='bfbd3c8e'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_send_space_resume_redacted' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='bfbd3c8e'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzc_rename' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_setproctitle' mangled-name='zfs_setproctitle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle'>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='avl_insert' mangled-name='avl_insert' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='fba6cb51'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvpair_value_int32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='4aafb922'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fnvlist_size' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='fnvlist_merge' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fletcher_4_native_varsize' mangled-name='fletcher_4_native_varsize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_native_varsize'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='c24fc2ee'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fletcher_4_incremental_native' mangled-name='fletcher_4_incremental_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_native'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fletcher_4_incremental_byteswap' mangled-name='fletcher_4_incremental_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_byteswap'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_exit' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__pthread_register_cancel' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='ba7c727c'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__pthread_unwind_next' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='ba7c727c'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='sigaddset' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9e80f729'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='perror' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strndup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='time' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b2eb2c3f'/>
+ <return type-id='c9d12d66'/>
+ </function-decl>
+ <function-decl name='clock_gettime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a1c3b834'/>
+ <parameter type-id='3d83ba87'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='timer_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a1c3b834'/>
+ <parameter type-id='de0eb5a4'/>
+ <parameter type-id='de98c2bb'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='timer_delete' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b07ae406'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='timer_settime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b07ae406'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9b23e165'/>
+ <parameter type-id='3d3c4cf4'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
+ <function-decl name='pause' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_sigmask' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='5a8729d0'/>
+ <parameter type-id='65e6ec45'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='uncompress' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4c667223'/>
+ <parameter type-id='60db3356'/>
+ <parameter type-id='e8cb3e0e'/>
+ <parameter type-id='5bbcce85'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='create_parents' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_send_progress' mangled-name='zfs_send_progress' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_progress'>
<parameter type-id='9200a744' name='zhp'/>
<parameter type-id='95e97e5e' name='fd'/>
@@ -3856,78 +7652,48 @@
<parameter type-id='a3681dea' name='stream_avl'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-type size-in-bits='64' id='c70fa2e8'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
<function-type size-in-bits='64' id='d2a5e211'>
<parameter type-id='9200a744'/>
<parameter type-id='eaa32e2f'/>
<return type-id='c19b74c3'/>
</function-type>
+ <function-type size-in-bits='64' id='f1abb096'>
+ <parameter type-id='eabacd01'/>
+ <return type-id='48b5725f'/>
+ </function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_status.c' language='LANG_C99'>
- <enum-decl name='zpool_status_t' naming-typedef-id='d3dd6294' id='5e770b40'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='ZPOOL_STATUS_CORRUPT_CACHE' value='0'/>
- <enumerator name='ZPOOL_STATUS_MISSING_DEV_R' value='1'/>
- <enumerator name='ZPOOL_STATUS_MISSING_DEV_NR' value='2'/>
- <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_R' value='3'/>
- <enumerator name='ZPOOL_STATUS_CORRUPT_LABEL_NR' value='4'/>
- <enumerator name='ZPOOL_STATUS_BAD_GUID_SUM' value='5'/>
- <enumerator name='ZPOOL_STATUS_CORRUPT_POOL' value='6'/>
- <enumerator name='ZPOOL_STATUS_CORRUPT_DATA' value='7'/>
- <enumerator name='ZPOOL_STATUS_FAILING_DEV' value='8'/>
- <enumerator name='ZPOOL_STATUS_VERSION_NEWER' value='9'/>
- <enumerator name='ZPOOL_STATUS_HOSTID_MISMATCH' value='10'/>
- <enumerator name='ZPOOL_STATUS_HOSTID_ACTIVE' value='11'/>
- <enumerator name='ZPOOL_STATUS_HOSTID_REQUIRED' value='12'/>
- <enumerator name='ZPOOL_STATUS_IO_FAILURE_WAIT' value='13'/>
- <enumerator name='ZPOOL_STATUS_IO_FAILURE_CONTINUE' value='14'/>
- <enumerator name='ZPOOL_STATUS_IO_FAILURE_MMP' value='15'/>
- <enumerator name='ZPOOL_STATUS_BAD_LOG' value='16'/>
- <enumerator name='ZPOOL_STATUS_ERRATA' value='17'/>
- <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_READ' value='18'/>
- <enumerator name='ZPOOL_STATUS_UNSUP_FEAT_WRITE' value='19'/>
- <enumerator name='ZPOOL_STATUS_FAULTED_DEV_R' value='20'/>
- <enumerator name='ZPOOL_STATUS_FAULTED_DEV_NR' value='21'/>
- <enumerator name='ZPOOL_STATUS_VERSION_OLDER' value='22'/>
- <enumerator name='ZPOOL_STATUS_FEAT_DISABLED' value='23'/>
- <enumerator name='ZPOOL_STATUS_RESILVERING' value='24'/>
- <enumerator name='ZPOOL_STATUS_OFFLINE_DEV' value='25'/>
- <enumerator name='ZPOOL_STATUS_REMOVED_DEV' value='26'/>
- <enumerator name='ZPOOL_STATUS_REBUILDING' value='27'/>
- <enumerator name='ZPOOL_STATUS_REBUILD_SCRUB' value='28'/>
- <enumerator name='ZPOOL_STATUS_NON_NATIVE_ASHIFT' value='29'/>
- <enumerator name='ZPOOL_STATUS_COMPATIBILITY_ERR' value='30'/>
- <enumerator name='ZPOOL_STATUS_INCOMPATIBLE_FEAT' value='31'/>
- <enumerator name='ZPOOL_STATUS_OK' value='32'/>
- </enum-decl>
- <typedef-decl name='zpool_status_t' type-id='5e770b40' id='d3dd6294'/>
- <enum-decl name='zpool_errata' id='d9abbf54'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='ZPOOL_ERRATA_NONE' value='0'/>
- <enumerator name='ZPOOL_ERRATA_ZOL_2094_SCRUB' value='1'/>
- <enumerator name='ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY' value='2'/>
- <enumerator name='ZPOOL_ERRATA_ZOL_6845_ENCRYPTION' value='3'/>
- <enumerator name='ZPOOL_ERRATA_ZOL_8308_ENCRYPTION' value='4'/>
- </enum-decl>
- <typedef-decl name='zpool_errata_t' type-id='d9abbf54' id='688c495b'/>
- <pointer-type-def type-id='688c495b' size-in-bits='64' id='cec6f2e4'/>
- <function-decl name='zpool_get_status' mangled-name='zpool_get_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_status'>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='9b23c9ad' name='msgid'/>
- <parameter type-id='cec6f2e4' name='errata'/>
- <return type-id='d3dd6294'/>
- </function-decl>
<function-decl name='zpool_import_status' mangled-name='zpool_import_status' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_import_status'>
<parameter type-id='5ce45b60' name='config'/>
- <parameter type-id='9b23c9ad' name='msgid'/>
+ <parameter type-id='7d3cd834' name='msgid'/>
<parameter type-id='cec6f2e4' name='errata'/>
<return type-id='d3dd6294'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/libzfs_util.c' language='LANG_C99'>
+ <class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <type-decl name='double' size-in-bits='64' id='a0eb0f08'/>
<array-type-def dimensions='1' type-id='95e97e5e' size-in-bits='192' id='e41bdf22'>
<subrange length='6' type-id='7359adad' id='52fa524b'/>
</array-type-def>
- <type-decl name='variadic parameter type' id='2c1145c5'/>
<array-type-def dimensions='1' type-id='19cefcee' size-in-bits='160' alignment-in-bits='32' id='3fcf57d2'>
<subrange length='5' type-id='7359adad' id='53010e10'/>
</array-type-def>
@@ -3984,9 +7750,313 @@
</class-decl>
<typedef-decl name='zprop_get_cbdata_t' type-id='f3d3c319' id='f3d87113'/>
<typedef-decl name='zprop_func' type-id='2e711a2a' id='1ec3747a'/>
+ <enum-decl name='zprop_attr_t' naming-typedef-id='999701cc' id='77d05200'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='PROP_DEFAULT' value='0'/>
+ <enumerator name='PROP_READONLY' value='1'/>
+ <enumerator name='PROP_INHERIT' value='2'/>
+ <enumerator name='PROP_ONETIME' value='3'/>
+ <enumerator name='PROP_ONETIME_DEFAULT' value='4'/>
+ </enum-decl>
+ <typedef-decl name='zprop_attr_t' type-id='77d05200' id='999701cc'/>
+ <class-decl name='zfs_index' size-in-bits='128' is-struct='yes' visibility='default' id='87957af9'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='pi_name' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='pi_value' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zprop_index_t' type-id='87957af9' id='64636ce3'/>
+ <class-decl name='zprop_desc_t' size-in-bits='640' is-struct='yes' naming-typedef-id='ffa52b96' visibility='default' id='bbff5e4b'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='pd_name' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='pd_propnum' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='pd_proptype' type-id='31429eff' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='pd_strdefault' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='pd_numdefault' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='pd_attr' type-id='999701cc' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='pd_types' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='pd_values' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='pd_colname' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='pd_rightalign' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='449'>
+ <var-decl name='pd_visible' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='450'>
+ <var-decl name='pd_zfs_mod_supported' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='451'>
+ <var-decl name='pd_always_flex' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='pd_table' type-id='c8bc397b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='pd_table_size' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zprop_desc_t' type-id='bbff5e4b' id='ffa52b96'/>
+ <class-decl name='extmnttab' size-in-bits='320' is-struct='yes' visibility='default' id='0c544dc0'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='mnt_major' type-id='3502e3ff' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
+ <qualified-type-def type-id='26a90f95' const='yes' id='57de658a'/>
+ <pointer-type-def type-id='57de658a' size-in-bits='64' id='f319fae0'/>
<pointer-type-def type-id='9b23c9ad' size-in-bits='64' id='c0563f85'/>
- <pointer-type-def type-id='c70fa2e8' size-in-bits='64' id='2e711a2a'/>
+ <qualified-type-def type-id='33f57a65' const='yes' id='21fd6035'/>
+ <pointer-type-def type-id='21fd6035' size-in-bits='64' id='a0de50cd'/>
+ <pointer-type-def type-id='a0de50cd' size-in-bits='64' id='24f95ba5'/>
+ <qualified-type-def type-id='64636ce3' const='yes' id='072f7953'/>
+ <pointer-type-def type-id='072f7953' size-in-bits='64' id='c8bc397b'/>
+ <pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
+ <pointer-type-def type-id='aca3bac8' size-in-bits='64' id='d33f11cb'/>
+ <qualified-type-def type-id='d33f11cb' restrict='yes' id='5c53ba29'/>
+ <pointer-type-def type-id='ffa52b96' size-in-bits='64' id='76c8174b'/>
<pointer-type-def type-id='f3d87113' size-in-bits='64' id='0d2a0670'/>
+ <function-decl name='zpool_label_disk' mangled-name='zpool_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_version_kernel' mangled-name='zfs_version_kernel' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_kernel'>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='libzfs_core_init' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='libzfs_core_fini' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_get_underlying_path' mangled-name='zfs_get_underlying_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_underlying_path'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='zpool_prop_unsupported' mangled-name='zpool_prop_unsupported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_unsupported'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='zpool_feature_init' mangled-name='zpool_feature_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_feature_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fletcher_4_init' mangled-name='fletcher_4_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fletcher_4_fini' mangled-name='fletcher_4_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_fini'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_prop_init' mangled-name='zfs_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfs_prop_get_table' mangled-name='zfs_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_table'>
+ <return type-id='76c8174b'/>
+ </function-decl>
+ <function-decl name='zpool_prop_init' mangled-name='zpool_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zpool_prop_get_table' mangled-name='zpool_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_table'>
+ <return type-id='76c8174b'/>
+ </function-decl>
+ <function-decl name='vdev_prop_init' mangled-name='vdev_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zprop_iter_common' mangled-name='zprop_iter_common' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_iter_common'>
+ <parameter type-id='1ec3747a'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zprop_name_to_prop' mangled-name='zprop_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_name_to_prop'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zprop_string_to_index' mangled-name='zprop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_string_to_index'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5d6479ae'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zprop_values' mangled-name='zprop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_values'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zprop_width' mangled-name='zprop_width' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_width'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='37e3bd22'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='zprop_valid_for_type' mangled-name='zprop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_for_type'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='2e45de5d'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='getextmntent' mangled-name='getextmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getextmntent'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='394fc496'/>
+ <parameter type-id='62f7a03d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__ctype_toupper_loc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='24f95ba5'/>
+ </function-decl>
+ <function-decl name='dlclose' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='regcomp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5c53ba29'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='regfree' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='d33f11cb'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='puts' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strtod' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <return type-id='a0eb0f08'/>
+ </function-decl>
+ <function-decl name='realloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='exit' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strnlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='strncasecmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='access' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='dup2' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='execve' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='f319fae0'/>
+ <parameter type-id='f319fae0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='execv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='f319fae0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='execvp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='f319fae0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='execvpe' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='f319fae0'/>
+ <parameter type-id='f319fae0'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='_exit' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fork' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='3629bad8'/>
+ </function-decl>
+ <function-decl name='pow' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a0eb0f08'/>
+ <parameter type-id='a0eb0f08'/>
+ <return type-id='a0eb0f08'/>
+ </function-decl>
+ <function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b7f2d5e6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__vasprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b7f2d5e6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='waitpid' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='3629bad8'/>
+ <parameter type-id='7292109c'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='3629bad8'/>
+ </function-decl>
+ <function-decl name='namespace_clear' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='libzfs_load_module' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='libzfs_errno' mangled-name='libzfs_errno' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_errno'>
<parameter type-id='b0382bb3' name='hdl'/>
<return type-id='95e97e5e'/>
@@ -3999,12 +8069,6 @@
<parameter type-id='b0382bb3' name='hdl'/>
<return type-id='80f4b756'/>
</function-decl>
- <function-decl name='zfs_standard_error' mangled-name='zfs_standard_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_standard_error'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='95e97e5e' name='error'/>
- <parameter type-id='80f4b756' name='msg'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='libzfs_print_on_error' mangled-name='libzfs_print_on_error' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_print_on_error'>
<parameter type-id='b0382bb3' name='hdl'/>
<parameter type-id='c19b74c3' name='printerr'/>
@@ -4037,10 +8101,6 @@
<parameter type-id='95e97e5e' name='count'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='libzfs_envvar_is_set' mangled-name='libzfs_envvar_is_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_envvar_is_set'>
- <parameter type-id='26a90f95' name='envvar'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='libzfs_init' mangled-name='libzfs_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_init'>
<return type-id='b0382bb3'/>
</function-decl>
@@ -4048,18 +8108,6 @@
<parameter type-id='b0382bb3' name='hdl'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zpool_get_handle' mangled-name='zpool_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_handle'>
- <parameter type-id='4c81de99' name='zhp'/>
- <return type-id='b0382bb3'/>
- </function-decl>
- <function-decl name='zfs_get_handle' mangled-name='zfs_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_handle'>
- <parameter type-id='9200a744' name='zhp'/>
- <return type-id='b0382bb3'/>
- </function-decl>
- <function-decl name='zfs_get_pool_handle' mangled-name='zfs_get_pool_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_pool_handle'>
- <parameter type-id='fcd57163' name='zhp'/>
- <return type-id='4c81de99'/>
- </function-decl>
<function-decl name='zfs_path_to_zhandle' mangled-name='zfs_path_to_zhandle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_path_to_zhandle'>
<parameter type-id='b0382bb3' name='hdl'/>
<parameter type-id='80f4b756' name='path'/>
@@ -4076,12 +8124,6 @@
<parameter type-id='80f4b756' name='recvd_value'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_nicestrtonum' mangled-name='zfs_nicestrtonum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicestrtonum'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='80f4b756' name='value'/>
- <parameter type-id='5d6479ae' name='num'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zprop_get_list' mangled-name='zprop_get_list' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_get_list'>
<parameter type-id='b0382bb3' name='hdl'/>
<parameter type-id='26a90f95' name='props'/>
@@ -4107,29 +8149,67 @@
<function-decl name='zfs_version_print' mangled-name='zfs_version_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_print'>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='color_start' mangled-name='color_start' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_start'>
- <parameter type-id='26a90f95' name='color'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='color_end' mangled-name='color_end' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_end'>
- <return type-id='48b5725f'/>
+ <function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'>
+ <return type-id='95e97e5e'/>
</function-decl>
<function-decl name='printf_color' mangled-name='printf_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='printf_color'>
- <parameter type-id='26a90f95' name='color'/>
- <parameter type-id='26a90f95' name='format'/>
+ <parameter type-id='80f4b756' name='color'/>
+ <parameter type-id='80f4b756' name='format'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-type size-in-bits='64' id='c70fa2e8'>
- <parameter type-id='95e97e5e'/>
- <parameter type-id='eaa32e2f'/>
+ <function-decl name='zpool_vdev_script_alloc_env' mangled-name='zpool_vdev_script_alloc_env' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_script_alloc_env'>
+ <parameter type-id='80f4b756' name='pool_name'/>
+ <parameter type-id='80f4b756' name='vdev_path'/>
+ <parameter type-id='80f4b756' name='vdev_upath'/>
+ <parameter type-id='80f4b756' name='vdev_enc_sysfs_path'/>
+ <parameter type-id='80f4b756' name='opt_key'/>
+ <parameter type-id='80f4b756' name='opt_val'/>
+ <return type-id='9b23c9ad'/>
+ </function-decl>
+ <function-decl name='zpool_vdev_script_free_env' mangled-name='zpool_vdev_script_free_env' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_script_free_env'>
+ <parameter type-id='9b23c9ad' name='env'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zpool_prepare_disk' mangled-name='zpool_prepare_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prepare_disk'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='5ce45b60' name='vdev_nv'/>
+ <parameter type-id='80f4b756' name='prepare_str'/>
+ <parameter type-id='c0563f85' name='lines'/>
+ <parameter type-id='7292109c' name='lines_cnt'/>
<return type-id='95e97e5e'/>
- </function-type>
+ </function-decl>
+ <function-decl name='zpool_prepare_and_label_disk' mangled-name='zpool_prepare_and_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prepare_and_label_disk'>
+ <parameter type-id='b0382bb3' name='hdl'/>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='5ce45b60' name='vdev_nv'/>
+ <parameter type-id='80f4b756' name='prepare_str'/>
+ <parameter type-id='c0563f85' name='lines'/>
+ <parameter type-id='7292109c' name='lines_cnt'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_mount_os.c' language='LANG_C99'>
<pointer-type-def type-id='7359adad' size-in-bits='64' id='1d2c2b85'/>
+ <function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='cc5fcceb'/>
+ </function-decl>
+ <function-decl name='mount' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='7359adad'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='umount2' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_parse_mount_options' mangled-name='zfs_parse_mount_options' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parse_mount_options'>
- <parameter type-id='26a90f95' name='mntopts'/>
+ <parameter type-id='80f4b756' name='mntopts'/>
<parameter type-id='1d2c2b85' name='mntflags'/>
<parameter type-id='1d2c2b85' name='zfsflags'/>
<parameter type-id='95e97e5e' name='sloppy'/>
@@ -4147,273 +8227,204 @@
<function-decl name='zfs_mount_delegation_check' mangled-name='zfs_mount_delegation_check' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_mount_delegation_check'>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_disable_datasets_os' mangled-name='zpool_disable_datasets_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_datasets_os'>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='c19b74c3' name='force'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zpool_disable_volume_os' mangled-name='zpool_disable_volume_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_volume_os'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='48b5725f'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_pool_os.c' language='LANG_C99'>
- <function-decl name='zpool_label_disk' mangled-name='zpool_label_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='4c81de99' name='zhp'/>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_util_os.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
- <subrange length='4096' type-id='7359adad' id='bc1b5ddc'/>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='288' id='16e6f2c6'>
+ <subrange length='36' type-id='7359adad' id='ae666bde'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='65536' id='163f6aa5'>
- <subrange length='8192' type-id='7359adad' id='c88f397d'/>
+ <array-type-def dimensions='1' type-id='a65ae39c' size-in-bits='960' id='fa198beb'>
+ <subrange length='1' type-id='7359adad' id='52f813b4'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='128' id='c1c22e6c'>
- <subrange length='2' type-id='7359adad' id='52efc4ef'/>
+ <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='384' id='dba89ba3'>
+ <subrange length='12' type-id='7359adad' id='84827bdc'/>
</array-type-def>
- <array-type-def dimensions='1' type-id='b96825af' size-in-bits='24' id='d3490169'>
- <subrange length='3' type-id='7359adad' id='56f209d2'/>
+ <array-type-def dimensions='1' type-id='3502e3ff' size-in-bits='256' id='01d84ed4'>
+ <subrange length='8' type-id='7359adad' id='56e0c0b1'/>
</array-type-def>
- <class-decl name='drr_begin' size-in-bits='2432' is-struct='yes' visibility='default' id='09fcdc01'>
+ <class-decl name='dk_part' size-in-bits='960' is-struct='yes' visibility='default' id='a65ae39c'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='drr_magic' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='p_start' type-id='804dc465' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='drr_versioninfo' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='p_size' type-id='804dc465' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='drr_creation_time' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='p_guid' type-id='214f32ea' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='drr_type' type-id='230f1e16' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='p_tag' type-id='d908a348' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='224'>
- <var-decl name='drr_flags' type-id='8f92235e' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='272'>
+ <var-decl name='p_flag' type-id='d908a348' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='drr_toguid' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='p_name' type-id='16e6f2c6' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='drr_fromguid' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='p_uguid' type-id='214f32ea' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='drr_toname' type-id='d1617432' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='p_resv' type-id='01d84ed4' visibility='default'/>
</data-member>
</class-decl>
- <class-decl name='zinject_record' size-in-bits='2816' is-struct='yes' visibility='default' id='3216f820'>
+ <class-decl name='dk_gpt' size-in-bits='1920' is-struct='yes' visibility='default' id='dd4a2e5a'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zi_objset' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_version' type-id='3502e3ff' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='efi_nparts' type-id='3502e3ff' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='zi_object' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_part_size' type-id='3502e3ff' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='efi_lbasize' type-id='3502e3ff' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='zi_start' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_last_lba' type-id='804dc465' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='zi_end' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_first_u_lba' type-id='804dc465' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='zi_guid' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_last_u_lba' type-id='804dc465' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='zi_level' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='352'>
- <var-decl name='zi_error' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='zi_type' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_disk_uguid' type-id='214f32ea' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='zi_freq' type-id='8f92235e' visibility='default'/>
+ <var-decl name='efi_flags' type-id='3502e3ff' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='480'>
- <var-decl name='zi_failfast' type-id='8f92235e' visibility='default'/>
+ <var-decl name='efi_reserved1' type-id='3502e3ff' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='zi_func' type-id='d1617432' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2560'>
- <var-decl name='zi_iotype' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2592'>
- <var-decl name='zi_duration' type-id='3ff5601b' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2624'>
- <var-decl name='zi_timer' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2688'>
- <var-decl name='zi_nlanes' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2752'>
- <var-decl name='zi_cmd' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2784'>
- <var-decl name='zi_dvas' type-id='8f92235e' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zinject_record_t' type-id='3216f820' id='a4301ca6'/>
- <class-decl name='zfs_share' size-in-bits='256' is-struct='yes' visibility='default' id='feb6f2da'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='z_exportdata' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='z_sharedata' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='efi_altern_lba' type-id='804dc465' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='z_sharetype' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='efi_reserved' type-id='dba89ba3' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='z_sharemax' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='efi_parts' type-id='fa198beb' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='zfs_share_t' type-id='feb6f2da' id='ee5cec36'/>
- <class-decl name='zfs_cmd' size-in-bits='109952' is-struct='yes' visibility='default' id='3522cd69'>
+ <class-decl name='uuid' size-in-bits='128' is-struct='yes' visibility='default' id='214f32ea'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zc_name' type-id='d16c6df4' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32768'>
- <var-decl name='zc_nvlist_src' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32832'>
- <var-decl name='zc_nvlist_src_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32896'>
- <var-decl name='zc_nvlist_dst' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32960'>
- <var-decl name='zc_nvlist_dst_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33024'>
- <var-decl name='zc_nvlist_dst_filled' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33056'>
- <var-decl name='zc_pad2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33088'>
- <var-decl name='zc_history' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33152'>
- <var-decl name='zc_value' type-id='163f6aa5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='98688'>
- <var-decl name='zc_string' type-id='d1617432' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100736'>
- <var-decl name='zc_guid' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100800'>
- <var-decl name='zc_nvlist_conf' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100864'>
- <var-decl name='zc_nvlist_conf_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100928'>
- <var-decl name='zc_cookie' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100992'>
- <var-decl name='zc_objset_type' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101056'>
- <var-decl name='zc_perm_action' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101120'>
- <var-decl name='zc_history_len' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101184'>
- <var-decl name='zc_history_offset' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101248'>
- <var-decl name='zc_obj' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101312'>
- <var-decl name='zc_iflags' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101376'>
- <var-decl name='zc_share' type-id='ee5cec36' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101632'>
- <var-decl name='zc_objset_stats' type-id='b2c14f17' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='103936'>
- <var-decl name='zc_begin_record' type-id='09fcdc01' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='106368'>
- <var-decl name='zc_inject_record' type-id='a4301ca6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109184'>
- <var-decl name='zc_defer_destroy' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109216'>
- <var-decl name='zc_flags' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109248'>
- <var-decl name='zc_action_handle' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109312'>
- <var-decl name='zc_cleanup_fd' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109344'>
- <var-decl name='zc_simple' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109352'>
- <var-decl name='zc_pad' type-id='d3490169' visibility='default'/>
+ <var-decl name='time_low' type-id='8f92235e' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='109376'>
- <var-decl name='zc_sendobj' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='time_mid' type-id='149c6638' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='109440'>
- <var-decl name='zc_fromobj' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='48'>
+ <var-decl name='time_hi_and_version' type-id='149c6638' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='109504'>
- <var-decl name='zc_createtxg' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='clock_seq_hi_and_reserved' type-id='b96825af' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='109568'>
- <var-decl name='zc_stat' type-id='0371a9c7' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='72'>
+ <var-decl name='clock_seq_low' type-id='b96825af' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='109888'>
- <var-decl name='zc_zoneid' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='80'>
+ <var-decl name='node_addr' type-id='0f562bd0' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='zfs_cmd_t' type-id='3522cd69' id='a5559cdd'/>
- <class-decl name='zfs_stat' size-in-bits='320' is-struct='yes' visibility='default' id='6417f0b9'>
+ <typedef-decl name='ushort_t' type-id='8efea9e5' id='d908a348'/>
+ <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
+ <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
+ <pointer-type-def type-id='dd4a2e5a' size-in-bits='64' id='0d8119a8'/>
+ <pointer-type-def type-id='0d8119a8' size-in-bits='64' id='c43b27a6'/>
+ <function-decl name='zpool_label_disk_wait' mangled-name='zpool_label_disk_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk_wait'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_append_partition' mangled-name='zfs_append_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_append_partition'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='efi_alloc_and_init' mangled-name='efi_alloc_and_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_init'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='8f92235e'/>
+ <parameter type-id='c43b27a6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='efi_alloc_and_read' mangled-name='efi_alloc_and_read' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_alloc_and_read'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='c43b27a6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='efi_write' mangled-name='efi_write' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_write'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='0d8119a8'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='efi_rescan' mangled-name='efi_rescan' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_rescan'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='efi_free' mangled-name='efi_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_free'>
+ <parameter type-id='0d8119a8'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='efi_use_whole_disk' mangled-name='efi_use_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='efi_use_whole_disk'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='rand' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fsync' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libzfs/os/linux/libzfs_util_os.c' language='LANG_C99'>
+ <typedef-decl name='nfds_t' type-id='7359adad' id='555eef66'/>
+ <class-decl name='pollfd' size-in-bits='64' is-struct='yes' visibility='default' id='b440e872'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zs_gen' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='zs_mode' type-id='9c313c2d' visibility='default'/>
+ <var-decl name='fd' type-id='95e97e5e' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='zs_links' type-id='9c313c2d' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='events' type-id='a2185560' visibility='default'/>
</data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='zs_ctime' type-id='c1c22e6c' visibility='default'/>
+ <data-member access='public' layout-offset-in-bits='48'>
+ <var-decl name='revents' type-id='a2185560' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='zfs_stat_t' type-id='6417f0b9' id='0371a9c7'/>
- <pointer-type-def type-id='a5559cdd' size-in-bits='64' id='e4ec4540'/>
- <function-decl name='zfs_ioctl' mangled-name='zfs_ioctl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_ioctl'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='95e97e5e' name='request'/>
- <parameter type-id='e4ec4540' name='zc'/>
+ <pointer-type-def type-id='b440e872' size-in-bits='64' id='3ac36db0'/>
+ <function-decl name='__poll_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='3ac36db0'/>
+ <parameter type-id='555eef66'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7359adad'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='libzfs_error_init' mangled-name='libzfs_error_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_error_init'>
- <parameter type-id='95e97e5e' name='error'/>
- <return type-id='80f4b756'/>
+ <function-decl name='inotify_init1' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_destroy_snaps_nvl_os' mangled-name='zfs_destroy_snaps_nvl_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps_nvl_os'>
- <parameter type-id='b0382bb3' name='hdl'/>
- <parameter type-id='5ce45b60' name='snaps'/>
+ <function-decl name='inotify_add_watch' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='8f92235e'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_version_kernel' mangled-name='zfs_version_kernel' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_kernel'>
- <return type-id='26a90f95'/>
+ <function-decl name='timerfd_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='08f9a87a'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='timerfd_settime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='f39579e7'/>
+ <parameter type-id='116842ac'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='libzfs_error_init' mangled-name='libzfs_error_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_error_init'>
+ <parameter type-id='95e97e5e' name='error'/>
+ <return type-id='80f4b756'/>
</function-decl>
<function-decl name='zfs_userns' mangled-name='zfs_userns' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_userns'>
<parameter type-id='9200a744' name='zhp'/>
@@ -4423,19 +8434,37 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_device_path_os.c' language='LANG_C99'>
- <function-decl name='zfs_append_partition' mangled-name='zfs_append_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_append_partition'>
- <parameter type-id='26a90f95' name='path'/>
- <parameter type-id='b59d7dce' name='max_len'/>
- <return type-id='95e97e5e'/>
+ <class-decl name='udev' is-struct='yes' visibility='default' is-declaration-only='yes' id='e4a7fb7f'/>
+ <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/>
+ <pointer-type-def type-id='e4a7fb7f' size-in-bits='64' id='025eefe7'/>
+ <pointer-type-def type-id='640b33ca' size-in-bits='64' id='b32bae08'/>
+ <class-decl name='udev' is-struct='yes' visibility='default' is-declaration-only='yes' id='e4a7fb7f'/>
+ <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/>
+ <function-decl name='udev_new' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='025eefe7'/>
</function-decl>
- <function-decl name='zfs_strip_partition' mangled-name='zfs_strip_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_partition'>
- <parameter type-id='80f4b756' name='path'/>
- <return type-id='26a90f95'/>
+ <function-decl name='udev_device_unref' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b32bae08'/>
+ <return type-id='b32bae08'/>
</function-decl>
- <function-decl name='zfs_strip_path' mangled-name='zfs_strip_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_path'>
- <parameter type-id='80f4b756' name='path'/>
+ <function-decl name='udev_device_new_from_subsystem_sysname' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='025eefe7'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b32bae08'/>
+ </function-decl>
+ <function-decl name='udev_device_get_property_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b32bae08'/>
+ <parameter type-id='80f4b756'/>
<return type-id='80f4b756'/>
</function-decl>
+ <function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
<function-decl name='zfs_get_enclosure_sysfs_path' mangled-name='zfs_get_enclosure_sysfs_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_enclosure_sysfs_path'>
<parameter type-id='80f4b756' name='dev_name'/>
<return type-id='26a90f95'/>
@@ -4448,29 +8477,129 @@
<parameter type-id='80f4b756' name='dev_name'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zfs_get_underlying_path' mangled-name='zfs_get_underlying_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_get_underlying_path'>
- <parameter type-id='80f4b756' name='dev_name'/>
- <return type-id='26a90f95'/>
- </function-decl>
<function-decl name='is_mpath_whole_disk' mangled-name='is_mpath_whole_disk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='is_mpath_whole_disk'>
<parameter type-id='80f4b756' name='path'/>
<return type-id='c19b74c3'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_import_os.c' language='LANG_C99'>
- <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/>
- <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
- <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/>
- <pointer-type-def type-id='640b33ca' size-in-bits='64' id='b32bae08'/>
- <class-decl name='udev_device' is-struct='yes' visibility='default' is-declaration-only='yes' id='640b33ca'/>
+ <class-decl name='blkid_struct_cache' is-struct='yes' visibility='default' is-declaration-only='yes' id='09286066'/>
+ <class-decl name='blkid_struct_dev' is-struct='yes' visibility='default' is-declaration-only='yes' id='86223623'/>
+ <class-decl name='blkid_struct_dev_iterate' is-struct='yes' visibility='default' is-declaration-only='yes' id='d88420d6'/>
+ <class-decl name='udev_list_entry' is-struct='yes' visibility='default' is-declaration-only='yes' id='e7dbdca3'/>
+ <typedef-decl name='pool_vdev_iter_f' type-id='6c16a6c8' id='dff793e0'/>
+ <typedef-decl name='blkid_dev' type-id='8433f053' id='f47b023a'/>
+ <typedef-decl name='blkid_cache' type-id='940e3afc' id='0882dfdf'/>
+ <typedef-decl name='blkid_dev_iterate' type-id='b8fa2efc' id='f4760fa7'/>
+ <typedef-decl name='__useconds_t' type-id='f0981eeb' id='4e80d4b1'/>
+ <pointer-type-def type-id='0882dfdf' size-in-bits='64' id='2e3e7caa'/>
+ <pointer-type-def type-id='f47b023a' size-in-bits='64' id='d87f9b75'/>
+ <pointer-type-def type-id='09286066' size-in-bits='64' id='940e3afc'/>
+ <pointer-type-def type-id='86223623' size-in-bits='64' id='8433f053'/>
+ <pointer-type-def type-id='d88420d6' size-in-bits='64' id='b8fa2efc'/>
+ <pointer-type-def type-id='2ec2411e' size-in-bits='64' id='6c16a6c8'/>
+ <pointer-type-def type-id='e7dbdca3' size-in-bits='64' id='deabd0d3'/>
+ <class-decl name='blkid_struct_cache' is-struct='yes' visibility='default' is-declaration-only='yes' id='09286066'/>
+ <class-decl name='blkid_struct_dev' is-struct='yes' visibility='default' is-declaration-only='yes' id='86223623'/>
+ <class-decl name='blkid_struct_dev_iterate' is-struct='yes' visibility='default' is-declaration-only='yes' id='d88420d6'/>
+ <class-decl name='udev_list_entry' is-struct='yes' visibility='default' is-declaration-only='yes' id='e7dbdca3'/>
+ <function-decl name='for_each_vdev_in_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='dff793e0'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='label_paths' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5507783b'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='7d3cd834'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zutil_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5507783b'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='zutil_strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5507783b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='slice_cache_compare' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='blkid_put_cache' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0882dfdf'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='blkid_get_cache' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='2e3e7caa'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='blkid_dev_devname' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f47b023a'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='blkid_dev_iterate_begin' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0882dfdf'/>
+ <return type-id='f4760fa7'/>
+ </function-decl>
+ <function-decl name='blkid_dev_set_search' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f4760fa7'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='blkid_dev_next' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f4760fa7'/>
+ <parameter type-id='d87f9b75'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='blkid_dev_iterate_end' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f4760fa7'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='blkid_probe_all_new' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='0882dfdf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='udev_unref' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='025eefe7'/>
+ <return type-id='025eefe7'/>
+ </function-decl>
+ <function-decl name='udev_list_entry_get_next' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='deabd0d3'/>
+ <return type-id='deabd0d3'/>
+ </function-decl>
+ <function-decl name='udev_list_entry_get_name' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='deabd0d3'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='udev_device_get_parent_with_subsystem_devtype' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b32bae08'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b32bae08'/>
+ </function-decl>
+ <function-decl name='udev_device_get_devlinks_list_entry' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b32bae08'/>
+ <return type-id='deabd0d3'/>
+ </function-decl>
+ <function-decl name='sched_yield' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='usleep' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4e80d4b1'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zfs_dev_flush' mangled-name='zfs_dev_flush' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dev_flush'>
<parameter type-id='95e97e5e' name='fd'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_default_search_paths' mangled-name='zpool_default_search_paths' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_default_search_paths'>
- <parameter type-id='78c01427' name='count'/>
- <return type-id='13956559'/>
- </function-decl>
<function-decl name='zfs_device_get_devid' mangled-name='zfs_device_get_devid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_device_get_devid'>
<parameter type-id='b32bae08' name='dev'/>
<parameter type-id='26a90f95' name='bufptr'/>
@@ -4483,41 +8612,65 @@
<parameter type-id='b59d7dce' name='buflen'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_label_disk_wait' mangled-name='zpool_label_disk_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_label_disk_wait'>
+ <function-decl name='zpool_disk_wait' mangled-name='zpool_disk_wait' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disk_wait'>
<parameter type-id='80f4b756' name='path'/>
- <parameter type-id='95e97e5e' name='timeout_ms'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='update_vdev_config_dev_strs' mangled-name='update_vdev_config_dev_strs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='update_vdev_config_dev_strs'>
+ <function-decl name='update_vdev_config_dev_sysfs_path' mangled-name='update_vdev_config_dev_sysfs_path' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='update_vdev_config_dev_sysfs_path'>
<parameter type-id='5ce45b60' name='nv'/>
+ <parameter type-id='80f4b756' name='path'/>
+ <parameter type-id='80f4b756' name='key'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-type size-in-bits='64' id='2ec2411e'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-type>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libzutil/os/linux/zutil_setproctitle.c' language='LANG_C99'>
+ <function-decl name='warnx' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='setenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='clearenv' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_setproctitle_init' mangled-name='zfs_setproctitle_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_setproctitle_init'>
+ <parameter type-id='95e97e5e' name='argc'/>
+ <parameter type-id='9b23c9ad' name='argv'/>
+ <parameter type-id='9b23c9ad' name='envp'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/zutil_device_path.c' language='LANG_C99'>
- <typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
- <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
- <function-decl name='zfs_basename' mangled-name='zfs_basename' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_basename'>
- <parameter type-id='80f4b756' name='path'/>
- <return type-id='80f4b756'/>
+ <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
+ <function-decl name='zpool_default_search_paths' mangled-name='zpool_default_search_paths' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_default_search_paths'>
+ <parameter type-id='78c01427'/>
+ <return type-id='13956559'/>
+ </function-decl>
+ <function-decl name='strspn' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
</function-decl>
<function-decl name='zfs_dirnamelen' mangled-name='zfs_dirnamelen' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dirnamelen'>
<parameter type-id='80f4b756' name='path'/>
<return type-id='79a0948f'/>
</function-decl>
- <function-decl name='zfs_resolve_shortname' mangled-name='zfs_resolve_shortname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_resolve_shortname'>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='26a90f95' name='path'/>
- <parameter type-id='b59d7dce' name='len'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zfs_strcmp_pathname' mangled-name='zfs_strcmp_pathname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strcmp_pathname'>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='80f4b756' name='cmp'/>
- <parameter type-id='95e97e5e' name='wholedisk'/>
- <return type-id='95e97e5e'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/zutil_import.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='256' id='16dc656a'>
+ <subrange length='32' type-id='7359adad' id='ae5bde82'/>
+ </array-type-def>
<class-decl name='importargs' size-in-bits='448' is-struct='yes' visibility='default' id='7ac83801'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='path' type-id='9b23c9ad' visibility='default'/>
@@ -4545,30 +8698,137 @@
</data-member>
</class-decl>
<typedef-decl name='importargs_t' type-id='7ac83801' id='7a842a6b'/>
+ <class-decl name='libpc_handle' size-in-bits='8448' is-struct='yes' visibility='default' id='7c8737f0'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='lpc_error' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='lpc_printerr' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='lpc_open_access_error' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='lpc_desc_active' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='lpc_desc' type-id='b54ce520' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8320'>
+ <var-decl name='lpc_ops' type-id='f095e320' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='8384'>
+ <var-decl name='lpc_lib_handle' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='libpc_handle_t' type-id='7c8737f0' id='8a70a786'/>
+ <class-decl name='aiocb' size-in-bits='1344' is-struct='yes' visibility='default' id='e4957c49'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='aio_fildes' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='aio_lio_opcode' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='aio_reqprio' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='aio_buf' type-id='fe09dd29' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='aio_nbytes' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='aio_sigevent' type-id='519bc206' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='__next_prio' type-id='924bbc81' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='__abs_prio' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='864'>
+ <var-decl name='__policy' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='__error_code' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='__return_value' type-id='41060289' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='aio_offset' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='__glibc_reserved' type-id='16dc656a' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='e4957c49' size-in-bits='64' id='924bbc81'/>
+ <qualified-type-def type-id='924bbc81' const='yes' id='5499dcde'/>
+ <pointer-type-def type-id='5499dcde' size-in-bits='64' id='2236d41c'/>
+ <qualified-type-def type-id='2236d41c' restrict='yes' id='31488924'/>
+ <pointer-type-def type-id='a3681dea' size-in-bits='64' id='fce6d540'/>
+ <qualified-type-def type-id='e4957c49' const='yes' id='fced9da2'/>
+ <pointer-type-def type-id='fced9da2' size-in-bits='64' id='b20efd18'/>
<pointer-type-def type-id='7a842a6b' size-in-bits='64' id='07ee4a58'/>
+ <pointer-type-def type-id='8a70a786' size-in-bits='64' id='5507783b'/>
<pointer-type-def type-id='b1e62775' size-in-bits='64' id='f095e320'/>
- <function-decl name='zpool_read_label' mangled-name='zpool_read_label' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_read_label'>
- <parameter type-id='95e97e5e' name='fd'/>
- <parameter type-id='857bb57e' name='config'/>
- <parameter type-id='7292109c' name='num_labels'/>
+ <qualified-type-def type-id='48b5725f' volatile='yes' id='b0b3cbf9'/>
+ <pointer-type-def type-id='b0b3cbf9' size-in-bits='64' id='fe09dd29'/>
+ <function-decl name='update_vdev_config_dev_strs' mangled-name='update_vdev_config_dev_strs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='update_vdev_config_dev_strs'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='update_vdevs_config_dev_sysfs_path' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='posix_memalign' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='63e171df'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
+ <function-decl name='libpc_error_description' mangled-name='libpc_error_description' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libpc_error_description'>
+ <parameter type-id='5507783b' name='hdl'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
<function-decl name='zpool_search_import' mangled-name='zpool_search_import' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_search_import'>
- <parameter type-id='eaa32e2f' name='hdl'/>
+ <parameter type-id='5507783b' name='hdl'/>
<parameter type-id='07ee4a58' name='import'/>
- <parameter type-id='f095e320' name='pco'/>
<return type-id='5ce45b60'/>
</function-decl>
<function-decl name='zpool_find_config' mangled-name='zpool_find_config' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_config'>
- <parameter type-id='eaa32e2f' name='hdl'/>
+ <parameter type-id='5507783b' name='hdl'/>
<parameter type-id='80f4b756' name='target'/>
<parameter type-id='857bb57e' name='configp'/>
<parameter type-id='07ee4a58' name='args'/>
- <parameter type-id='f095e320' name='pco'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='zpool_find_import_blkid' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5507783b'/>
+ <parameter type-id='18c91f9e'/>
+ <parameter type-id='fce6d540'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_open_func' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/zutil_nicenum.c' language='LANG_C99'>
+ <type-decl name='long double' size-in-bits='128' id='e095c704'/>
<enum-decl name='zfs_nicenum_format' id='29cf1969'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_NICENUM_1024' value='0'/>
@@ -4577,6 +8837,15 @@
<enumerator name='ZFS_NICENUM_RAW' value='3'/>
<enumerator name='ZFS_NICENUM_RAWTIME' value='4'/>
</enum-decl>
+ <function-decl name='powl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e095c704'/>
+ <parameter type-id='e095c704'/>
+ <return type-id='e095c704'/>
+ </function-decl>
+ <function-decl name='floor' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a0eb0f08'/>
+ <return type-id='a0eb0f08'/>
+ </function-decl>
<function-decl name='zfs_isnumber' mangled-name='zfs_isnumber' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_isnumber'>
<parameter type-id='80f4b756' name='str'/>
<return type-id='c19b74c3'/>
@@ -4588,12 +8857,6 @@
<parameter type-id='29cf1969' name='format'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_nicenum' mangled-name='zfs_nicenum' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicenum'>
- <parameter type-id='9c313c2d' name='num'/>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='zfs_nicetime' mangled-name='zfs_nicetime' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicetime'>
<parameter type-id='9c313c2d' name='num'/>
<parameter type-id='26a90f95' name='buf'/>
@@ -4606,17 +8869,12 @@
<parameter type-id='b59d7dce' name='buflen'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_nicebytes' mangled-name='zfs_nicebytes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_nicebytes'>
- <parameter type-id='9c313c2d' name='num'/>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='b59d7dce' name='buflen'/>
- <return type-id='48b5725f'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libzutil/zutil_pool.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='853fd5dc' size-in-bits='32768' id='b505fc2f'>
<subrange length='64' type-id='7359adad' id='b10be967'/>
</array-type-def>
+ <type-decl name='float' size-in-bits='32' id='a6c45d85'/>
<class-decl name='ddt_stat' size-in-bits='512' is-struct='yes' visibility='default' id='65242dfe'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='dds_blocks' type-id='9c313c2d' visibility='default'/>
@@ -4654,35 +8912,29 @@
<pointer-type-def type-id='ec92d602' size-in-bits='64' id='932720f8'/>
<qualified-type-def type-id='853fd5dc' const='yes' id='764c298c'/>
<pointer-type-def type-id='764c298c' size-in-bits='64' id='dfe59052'/>
- <pointer-type-def type-id='857bb57e' size-in-bits='64' id='75be733c'/>
+ <qualified-type-def type-id='a9c79a1f' const='yes' id='cd087e36'/>
+ <pointer-type-def type-id='cd087e36' size-in-bits='64' id='e05e8614'/>
+ <function-decl name='nanosleep' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e05e8614'/>
+ <parameter type-id='3d83ba87'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_dump_ddt' mangled-name='zpool_dump_ddt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_dump_ddt'>
<parameter type-id='dfe59052' name='dds_total'/>
<parameter type-id='932720f8' name='ddh'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zpool_history_unpack' mangled-name='zpool_history_unpack' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_history_unpack'>
- <parameter type-id='26a90f95' name='buf'/>
- <parameter type-id='9c313c2d' name='bytes_read'/>
- <parameter type-id='5d6479ae' name='leftover'/>
- <parameter type-id='75be733c' name='records'/>
- <parameter type-id='4dd26a40' name='numrecords'/>
+ <function-decl name='fsleep' mangled-name='fsleep' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fsleep'>
+ <parameter type-id='a6c45d85' name='sec'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zpool_getenv_int' mangled-name='zpool_getenv_int' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_getenv_int'>
+ <parameter type-id='80f4b756' name='env'/>
+ <parameter type-id='95e97e5e' name='default_val'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/avl/avl.c' language='LANG_C99'>
- <typedef-decl name='avl_index_t' type-id='e475ab95' id='fba6cb51'/>
- <pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
- <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
- <function-decl name='avl_walk' mangled-name='avl_walk' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_walk'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='oldnode'/>
- <parameter type-id='95e97e5e' name='left'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_first' mangled-name='avl_first' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_first'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
<function-decl name='avl_last' mangled-name='avl_last' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_last'>
<parameter type-id='a3681dea' name='tree'/>
<return type-id='eaa32e2f'/>
@@ -4693,18 +8945,6 @@
<parameter type-id='95e97e5e' name='direction'/>
<return type-id='eaa32e2f'/>
</function-decl>
- <function-decl name='avl_find' mangled-name='avl_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_find'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='value'/>
- <parameter type-id='32adbf30' name='where'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
- <function-decl name='avl_insert' mangled-name='avl_insert' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='new_data'/>
- <parameter type-id='fba6cb51' name='where'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='avl_insert_here' mangled-name='avl_insert_here' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_insert_here'>
<parameter type-id='a3681dea' name='tree'/>
<parameter type-id='eaa32e2f' name='new_data'/>
@@ -4712,16 +8952,6 @@
<parameter type-id='95e97e5e' name='direction'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='new_node'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_remove' mangled-name='avl_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_remove'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='eaa32e2f' name='data'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='avl_update_lt' mangled-name='avl_update_lt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_update_lt'>
<parameter type-id='a3681dea' name='t'/>
<parameter type-id='eaa32e2f' name='obj'/>
@@ -4742,30 +8972,10 @@
<parameter type-id='a3681dea' name='tree2'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='avl_create' mangled-name='avl_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_create'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='585e1de9' name='compar'/>
- <parameter type-id='b59d7dce' name='size'/>
- <parameter type-id='b59d7dce' name='offset'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_destroy' mangled-name='avl_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'>
- <parameter type-id='a3681dea' name='tree'/>
- <return type-id='ee1f298e'/>
- </function-decl>
<function-decl name='avl_is_empty' mangled-name='avl_is_empty' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_is_empty'>
<parameter type-id='a3681dea' name='tree'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='avl_destroy_nodes' mangled-name='avl_destroy_nodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_destroy_nodes'>
- <parameter type-id='a3681dea' name='tree'/>
- <parameter type-id='63e171df' name='cookie'/>
- <return type-id='eaa32e2f'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/cityhash.c' language='LANG_C99'>
<function-decl name='cityhash4' mangled-name='cityhash4' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='cityhash4'>
@@ -4777,52 +8987,9 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='16576' id='9d5e9e2e'>
- <subrange length='37' type-id='7359adad' id='ae666bde'/>
+ <array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='18368' id='b93e4d14'>
+ <subrange length='41' type-id='7359adad' id='cb834f44'/>
</array-type-def>
- <enum-decl name='spa_feature' id='33ecb627'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='SPA_FEATURE_NONE' value='-1'/>
- <enumerator name='SPA_FEATURE_ASYNC_DESTROY' value='0'/>
- <enumerator name='SPA_FEATURE_EMPTY_BPOBJ' value='1'/>
- <enumerator name='SPA_FEATURE_LZ4_COMPRESS' value='2'/>
- <enumerator name='SPA_FEATURE_MULTI_VDEV_CRASH_DUMP' value='3'/>
- <enumerator name='SPA_FEATURE_SPACEMAP_HISTOGRAM' value='4'/>
- <enumerator name='SPA_FEATURE_ENABLED_TXG' value='5'/>
- <enumerator name='SPA_FEATURE_HOLE_BIRTH' value='6'/>
- <enumerator name='SPA_FEATURE_EXTENSIBLE_DATASET' value='7'/>
- <enumerator name='SPA_FEATURE_EMBEDDED_DATA' value='8'/>
- <enumerator name='SPA_FEATURE_BOOKMARKS' value='9'/>
- <enumerator name='SPA_FEATURE_FS_SS_LIMIT' value='10'/>
- <enumerator name='SPA_FEATURE_LARGE_BLOCKS' value='11'/>
- <enumerator name='SPA_FEATURE_LARGE_DNODE' value='12'/>
- <enumerator name='SPA_FEATURE_SHA512' value='13'/>
- <enumerator name='SPA_FEATURE_SKEIN' value='14'/>
- <enumerator name='SPA_FEATURE_EDONR' value='15'/>
- <enumerator name='SPA_FEATURE_USEROBJ_ACCOUNTING' value='16'/>
- <enumerator name='SPA_FEATURE_ENCRYPTION' value='17'/>
- <enumerator name='SPA_FEATURE_PROJECT_QUOTA' value='18'/>
- <enumerator name='SPA_FEATURE_DEVICE_REMOVAL' value='19'/>
- <enumerator name='SPA_FEATURE_OBSOLETE_COUNTS' value='20'/>
- <enumerator name='SPA_FEATURE_POOL_CHECKPOINT' value='21'/>
- <enumerator name='SPA_FEATURE_SPACEMAP_V2' value='22'/>
- <enumerator name='SPA_FEATURE_ALLOCATION_CLASSES' value='23'/>
- <enumerator name='SPA_FEATURE_RESILVER_DEFER' value='24'/>
- <enumerator name='SPA_FEATURE_BOOKMARK_V2' value='25'/>
- <enumerator name='SPA_FEATURE_REDACTION_BOOKMARKS' value='26'/>
- <enumerator name='SPA_FEATURE_REDACTED_DATASETS' value='27'/>
- <enumerator name='SPA_FEATURE_BOOKMARK_WRITTEN' value='28'/>
- <enumerator name='SPA_FEATURE_LOG_SPACEMAP' value='29'/>
- <enumerator name='SPA_FEATURE_LIVELIST' value='30'/>
- <enumerator name='SPA_FEATURE_DEVICE_REBUILD' value='31'/>
- <enumerator name='SPA_FEATURE_ZSTD_COMPRESS' value='32'/>
- <enumerator name='SPA_FEATURE_DRAID' value='33'/>
- <enumerator name='SPA_FEATURE_ZILSAXATTR' value='34'/>
- <enumerator name='SPA_FEATURE_HEAD_ERRLOG' value='35'/>
- <enumerator name='SPA_FEATURE_BLAKE3' value='36'/>
- <enumerator name='SPA_FEATURES' value='37'/>
- </enum-decl>
- <typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/>
<enum-decl name='zfeature_flags' id='6db816a4'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFEATURE_FLAG_READONLY_COMPAT' value='1'/>
@@ -4865,6 +9032,24 @@
</data-member>
</class-decl>
<typedef-decl name='zfeature_info_t' type-id='1178d146' id='83f29ca2'/>
+ <typedef-decl name='__free_fn_t' type-id='b7f9d8e6' id='3ff5e51e'/>
+ <class-decl name='dirent' size-in-bits='2240' is-struct='yes' visibility='default' id='611586a1'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='d_ino' type-id='71288a47' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='d_off' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='d_reclen' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='144'>
+ <var-decl name='d_type' type-id='002ac4a6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='152'>
+ <var-decl name='d_name' type-id='d1617432' visibility='default'/>
+ </data-member>
+ </class-decl>
<class-decl name='zfs_mod_supported_features' size-in-bits='128' is-struct='yes' visibility='default' id='3eee3342'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tree' type-id='eaa32e2f' visibility='default'/>
@@ -4877,26 +9062,35 @@
<pointer-type-def type-id='81a65028' size-in-bits='64' id='1acff326'/>
<qualified-type-def type-id='3eee3342' const='yes' id='0c1d5bbb'/>
<pointer-type-def type-id='0c1d5bbb' size-in-bits='64' id='a3372543'/>
- <pointer-type-def type-id='d6618c78' size-in-bits='64' id='a8425263'/>
- <var-decl name='spa_feature_table' type-id='9d5e9e2e' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
+ <pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/>
+ <qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
+ <pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
+ <var-decl name='spa_feature_table' type-id='b93e4d14' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
<var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/>
- <function-decl name='zfeature_is_valid_guid' mangled-name='zfeature_is_valid_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_valid_guid'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='f09217ba'/>
</function-decl>
- <function-decl name='zfeature_is_supported' mangled-name='zfeature_is_supported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_supported'>
- <parameter type-id='80f4b756' name='guid'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='tsearch' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='63e171df'/>
+ <parameter type-id='aba7edd8'/>
+ <return type-id='eaa32e2f'/>
</function-decl>
- <function-decl name='zfeature_lookup_guid' mangled-name='zfeature_lookup_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_guid'>
- <parameter type-id='80f4b756' name='guid'/>
- <parameter type-id='a8425263' name='res'/>
- <return type-id='95e97e5e'/>
+ <function-decl name='tfind' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='7acd98a2'/>
+ <parameter type-id='aba7edd8'/>
+ <return type-id='eaa32e2f'/>
</function-decl>
- <function-decl name='zfeature_lookup_name' mangled-name='zfeature_lookup_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_lookup_name'>
+ <function-decl name='tdestroy' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='3ff5e51e'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zfeature_is_valid_guid' mangled-name='zfeature_is_valid_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_is_valid_guid'>
<parameter type-id='80f4b756' name='name'/>
- <parameter type-id='a8425263' name='res'/>
- <return type-id='95e97e5e'/>
+ <return type-id='c19b74c3'/>
</function-decl>
<function-decl name='zfeature_depends_on' mangled-name='zfeature_depends_on' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfeature_depends_on'>
<parameter type-id='d6618c78' name='fid'/>
@@ -4909,46 +9103,33 @@
<parameter type-id='a3372543' name='sfeatures'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zpool_feature_init' mangled-name='zpool_feature_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_feature_init'>
- <return type-id='48b5725f'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfs_comutil.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='2624' id='5ce15418'>
<subrange length='41' type-id='7359adad' id='cb834f44'/>
</array-type-def>
- <class-decl name='zpool_load_policy' size-in-bits='256' is-struct='yes' visibility='default' id='2f65b36f'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zlp_rewind' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='zlp_maxmeta' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='zlp_maxdata' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='zlp_txg' type-id='9c313c2d' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zpool_load_policy_t' type-id='2f65b36f' id='d11b7617'/>
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
- <pointer-type-def type-id='d11b7617' size-in-bits='64' id='23432aaa'/>
+ <pointer-type-def type-id='8f92235e' size-in-bits='64' id='90421557'/>
+ <function-decl name='nvpair_value_uint32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <parameter type-id='90421557'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<var-decl name='zfs_history_event_names' type-id='5ce15418' mangled-name='zfs_history_event_names' visibility='default' elf-symbol-id='zfs_history_event_names'/>
+ <function-decl name='strpbrk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
<function-decl name='zfs_allocatable_devs' mangled-name='zfs_allocatable_devs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_allocatable_devs'>
<parameter type-id='5ce45b60' name='nv'/>
<return type-id='c19b74c3'/>
</function-decl>
<function-decl name='zfs_special_devs' mangled-name='zfs_special_devs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_special_devs'>
<parameter type-id='5ce45b60' name='nv'/>
- <parameter type-id='26a90f95' name='type'/>
+ <parameter type-id='80f4b756' name='type'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zpool_get_load_policy' mangled-name='zpool_get_load_policy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_load_policy'>
- <parameter type-id='5ce45b60' name='nvl'/>
- <parameter type-id='23432aaa' name='zlpp'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='zfs_zpl_version_map' mangled-name='zfs_zpl_version_map' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_zpl_version_map'>
<parameter type-id='95e97e5e' name='spa_version'/>
<return type-id='95e97e5e'/>
@@ -4963,6 +9144,9 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfs_deleg.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4096' id='59e94aca'>
+ <subrange length='32' type-id='7359adad' id='ae5bde82'/>
+ </array-type-def>
<array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='infinite' id='7c00e69d'>
<subrange length='infinite' id='031f2035'/>
</array-type-def>
@@ -5019,7 +9203,7 @@
<typedef-decl name='zfs_deleg_note_t' type-id='729d4547' id='4613c173'/>
<class-decl name='zfs_deleg_perm_tab' size-in-bits='128' is-struct='yes' visibility='default' id='5aa05c1f'>
<data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='z_perm' type-id='26a90f95' visibility='default'/>
+ <var-decl name='z_perm' type-id='80f4b756' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='z_note' type-id='4613c173' visibility='default'/>
@@ -5028,6 +9212,16 @@
<typedef-decl name='zfs_deleg_perm_tab_t' type-id='5aa05c1f' id='f3f851ad'/>
<qualified-type-def type-id='f3f851ad' const='yes' id='fa1870fd'/>
<var-decl name='zfs_deleg_perm_tab' type-id='7c00e69d' mangled-name='zfs_deleg_perm_tab' visibility='default' elf-symbol-id='zfs_deleg_perm_tab'/>
+ <function-decl name='permset_namecheck' mangled-name='permset_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='permset_namecheck'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='053457bd'/>
+ <parameter type-id='26a90f95'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zfs_prop_delegatable' mangled-name='zfs_prop_delegatable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_delegatable'>
+ <parameter type-id='58603c44'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
<function-decl name='zfs_deleg_canonicalize_perm' mangled-name='zfs_deleg_canonicalize_perm' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_deleg_canonicalize_perm'>
<parameter type-id='80f4b756' name='perm'/>
<return type-id='80f4b756'/>
@@ -5045,9 +9239,6 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfs_fletcher.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='256' id='85c64d26'>
- <subrange length='4' type-id='7359adad' id='16fe7105'/>
- </array-type-def>
<array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='512' id='c5d13f42'>
<subrange length='8' type-id='7359adad' id='56e0c0b1'/>
</array-type-def>
@@ -5063,12 +9254,6 @@
<array-type-def dimensions='1' type-id='6d059eaa' size-in-bits='1024' id='729b6ebb'>
<subrange length='4' type-id='7359adad' id='16fe7105'/>
</array-type-def>
- <class-decl name='zio_cksum' size-in-bits='256' is-struct='yes' visibility='default' id='1d53e28b'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zc_word' type-id='85c64d26' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zio_cksum_t' type-id='1d53e28b' id='39730d0b'/>
<enum-decl name='zio_byteorder_t' naming-typedef-id='595a65ec' id='fc861be0'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZIO_CHECKSUM_NATIVE' value='0'/>
@@ -5149,12 +9334,21 @@
<typedef-decl name='fletcher_4_ctx_t' type-id='1f951ade' id='4b675395'/>
<qualified-type-def type-id='aa14691a' const='yes' id='3f8e8d11'/>
<pointer-type-def type-id='4b675395' size-in-bits='64' id='0f7df99e'/>
+ <qualified-type-def type-id='8f92235e' volatile='yes' id='430e0681'/>
+ <pointer-type-def type-id='430e0681' size-in-bits='64' id='3a147f31'/>
<pointer-type-def type-id='74e39470' size-in-bits='64' id='eefe7427'/>
<pointer-type-def type-id='d6fd5c6c' size-in-bits='64' id='bfe36153'/>
<pointer-type-def type-id='029a8ebe' size-in-bits='64' id='0bcca125'/>
<pointer-type-def type-id='cefa0f4a' size-in-bits='64' id='1e276399'/>
- <pointer-type-def type-id='39730d0b' size-in-bits='64' id='c24fc2ee'/>
<var-decl name='fletcher_4_abd_ops' type-id='c2eb138a' mangled-name='fletcher_4_abd_ops' visibility='default' elf-symbol-id='fletcher_4_abd_ops'/>
+ <function-decl name='atomic_swap_32' mangled-name='atomic_swap_32' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_swap_32'>
+ <parameter type-id='3a147f31'/>
+ <parameter type-id='8f92235e'/>
+ <return type-id='8f92235e'/>
+ </function-decl>
+ <function-decl name='membar_producer' mangled-name='membar_producer' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='membar_producer'>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='fletcher_init' mangled-name='fletcher_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_init'>
<parameter type-id='c24fc2ee' name='zcp'/>
<return type-id='48b5725f'/>
@@ -5196,12 +9390,6 @@
<parameter type-id='c24fc2ee' name='zcp'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='fletcher_4_native_varsize' mangled-name='fletcher_4_native_varsize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_native_varsize'>
- <parameter type-id='eaa32e2f' name='buf'/>
- <parameter type-id='9c313c2d' name='size'/>
- <parameter type-id='c24fc2ee' name='zcp'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='fletcher_4_byteswap' mangled-name='fletcher_4_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_byteswap'>
<parameter type-id='eaa32e2f' name='buf'/>
<parameter type-id='9c313c2d' name='size'/>
@@ -5209,24 +9397,6 @@
<parameter type-id='c24fc2ee' name='zcp'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='fletcher_4_incremental_native' mangled-name='fletcher_4_incremental_native' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_native'>
- <parameter type-id='eaa32e2f' name='buf'/>
- <parameter type-id='b59d7dce' name='size'/>
- <parameter type-id='eaa32e2f' name='data'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='fletcher_4_incremental_byteswap' mangled-name='fletcher_4_incremental_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_incremental_byteswap'>
- <parameter type-id='eaa32e2f' name='buf'/>
- <parameter type-id='b59d7dce' name='size'/>
- <parameter type-id='eaa32e2f' name='data'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='fletcher_4_init' mangled-name='fletcher_4_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_init'>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='fletcher_4_fini' mangled-name='fletcher_4_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_fini'>
- <return type-id='48b5725f'/>
- </function-decl>
<function-type size-in-bits='64' id='f4a1892e'>
<parameter type-id='eaa32e2f'/>
<parameter type-id='b59d7dce'/>
@@ -5242,7 +9412,7 @@
<typedef-decl name='fletcher_4_init_f' type-id='173aa527' id='b9ae1656'/>
<typedef-decl name='fletcher_4_fini_f' type-id='0ad5b8a8' id='c4c1f4fc'/>
<typedef-decl name='fletcher_4_compute_f' type-id='38147eff' id='ad1dc4cb'/>
- <class-decl name='fletcher_4_func' size-in-bits='512' is-struct='yes' visibility='default' id='57f479a0'>
+ <class-decl name='fletcher_4_func' size-in-bits='1024' is-struct='yes' visibility='default' id='57f479a0'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='init_native' type-id='b9ae1656' visibility='default'/>
</data-member>
@@ -5265,6 +9435,9 @@
<var-decl name='valid' type-id='297d38bc' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='uses_fpu' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
<var-decl name='name' type-id='80f4b756' visibility='default'/>
</data-member>
</class-decl>
@@ -5309,24 +9482,6 @@
<var-decl name='fletcher_4_superscalar4_ops' type-id='9eeabdc8' mangled-name='fletcher_4_superscalar4_ops' visibility='default' elf-symbol-id='fletcher_4_superscalar4_ops'/>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfs_namecheck.c' language='LANG_C99'>
- <enum-decl name='namecheck_err_t' naming-typedef-id='8e0af06e' id='f43bbcda'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='NAME_ERR_LEADING_SLASH' value='0'/>
- <enumerator name='NAME_ERR_EMPTY_COMPONENT' value='1'/>
- <enumerator name='NAME_ERR_TRAILING_SLASH' value='2'/>
- <enumerator name='NAME_ERR_INVALCHAR' value='3'/>
- <enumerator name='NAME_ERR_MULTIPLE_DELIMITERS' value='4'/>
- <enumerator name='NAME_ERR_NOLETTER' value='5'/>
- <enumerator name='NAME_ERR_RESERVED' value='6'/>
- <enumerator name='NAME_ERR_DISKLIKE' value='7'/>
- <enumerator name='NAME_ERR_TOOLONG' value='8'/>
- <enumerator name='NAME_ERR_SELF_REF' value='9'/>
- <enumerator name='NAME_ERR_PARENT_REF' value='10'/>
- <enumerator name='NAME_ERR_NO_AT' value='11'/>
- <enumerator name='NAME_ERR_NO_POUND' value='12'/>
- </enum-decl>
- <typedef-decl name='namecheck_err_t' type-id='f43bbcda' id='8e0af06e'/>
- <pointer-type-def type-id='8e0af06e' size-in-bits='64' id='053457bd'/>
<var-decl name='zfs_max_dataset_nesting' type-id='95e97e5e' mangled-name='zfs_max_dataset_nesting' visibility='default' elf-symbol-id='zfs_max_dataset_nesting'/>
<function-decl name='get_dataset_depth' mangled-name='get_dataset_depth' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_dataset_depth'>
<parameter type-id='80f4b756' name='path'/>
@@ -5338,22 +9493,6 @@
<parameter type-id='26a90f95' name='what'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='permset_namecheck' mangled-name='permset_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='permset_namecheck'>
- <parameter type-id='80f4b756' name='path'/>
- <parameter type-id='053457bd' name='why'/>
- <parameter type-id='26a90f95' name='what'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='dataset_nestcheck' mangled-name='dataset_nestcheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='dataset_nestcheck'>
- <parameter type-id='80f4b756' name='path'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='entity_namecheck' mangled-name='entity_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='entity_namecheck'>
- <parameter type-id='80f4b756' name='path'/>
- <parameter type-id='053457bd' name='why'/>
- <parameter type-id='26a90f95' name='what'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='dataset_namecheck' mangled-name='dataset_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='dataset_namecheck'>
<parameter type-id='80f4b756' name='path'/>
<parameter type-id='053457bd' name='why'/>
@@ -5372,125 +9511,100 @@
<parameter type-id='26a90f95' name='what'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='mountpoint_namecheck' mangled-name='mountpoint_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mountpoint_namecheck'>
- <parameter type-id='80f4b756' name='path'/>
- <parameter type-id='053457bd' name='why'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='pool_namecheck' mangled-name='pool_namecheck' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='pool_namecheck'>
- <parameter type-id='80f4b756' name='pool'/>
- <parameter type-id='053457bd' name='why'/>
- <parameter type-id='26a90f95' name='what'/>
- <return type-id='95e97e5e'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfs_prop.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='b99c00c9' size-in-bits='768' id='bcc77e38'>
<subrange length='12' type-id='7359adad' id='84827bdc'/>
</array-type-def>
- <enum-decl name='zprop_type_t' naming-typedef-id='31429eff' id='87676253'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='PROP_TYPE_NUMBER' value='0'/>
- <enumerator name='PROP_TYPE_STRING' value='1'/>
- <enumerator name='PROP_TYPE_INDEX' value='2'/>
- </enum-decl>
- <typedef-decl name='zprop_type_t' type-id='87676253' id='31429eff'/>
- <enum-decl name='zprop_attr_t' naming-typedef-id='999701cc' id='77d05200'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='PROP_DEFAULT' value='0'/>
- <enumerator name='PROP_READONLY' value='1'/>
- <enumerator name='PROP_INHERIT' value='2'/>
- <enumerator name='PROP_ONETIME' value='3'/>
- <enumerator name='PROP_ONETIME_DEFAULT' value='4'/>
- </enum-decl>
- <typedef-decl name='zprop_attr_t' type-id='77d05200' id='999701cc'/>
- <class-decl name='zfs_index' size-in-bits='128' is-struct='yes' visibility='default' id='87957af9'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='pi_name' type-id='80f4b756' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='pi_value' type-id='9c313c2d' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zprop_index_t' type-id='87957af9' id='64636ce3'/>
- <class-decl name='zprop_desc_t' size-in-bits='640' is-struct='yes' naming-typedef-id='ffa52b96' visibility='default' id='bbff5e4b'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='pd_name' type-id='80f4b756' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='pd_propnum' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='96'>
- <var-decl name='pd_proptype' type-id='31429eff' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='pd_strdefault' type-id='80f4b756' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='pd_numdefault' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='pd_attr' type-id='999701cc' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='288'>
- <var-decl name='pd_types' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='pd_values' type-id='80f4b756' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='pd_colname' type-id='80f4b756' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='pd_rightalign' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='449'>
- <var-decl name='pd_visible' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='450'>
- <var-decl name='pd_zfs_mod_supported' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='451'>
- <var-decl name='pd_always_flex' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='pd_table' type-id='c8bc397b' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='pd_table_size' type-id='b59d7dce' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zprop_desc_t' type-id='bbff5e4b' id='ffa52b96'/>
- <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/>
- <qualified-type-def type-id='64636ce3' const='yes' id='072f7953'/>
- <pointer-type-def type-id='072f7953' size-in-bits='64' id='c8bc397b'/>
- <pointer-type-def type-id='ffa52b96' size-in-bits='64' id='76c8174b'/>
+ <pointer-type-def type-id='3eee3342' size-in-bits='64' id='73f8e240'/>
<var-decl name='zfs_userquota_prop_prefixes' type-id='bcc77e38' mangled-name='zfs_userquota_prop_prefixes' visibility='default' elf-symbol-id='zfs_userquota_prop_prefixes'/>
- <function-decl name='zfs_prop_get_table' mangled-name='zfs_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_table'>
- <return type-id='76c8174b'/>
+ <function-decl name='zfs_mod_list_supported' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='73f8e240'/>
</function-decl>
- <function-decl name='zfs_prop_init' mangled-name='zfs_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_init'>
+ <function-decl name='zfs_mod_list_supported_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='73f8e240'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_prop_delegatable' mangled-name='zfs_prop_delegatable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_delegatable'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='zprop_register_impl' mangled-name='zprop_register_impl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_impl'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='31429eff'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='999701cc'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='c8bc397b'/>
+ <parameter type-id='a3372543'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_name_to_prop' mangled-name='zfs_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_name_to_prop'>
- <parameter type-id='80f4b756' name='propname'/>
- <return type-id='58603c44'/>
+ <function-decl name='zprop_register_string' mangled-name='zprop_register_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_string'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='999701cc'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a3372543'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_prop_user' mangled-name='zfs_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_user'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='zprop_register_number' mangled-name='zprop_register_number' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_number'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='999701cc'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='a3372543'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_prop_userquota' mangled-name='zfs_prop_userquota' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_userquota'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='zprop_register_index' mangled-name='zprop_register_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_index'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='999701cc'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c8bc397b'/>
+ <parameter type-id='a3372543'/>
+ <return type-id='48b5725f'/>
</function-decl>
- <function-decl name='zfs_prop_written' mangled-name='zfs_prop_written' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_written'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
+ <function-decl name='zprop_register_hidden' mangled-name='zprop_register_hidden' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_hidden'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='31429eff'/>
+ <parameter type-id='999701cc'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <parameter type-id='a3372543'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zprop_index_to_string' mangled-name='zprop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_index_to_string'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='7d3cd834'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zprop_random_value' mangled-name='zprop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_random_value'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9c313c2d'/>
+ <parameter type-id='2e45de5d'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='zprop_valid_char' mangled-name='zprop_valid_char' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_char'>
+ <parameter type-id='a84c031d'/>
+ <return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_prop_string_to_index' mangled-name='zfs_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_string_to_index'>
<parameter type-id='58603c44' name='prop'/>
@@ -5498,64 +9612,15 @@
<parameter type-id='5d6479ae' name='index'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zfs_prop_index_to_string' mangled-name='zfs_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_index_to_string'>
- <parameter type-id='58603c44' name='prop'/>
- <parameter type-id='9c313c2d' name='index'/>
- <parameter type-id='7d3cd834' name='string'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zfs_prop_random_value' mangled-name='zfs_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_random_value'>
<parameter type-id='58603c44' name='prop'/>
<parameter type-id='9c313c2d' name='seed'/>
<return type-id='9c313c2d'/>
</function-decl>
- <function-decl name='zfs_prop_valid_for_type' mangled-name='zfs_prop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_for_type'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='2e45de5d' name='types'/>
- <parameter type-id='c19b74c3' name='headcheck'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zfs_prop_get_type' mangled-name='zfs_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_get_type'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='31429eff'/>
- </function-decl>
- <function-decl name='zfs_prop_readonly' mangled-name='zfs_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_readonly'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
<function-decl name='zfs_prop_visible' mangled-name='zfs_prop_visible' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_visible'>
<parameter type-id='58603c44' name='prop'/>
<return type-id='c19b74c3'/>
</function-decl>
- <function-decl name='zfs_prop_setonce' mangled-name='zfs_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_setonce'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zfs_prop_default_string' mangled-name='zfs_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_string'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='zfs_prop_default_numeric' mangled-name='zfs_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_default_numeric'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='9c313c2d'/>
- </function-decl>
- <function-decl name='zfs_prop_to_name' mangled-name='zfs_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_to_name'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='zfs_prop_inheritable' mangled-name='zfs_prop_inheritable' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inheritable'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zfs_prop_encryption_key_param' mangled-name='zfs_prop_encryption_key_param' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_encryption_key_param'>
- <parameter type-id='58603c44' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zfs_prop_valid_keylocation' mangled-name='zfs_prop_valid_keylocation' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_valid_keylocation'>
- <parameter type-id='80f4b756' name='str'/>
- <parameter type-id='c19b74c3' name='encrypted'/>
- <return type-id='c19b74c3'/>
- </function-decl>
<function-decl name='zfs_prop_values' mangled-name='zfs_prop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_values'>
<parameter type-id='58603c44' name='prop'/>
<return type-id='80f4b756'/>
@@ -5574,60 +9639,12 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zpool_prop.c' language='LANG_C99'>
- <function-decl name='zpool_prop_get_table' mangled-name='zpool_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_table'>
- <return type-id='76c8174b'/>
- </function-decl>
- <function-decl name='zpool_prop_init' mangled-name='zpool_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_init'>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zpool_name_to_prop' mangled-name='zpool_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_name_to_prop'>
- <parameter type-id='80f4b756' name='propname'/>
- <return type-id='5d0c23fb'/>
- </function-decl>
- <function-decl name='zpool_prop_to_name' mangled-name='zpool_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_to_name'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='zpool_prop_get_type' mangled-name='zpool_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_type'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='31429eff'/>
- </function-decl>
- <function-decl name='zpool_prop_readonly' mangled-name='zpool_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_readonly'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zpool_prop_setonce' mangled-name='zpool_prop_setonce' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_setonce'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zpool_prop_default_string' mangled-name='zpool_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_string'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='zpool_prop_default_numeric' mangled-name='zpool_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_default_numeric'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <return type-id='9c313c2d'/>
- </function-decl>
- <function-decl name='zpool_prop_feature' mangled-name='zpool_prop_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_feature'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zpool_prop_unsupported' mangled-name='zpool_prop_unsupported' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_unsupported'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
<function-decl name='zpool_prop_string_to_index' mangled-name='zpool_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_string_to_index'>
<parameter type-id='5d0c23fb' name='prop'/>
<parameter type-id='80f4b756' name='string'/>
<parameter type-id='5d6479ae' name='index'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='zpool_prop_index_to_string' mangled-name='zpool_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_index_to_string'>
- <parameter type-id='5d0c23fb' name='prop'/>
- <parameter type-id='9c313c2d' name='index'/>
- <parameter type-id='7d3cd834' name='string'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='zpool_prop_random_value' mangled-name='zpool_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_random_value'>
<parameter type-id='5d0c23fb' name='prop'/>
<parameter type-id='9c313c2d' name='seed'/>
@@ -5648,53 +9665,12 @@
<function-decl name='vdev_prop_get_table' mangled-name='vdev_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_table'>
<return type-id='76c8174b'/>
</function-decl>
- <function-decl name='vdev_prop_init' mangled-name='vdev_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_init'>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='vdev_name_to_prop' mangled-name='vdev_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_name_to_prop'>
- <parameter type-id='80f4b756' name='propname'/>
- <return type-id='5aa5c90c'/>
- </function-decl>
- <function-decl name='vdev_prop_user' mangled-name='vdev_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_user'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='vdev_prop_to_name' mangled-name='vdev_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_to_name'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='vdev_prop_get_type' mangled-name='vdev_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_type'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <return type-id='31429eff'/>
- </function-decl>
- <function-decl name='vdev_prop_readonly' mangled-name='vdev_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_readonly'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='vdev_prop_default_string' mangled-name='vdev_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_string'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='vdev_prop_default_numeric' mangled-name='vdev_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_numeric'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <return type-id='9c313c2d'/>
- </function-decl>
<function-decl name='vdev_prop_string_to_index' mangled-name='vdev_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_string_to_index'>
<parameter type-id='5aa5c90c' name='prop'/>
<parameter type-id='80f4b756' name='string'/>
<parameter type-id='5d6479ae' name='index'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='vdev_prop_index_to_string' mangled-name='vdev_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_index_to_string'>
- <parameter type-id='5aa5c90c' name='prop'/>
- <parameter type-id='9c313c2d' name='index'/>
- <parameter type-id='7d3cd834' name='string'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zpool_prop_vdev' mangled-name='zpool_prop_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_vdev'>
- <parameter type-id='80f4b756' name='name'/>
- <return type-id='c19b74c3'/>
- </function-decl>
<function-decl name='vdev_prop_random_value' mangled-name='vdev_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_random_value'>
<parameter type-id='5aa5c90c' name='prop'/>
<parameter type-id='9c313c2d' name='seed'/>
@@ -5714,122 +9690,8 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zprop_common.c' language='LANG_C99'>
- <function-decl name='zprop_register_impl' mangled-name='zprop_register_impl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_impl'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='31429eff' name='type'/>
- <parameter type-id='9c313c2d' name='numdefault'/>
- <parameter type-id='80f4b756' name='strdefault'/>
- <parameter type-id='999701cc' name='attr'/>
- <parameter type-id='95e97e5e' name='objset_types'/>
- <parameter type-id='80f4b756' name='values'/>
- <parameter type-id='80f4b756' name='colname'/>
- <parameter type-id='c19b74c3' name='rightalign'/>
- <parameter type-id='c19b74c3' name='visible'/>
- <parameter type-id='c19b74c3' name='flex'/>
- <parameter type-id='c8bc397b' name='idx_tbl'/>
- <parameter type-id='a3372543' name='sfeatures'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zprop_register_string' mangled-name='zprop_register_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_string'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='80f4b756' name='def'/>
- <parameter type-id='999701cc' name='attr'/>
- <parameter type-id='95e97e5e' name='objset_types'/>
- <parameter type-id='80f4b756' name='values'/>
- <parameter type-id='80f4b756' name='colname'/>
- <parameter type-id='a3372543' name='sfeatures'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zprop_register_number' mangled-name='zprop_register_number' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_number'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9c313c2d' name='def'/>
- <parameter type-id='999701cc' name='attr'/>
- <parameter type-id='95e97e5e' name='objset_types'/>
- <parameter type-id='80f4b756' name='values'/>
- <parameter type-id='80f4b756' name='colname'/>
- <parameter type-id='c19b74c3' name='flex'/>
- <parameter type-id='a3372543' name='sfeatures'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zprop_register_index' mangled-name='zprop_register_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_index'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='9c313c2d' name='def'/>
- <parameter type-id='999701cc' name='attr'/>
- <parameter type-id='95e97e5e' name='objset_types'/>
- <parameter type-id='80f4b756' name='values'/>
- <parameter type-id='80f4b756' name='colname'/>
- <parameter type-id='c8bc397b' name='idx_tbl'/>
- <parameter type-id='a3372543' name='sfeatures'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zprop_register_hidden' mangled-name='zprop_register_hidden' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_hidden'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='name'/>
- <parameter type-id='31429eff' name='type'/>
- <parameter type-id='999701cc' name='attr'/>
- <parameter type-id='95e97e5e' name='objset_types'/>
- <parameter type-id='80f4b756' name='colname'/>
- <parameter type-id='c19b74c3' name='flex'/>
- <parameter type-id='a3372543' name='sfeatures'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='zprop_iter_common' mangled-name='zprop_iter_common' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_iter_common'>
- <parameter type-id='1ec3747a' name='func'/>
- <parameter type-id='eaa32e2f' name='cb'/>
- <parameter type-id='c19b74c3' name='show_all'/>
- <parameter type-id='c19b74c3' name='ordered'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zprop_name_to_prop' mangled-name='zprop_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_name_to_prop'>
- <parameter type-id='80f4b756' name='propname'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zprop_string_to_index' mangled-name='zprop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_string_to_index'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='80f4b756' name='string'/>
- <parameter type-id='5d6479ae' name='index'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zprop_index_to_string' mangled-name='zprop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_index_to_string'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='9c313c2d' name='index'/>
- <parameter type-id='7d3cd834' name='string'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zprop_random_value' mangled-name='zprop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_random_value'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='9c313c2d' name='seed'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='9c313c2d'/>
- </function-decl>
- <function-decl name='zprop_values' mangled-name='zprop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_values'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='80f4b756'/>
- </function-decl>
- <function-decl name='zprop_valid_for_type' mangled-name='zprop_valid_for_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_for_type'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='2e45de5d' name='type'/>
- <parameter type-id='c19b74c3' name='headcheck'/>
- <return type-id='c19b74c3'/>
- </function-decl>
- <function-decl name='zprop_valid_char' mangled-name='zprop_valid_char' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_char'>
- <parameter type-id='a84c031d' name='c'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='zprop_width' mangled-name='zprop_width' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_width'>
- <parameter type-id='95e97e5e' name='prop'/>
- <parameter type-id='37e3bd22' name='fixed'/>
- <parameter type-id='2e45de5d' name='type'/>
- <return type-id='b59d7dce'/>
+ <function-decl name='__ctype_tolower_loc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='24f95ba5'/>
</function-decl>
</abi-instr>
</abi-corpus>
diff --git a/lib/libzfs/libzfs_changelist.c b/lib/libzfs/libzfs_changelist.c
index d31bbc4a3b42..4db1cbce9568 100644
--- a/lib/libzfs/libzfs_changelist.c
+++ b/lib/libzfs/libzfs_changelist.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -105,6 +105,15 @@ changelist_prefix(prop_changelist_t *clp)
clp->cl_prop != ZFS_PROP_SHARESMB)
return (0);
+ /*
+ * If CL_GATHER_DONT_UNMOUNT is set, don't want to unmount/unshare and
+ * later (re)mount/(re)share the filesystem in postfix phase, so we
+ * return from here. If filesystem is mounted or unmounted, leave it
+ * as it is.
+ */
+ if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
+ return (0);
+
if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL)
return (-1);
@@ -129,8 +138,6 @@ changelist_prefix(prop_changelist_t *clp)
*/
switch (clp->cl_prop) {
case ZFS_PROP_MOUNTPOINT:
- if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
- break;
if (zfs_unmount(cn->cn_handle, NULL,
clp->cl_mflags) != 0) {
ret = -1;
@@ -164,9 +171,8 @@ changelist_prefix(prop_changelist_t *clp)
* reshare the filesystems as necessary. In changelist_gather() we recorded
* whether the filesystem was previously shared or mounted. The action we take
* depends on the previous state, and whether the value was previously 'legacy'.
- * For non-legacy properties, we only remount/reshare the filesystem if it was
- * previously mounted/shared. Otherwise, we always remount/reshare the
- * filesystem.
+ * For non-legacy properties, we always remount/reshare the filesystem,
+ * if CL_GATHER_DONT_UNMOUNT is not set.
*/
int
changelist_postfix(prop_changelist_t *clp)
@@ -174,11 +180,18 @@ changelist_postfix(prop_changelist_t *clp)
prop_changenode_t *cn;
uu_avl_walk_t *walk;
char shareopts[ZFS_MAXPROPLEN];
- int errors = 0;
boolean_t commit_smb_shares = B_FALSE;
boolean_t commit_nfs_shares = B_FALSE;
/*
+ * If CL_GATHER_DONT_UNMOUNT is set, it means we don't want to (un)mount
+ * or (re/un)share the filesystem, so we return from here. If filesystem
+ * is mounted or unmounted, leave it as it is.
+ */
+ if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
+ return (0);
+
+ /*
* If we're changing the mountpoint, attempt to destroy the underlying
* mountpoint. All other datasets will have inherited from this dataset
* (in which case their mountpoints exist in the filesystem in the new
@@ -240,17 +253,16 @@ changelist_postfix(prop_changelist_t *clp)
needs_key = (zfs_prop_get_int(cn->cn_handle,
ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE);
- mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) ||
- zfs_is_mounted(cn->cn_handle, NULL);
+ mounted = zfs_is_mounted(cn->cn_handle, NULL);
if (!mounted && !needs_key && (cn->cn_mounted ||
- ((sharenfs || sharesmb || clp->cl_waslegacy) &&
+ (((clp->cl_prop == ZFS_PROP_MOUNTPOINT &&
+ clp->cl_prop == clp->cl_realprop) ||
+ sharenfs || sharesmb || clp->cl_waslegacy) &&
(zfs_prop_get_int(cn->cn_handle,
ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_ON)))) {
- if (zfs_mount(cn->cn_handle, NULL, 0) != 0)
- errors++;
- else
+ if (zfs_mount(cn->cn_handle, NULL, 0) == 0)
mounted = TRUE;
}
@@ -262,19 +274,19 @@ changelist_postfix(prop_changelist_t *clp)
const enum sa_protocol nfs[] =
{SA_PROTOCOL_NFS, SA_NO_PROTOCOL};
if (sharenfs && mounted) {
- errors += zfs_share(cn->cn_handle, nfs);
+ zfs_share(cn->cn_handle, nfs);
commit_nfs_shares = B_TRUE;
} else if (cn->cn_shared || clp->cl_waslegacy) {
- errors += zfs_unshare(cn->cn_handle, NULL, nfs);
+ zfs_unshare(cn->cn_handle, NULL, nfs);
commit_nfs_shares = B_TRUE;
}
const enum sa_protocol smb[] =
{SA_PROTOCOL_SMB, SA_NO_PROTOCOL};
if (sharesmb && mounted) {
- errors += zfs_share(cn->cn_handle, smb);
+ zfs_share(cn->cn_handle, smb);
commit_smb_shares = B_TRUE;
} else if (cn->cn_shared || clp->cl_waslegacy) {
- errors += zfs_unshare(cn->cn_handle, NULL, smb);
+ zfs_unshare(cn->cn_handle, NULL, smb);
commit_smb_shares = B_TRUE;
}
}
@@ -288,7 +300,7 @@ changelist_postfix(prop_changelist_t *clp)
zfs_commit_shares(proto);
uu_avl_walk_end(walk);
- return (errors ? -1 : 0);
+ return (0);
}
/*
@@ -552,7 +564,7 @@ change_one(zfs_handle_t *zhp, void *data)
}
if (!clp->cl_alldependents)
- ret = zfs_iter_children(zhp, change_one, data);
+ ret = zfs_iter_children_v2(zhp, 0, change_one, data);
/*
* If we added the handle to the changelist, we will re-use it
@@ -721,11 +733,12 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
return (NULL);
}
} else if (clp->cl_alldependents) {
- if (zfs_iter_dependents(zhp, B_TRUE, change_one, clp) != 0) {
+ if (zfs_iter_dependents_v2(zhp, 0, B_TRUE, change_one,
+ clp) != 0) {
changelist_free(clp);
return (NULL);
}
- } else if (zfs_iter_children(zhp, change_one, clp) != 0) {
+ } else if (zfs_iter_children_v2(zhp, 0, change_one, clp) != 0) {
changelist_free(clp);
return (NULL);
}
diff --git a/lib/libzfs/libzfs_config.c b/lib/libzfs/libzfs_config.c
index e3c815cf58b2..437afb3b7467 100644
--- a/lib/libzfs/libzfs_config.c
+++ b/lib/libzfs/libzfs_config.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c
index c241aeaa4da0..93dfa9cbc2c0 100644
--- a/lib/libzfs/libzfs_crypto.c
+++ b/lib/libzfs/libzfs_crypto.c
@@ -37,6 +37,7 @@
#include <curl/curl.h>
#endif
#include <libzfs.h>
+#include <libzutil.h>
#include "libzfs_impl.h"
#include "zfeature_common.h"
@@ -493,7 +494,7 @@ get_key_material_file(libzfs_handle_t *hdl, const char *uri,
ret = errno;
errno = 0;
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Failed to open key material file: %s"), strerror(ret));
+ "Failed to open key material file: %s"), zfs_strerror(ret));
return (ret);
}
@@ -595,7 +596,7 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri,
"%s/libzfs-XXXXXXXX.https", getenv("TMPDIR") ?: "/tmp") == -1) {
ret = ENOMEM;
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s"),
- strerror(ret));
+ zfs_strerror(ret));
goto end;
}
@@ -604,7 +605,7 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri,
ret = errno;
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"Couldn't create temporary file %s: %s"),
- path, strerror(ret));
+ path, zfs_strerror(ret));
free(path);
goto end;
}
@@ -616,7 +617,7 @@ kfdok:
ret = errno;
(void) close(kfd);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Couldn't reopen temporary file: %s"), strerror(ret));
+ "Couldn't reopen temporary file: %s"), zfs_strerror(ret));
goto end;
}
@@ -942,7 +943,7 @@ proplist_has_encryption_props(nvlist_t *props)
{
int ret;
uint64_t intval;
- char *strval;
+ const char *strval;
ret = nvlist_lookup_uint64(props,
zfs_prop_to_name(ZFS_PROP_ENCRYPTION), &intval);
@@ -1007,7 +1008,7 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props,
char errbuf[ERRBUFLEN];
uint64_t crypt = ZIO_CRYPT_INHERIT, pcrypt = ZIO_CRYPT_INHERIT;
uint64_t keyformat = ZFS_KEYFORMAT_NONE;
- char *keylocation = NULL;
+ const char *keylocation = NULL;
zfs_handle_t *pzhp = NULL;
uint8_t *wkeydata = NULL;
uint_t wkeylen = 0;
@@ -1226,7 +1227,7 @@ load_keys_cb(zfs_handle_t *zhp, void *arg)
cb->cb_numfailed++;
out:
- (void) zfs_iter_filesystems(zhp, load_keys_cb, cb);
+ (void) zfs_iter_filesystems_v2(zhp, 0, load_keys_cb, cb);
zfs_close(zhp);
/* always return 0, since this function is best effort */
@@ -1407,6 +1408,11 @@ try_again:
"Incorrect key provided for '%s'."),
zfs_get_name(zhp));
break;
+ case ZFS_ERR_CRYPTO_NOTSUP:
+ zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
+ "'%s' uses an unsupported encryption suite."),
+ zfs_get_name(zhp));
+ break;
}
goto error;
}
@@ -1590,7 +1596,7 @@ zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey)
uint64_t crypt, pcrypt, keystatus, pkeystatus;
uint64_t keyformat = ZFS_KEYFORMAT_NONE;
zfs_handle_t *pzhp = NULL;
- char *keylocation = NULL;
+ const char *keylocation = NULL;
char origin_name[MAXNAMELEN];
char prop_keylocation[MAXNAMELEN];
char parent_name[ZFS_MAX_DATASET_NAME_LEN];
@@ -1700,7 +1706,7 @@ zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey)
/* default to prompt if no keylocation is specified */
if (keylocation == NULL) {
- keylocation = (char *)"prompt";
+ keylocation = "prompt";
ret = nvlist_add_string(props,
zfs_prop_to_name(ZFS_PROP_KEYLOCATION),
keylocation);
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index 4e25985a4ae8..231bbbd92dbf 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -67,6 +67,10 @@
#include "libzfs_impl.h"
#include "zfs_deleg.h"
+static __thread struct passwd gpwd;
+static __thread struct group ggrp;
+static __thread char rpbuf[2048];
+
static int userquota_propname_decode(const char *propname, boolean_t zoned,
zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
@@ -528,6 +532,30 @@ make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
zhp->zpool_hdl = zpool_handle(zhp);
+ if (zc->zc_objset_stats.dds_creation_txg != 0) {
+ /* structure assignment */
+ zhp->zfs_dmustats = zc->zc_objset_stats;
+ } else {
+ if (get_stats_ioctl(zhp, zc) == -1) {
+ zcmd_free_nvlists(zc);
+ free(zhp);
+ return (NULL);
+ }
+ if (make_dataset_handle_common(zhp, zc) == -1) {
+ zcmd_free_nvlists(zc);
+ free(zhp);
+ return (NULL);
+ }
+ }
+
+ if (zhp->zfs_dmustats.dds_is_snapshot ||
+ strchr(zc->zc_name, '@') != NULL)
+ zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+ else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
+ zhp->zfs_type = ZFS_TYPE_VOLUME;
+ else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
+ zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
+
return (zhp);
}
@@ -689,6 +717,7 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
*/
if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
+ errno = EINVAL;
return (NULL);
}
@@ -716,8 +745,8 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
* to get the parent dataset name only.
*/
assert(bookp - path < sizeof (dsname));
- (void) strncpy(dsname, path, bookp - path);
- dsname[bookp - path] = '\0';
+ (void) strlcpy(dsname, path,
+ MIN(sizeof (dsname), bookp - path + 1));
/*
* Create handle for the parent dataset.
@@ -732,10 +761,11 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
* Iterate bookmarks to find the right one.
*/
errno = 0;
- if ((zfs_iter_bookmarks(pzhp, zfs_open_bookmarks_cb,
+ if ((zfs_iter_bookmarks_v2(pzhp, 0, zfs_open_bookmarks_cb,
&cb_data) == 0) && (cb_data.zhp == NULL)) {
(void) zfs_error(hdl, EZFS_NOENT, errbuf);
zfs_close(pzhp);
+ errno = ENOENT;
return (NULL);
}
if (cb_data.zhp == NULL) {
@@ -754,6 +784,7 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
if (!(types & zhp->zfs_type)) {
(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
zfs_close(zhp);
+ errno = EINVAL;
return (NULL);
}
@@ -1002,11 +1033,12 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
{
nvpair_t *elem;
uint64_t intval;
- char *strval;
+ const char *strval;
zfs_prop_t prop;
nvlist_t *ret;
int chosen_normal = -1;
int chosen_utf = -1;
+ int set_maxbs = 0;
if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
@@ -1225,12 +1257,17 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
+ /* save the ZFS_PROP_RECORDSIZE during create op */
+ if (zpool_hdl == NULL && prop == ZFS_PROP_RECORDSIZE) {
+ set_maxbs = intval;
+ }
break;
}
case ZFS_PROP_SPECIAL_SMALL_BLOCKS:
{
- int maxbs = SPA_OLD_MAXBLOCKSIZE;
+ int maxbs =
+ set_maxbs == 0 ? SPA_OLD_MAXBLOCKSIZE : set_maxbs;
char buf[64];
if (zpool_hdl != NULL) {
@@ -1738,8 +1775,6 @@ error:
return (ret);
}
-
-
/*
* Given an nvlist of property names and values, set the properties for the
* given dataset.
@@ -1747,6 +1782,18 @@ error:
int
zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
{
+ return (zfs_prop_set_list_flags(zhp, props, 0));
+}
+
+/*
+ * Given an nvlist of property names, values and flags, set the properties
+ * for the given dataset. If ZFS_SET_NOMOUNT is set, it allows to update
+ * mountpoint, sharenfs and sharesmb properties without (un/re)mounting
+ * and (un/re)sharing the dataset.
+ */
+int
+zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
+{
zfs_cmd_t zc = {"\0"};
int ret = -1;
prop_changelist_t **cls = NULL;
@@ -1756,7 +1803,8 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
nvlist_t *nvl;
int nvl_len = 0;
int added_resv = 0;
- zfs_prop_t prop = 0;
+ zfs_prop_t prop;
+ boolean_t nsprop = B_FALSE;
nvpair_t *elem;
(void) snprintf(errbuf, sizeof (errbuf),
@@ -1803,6 +1851,7 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
elem = nvlist_next_nvpair(nvl, elem)) {
prop = zfs_name_to_prop(nvpair_name(elem));
+ nsprop |= zfs_is_namespace_prop(prop);
assert(cl_idx < nvl_len);
/*
@@ -1813,7 +1862,9 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
if (prop != ZFS_PROP_CANMOUNT ||
(fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
zfs_is_mounted(zhp, NULL))) {
- cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
+ cls[cl_idx] = changelist_gather(zhp, prop,
+ ((flags & ZFS_SET_NOMOUNT) ?
+ CL_GATHER_DONT_UNMOUNT : 0), 0);
if (cls[cl_idx] == NULL)
goto error;
}
@@ -1901,8 +1952,7 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
* if one of the options handled by the generic
* Linux namespace layer has been modified.
*/
- if (zfs_is_namespace_prop(prop) &&
- zfs_is_mounted(zhp, NULL))
+ if (nsprop && zfs_is_mounted(zhp, NULL))
ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
}
}
@@ -2005,7 +2055,8 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
if ((ret = changelist_prefix(cl)) != 0)
goto error;
- if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) {
+ if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) {
+ changelist_free(cl);
return (zfs_standard_error(hdl, errno, errbuf));
} else {
@@ -2037,7 +2088,7 @@ error:
* extract them appropriately.
*/
uint64_t
-getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
+getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, const char **source)
{
nvlist_t *nv;
uint64_t value;
@@ -2051,14 +2102,14 @@ getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
verify(!zhp->zfs_props_table ||
zhp->zfs_props_table[prop] == B_TRUE);
value = zfs_prop_default_numeric(prop);
- *source = (char *)"";
+ *source = "";
}
return (value);
}
static const char *
-getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
+getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, const char **source)
{
nvlist_t *nv;
const char *value;
@@ -2072,7 +2123,7 @@ getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
verify(!zhp->zfs_props_table ||
zhp->zfs_props_table[prop] == B_TRUE);
value = zfs_prop_default_string(prop);
- *source = (char *)"";
+ *source = "";
}
return (value);
@@ -2081,20 +2132,21 @@ getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
static boolean_t
zfs_is_recvd_props_mode(zfs_handle_t *zhp)
{
- return (zhp->zfs_props == zhp->zfs_recvd_props);
+ return (zhp->zfs_props != NULL &&
+ zhp->zfs_props == zhp->zfs_recvd_props);
}
static void
-zfs_set_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
+zfs_set_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie)
{
- *cookie = (uint64_t)(uintptr_t)zhp->zfs_props;
+ *cookie = (uintptr_t)zhp->zfs_props;
zhp->zfs_props = zhp->zfs_recvd_props;
}
static void
-zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
+zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uintptr_t *cookie)
{
- zhp->zfs_props = (nvlist_t *)(uintptr_t)*cookie;
+ zhp->zfs_props = (nvlist_t *)*cookie;
*cookie = 0;
}
@@ -2109,7 +2161,7 @@ zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
*/
static int
get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
- char **source, uint64_t *val)
+ const char **source, uint64_t *val)
{
zfs_cmd_t zc = {"\0"};
nvlist_t *zplprops = NULL;
@@ -2283,6 +2335,28 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
*val = zhp->zfs_dmustats.dds_redacted;
break;
+ case ZFS_PROP_GUID:
+ if (zhp->zfs_dmustats.dds_guid != 0)
+ *val = zhp->zfs_dmustats.dds_guid;
+ else
+ *val = getprop_uint64(zhp, prop, source);
+ break;
+
+ case ZFS_PROP_CREATETXG:
+ /*
+ * We can directly read createtxg property from zfs
+ * handle for Filesystem, Snapshot and ZVOL types.
+ */
+ if (((zhp->zfs_type == ZFS_TYPE_FILESYSTEM) ||
+ (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) ||
+ (zhp->zfs_type == ZFS_TYPE_VOLUME)) &&
+ (zhp->zfs_dmustats.dds_creation_txg != 0)) {
+ *val = zhp->zfs_dmustats.dds_creation_txg;
+ break;
+ } else {
+ *val = getprop_uint64(zhp, prop, source);
+ }
+ zfs_fallthrough;
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
@@ -2319,7 +2393,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
* Calculate the source type, given the raw source string.
*/
static void
-get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
+get_source(zfs_handle_t *zhp, zprop_source_t *srctype, const char *source,
char *statbuf, size_t statlen)
{
if (statbuf == NULL ||
@@ -2358,7 +2432,7 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
prop = zfs_name_to_prop(propname);
if (prop != ZPROP_USERPROP) {
- uint64_t cookie;
+ uintptr_t cookie;
if (!nvlist_exists(zhp->zfs_recvd_props, propname))
return (-1);
zfs_set_recvd_props_mode(zhp, &cookie);
@@ -2367,7 +2441,7 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
zfs_unset_recvd_props_mode(zhp, &cookie);
} else {
nvlist_t *propval;
- char *recvdval;
+ const char *recvdval;
if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
propname, &propval) != 0)
return (-1);
@@ -2425,7 +2499,7 @@ get_clones_cb(zfs_handle_t *zhp, void *arg)
}
out:
- (void) zfs_iter_children(zhp, get_clones_cb, gca);
+ (void) zfs_iter_children_v2(zhp, 0, get_clones_cb, gca);
zfs_close(zhp);
return (0);
}
@@ -2569,7 +2643,7 @@ zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
(u_longlong_t)intval, (u_longlong_t)ans);
}
} else {
- char *str_ans;
+ const char *str_ans;
error = nvlist_lookup_string(retnvl, "value", &str_ans);
if (error != 0) {
(void) fprintf(stderr, "%s: zcp check error: "
@@ -2601,7 +2675,7 @@ int
zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
{
- char *source = NULL;
+ const char *source = NULL;
uint64_t val;
const char *str;
const char *strval;
@@ -2710,7 +2784,13 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
break;
case ZFS_PROP_ORIGIN:
- str = getprop_string(zhp, prop, &source);
+ if (*zhp->zfs_dmustats.dds_origin != '\0') {
+ str = (char *)&zhp->zfs_dmustats.dds_origin;
+ } else {
+ str = getprop_string(zhp, prop, &source);
+ }
+ if (str == NULL || *str == '\0')
+ str = zfs_prop_default_string(prop);
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
@@ -2921,6 +3001,26 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
zcp_check(zhp, prop, val, NULL);
break;
+ case ZFS_PROP_SNAPSHOTS_CHANGED:
+ {
+ if ((get_numeric_property(zhp, prop, src, &source,
+ &val) != 0) || val == 0) {
+ return (-1);
+ }
+
+ time_t time = (time_t)val;
+ struct tm t;
+
+ if (literal ||
+ localtime_r(&time, &t) == NULL ||
+ strftime(propbuf, proplen, "%a %b %e %k:%M:%S %Y",
+ &t) == 0)
+ (void) snprintf(propbuf, proplen, "%llu",
+ (u_longlong_t)val);
+ }
+ zcp_check(zhp, prop, val, NULL);
+ break;
+
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
@@ -2976,7 +3076,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
uint64_t
zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
{
- char *source;
+ const char *source;
uint64_t val = 0;
(void) get_numeric_property(zhp, prop, NULL, &source, &val);
@@ -3000,7 +3100,7 @@ int
zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
zprop_source_t *src, char *statbuf, size_t statlen)
{
- char *source;
+ const char *source;
/*
* Check to see if this property applies to our object
@@ -3099,11 +3199,15 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
cp = strchr(propname, '@') + 1;
- if (isuser && (pw = getpwnam(cp)) != NULL) {
+ if (isuser &&
+ getpwnam_r(cp, &gpwd, rpbuf, sizeof (rpbuf), &pw) == 0 &&
+ pw != NULL) {
if (zoned && getzoneid() == GLOBAL_ZONEID)
return (ENOENT);
*ridp = pw->pw_uid;
- } else if (isgroup && (gr = getgrnam(cp)) != NULL) {
+ } else if (isgroup &&
+ getgrnam_r(cp, &ggrp, rpbuf, sizeof (rpbuf), &gr) == 0 &&
+ gr != NULL) {
if (zoned && getzoneid() == GLOBAL_ZONEID)
return (ENOENT);
*ridp = gr->gr_gid;
@@ -3419,8 +3523,8 @@ check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
/* check to see if the pool exists */
if ((slash = strchr(parent, '/')) == NULL)
slash = parent + strlen(parent);
- (void) strncpy(zc.zc_name, parent, slash - parent);
- zc.zc_name[slash - parent] = '\0';
+ (void) strlcpy(zc.zc_name, parent,
+ MIN(sizeof (zc.zc_name), slash - parent + 1));
if (zfs_ioctl(hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
errno == ENOENT) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -3848,7 +3952,7 @@ zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
if (lzc_exists(name))
fnvlist_add_boolean(dd->nvl, name);
- rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
+ rv = zfs_iter_filesystems_v2(zhp, 0, zfs_check_snap_cb, dd);
zfs_close(zhp);
return (rv);
}
@@ -4086,7 +4190,7 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
fnvlist_add_boolean(sd->sd_nvl, name);
- rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
+ rv = zfs_iter_filesystems_v2(zhp, 0, zfs_snapshot_cb, sd);
}
zfs_close(zhp);
@@ -4129,6 +4233,8 @@ zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
* same pool, as does lzc_snapshot (below).
*/
elem = nvlist_next_nvpair(snaps, NULL);
+ if (elem == NULL)
+ return (-1);
(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
pool[strcspn(pool, "/@")] = '\0';
zpool_hdl = zpool_open(hdl, pool);
@@ -4261,7 +4367,7 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
rollback_data_t *cbp = data;
if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
- cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
+ cbp->cb_error |= zfs_iter_dependents_v2(zhp, 0, B_FALSE,
rollback_destroy_dependent, cbp);
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
@@ -4301,10 +4407,10 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
if (cb.cb_create > 0)
min_txg = cb.cb_create;
- (void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb,
+ (void) zfs_iter_snapshots_v2(zhp, 0, rollback_destroy, &cb,
min_txg, 0);
- (void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
+ (void) zfs_iter_bookmarks_v2(zhp, 0, rollback_destroy, &cb);
if (cb.cb_error)
return (-1);
@@ -4619,7 +4725,7 @@ zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
zprop_list_t **last, **start;
nvlist_t *userprops, *propval;
nvpair_t *elem;
- char *strval;
+ const char *strval;
char buf[ZFS_MAXPROPLEN];
if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
@@ -4885,7 +4991,7 @@ zfs_hold_one(zfs_handle_t *zhp, void *arg)
fnvlist_add_string(ha->nvl, name, ha->tag);
if (ha->recursive)
- rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
+ rv = zfs_iter_filesystems_v2(zhp, 0, zfs_hold_one, ha);
zfs_close(zhp);
return (rv);
}
@@ -5016,7 +5122,7 @@ zfs_release_one(zfs_handle_t *zhp, void *arg)
}
if (ha->recursive)
- rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
+ rv = zfs_iter_filesystems_v2(zhp, 0, zfs_release_one, ha);
zfs_close(zhp);
return (rv);
}
@@ -5119,7 +5225,7 @@ tryagain:
nvbuf = malloc(nvsz);
if (nvbuf == NULL) {
- err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
+ err = (zfs_error(hdl, EZFS_NOMEM, zfs_strerror(errno)));
goto out;
}
@@ -5405,7 +5511,7 @@ volsize_from_vdevs(zpool_handle_t *zhp, uint64_t nblocks, uint64_t blksize)
}
for (int v = 0; v < nvdevs; v++) {
- char *type;
+ const char *type;
uint64_t nparity, ashift, asize, tsize;
uint64_t volsize;
@@ -5459,8 +5565,21 @@ volsize_from_vdevs(zpool_handle_t *zhp, uint64_t nblocks, uint64_t blksize)
/*
* Scale this size down as a ratio of 128k / tsize.
* See theory statement above.
+ *
+ * Bitshift is to avoid the case of nblocks * asize < tsize
+ * producing a size of 0.
+ */
+ volsize = (nblocks * asize) / (tsize >> SPA_MINBLOCKSHIFT);
+ /*
+ * If we would blow UINT64_MAX with this next multiplication,
+ * don't.
*/
- volsize = nblocks * asize * SPA_OLD_MAXBLOCKSIZE / tsize;
+ if (volsize >
+ (UINT64_MAX / (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT)))
+ volsize = UINT64_MAX;
+ else
+ volsize *= (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
+
if (volsize > ret) {
ret = volsize;
}
@@ -5487,7 +5606,7 @@ zvol_volsize_to_reservation(zpool_handle_t *zph, uint64_t volsize,
uint64_t numdb;
uint64_t nblocks, volblocksize;
int ncopies;
- char *strval;
+ const char *strval;
if (nvlist_lookup_string(props,
zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c
index f0e9a262e6bf..edf290c4d040 100644
--- a/lib/libzfs/libzfs_diff.c
+++ b/lib/libzfs/libzfs_diff.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -44,6 +44,7 @@
#include <pthread.h>
#include <sys/zfs_ioctl.h>
#include <libzfs.h>
+#include <libzutil.h>
#include "libzfs_impl.h"
#define ZDIFF_SNAPDIR "/.zfs/snapshot/"
@@ -54,6 +55,10 @@
#define ZDIFF_REMOVED '-'
#define ZDIFF_RENAMED "R"
+#define ZDIFF_ADDED_COLOR ANSI_GREEN
+#define ZDIFF_MODIFIED_COLOR ANSI_YELLOW
+#define ZDIFF_REMOVED_COLOR ANSI_RED
+#define ZDIFF_RENAMED_COLOR ANSI_BOLD_BLUE
/*
* Given a {dsname, object id}, get the object path
@@ -128,6 +133,25 @@ stream_bytes(FILE *fp, const char *string)
}
}
+/*
+ * Takes the type of change (like `print_file`), outputs the appropriate color
+ */
+static const char *
+type_to_color(char type)
+{
+ if (type == '+')
+ return (ZDIFF_ADDED_COLOR);
+ else if (type == '-')
+ return (ZDIFF_REMOVED_COLOR);
+ else if (type == 'M')
+ return (ZDIFF_MODIFIED_COLOR);
+ else if (type == 'R')
+ return (ZDIFF_RENAMED_COLOR);
+ else
+ return (NULL);
+}
+
+
static char
get_what(mode_t what)
{
@@ -175,6 +199,8 @@ static void
print_rename(FILE *fp, differ_info_t *di, const char *old, const char *new,
zfs_stat_t *isb)
{
+ if (isatty(fileno(fp)))
+ color_start(ZDIFF_RENAMED_COLOR);
if (di->timestamped)
(void) fprintf(fp, "%10lld.%09lld\t",
(longlong_t)isb->zs_ctime[0],
@@ -186,12 +212,18 @@ print_rename(FILE *fp, differ_info_t *di, const char *old, const char *new,
(void) fputs(di->scripted ? "\t" : " -> ", fp);
print_cmn(fp, di, new);
(void) fputc('\n', fp);
+
+ if (isatty(fileno(fp)))
+ color_end();
}
static void
print_link_change(FILE *fp, differ_info_t *di, int delta, const char *file,
zfs_stat_t *isb)
{
+ if (isatty(fileno(fp)))
+ color_start(ZDIFF_MODIFIED_COLOR);
+
if (di->timestamped)
(void) fprintf(fp, "%10lld.%09lld\t",
(longlong_t)isb->zs_ctime[0],
@@ -201,12 +233,17 @@ print_link_change(FILE *fp, differ_info_t *di, int delta, const char *file,
(void) fprintf(fp, "%c\t", get_what(isb->zs_mode));
print_cmn(fp, di, file);
(void) fprintf(fp, "\t(%+d)\n", delta);
+ if (isatty(fileno(fp)))
+ color_end();
}
static void
print_file(FILE *fp, differ_info_t *di, char type, const char *file,
zfs_stat_t *isb)
{
+ if (isatty(fileno(fp)))
+ color_start(type_to_color(type));
+
if (di->timestamped)
(void) fprintf(fp, "%10lld.%09lld\t",
(longlong_t)isb->zs_ctime[0],
@@ -216,6 +253,9 @@ print_file(FILE *fp, differ_info_t *di, char type, const char *file,
(void) fprintf(fp, "%c\t", get_what(isb->zs_mode));
print_cmn(fp, di, file);
(void) fputc('\n', fp);
+
+ if (isatty(fileno(fp)))
+ color_end();
}
static int
@@ -243,7 +283,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
fobjerr = get_stats_for_obj(di, di->fromsnap, dobj, fobjname,
MAXPATHLEN, &fsb);
if (fobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
- zfs_error_aux(di->zhp->zfs_hdl, "%s", strerror(di->zerr));
+ zfs_error_aux(di->zhp->zfs_hdl, "%s", zfs_strerror(di->zerr));
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
/*
* Let's not print an error for the same object more than
@@ -258,7 +298,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
if (tobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
if (!already_logged) {
zfs_error_aux(di->zhp->zfs_hdl,
- "%s", strerror(di->zerr));
+ "%s", zfs_strerror(di->zerr));
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
}
}
@@ -377,7 +417,7 @@ write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr)
if (zc.zc_obj > dr->ddr_last) {
break;
}
- err = describe_free(fp, di, zc.zc_obj, fobjname,
+ (void) describe_free(fp, di, zc.zc_obj, fobjname,
MAXPATHLEN);
} else if (errno == ESRCH) {
break;
@@ -405,7 +445,7 @@ differ(void *arg)
if ((ofp = fdopen(di->outputfd, "w")) == NULL) {
di->zerr = errno;
- strlcpy(di->errbuf, strerror(errno), sizeof (di->errbuf));
+ strlcpy(di->errbuf, zfs_strerror(errno), sizeof (di->errbuf));
(void) close(di->datafd);
return ((void *)-1);
}
@@ -572,8 +612,7 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap,
zfs_handle_t *zhp;
di->ds = zfs_alloc(di->zhp->zfs_hdl, tdslen + 1);
- (void) strncpy(di->ds, tosnap, tdslen);
- di->ds[tdslen] = '\0';
+ (void) strlcpy(di->ds, tosnap, tdslen + 1);
zhp = zfs_open(hdl, di->ds, ZFS_TYPE_FILESYSTEM);
while (zhp != NULL) {
@@ -609,8 +648,7 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap,
int dslen = fdslen ? fdslen : tdslen;
di->ds = zfs_alloc(hdl, dslen + 1);
- (void) strncpy(di->ds, fdslen ? fromsnap : tosnap, dslen);
- di->ds[dslen] = '\0';
+ (void) strlcpy(di->ds, fdslen ? fromsnap : tosnap, dslen + 1);
di->fromsnap = zfs_asprintf(hdl, "%s%s", di->ds, atptrf);
if (tsnlen) {
@@ -724,7 +762,7 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
}
if (pipe2(pipefd, O_CLOEXEC)) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno));
teardown_differ_info(&di);
return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED, errbuf));
}
@@ -738,7 +776,7 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
di.datafd = pipefd[0];
if (pthread_create(&tid, NULL, differ, &di)) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno));
(void) close(pipefd[0]);
(void) close(pipefd[1]);
teardown_differ_info(&di);
@@ -764,14 +802,15 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
"\n Not an earlier snapshot from the same fs"));
} else if (errno != EPIPE || di.zerr == 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno));
}
(void) close(pipefd[1]);
(void) pthread_cancel(tid);
(void) pthread_join(tid, NULL);
teardown_differ_info(&di);
if (di.zerr != 0 && di.zerr != EPIPE) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(di.zerr));
+ zfs_error_aux(zhp->zfs_hdl, "%s",
+ zfs_strerror(di.zerr));
return (zfs_error(zhp->zfs_hdl, EZFS_DIFF, di.errbuf));
} else {
return (zfs_error(zhp->zfs_hdl, EZFS_DIFFDATA, errbuf));
@@ -782,7 +821,7 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
(void) pthread_join(tid, NULL);
if (di.zerr != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(di.zerr));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(di.zerr));
return (zfs_error(zhp->zfs_hdl, EZFS_DIFF, di.errbuf));
}
teardown_differ_info(&di);
diff --git a/lib/libzfs/libzfs_impl.h b/lib/libzfs/libzfs_impl.h
index 878daab3fe20..ef0359f45ea0 100644
--- a/lib/libzfs/libzfs_impl.h
+++ b/lib/libzfs/libzfs_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -140,7 +140,7 @@ extern zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *);
extern zfs_handle_t *make_dataset_simple_handle_zc(zfs_handle_t *, zfs_cmd_t *);
extern int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
- nvlist_t *, char **, uint64_t *, const char *);
+ nvlist_t *, const char **, uint64_t *, const char *);
extern int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
zfs_type_t type);
diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c
index ed3cfea56fa0..e2d40a7b3bfb 100644
--- a/lib/libzfs/libzfs_import.c
+++ b/lib/libzfs/libzfs_import.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -280,7 +280,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
boolean_t *inuse)
{
nvlist_t *config;
- char *name = NULL;
+ const char *name = NULL;
boolean_t ret;
uint64_t guid = 0, vdev_guid;
zpool_handle_t *zhp;
@@ -291,10 +291,8 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
*inuse = B_FALSE;
- if (zpool_read_label(fd, &config, NULL) != 0) {
- (void) no_memory(hdl);
+ if (zpool_read_label(fd, &config, NULL) != 0)
return (-1);
- }
if (config == NULL)
return (0);
diff --git a/lib/libzfs/libzfs_iter.c b/lib/libzfs/libzfs_iter.c
index db199c44ed30..452d8fd6ab71 100644
--- a/lib/libzfs/libzfs_iter.c
+++ b/lib/libzfs/libzfs_iter.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -39,7 +39,8 @@
#include "libzfs_impl.h"
static int
-zfs_iter_clones(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+zfs_iter_clones(zfs_handle_t *zhp, int flags __maybe_unused, zfs_iter_f func,
+ void *data)
{
nvlist_t *nvl = zfs_get_clones_nvl(zhp);
nvpair_t *pair;
@@ -69,6 +70,7 @@ zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc)
orig_cookie = zc->zc_cookie;
top:
(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
+ zc->zc_objset_stats.dds_creation_txg = 0;
rc = zfs_ioctl(zhp->zfs_hdl, arg, zc);
if (rc == -1) {
@@ -103,6 +105,13 @@ top:
int
zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
+ return (zfs_iter_filesystems_v2(zhp, 0, func, data));
+}
+
+int
+zfs_iter_filesystems_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func,
+ void *data)
+{
zfs_cmd_t zc = {"\0"};
zfs_handle_t *nzhp;
int ret;
@@ -112,16 +121,21 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0);
+ if ((flags & ZFS_ITER_SIMPLE) == ZFS_ITER_SIMPLE)
+ zc.zc_simple = B_TRUE;
+
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
&zc)) == 0) {
+ if (zc.zc_simple)
+ nzhp = make_dataset_simple_handle_zc(zhp, &zc);
+ else
+ nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc);
/*
* Silently ignore errors, as the only plausible explanation is
* that the pool has since been removed.
*/
- if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
- &zc)) == NULL) {
+ if (nzhp == NULL)
continue;
- }
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
@@ -139,6 +153,14 @@ int
zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
void *data, uint64_t min_txg, uint64_t max_txg)
{
+ return (zfs_iter_snapshots_v2(zhp, simple ? ZFS_ITER_SIMPLE : 0, func,
+ data, min_txg, max_txg));
+}
+
+int
+zfs_iter_snapshots_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func,
+ void *data, uint64_t min_txg, uint64_t max_txg)
+{
zfs_cmd_t zc = {"\0"};
zfs_handle_t *nzhp;
int ret;
@@ -148,7 +170,7 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
zhp->zfs_type == ZFS_TYPE_BOOKMARK)
return (0);
- zc.zc_simple = simple;
+ zc.zc_simple = (flags & ZFS_ITER_SIMPLE) != 0;
zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0);
@@ -168,7 +190,7 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
- if (simple)
+ if (zc.zc_simple)
nzhp = make_dataset_simple_handle_zc(zhp, &zc);
else
nzhp = make_dataset_handle_zc(zhp->zfs_hdl, &zc);
@@ -192,6 +214,13 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
int
zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
+ return (zfs_iter_bookmarks_v2(zhp, 0, func, data));
+}
+
+int
+zfs_iter_bookmarks_v2(zfs_handle_t *zhp, int flags __maybe_unused,
+ zfs_iter_f func, void *data)
+{
zfs_handle_t *nzhp;
nvlist_t *props = NULL;
nvlist_t *bmarks = NULL;
@@ -216,7 +245,7 @@ zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data)
for (pair = nvlist_next_nvpair(bmarks, NULL);
pair != NULL; pair = nvlist_next_nvpair(bmarks, pair)) {
char name[ZFS_MAX_DATASET_NAME_LEN];
- char *bmark_name;
+ const char *bmark_name;
nvlist_t *bmark_props;
bmark_name = nvpair_name(pair);
@@ -297,8 +326,16 @@ zfs_snapshot_compare(const void *larg, const void *rarg)
}
int
-zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data,
- uint64_t min_txg, uint64_t max_txg)
+zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback,
+ void *data, uint64_t min_txg, uint64_t max_txg)
+{
+ return (zfs_iter_snapshots_sorted_v2(zhp, 0, callback, data,
+ min_txg, max_txg));
+}
+
+int
+zfs_iter_snapshots_sorted_v2(zfs_handle_t *zhp, int flags, zfs_iter_f callback,
+ void *data, uint64_t min_txg, uint64_t max_txg)
{
int ret = 0;
zfs_node_t *node;
@@ -308,7 +345,7 @@ zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data,
avl_create(&avl, zfs_snapshot_compare,
sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
- ret = zfs_iter_snapshots(zhp, B_FALSE, zfs_sort_snaps, &avl, min_txg,
+ ret = zfs_iter_snapshots_v2(zhp, flags, zfs_sort_snaps, &avl, min_txg,
max_txg);
for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
@@ -374,6 +411,13 @@ int
zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
zfs_iter_f func, void *arg)
{
+ return (zfs_iter_snapspec_v2(fs_zhp, 0, spec_orig, func, arg));
+}
+
+int
+zfs_iter_snapspec_v2(zfs_handle_t *fs_zhp, int flags, const char *spec_orig,
+ zfs_iter_f func, void *arg)
+{
char *buf, *comma_separated, *cp;
int err = 0;
int ret = 0;
@@ -411,7 +455,7 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
}
}
- err = zfs_iter_snapshots_sorted(fs_zhp,
+ err = zfs_iter_snapshots_sorted_v2(fs_zhp, flags,
snapspec_cb, &ssa, 0, 0);
if (ret == 0)
ret = err;
@@ -450,12 +494,18 @@ zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
int
zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
+ return (zfs_iter_children_v2(zhp, 0, func, data));
+}
+
+int
+zfs_iter_children_v2(zfs_handle_t *zhp, int flags, zfs_iter_f func, void *data)
+{
int ret;
- if ((ret = zfs_iter_snapshots(zhp, B_FALSE, func, data, 0, 0)) != 0)
+ if ((ret = zfs_iter_snapshots_v2(zhp, flags, func, data, 0, 0)) != 0)
return (ret);
- return (zfs_iter_filesystems(zhp, func, data));
+ return (zfs_iter_filesystems_v2(zhp, flags, func, data));
}
@@ -466,6 +516,7 @@ typedef struct iter_stack_frame {
typedef struct iter_dependents_arg {
boolean_t first;
+ int flags;
boolean_t allowrecursion;
iter_stack_frame_t *stack;
zfs_iter_f func;
@@ -481,7 +532,7 @@ iter_dependents_cb(zfs_handle_t *zhp, void *arg)
ida->first = B_FALSE;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
- err = zfs_iter_clones(zhp, iter_dependents_cb, ida);
+ err = zfs_iter_clones(zhp, ida->flags, iter_dependents_cb, ida);
} else if (zhp->zfs_type != ZFS_TYPE_BOOKMARK) {
iter_stack_frame_t isf;
iter_stack_frame_t *f;
@@ -515,9 +566,10 @@ iter_dependents_cb(zfs_handle_t *zhp, void *arg)
isf.zhp = zhp;
isf.next = ida->stack;
ida->stack = &isf;
- err = zfs_iter_filesystems(zhp, iter_dependents_cb, ida);
+ err = zfs_iter_filesystems_v2(zhp, ida->flags,
+ iter_dependents_cb, ida);
if (err == 0)
- err = zfs_iter_snapshots(zhp, B_FALSE,
+ err = zfs_iter_snapshots_v2(zhp, ida->flags,
iter_dependents_cb, ida, 0, 0);
ida->stack = isf.next;
}
@@ -534,7 +586,15 @@ int
zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
zfs_iter_f func, void *data)
{
+ return (zfs_iter_dependents_v2(zhp, 0, allowrecursion, func, data));
+}
+
+int
+zfs_iter_dependents_v2(zfs_handle_t *zhp, int flags, boolean_t allowrecursion,
+ zfs_iter_f func, void *data)
+{
iter_dependents_arg_t ida;
+ ida.flags = flags;
ida.allowrecursion = allowrecursion;
ida.stack = NULL;
ida.func = func;
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index 511552884947..ec6ebad2f180 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -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, 2021 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2022 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2018 Datto Inc.
@@ -74,6 +74,7 @@
#include <sys/dsl_crypt.h>
#include <libzfs.h>
+#include <libzutil.h>
#include "libzfs_impl.h"
#include <thread_pool.h>
@@ -291,7 +292,7 @@ static int
zfs_add_option(zfs_handle_t *zhp, char *options, int len,
zfs_prop_t prop, const char *on, const char *off)
{
- char *source;
+ const char *source;
uint64_t value;
/* Skip adding duplicate default options */
@@ -466,7 +467,7 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
if (mkdirp(mountpoint, 0755) != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"failed to create mountpoint: %s"),
- strerror(errno));
+ zfs_strerror(errno));
return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
mountpoint));
@@ -524,7 +525,7 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
(u_longlong_t)zfs_prop_get_int(zhp,
ZFS_PROP_VERSION), spa_version);
} else {
- zfs_error_aux(hdl, "%s", strerror(rc));
+ zfs_error_aux(hdl, "%s", zfs_strerror(rc));
}
return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
@@ -788,6 +789,16 @@ zfs_commit_shares(const enum sa_protocol *proto)
sa_commit_shares(*p);
}
+void
+zfs_truncate_shares(const enum sa_protocol *proto)
+{
+ if (proto == NULL)
+ proto = share_all_proto;
+
+ for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p)
+ sa_truncate_shares(*p);
+}
+
/*
* Unshare the given filesystem.
*/
@@ -930,7 +941,7 @@ zfs_iter_cb(zfs_handle_t *zhp, void *data)
}
libzfs_add_handle(cbp, zhp);
- if (zfs_iter_filesystems(zhp, zfs_iter_cb, cbp) != 0) {
+ if (zfs_iter_filesystems_v2(zhp, 0, zfs_iter_cb, cbp) != 0) {
zfs_close(zhp);
return (-1);
}
@@ -1279,7 +1290,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
* over all child filesystems.
*/
libzfs_add_handle(&cb, zfsp);
- if (zfs_iter_filesystems(zfsp, zfs_iter_cb, &cb) != 0)
+ if (zfs_iter_filesystems_v2(zfsp, 0, zfs_iter_cb, &cb) != 0)
goto out;
/*
@@ -1290,7 +1301,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
zfs_mount_one, &ms, B_TRUE);
if (ms.ms_mntstatus != 0)
- ret = ms.ms_mntstatus;
+ ret = EZFS_MOUNTFAILED;
/*
* Share all filesystems that need to be shared. This needs to be
@@ -1301,7 +1312,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
zfs_share_one, &ms, B_FALSE);
if (ms.ms_mntstatus != 0)
- ret = ms.ms_mntstatus;
+ ret = EZFS_SHAREFAILED;
else
zfs_commit_shares(NULL);
@@ -1412,10 +1423,10 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
* Walk through and first unshare everything.
*/
for (i = 0; i < used; i++) {
- for (enum sa_protocol i = 0; i < SA_PROTOCOL_COUNT; ++i) {
- if (sa_is_shared(sets[i].mountpoint, i) &&
+ for (enum sa_protocol p = 0; p < SA_PROTOCOL_COUNT; ++p) {
+ if (sa_is_shared(sets[i].mountpoint, p) &&
unshare_one(hdl, sets[i].mountpoint,
- sets[i].mountpoint, i) != 0)
+ sets[i].mountpoint, p) != 0)
goto out;
}
}
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 375abb944e24..979bbdd3809a 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,14 +22,14 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright (c) 2018 Datto Inc.
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
- * Copyright (c) 2021, Klara Inc.
+ * Copyright (c) 2021, 2023, Klara Inc.
*/
#include <errno.h>
@@ -60,9 +60,9 @@
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 */
- int vdevprop:1; /* Validate property as a VDEV property */
+ unsigned int create:1; /* Validate property on creation */
+ unsigned int import:1; /* Validate property on import */
+ unsigned int vdevprop:1; /* Validate property as a VDEV property */
} prop_flags_t;
/*
@@ -255,6 +255,7 @@ zpool_get_state_str(zpool_handle_t *zhp)
if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
str = gettext("FAULTED");
} else if (status == ZPOOL_STATUS_IO_FAILURE_WAIT ||
+ status == ZPOOL_STATUS_IO_FAILURE_CONTINUE ||
status == ZPOOL_STATUS_IO_FAILURE_MMP) {
str = gettext("SUSPENDED");
} else {
@@ -339,6 +340,8 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
case ZPOOL_PROP_ASHIFT:
case ZPOOL_PROP_MAXBLOCKSIZE:
case ZPOOL_PROP_MAXDNODESIZE:
+ case ZPOOL_PROP_BCLONESAVED:
+ case ZPOOL_PROP_BCLONEUSED:
if (literal)
(void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
@@ -380,6 +383,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
}
break;
+ case ZPOOL_PROP_BCLONERATIO:
case ZPOOL_PROP_DEDUPRATIO:
if (literal)
(void) snprintf(buf, len, "%llu.%02llu",
@@ -424,6 +428,37 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
}
/*
+ * Get a zpool property value for 'propname' and return the value in
+ * a pre-allocated buffer.
+ */
+int
+zpool_get_userprop(zpool_handle_t *zhp, const char *propname, char *buf,
+ size_t len, zprop_source_t *srctype)
+{
+ nvlist_t *nv, *nvl;
+ uint64_t ival;
+ const char *value;
+ zprop_source_t source = ZPROP_SRC_LOCAL;
+
+ nvl = zhp->zpool_props;
+ if (nvlist_lookup_nvlist(nvl, propname, &nv) == 0) {
+ if (nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0)
+ source = ival;
+ verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
+ } else {
+ source = ZPROP_SRC_DEFAULT;
+ value = "-";
+ }
+
+ if (srctype)
+ *srctype = source;
+
+ (void) strlcpy(buf, value, len);
+
+ return (0);
+}
+
+/*
* Check if the bootfs name has the same pool name as it is set to.
* Assuming bootfs is a valid dataset name.
*/
@@ -456,9 +491,9 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
nvpair_t *elem;
nvlist_t *retprops;
zpool_prop_t prop;
- char *strval;
+ const char *strval;
uint64_t intval;
- char *slash, *check;
+ const char *slash, *check;
struct stat64 statbuf;
zpool_handle_t *zhp;
char report[1024];
@@ -547,6 +582,44 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
goto error;
}
continue;
+ } else if (prop == ZPOOL_PROP_INVAL &&
+ zfs_prop_user(propname)) {
+ /*
+ * This is a user property: make sure it's a
+ * string, and that it's less than ZAP_MAXNAMELEN.
+ */
+ if (nvpair_type(elem) != DATA_TYPE_STRING) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "'%s' must be a string"), propname);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+
+ if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "property name '%s' is too long"),
+ propname);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+
+ (void) nvpair_value_string(elem, &strval);
+
+ if (strlen(strval) >= ZFS_MAXPROPLEN) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "property value '%s' is too long"),
+ strval);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+
+ if (nvlist_add_string(retprops, propname,
+ strval) != 0) {
+ (void) no_memory(hdl);
+ goto error;
+ }
+
+ continue;
}
/*
@@ -686,11 +759,12 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
goto error;
}
- *slash = '\0';
+ *(char *)slash = '\0';
if (strval[0] != '\0' &&
(stat64(strval, &statbuf) != 0 ||
!S_ISDIR(statbuf.st_mode))) {
+ *(char *)slash = '/';
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' is not a valid directory"),
strval);
@@ -698,7 +772,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
goto error;
}
- *slash = '/';
+ *(char *)slash = '/';
break;
case ZPOOL_PROP_COMPATIBILITY:
@@ -851,9 +925,30 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
features = zpool_get_features(zhp);
if ((*plp)->pl_all && firstexpand) {
+ /* Handle userprops in the all properties case */
+ if (zhp->zpool_props == NULL && zpool_props_refresh(zhp))
+ return (-1);
+
+ nvp = NULL;
+ while ((nvp = nvlist_next_nvpair(zhp->zpool_props, nvp)) !=
+ NULL) {
+ const char *propname = nvpair_name(nvp);
+
+ if (!zfs_prop_user(propname))
+ continue;
+
+ entry = zfs_alloc(hdl, sizeof (zprop_list_t));
+ entry->pl_prop = ZPROP_USERPROP;
+ entry->pl_user_prop = zfs_strdup(hdl, propname);
+ entry->pl_width = strlen(entry->pl_user_prop);
+ entry->pl_all = B_TRUE;
+
+ *last = entry;
+ last = &entry->pl_next;
+ }
+
for (i = 0; i < SPA_FEATURES; i++) {
- zprop_list_t *entry = zfs_alloc(hdl,
- sizeof (zprop_list_t));
+ entry = zfs_alloc(hdl, sizeof (zprop_list_t));
entry->pl_prop = ZPROP_USERPROP;
entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
spa_feature_table[i].fi_uname);
@@ -870,7 +965,6 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
char *propname;
boolean_t found;
- zprop_list_t *entry;
if (zfeature_is_supported(nvpair_name(nvp)))
continue;
@@ -916,6 +1010,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
NULL, literal) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
+ } else if (entry->pl_prop == ZPROP_INVAL &&
+ zfs_prop_user(entry->pl_user_prop) &&
+ zpool_get_userprop(zhp, entry->pl_user_prop, buf,
+ sizeof (buf), NULL) == 0) {
+ if (strlen(buf) > entry->pl_width)
+ entry->pl_width = strlen(buf);
}
}
@@ -928,7 +1028,7 @@ vdev_expand_proplist(zpool_handle_t *zhp, const char *vdevname,
{
zprop_list_t *entry;
char buf[ZFS_MAXPROPLEN];
- char *strval = NULL;
+ const char *strval = NULL;
int err = 0;
nvpair_t *elem = NULL;
nvlist_t *vprops = NULL;
@@ -1286,7 +1386,7 @@ zpool_has_special_vdev(nvlist_t *nvroot)
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child,
&children) == 0) {
for (uint_t c = 0; c < children; c++) {
- char *bias;
+ const char *bias;
if (nvlist_lookup_string(child[c],
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0 &&
@@ -1310,7 +1410,7 @@ zpool_has_draid_vdev(nvlist_t *nvroot)
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0) {
for (uint_t c = 0; c < children; c++) {
- char *type;
+ const char *type;
if (nvlist_lookup_string(child[c],
ZPOOL_CONFIG_TYPE, &type) == 0 &&
@@ -1390,7 +1490,7 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
if (fsprops) {
uint64_t zoned;
- char *zonestr;
+ const char *zonestr;
zoned = ((nvlist_lookup_string(fsprops,
zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
@@ -1624,7 +1724,7 @@ zpool_discard_checkpoint(zpool_handle_t *zhp)
* necessary verification to ensure that the vdev specification is well-formed.
*/
int
-zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
+zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot, boolean_t check_ashift)
{
zfs_cmd_t zc = {"\0"};
int ret;
@@ -1656,6 +1756,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
zcmd_write_conf_nvlist(hdl, &zc, nvroot);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+ zc.zc_flags = check_ashift;
if (zfs_ioctl(hdl, ZFS_IOC_VDEV_ADD, &zc) != 0) {
switch (errno) {
@@ -1799,7 +1900,8 @@ zpool_rewind_exclaim(libzfs_handle_t *hdl, const char *name, boolean_t dryrun,
(void) nvlist_lookup_int64(nv, ZPOOL_CONFIG_REWIND_TIME, &loss);
if (localtime_r((time_t *)&rewindto, &t) != NULL &&
- strftime(timestr, 128, "%c", &t) != 0) {
+ ctime_r((time_t *)&rewindto, timestr) != NULL) {
+ timestr[24] = 0;
if (dryrun) {
(void) printf(dgettext(TEXT_DOMAIN,
"Would be able to return %s "
@@ -1861,7 +1963,8 @@ zpool_explain_recover(libzfs_handle_t *hdl, const char *name, int reason,
"Recovery is possible, but will result in some data loss.\n"));
if (localtime_r((time_t *)&rewindto, &t) != NULL &&
- strftime(timestr, 128, "%c", &t) != 0) {
+ ctime_r((time_t *)&rewindto, timestr) != NULL) {
+ timestr[24] = 0;
(void) printf(dgettext(TEXT_DOMAIN,
"\tReturning the pool to its state as of %s\n"
"\tshould correct the problem. "),
@@ -1983,7 +2086,7 @@ zpool_print_unsup_feat(nvlist_t *config)
for (nvpair_t *nvp = nvlist_next_nvpair(unsup_feat, NULL);
nvp != NULL; nvp = nvlist_next_nvpair(unsup_feat, nvp)) {
- char *desc = fnvpair_value_string(nvp);
+ const char *desc = fnvpair_value_string(nvp);
if (strlen(desc) > 0)
(void) printf("\t%s (%s)\n", nvpair_name(nvp), desc);
else
@@ -2007,7 +2110,7 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
nvlist_t *nvinfo = NULL;
nvlist_t *missing = NULL;
const char *thename;
- char *origname;
+ const char *origname;
int ret;
int error = 0;
char errbuf[ERRBUFLEN];
@@ -2214,7 +2317,6 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
((policy.zlp_rewind & ZPOOL_TRY_REWIND) != 0), nv);
}
nvlist_free(nv);
- return (0);
}
return (ret);
@@ -2236,7 +2338,7 @@ zpool_translate_vdev_guids(zpool_handle_t *zhp, nvlist_t *vds,
elem = nvlist_next_nvpair(vds, elem)) {
boolean_t spare, cache;
- char *vd_path = nvpair_name(elem);
+ const char *vd_path = nvpair_name(elem);
nvlist_t *tgt = zpool_find_vdev(zhp, vd_path, &spare, &cache,
NULL);
@@ -2289,8 +2391,8 @@ xlate_init_err(int err)
}
/*
- * Begin, suspend, or cancel the initialization (initializing of all free
- * blocks) for the given vdevs in the given pool.
+ * Begin, suspend, cancel, or uninit (clear) the initialization (initializing
+ * of all free blocks) for the given vdevs in the given pool.
*/
static int
zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
@@ -2316,11 +2418,16 @@ zpool_initialize_impl(zpool_handle_t *zhp, pool_initialize_func_t cmd_type,
vdev_guids, &errlist);
if (err != 0) {
- if (errlist != NULL) {
- vd_errlist = fnvlist_lookup_nvlist(errlist,
- ZPOOL_INITIALIZE_VDEVS);
+ if (errlist != NULL && nvlist_lookup_nvlist(errlist,
+ ZPOOL_INITIALIZE_VDEVS, &vd_errlist) == 0) {
goto list_errors;
}
+
+ if (err == EINVAL && cmd_type == POOL_INITIALIZE_UNINIT) {
+ zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
+ "uninitialize is not supported by kernel"));
+ }
+
(void) zpool_standard_error(zhp->zpool_hdl, err,
dgettext(TEXT_DOMAIN, "operation failed"));
goto out;
@@ -2350,7 +2457,7 @@ list_errors:
for (elem = nvlist_next_nvpair(vd_errlist, NULL); elem != NULL;
elem = nvlist_next_nvpair(vd_errlist, elem)) {
int64_t vd_error = xlate_init_err(fnvpair_value_int64(elem));
- char *path;
+ const char *path;
if (nvlist_lookup_string(guids_to_paths, nvpair_name(elem),
&path) != 0)
@@ -2448,7 +2555,7 @@ check_trim_errs(zpool_handle_t *zhp, trimflags_t *trim_flags,
for (elem = nvlist_next_nvpair(errlist, NULL);
elem != NULL; elem = nvlist_next_nvpair(errlist, elem)) {
int64_t vd_error = xlate_trim_err(fnvpair_value_int64(elem));
- char *path;
+ const char *path;
/*
* If only the pool was specified, and it was not a secure
@@ -2545,50 +2652,84 @@ out:
int
zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
{
- zfs_cmd_t zc = {"\0"};
char errbuf[ERRBUFLEN];
int err;
libzfs_handle_t *hdl = zhp->zpool_hdl;
- (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
- zc.zc_cookie = func;
- zc.zc_flags = cmd;
+ nvlist_t *args = fnvlist_alloc();
+ fnvlist_add_uint64(args, "scan_type", (uint64_t)func);
+ fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd);
+
+ err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL);
+ fnvlist_free(args);
- if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
+ if (err == 0) {
return (0);
+ } else if (err == ZFS_ERR_IOC_CMD_UNAVAIL) {
+ zfs_cmd_t zc = {"\0"};
+ (void) strlcpy(zc.zc_name, zhp->zpool_name,
+ sizeof (zc.zc_name));
+ zc.zc_cookie = func;
+ zc.zc_flags = cmd;
- err = errno;
+ if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
+ return (0);
+ }
- /* ECANCELED on a scrub means we resumed a paused scrub */
- if (err == ECANCELED && func == POOL_SCAN_SCRUB &&
- cmd == POOL_SCRUB_NORMAL)
+ /*
+ * An ECANCELED on a scrub means one of the following:
+ * 1. we resumed a paused scrub.
+ * 2. we resumed a paused error scrub.
+ * 3. Error scrub is not run because of no error log.
+ */
+ if (err == ECANCELED && (func == POOL_SCAN_SCRUB ||
+ func == POOL_SCAN_ERRORSCRUB) && cmd == POOL_SCRUB_NORMAL)
return (0);
-
- if (err == ENOENT && func != POOL_SCAN_NONE && cmd == POOL_SCRUB_NORMAL)
+ /*
+ * The following cases have been handled here:
+ * 1. Paused a scrub/error scrub if there is none in progress.
+ */
+ if (err == ENOENT && func != POOL_SCAN_NONE && cmd ==
+ POOL_SCRUB_PAUSE) {
return (0);
+ }
+
+ ASSERT3U(func, >=, POOL_SCAN_NONE);
+ ASSERT3U(func, <, POOL_SCAN_FUNCS);
- if (func == POOL_SCAN_SCRUB) {
+ if (func == POOL_SCAN_SCRUB || func == POOL_SCAN_ERRORSCRUB) {
if (cmd == POOL_SCRUB_PAUSE) {
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot pause scrubbing %s"),
- zc.zc_name);
+ zhp->zpool_name);
} else {
assert(cmd == POOL_SCRUB_NORMAL);
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot scrub %s"),
- zc.zc_name);
+ zhp->zpool_name);
}
} else if (func == POOL_SCAN_RESILVER) {
assert(cmd == POOL_SCRUB_NORMAL);
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "cannot restart resilver on %s"), zc.zc_name);
+ "cannot restart resilver on %s"), zhp->zpool_name);
} else if (func == POOL_SCAN_NONE) {
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "cannot cancel scrubbing %s"), zc.zc_name);
+ "cannot cancel scrubbing %s"), zhp->zpool_name);
} else {
assert(!"unexpected result");
}
+ /*
+ * With EBUSY, five cases are possible:
+ *
+ * Current state Requested
+ * 1. Normal Scrub Running Normal Scrub or Error Scrub
+ * 2. Normal Scrub Paused Error Scrub
+ * 3. Normal Scrub Paused Pause Normal Scrub
+ * 4. Error Scrub Running Normal Scrub or Error Scrub
+ * 5. Error Scrub Paused Pause Error Scrub
+ * 6. Resilvering Anything else
+ */
if (err == EBUSY) {
nvlist_t *nvroot;
pool_scan_stat_t *ps = NULL;
@@ -2600,12 +2741,43 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
if (ps && ps->pss_func == POOL_SCAN_SCRUB &&
ps->pss_state == DSS_SCANNING) {
- if (cmd == POOL_SCRUB_PAUSE)
- return (zfs_error(hdl, EZFS_SCRUB_PAUSED,
+ if (ps->pss_pass_scrub_pause == 0) {
+ /* handles case 1 */
+ assert(cmd == POOL_SCRUB_NORMAL);
+ return (zfs_error(hdl, EZFS_SCRUBBING,
errbuf));
- else
- return (zfs_error(hdl, EZFS_SCRUBBING, errbuf));
+ } else {
+ if (func == POOL_SCAN_ERRORSCRUB) {
+ /* handles case 2 */
+ ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
+ return (zfs_error(hdl,
+ EZFS_SCRUB_PAUSED_TO_CANCEL,
+ errbuf));
+ } else {
+ /* handles case 3 */
+ ASSERT3U(func, ==, POOL_SCAN_SCRUB);
+ ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
+ return (zfs_error(hdl,
+ EZFS_SCRUB_PAUSED, errbuf));
+ }
+ }
+ } else if (ps &&
+ ps->pss_error_scrub_func == POOL_SCAN_ERRORSCRUB &&
+ ps->pss_error_scrub_state == DSS_ERRORSCRUBBING) {
+ if (ps->pss_pass_error_scrub_pause == 0) {
+ /* handles case 4 */
+ ASSERT3U(cmd, ==, POOL_SCRUB_NORMAL);
+ return (zfs_error(hdl, EZFS_ERRORSCRUBBING,
+ errbuf));
+ } else {
+ /* handles case 5 */
+ ASSERT3U(func, ==, POOL_SCAN_ERRORSCRUB);
+ ASSERT3U(cmd, ==, POOL_SCRUB_PAUSE);
+ return (zfs_error(hdl, EZFS_ERRORSCRUB_PAUSED,
+ errbuf));
+ }
} else {
+ /* handles case 6 */
return (zfs_error(hdl, EZFS_RESILVERING, errbuf));
}
} else if (err == ENOENT) {
@@ -2631,7 +2803,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
nvlist_t **child;
nvlist_t *ret;
uint64_t is_log;
- char *srchkey;
+ const char *srchkey;
nvpair_t *pair = nvlist_next_nvpair(search, NULL);
/* Nothing to look for */
@@ -2653,7 +2825,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
break;
case DATA_TYPE_STRING: {
- char *srchval, *val;
+ const char *srchval, *val;
srchval = fnvpair_value_string(pair);
if (nvlist_lookup_string(nv, srchkey, &val) != 0)
@@ -2679,7 +2851,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
if (zfs_strcmp_pathname(srchval, val, wholedisk) == 0)
return (nv);
- } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0 && val) {
+ } else if (strcmp(srchkey, ZPOOL_CONFIG_TYPE) == 0) {
char *type, *idx, *end, *p;
uint64_t id, vdev_id;
@@ -2856,6 +3028,7 @@ zpool_vdev_is_interior(const char *name)
strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 ||
strncmp(name,
VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 ||
+ strncmp(name, VDEV_TYPE_ROOT, strlen(VDEV_TYPE_ROOT)) == 0 ||
strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0)
return (B_TRUE);
@@ -2866,6 +3039,9 @@ zpool_vdev_is_interior(const char *name)
return (B_FALSE);
}
+/*
+ * Lookup the nvlist for a given vdev.
+ */
nvlist_t *
zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
boolean_t *l2cache, boolean_t *log)
@@ -2873,6 +3049,7 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
char *end;
nvlist_t *nvroot, *search, *ret;
uint64_t guid;
+ boolean_t __avail_spare, __l2cache, __log;
search = fnvlist_alloc();
@@ -2888,6 +3065,18 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
nvroot = fnvlist_lookup_nvlist(zhp->zpool_config,
ZPOOL_CONFIG_VDEV_TREE);
+ /*
+ * User can pass NULL for avail_spare, l2cache, and log, but
+ * we still need to provide variables to vdev_to_nvlist_iter(), so
+ * just point them to junk variables here.
+ */
+ if (!avail_spare)
+ avail_spare = &__avail_spare;
+ if (!l2cache)
+ l2cache = &__l2cache;
+ if (!log)
+ log = &__log;
+
*avail_spare = B_FALSE;
*l2cache = B_FALSE;
if (log != NULL)
@@ -2898,154 +3087,6 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
return (ret);
}
-static int
-vdev_is_online(nvlist_t *nv)
-{
- uint64_t ival;
-
- if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_OFFLINE, &ival) == 0 ||
- nvlist_lookup_uint64(nv, ZPOOL_CONFIG_FAULTED, &ival) == 0 ||
- nvlist_lookup_uint64(nv, ZPOOL_CONFIG_REMOVED, &ival) == 0)
- return (0);
-
- return (1);
-}
-
-/*
- * Helper function for zpool_get_physpaths().
- */
-static int
-vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
- size_t *bytes_written)
-{
- size_t bytes_left, pos, rsz;
- char *tmppath;
- const char *format;
-
- if (nvlist_lookup_string(config, ZPOOL_CONFIG_PHYS_PATH,
- &tmppath) != 0)
- return (EZFS_NODEVICE);
-
- pos = *bytes_written;
- bytes_left = physpath_size - pos;
- format = (pos == 0) ? "%s" : " %s";
-
- rsz = snprintf(physpath + pos, bytes_left, format, tmppath);
- *bytes_written += rsz;
-
- if (rsz >= bytes_left) {
- /* if physpath was not copied properly, clear it */
- if (bytes_left != 0) {
- physpath[pos] = 0;
- }
- return (EZFS_NOSPC);
- }
- return (0);
-}
-
-static int
-vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
- size_t *rsz, boolean_t is_spare)
-{
- char *type;
- int ret;
-
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
- return (EZFS_INVALCONFIG);
-
- if (strcmp(type, VDEV_TYPE_DISK) == 0) {
- /*
- * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
- * For a spare vdev, we only want to boot from the active
- * spare device.
- */
- if (is_spare) {
- uint64_t spare = 0;
- (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
- &spare);
- if (!spare)
- return (EZFS_INVALCONFIG);
- }
-
- if (vdev_is_online(nv)) {
- if ((ret = vdev_get_one_physpath(nv, physpath,
- phypath_size, rsz)) != 0)
- return (ret);
- }
- } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
- strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
- strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
- (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
- nvlist_t **child;
- uint_t count;
- int i, ret;
-
- if (nvlist_lookup_nvlist_array(nv,
- ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
- return (EZFS_INVALCONFIG);
-
- for (i = 0; i < count; i++) {
- ret = vdev_get_physpaths(child[i], physpath,
- phypath_size, rsz, is_spare);
- if (ret == EZFS_NOSPC)
- return (ret);
- }
- }
-
- return (EZFS_POOL_INVALARG);
-}
-
-/*
- * Get phys_path for a root pool config.
- * Return 0 on success; non-zero on failure.
- */
-static int
-zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
-{
- size_t rsz;
- nvlist_t *vdev_root;
- nvlist_t **child;
- uint_t count;
- char *type;
-
- rsz = 0;
-
- if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
- &vdev_root) != 0)
- return (EZFS_INVALCONFIG);
-
- if (nvlist_lookup_string(vdev_root, ZPOOL_CONFIG_TYPE, &type) != 0 ||
- nvlist_lookup_nvlist_array(vdev_root, ZPOOL_CONFIG_CHILDREN,
- &child, &count) != 0)
- return (EZFS_INVALCONFIG);
-
- /*
- * root pool can only have a single top-level vdev.
- */
- if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1)
- return (EZFS_POOL_INVALARG);
-
- (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
- B_FALSE);
-
- /* No online devices */
- if (rsz == 0)
- return (EZFS_NODEVICE);
-
- return (0);
-}
-
-/*
- * Get phys_path for a root pool
- * Return 0 on success; non-zero on failure.
- */
-int
-zpool_get_physpath(zpool_handle_t *zhp, char *physpath, size_t phypath_size)
-{
- return (zpool_get_config_physpath(zhp->zpool_config, physpath,
- phypath_size));
-}
-
/*
* Convert a vdev path to a GUID. Returns GUID or 0 on error.
*
@@ -3110,11 +3151,11 @@ zpool_vdev_online(zpool_handle_t *zhp, const char *path, int flags,
zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
- if (avail_spare)
+ if (!(flags & ZFS_ONLINE_SPARE) && avail_spare)
return (zfs_error(hdl, EZFS_ISSPARE, errbuf));
#ifndef __FreeBSD__
- char *pathname;
+ const char *pathname;
if ((flags & ZFS_ONLINE_EXPAND ||
zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) &&
nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &pathname) == 0) {
@@ -3222,6 +3263,40 @@ zpool_vdev_offline(zpool_handle_t *zhp, const char *path, boolean_t istmp)
}
/*
+ * Remove the specified vdev asynchronously from the configuration, so
+ * that it may come ONLINE if reinserted. This is called from zed on
+ * Udev remove event.
+ * Note: We also have a similar function zpool_vdev_remove() that
+ * removes the vdev from the pool.
+ */
+int
+zpool_vdev_remove_wanted(zpool_handle_t *zhp, const char *path)
+{
+ zfs_cmd_t zc = {"\0"};
+ char errbuf[ERRBUFLEN];
+ nvlist_t *tgt;
+ boolean_t avail_spare, l2cache;
+ libzfs_handle_t *hdl = zhp->zpool_hdl;
+
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot remove %s"), path);
+
+ (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
+ if ((tgt = zpool_find_vdev(zhp, path, &avail_spare, &l2cache,
+ NULL)) == NULL)
+ return (zfs_error(hdl, EZFS_NODEVICE, errbuf));
+
+ zc.zc_guid = fnvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID);
+
+ zc.zc_cookie = VDEV_STATE_REMOVED;
+
+ if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
+ return (0);
+
+ return (zpool_standard_error(hdl, errno, errbuf));
+}
+
+/*
* Mark the given vdev faulted.
*/
int
@@ -3257,21 +3332,23 @@ zpool_vdev_fault(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
}
/*
- * Mark the given vdev degraded.
+ * Generic set vdev state function
*/
-int
-zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
+static int
+zpool_vdev_set_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux,
+ vdev_state_t state)
{
zfs_cmd_t zc = {"\0"};
char errbuf[ERRBUFLEN];
libzfs_handle_t *hdl = zhp->zpool_hdl;
(void) snprintf(errbuf, sizeof (errbuf),
- dgettext(TEXT_DOMAIN, "cannot degrade %llu"), (u_longlong_t)guid);
+ dgettext(TEXT_DOMAIN, "cannot set %s %llu"),
+ zpool_state_to_name(state, aux), (u_longlong_t)guid);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
zc.zc_guid = guid;
- zc.zc_cookie = VDEV_STATE_DEGRADED;
+ zc.zc_cookie = state;
zc.zc_obj = aux;
if (zfs_ioctl(hdl, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
@@ -3281,6 +3358,27 @@ zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
}
/*
+ * Mark the given vdev degraded.
+ */
+int
+zpool_vdev_degrade(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
+{
+ return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_DEGRADED));
+}
+
+/*
+ * Mark the given vdev as in a removed state (as if the device does not exist).
+ *
+ * This is different than zpool_vdev_remove() which does a removal of a device
+ * from the pool (but the device does exist).
+ */
+int
+zpool_vdev_set_removed_state(zpool_handle_t *zhp, uint64_t guid, vdev_aux_t aux)
+{
+ return (zpool_vdev_set_state(zhp, guid, aux, VDEV_STATE_REMOVED));
+}
+
+/*
* Returns TRUE if the given nvlist is a vdev that was originally swapped in as
* a hot spare.
*/
@@ -3292,7 +3390,8 @@ is_replacing_spare(nvlist_t *search, nvlist_t *tgt, int which)
if (nvlist_lookup_nvlist_array(search, ZPOOL_CONFIG_CHILDREN, &child,
&children) == 0) {
- char *type = fnvlist_lookup_string(search, ZPOOL_CONFIG_TYPE);
+ const char *type = fnvlist_lookup_string(search,
+ ZPOOL_CONFIG_TYPE);
if ((strcmp(type, VDEV_TYPE_SPARE) == 0 ||
strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0) &&
children == 2 && child[which] == tgt)
@@ -3321,6 +3420,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
boolean_t avail_spare, l2cache, islog;
uint64_t val;
char *newname;
+ const char *type;
nvlist_t **child;
uint_t children;
nvlist_t *config_root;
@@ -3355,6 +3455,14 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
}
+ type = fnvlist_lookup_string(tgt, ZPOOL_CONFIG_TYPE);
+ if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 &&
+ zfeature_lookup_guid("org.openzfs:raidz_expansion", NULL) != 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "the loaded zfs module doesn't support raidz expansion"));
+ return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
+ }
+
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0 || children != 1) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -3422,6 +3530,10 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"cannot replace a replacing device"));
}
+ } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "raidz_expansion feature must be enabled "
+ "in order to attach a device to raidz"));
} else {
char status[64] = {0};
zpool_prop_get_feature(zhp,
@@ -3451,8 +3563,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
break;
case EBUSY:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy, "
- "or device removal is in progress"),
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"),
new_disk);
(void) zfs_error(hdl, EZFS_BADDEV, errbuf);
break;
@@ -3483,6 +3594,34 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk,
(void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf);
break;
+ case ENXIO:
+ /*
+ * The existing raidz vdev has offline children
+ */
+ if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "raidz vdev has devices that are are offline or "
+ "being replaced"));
+ (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
+ break;
+ } else {
+ (void) zpool_standard_error(hdl, errno, errbuf);
+ }
+ break;
+
+ case EADDRINUSE:
+ /*
+ * The boot reserved area is already being used (FreeBSD)
+ */
+ if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "the reserved boot area needed for the expansion "
+ "is already being used by a boot loader"));
+ (void) zfs_error(hdl, EZFS_BADDEV, errbuf);
+ } else {
+ (void) zpool_standard_error(hdl, errno, errbuf);
+ }
+ break;
default:
(void) zpool_standard_error(hdl, errno, errbuf);
}
@@ -3595,7 +3734,8 @@ zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
nvlist_t *props, splitflags_t flags)
{
zfs_cmd_t zc = {"\0"};
- char errbuf[ERRBUFLEN], *bias;
+ char errbuf[ERRBUFLEN];
+ const char *bias;
nvlist_t *tree, *config, **child, **newchild, *newconfig = NULL;
nvlist_t **varray = NULL, *zc_props = NULL;
uint_t c, children, newchildren, lastlog = 0, vcount, found = 0;
@@ -3653,7 +3793,7 @@ zpool_vdev_split(zpool_handle_t *zhp, char *newname, nvlist_t **newroot,
for (c = 0; c < children; c++) {
uint64_t is_log = B_FALSE, is_hole = B_FALSE;
boolean_t is_special = B_FALSE, is_dedup = B_FALSE;
- char *type;
+ const char *type;
nvlist_t **mchild, *vdev;
uint_t mchildren;
int entry;
@@ -3869,6 +4009,12 @@ zpool_vdev_remove(zpool_handle_t *zhp, const char *path)
switch (errno) {
+ case EALREADY:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "removal for this vdev is already in progress."));
+ (void) zfs_error(hdl, EZFS_BUSY, errbuf);
+ break;
+
case EINVAL:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid config; all top-level vdevs must "
@@ -4126,7 +4272,7 @@ char *
zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
int name_flags)
{
- char *type, *tpath;
+ const char *type, *tpath;
const char *path;
uint64_t value;
char buf[PATH_BUF_LEN];
@@ -4245,33 +4391,28 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
{
zfs_cmd_t zc = {"\0"};
libzfs_handle_t *hdl = zhp->zpool_hdl;
- uint64_t count;
- zbookmark_phys_t *zb = NULL;
- int i;
+ zbookmark_phys_t *buf;
+ uint64_t buflen = 10000; /* approx. 1MB of RAM */
+
+ if (fnvlist_lookup_uint64(zhp->zpool_config,
+ ZPOOL_CONFIG_ERRCOUNT) == 0)
+ return (0);
/*
- * Retrieve the raw error list from the kernel. If the number of errors
- * has increased, allocate more space and continue until we get the
- * entire list.
+ * Retrieve the raw error list from the kernel. If it doesn't fit,
+ * allocate a larger buffer and retry.
*/
- count = fnvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_ERRCOUNT);
- if (count == 0)
- return (0);
- zc.zc_nvlist_dst = (uintptr_t)zfs_alloc(zhp->zpool_hdl,
- count * sizeof (zbookmark_phys_t));
- zc.zc_nvlist_dst_size = count;
(void) strcpy(zc.zc_name, zhp->zpool_name);
for (;;) {
+ buf = zfs_alloc(zhp->zpool_hdl,
+ buflen * sizeof (zbookmark_phys_t));
+ zc.zc_nvlist_dst = (uintptr_t)buf;
+ zc.zc_nvlist_dst_size = buflen;
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_ERROR_LOG,
&zc) != 0) {
- free((void *)(uintptr_t)zc.zc_nvlist_dst);
+ free(buf);
if (errno == ENOMEM) {
- void *dst;
-
- count = zc.zc_nvlist_dst_size;
- dst = zfs_alloc(zhp->zpool_hdl, count *
- sizeof (zbookmark_phys_t));
- zc.zc_nvlist_dst = (uintptr_t)dst;
+ buflen *= 2;
} else {
return (zpool_standard_error_fmt(hdl, errno,
dgettext(TEXT_DOMAIN, "errors: List of "
@@ -4289,18 +4430,17 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
* _not_ copied as part of the process. So we point the start of our
* array appropriate and decrement the total number of elements.
*/
- zb = ((zbookmark_phys_t *)(uintptr_t)zc.zc_nvlist_dst) +
- zc.zc_nvlist_dst_size;
- count -= zc.zc_nvlist_dst_size;
+ zbookmark_phys_t *zb = buf + zc.zc_nvlist_dst_size;
+ uint64_t zblen = buflen - zc.zc_nvlist_dst_size;
- qsort(zb, count, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
+ qsort(zb, zblen, sizeof (zbookmark_phys_t), zbookmark_mem_compare);
verify(nvlist_alloc(nverrlistp, 0, KM_SLEEP) == 0);
/*
* Fill in the nverrlistp with nvlist's of dataset and object numbers.
*/
- for (i = 0; i < count; i++) {
+ for (uint64_t i = 0; i < zblen; i++) {
nvlist_t *nv;
/* ignoring zb_blkid and zb_level for now */
@@ -4327,11 +4467,11 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
nvlist_free(nv);
}
- free((void *)(uintptr_t)zc.zc_nvlist_dst);
+ free(buf);
return (0);
nomem:
- free((void *)(uintptr_t)zc.zc_nvlist_dst);
+ free(buf);
return (no_memory(zhp->zpool_hdl));
}
@@ -4832,8 +4972,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()
@@ -5123,6 +5263,19 @@ zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name,
(u_longlong_t)intval);
}
break;
+ case VDEV_PROP_CHECKSUM_N:
+ case VDEV_PROP_CHECKSUM_T:
+ case VDEV_PROP_IO_N:
+ case VDEV_PROP_IO_T:
+ case VDEV_PROP_SLOW_IO_N:
+ case VDEV_PROP_SLOW_IO_T:
+ if (intval == UINT64_MAX) {
+ (void) strlcpy(buf, "-", len);
+ } else {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ }
+ break;
case VDEV_PROP_FRAGMENTATION:
if (intval == UINT64_MAX) {
(void) strlcpy(buf, "-", len);
@@ -5153,6 +5306,9 @@ zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name,
} else {
src = ZPROP_SRC_DEFAULT;
intval = vdev_prop_default_numeric(prop);
+ /* Only use if provided by the RAIDZ VDEV above */
+ if (prop == VDEV_PROP_RAIDZ_EXPANDING)
+ return (ENOENT);
}
if (vdev_prop_index_to_string(prop, intval,
(const char **)&strval) != 0)
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index 794aff5feef8..526f57ea403c 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -83,6 +83,9 @@ typedef struct progress_arg {
boolean_t pa_parsable;
boolean_t pa_estimate;
int pa_verbosity;
+ boolean_t pa_astitle;
+ boolean_t pa_progress;
+ uint64_t pa_size;
} progress_arg_t;
static int
@@ -116,7 +119,7 @@ dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len,
typedef struct fsavl_node {
avl_node_t fn_node;
nvlist_t *fn_nvfs;
- char *fn_snapname;
+ const char *fn_snapname;
uint64_t fn_guid;
} fsavl_node_t;
@@ -134,7 +137,7 @@ fsavl_compare(const void *arg1, const void *arg2)
* (optionally) name.
*/
static nvlist_t *
-fsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname)
+fsavl_find(avl_tree_t *avl, uint64_t snapguid, const char **snapname)
{
fsavl_node_t fn_find;
fsavl_node_t *fn;
@@ -285,7 +288,7 @@ send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv);
/*
* Collect guid, valid props, optionally holds, etc. of a snapshot.
- * This interface is intended for use as a zfs_iter_snapshots_sorted visitor.
+ * This interface is intended for use as a zfs_iter_snapshots_v2_sorted visitor.
*/
static int
send_iterate_snap(zfs_handle_t *zhp, void *arg)
@@ -381,7 +384,7 @@ send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
nvpair_t *elem = NULL;
while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
- char *propname = nvpair_name(elem);
+ const char *propname = nvpair_name(elem);
zfs_prop_t prop = zfs_name_to_prop(propname);
if (!zfs_prop_user(propname)) {
@@ -409,7 +412,7 @@ send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
if (isspacelimit && zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
continue;
- char *source;
+ const char *source;
if (nvlist_lookup_string(propnv, ZPROP_SOURCE, &source) == 0) {
if (strcmp(source, zhp->zfs_name) != 0 &&
strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0)
@@ -425,7 +428,7 @@ send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
if (zfs_prop_user(propname) ||
zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
- char *value;
+ const char *value;
value = fnvlist_lookup_string(propnv, ZPROP_VALUE);
fnvlist_add_string(nv, propname, value);
} else {
@@ -437,6 +440,29 @@ send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
}
/*
+ * returns snapshot guid
+ * and returns 0 if the snapshot does not exist
+ */
+static uint64_t
+get_snap_guid(libzfs_handle_t *hdl, const char *fs, const char *snap)
+{
+ char name[MAXPATHLEN + 1];
+ uint64_t guid = 0;
+
+ if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0')
+ return (guid);
+
+ (void) snprintf(name, sizeof (name), "%s@%s", fs, snap);
+ zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT);
+ if (zhp != NULL) {
+ guid = zfs_prop_get_int(zhp, ZFS_PROP_GUID);
+ zfs_close(zhp);
+ }
+
+ return (guid);
+}
+
+/*
* returns snapshot creation txg
* and returns 0 if the snapshot does not exist
*/
@@ -593,10 +619,10 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
min_txg = fromsnap_txg;
if (!sd->replicate && tosnap_txg != 0)
max_txg = tosnap_txg;
- (void) zfs_iter_snapshots_sorted(zhp, send_iterate_snap, sd,
- min_txg, max_txg);
+ (void) zfs_iter_snapshots_sorted_v2(zhp, 0, send_iterate_snap,
+ sd, min_txg, max_txg);
} else {
- char snapname[MAXPATHLEN];
+ char snapname[MAXPATHLEN] = { 0 };
zfs_handle_t *snap;
(void) snprintf(snapname, sizeof (snapname), "%s@%s",
@@ -636,7 +662,7 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
/* Iterate over children. */
if (sd->recursive)
- rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
+ rv = zfs_iter_filesystems_v2(zhp, 0, send_iterate_fs, sd);
out:
/* Restore saved fields. */
@@ -710,6 +736,7 @@ typedef struct send_dump_data {
boolean_t seenfrom, seento, replicate, doall, fromorigin;
boolean_t dryrun, parsable, progress, embed_data, std_out;
boolean_t large_block, compress, raw, holds;
+ boolean_t progressastitle;
int outfd;
boolean_t err;
nvlist_t *fss;
@@ -766,7 +793,7 @@ zfs_send_space(zfs_handle_t *zhp, const char *snapname, const char *from,
case EFAULT:
case EROFS:
case EINVAL:
- zfs_error_aux(hdl, "%s", strerror(error));
+ zfs_error_aux(hdl, "%s", zfs_strerror(error));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default:
@@ -849,13 +876,8 @@ dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
case EFAULT:
case EROFS:
case EINVAL:
- zfs_error_aux(hdl, "%s", strerror(errno));
+ zfs_error_aux(hdl, "%s", zfs_strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
- case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "large blocks detected but large_blocks feature "
- "is inactive; raw send unsupported"));
- return (zfs_error(hdl, EZFS_NOTSUP, errbuf));
default:
return (zfs_standard_error(hdl, errno, errbuf));
@@ -906,6 +928,39 @@ zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written,
return (0);
}
+static volatile boolean_t send_progress_thread_signal_duetotimer;
+static void
+send_progress_thread_act(int sig, siginfo_t *info, void *ucontext)
+{
+ (void) sig, (void) ucontext;
+ send_progress_thread_signal_duetotimer = info->si_code == SI_TIMER;
+}
+
+struct timer_desirability {
+ timer_t timer;
+ boolean_t desired;
+};
+static void
+timer_delete_cleanup(void *timer)
+{
+ struct timer_desirability *td = timer;
+ if (td->desired)
+ timer_delete(td->timer);
+}
+
+#ifdef SIGINFO
+#define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO sigaddset(&new, SIGINFO)
+#else
+#define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO
+#endif
+#define SEND_PROGRESS_THREAD_PARENT_BLOCK(old) { \
+ sigset_t new; \
+ sigemptyset(&new); \
+ sigaddset(&new, SIGUSR1); \
+ SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO; \
+ pthread_sigmask(SIG_BLOCK, &new, old); \
+}
+
static void *
send_progress_thread(void *arg)
{
@@ -913,12 +968,33 @@ send_progress_thread(void *arg)
zfs_handle_t *zhp = pa->pa_zhp;
uint64_t bytes;
uint64_t blocks;
+ uint64_t total = pa->pa_size / 100;
char buf[16];
time_t t;
struct tm tm;
int err;
- if (!pa->pa_parsable) {
+ const struct sigaction signal_action =
+ {.sa_sigaction = send_progress_thread_act, .sa_flags = SA_SIGINFO};
+ struct sigevent timer_cfg =
+ {.sigev_notify = SIGEV_SIGNAL, .sigev_signo = SIGUSR1};
+ const struct itimerspec timer_time =
+ {.it_value = {.tv_sec = 1}, .it_interval = {.tv_sec = 1}};
+ struct timer_desirability timer = {};
+
+ sigaction(SIGUSR1, &signal_action, NULL);
+#ifdef SIGINFO
+ sigaction(SIGINFO, &signal_action, NULL);
+#endif
+
+ if ((timer.desired = pa->pa_progress || pa->pa_astitle)) {
+ if (timer_create(CLOCK_MONOTONIC, &timer_cfg, &timer.timer))
+ return ((void *)(uintptr_t)errno);
+ (void) timer_settime(timer.timer, 0, &timer_time, NULL);
+ }
+ pthread_cleanup_push(timer_delete_cleanup, &timer);
+
+ if (!pa->pa_parsable && pa->pa_progress) {
(void) fprintf(stderr,
"TIME %s %sSNAPSHOT %s\n",
pa->pa_estimate ? "BYTES" : " SENT",
@@ -930,17 +1006,28 @@ send_progress_thread(void *arg)
* Print the progress from ZFS_IOC_SEND_PROGRESS every second.
*/
for (;;) {
- (void) sleep(1);
+ pause();
if ((err = zfs_send_progress(zhp, pa->pa_fd, &bytes,
&blocks)) != 0) {
if (err == EINTR || err == ENOENT)
- return ((void *)0);
- return ((void *)(uintptr_t)err);
+ err = 0;
+ pthread_exit(((void *)(uintptr_t)err));
}
(void) time(&t);
localtime_r(&t, &tm);
+ if (pa->pa_astitle) {
+ char buf_bytes[16];
+ char buf_size[16];
+ int pct;
+ zfs_nicenum(bytes, buf_bytes, sizeof (buf_bytes));
+ zfs_nicenum(pa->pa_size, buf_size, sizeof (buf_size));
+ pct = (total > 0) ? bytes / total : 100;
+ zfs_setproctitle("sending %s (%d%%: %s/%s)",
+ zhp->zfs_name, MIN(pct, 100), buf_bytes, buf_size);
+ }
+
if (pa->pa_verbosity >= 2 && pa->pa_parsable) {
(void) fprintf(stderr,
"%02d:%02d:%02d\t%llu\t%llu\t%s\n",
@@ -957,21 +1044,26 @@ send_progress_thread(void *arg)
(void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
(u_longlong_t)bytes, zhp->zfs_name);
- } else {
+ } else if (pa->pa_progress ||
+ !send_progress_thread_signal_duetotimer) {
zfs_nicebytes(bytes, buf, sizeof (buf));
(void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
buf, zhp->zfs_name);
}
}
+ pthread_cleanup_pop(B_TRUE);
+ return (NULL);
}
static boolean_t
-send_progress_thread_exit(libzfs_handle_t *hdl, pthread_t ptid)
+send_progress_thread_exit(
+ libzfs_handle_t *hdl, pthread_t ptid, sigset_t *oldmask)
{
void *status = NULL;
(void) pthread_cancel(ptid);
(void) pthread_join(ptid, &status);
+ pthread_sigmask(SIG_SETMASK, oldmask, NULL);
int error = (int)(uintptr_t)status;
if (error != 0 && status != PTHREAD_CANCELED)
return (zfs_standard_error(hdl, error,
@@ -989,8 +1081,23 @@ send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"incremental\t%s\t%s"), fromsnap, tosnap);
} else {
+/*
+ * Workaround for GCC 12+ with UBSan enabled deficencies.
+ *
+ * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
+ * below as violating -Wformat-overflow.
+ */
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-overflow"
+#endif
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"full\t%s"), tosnap);
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic pop
+#endif
}
(void) fprintf(fout, "\t%llu", (longlong_t)size);
} else {
@@ -1010,8 +1117,23 @@ send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
if (size != 0) {
char buf[16];
zfs_nicebytes(size, buf, sizeof (buf));
+/*
+ * Workaround for GCC 12+ with UBSan enabled deficencies.
+ *
+ * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
+ * below as violating -Wformat-overflow.
+ */
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-overflow"
+#endif
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
" estimated size is %s"), buf);
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
+#pragma GCC diagnostic pop
+#endif
}
}
(void) fprintf(fout, "\n");
@@ -1019,7 +1141,7 @@ send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
/*
* Send a single filesystem snapshot, updating the send dump data.
- * This interface is intended for use as a zfs_iter_snapshots_sorted visitor.
+ * This interface is intended for use as a zfs_iter_snapshots_v2_sorted visitor.
*/
static int
dump_snapshot(zfs_handle_t *zhp, void *arg)
@@ -1068,7 +1190,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
if (!sdd->doall && !isfromsnap && !istosnap) {
if (sdd->replicate) {
- char *snapname;
+ const char *snapname;
nvlist_t *snapprops;
/*
* Filter out all intermediate snapshots except origin
@@ -1135,29 +1257,33 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
* If progress reporting is requested, spawn a new thread to
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (sdd->progress) {
+ sigset_t oldmask;
+ {
pa.pa_zhp = zhp;
pa.pa_fd = sdd->outfd;
pa.pa_parsable = sdd->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = sdd->verbosity;
+ pa.pa_size = sdd->size;
+ pa.pa_astitle = sdd->progressastitle;
+ pa.pa_progress = sdd->progress;
if ((err = pthread_create(&tid, NULL,
send_progress_thread, &pa)) != 0) {
zfs_close(zhp);
return (err);
}
+ SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask);
}
err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
fromorigin, sdd->outfd, flags, sdd->debugnv);
- if (sdd->progress &&
- send_progress_thread_exit(zhp->zfs_hdl, tid))
+ if (send_progress_thread_exit(zhp->zfs_hdl, tid, &oldmask))
return (-1);
}
- (void) strcpy(sdd->prevsnap, thissnap);
+ (void) strlcpy(sdd->prevsnap, thissnap, sizeof (sdd->prevsnap));
sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
zfs_close(zhp);
return (err);
@@ -1226,7 +1352,7 @@ dump_filesystem(zfs_handle_t *zhp, send_dump_data_t *sdd)
zhp->zfs_name, sdd->tosnap);
}
}
- rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, sdd,
+ rv = zfs_iter_snapshots_sorted_v2(zhp, 0, dump_snapshot, sdd,
min_txg, max_txg);
} else {
char snapname[MAXPATHLEN] = { 0 };
@@ -1241,7 +1367,7 @@ dump_filesystem(zfs_handle_t *zhp, send_dump_data_t *sdd)
if (snap != NULL)
rv = dump_snapshot(snap, sdd);
else
- rv = -1;
+ rv = errno;
}
/* Dump tosnap. */
@@ -1253,7 +1379,7 @@ dump_filesystem(zfs_handle_t *zhp, send_dump_data_t *sdd)
if (snap != NULL)
rv = dump_snapshot(snap, sdd);
else
- rv = -1;
+ rv = errno;
}
}
@@ -1305,7 +1431,7 @@ dump_filesystems(zfs_handle_t *rzhp, send_dump_data_t *sdd)
nvfs = fnvpair_value_nvlist(fspair);
(void) nvlist_lookup_uint64(nvfs, "origin", &origin_guid);
if (origin_guid != 0) {
- char *snapname;
+ const char *snapname;
nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
origin_guid, &snapname);
if (origin_nv != NULL) {
@@ -1324,7 +1450,7 @@ again:
for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
nvlist_t *fslist, *parent_nv;
- char *fsname;
+ const char *fsname;
zfs_handle_t *zhp;
int err;
uint64_t origin_guid = 0;
@@ -1488,15 +1614,16 @@ lzc_flags_from_sendflags(const sendflags_t *flags)
static int
estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
uint64_t resumeobj, uint64_t resumeoff, uint64_t bytes,
- const char *redactbook, char *errbuf)
+ const char *redactbook, char *errbuf, uint64_t *sizep)
{
uint64_t size;
FILE *fout = flags->dryrun ? stdout : stderr;
progress_arg_t pa = { 0 };
int err = 0;
pthread_t ptid;
+ sigset_t oldmask;
- if (flags->progress) {
+ {
pa.pa_zhp = zhp;
pa.pa_fd = fd;
pa.pa_parsable = flags->parsable;
@@ -1506,21 +1633,26 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
err = pthread_create(&ptid, NULL,
send_progress_thread, &pa);
if (err != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno));
return (zfs_error(zhp->zfs_hdl,
EZFS_THREADCREATEFAILED, errbuf));
}
+ SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask);
}
err = lzc_send_space_resume_redacted(zhp->zfs_name, from,
lzc_flags_from_sendflags(flags), resumeobj, resumeoff, bytes,
redactbook, fd, &size);
+ *sizep = size;
- if (flags->progress && send_progress_thread_exit(zhp->zfs_hdl, ptid))
+ if (send_progress_thread_exit(zhp->zfs_hdl, ptid, &oldmask))
return (-1);
+ if (!flags->progress && !flags->parsable)
+ return (err);
+
if (err != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err));
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
errbuf));
}
@@ -1636,7 +1768,7 @@ find_redact_book(libzfs_handle_t *hdl, const char *path,
"dataset to be sent no longer exists"));
} else {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "unknown error: %s"), strerror(error));
+ "unknown error: %s"), zfs_strerror(error));
}
return (zfs_error(hdl, EZFS_BADPROP, errbuf));
}
@@ -1685,8 +1817,8 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
int outfd, nvlist_t *resume_nvl)
{
char errbuf[ERRBUFLEN];
- char *toname;
- char *fromname = NULL;
+ const char *toname;
+ const char *fromname = NULL;
uint64_t resumeobj, resumeoff, toguid, fromguid, bytes;
zfs_handle_t *zhp;
int error = 0;
@@ -1695,6 +1827,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
uint64_t *redact_snap_guids = NULL;
int num_redact_snaps = 0;
char *redact_book = NULL;
+ uint64_t size = 0;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot resume send"));
@@ -1718,7 +1851,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
(void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid);
if (flags->saved) {
- (void) strcpy(name, toname);
+ (void) strlcpy(name, toname, sizeof (name));
} else {
error = guid_to_name(hdl, toname, toguid, B_FALSE, name);
if (error != 0) {
@@ -1780,7 +1913,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
enum lzc_send_flags lzc_flags = lzc_flags_from_sendflags(flags) |
lzc_flags_from_resume_nvl(resume_nvl);
- if (flags->verbosity != 0) {
+ if (flags->verbosity != 0 || flags->progressastitle) {
/*
* Some of these may have come from the resume token, set them
* here for size estimate purposes.
@@ -1797,22 +1930,26 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
if (lzc_flags & LZC_SEND_FLAG_SAVED)
tmpflags.saved = B_TRUE;
error = estimate_size(zhp, fromname, outfd, &tmpflags,
- resumeobj, resumeoff, bytes, redact_book, errbuf);
+ resumeobj, resumeoff, bytes, redact_book, errbuf, &size);
}
if (!flags->dryrun) {
progress_arg_t pa = { 0 };
pthread_t tid;
+ sigset_t oldmask;
/*
* If progress reporting is requested, spawn a new thread to
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (flags->progress) {
+ {
pa.pa_zhp = zhp;
pa.pa_fd = outfd;
pa.pa_parsable = flags->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = flags->verbosity;
+ pa.pa_size = size;
+ pa.pa_astitle = flags->progressastitle;
+ pa.pa_progress = flags->progress;
error = pthread_create(&tid, NULL,
send_progress_thread, &pa);
@@ -1822,6 +1959,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
zfs_close(zhp);
return (error);
}
+ SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask);
}
error = lzc_send_resume_redacted(zhp->zfs_name, fromname, outfd,
@@ -1829,8 +1967,10 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
if (redact_book != NULL)
free(redact_book);
- if (flags->progress && send_progress_thread_exit(hdl, tid))
+ if (send_progress_thread_exit(hdl, tid, &oldmask)) {
+ zfs_close(zhp);
return (-1);
+ }
char errbuf[ERRBUFLEN];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -1865,7 +2005,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
case ERANGE:
case EFAULT:
case EROFS:
- zfs_error_aux(hdl, "%s", strerror(errno));
+ zfs_error_aux(hdl, "%s", zfs_strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default:
@@ -2099,9 +2239,9 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
fnvlist_add_boolean(hdrnv, "raw");
}
- if ((err = gather_nvlist(zhp->zfs_hdl, tofs,
+ if (gather_nvlist(zhp->zfs_hdl, tofs,
from, tosnap, recursive, raw, doall, replicate, skipmissing,
- verbose, backup, holds, props, &fss, fsavlp)) != 0) {
+ verbose, backup, holds, props, &fss, fsavlp) != 0) {
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
errbuf));
}
@@ -2151,13 +2291,13 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
err = dump_record(&drr, packbuf, buflen, &zc, fd);
free(packbuf);
if (err != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err));
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
errbuf));
}
err = send_conclusion_record(fd, &zc);
if (err != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(err));
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
errbuf));
}
@@ -2265,6 +2405,7 @@ zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sdd.verbosity = flags->verbosity;
sdd.parsable = flags->parsable;
sdd.progress = flags->progress;
+ sdd.progressastitle = flags->progressastitle;
sdd.dryrun = flags->dryrun;
sdd.large_block = flags->largeblock;
sdd.embed_data = flags->embed_data;
@@ -2514,6 +2655,7 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
char *name = zhp->zfs_name;
pthread_t ptid;
progress_arg_t pa = { 0 };
+ uint64_t size = 0;
char errbuf[ERRBUFLEN];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
@@ -2596,9 +2738,9 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
/*
* Perform size estimate if verbose was specified.
*/
- if (flags->verbosity != 0) {
+ if (flags->verbosity != 0 || flags->progressastitle) {
err = estimate_size(zhp, from, fd, flags, 0, 0, 0, redactbook,
- errbuf);
+ errbuf, &size);
if (err != 0)
return (err);
}
@@ -2610,26 +2752,31 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
* If progress reporting is requested, spawn a new thread to poll
* ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
- if (flags->progress) {
+ sigset_t oldmask;
+ {
pa.pa_zhp = zhp;
pa.pa_fd = fd;
pa.pa_parsable = flags->parsable;
pa.pa_estimate = B_FALSE;
pa.pa_verbosity = flags->verbosity;
+ pa.pa_size = size;
+ pa.pa_astitle = flags->progressastitle;
+ pa.pa_progress = flags->progress;
err = pthread_create(&ptid, NULL,
send_progress_thread, &pa);
if (err != 0) {
- zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
+ zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(errno));
return (zfs_error(zhp->zfs_hdl,
EZFS_THREADCREATEFAILED, errbuf));
}
+ SEND_PROGRESS_THREAD_PARENT_BLOCK(&oldmask);
}
err = lzc_send_redacted(name, from, fd,
lzc_flags_from_sendflags(flags), redactbook);
- if (flags->progress && send_progress_thread_exit(hdl, ptid))
+ if (send_progress_thread_exit(hdl, ptid, &oldmask))
return (-1);
if (err == 0 && (flags->props || flags->holds || flags->backup)) {
@@ -2677,13 +2824,8 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
case EPIPE:
case ERANGE:
case EROFS:
- zfs_error_aux(hdl, "%s", strerror(errno));
+ zfs_error_aux(hdl, "%s", zfs_strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
- case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "large blocks detected but large_blocks feature "
- "is inactive; raw send unsupported"));
- return (zfs_error(hdl, EZFS_NOTSUP, errbuf));
default:
return (zfs_standard_error(hdl, errno, errbuf));
@@ -2867,7 +3009,7 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
goto out;
if (tryname) {
- (void) strcpy(newname, tryname);
+ (void) strlcpy(newname, tryname, ZFS_MAX_DATASET_NAME_LEN);
if (flags->verbose) {
(void) printf("attempting rename %s to %s\n",
name, newname);
@@ -3082,9 +3224,9 @@ guid_to_name_cb(zfs_handle_t *zhp, void *arg)
return (EEXIST);
}
- err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
+ err = zfs_iter_children_v2(zhp, 0, guid_to_name_cb, gtnd);
if (err != EEXIST && gtnd->bookmark_ok)
- err = zfs_iter_bookmarks(zhp, guid_to_name_cb, gtnd);
+ err = zfs_iter_bookmarks_v2(zhp, 0, guid_to_name_cb, gtnd);
zfs_close(zhp);
return (err);
}
@@ -3138,9 +3280,11 @@ guid_to_name_redact_snaps(libzfs_handle_t *hdl, const char *parent,
continue;
int err = guid_to_name_cb(zfs_handle_dup(zhp), &gtnd);
if (err != EEXIST)
- err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
+ err = zfs_iter_children_v2(zhp, 0, guid_to_name_cb,
+ &gtnd);
if (err != EEXIST && bookmark_ok)
- err = zfs_iter_bookmarks(zhp, guid_to_name_cb, &gtnd);
+ err = zfs_iter_bookmarks_v2(zhp, 0, guid_to_name_cb,
+ &gtnd);
zfs_close(zhp);
if (err == EEXIST)
return (0);
@@ -3173,7 +3317,7 @@ created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
uint64_t guid1, uint64_t guid2)
{
nvlist_t *nvfs;
- char *fsname = NULL, *snapname = NULL;
+ const char *fsname = NULL, *snapname = NULL;
char buf[ZFS_MAX_DATASET_NAME_LEN];
int rv;
zfs_handle_t *guid1hdl, *guid2hdl;
@@ -3239,7 +3383,7 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs,
nvpair_t *snapel = NULL;
boolean_t is_encroot, is_clone, stream_encroot;
char *cp;
- char *stream_keylocation = NULL;
+ const char *stream_keylocation = NULL;
char keylocation[MAXNAMELEN];
char fsname[ZFS_MAX_DATASET_NAME_LEN];
@@ -3359,12 +3503,12 @@ recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
nvlist_t *local_nv, *deleted = NULL;
avl_tree_t *local_avl;
nvpair_t *fselem, *nextfselem;
- char *fromsnap;
+ const char *fromsnap;
char newname[ZFS_MAX_DATASET_NAME_LEN];
char guidname[32];
int error;
boolean_t needagain, progress, recursive;
- char *s1, *s2;
+ const char *s1, *s2;
fromsnap = fnvlist_lookup_string(stream_nv, "fromsnap");
@@ -3396,7 +3540,7 @@ again:
uint64_t originguid = 0;
uint64_t stream_originguid = 0;
uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
- char *fsname, *stream_fsname;
+ const char *fsname, *stream_fsname;
nextfselem = nvlist_next_nvpair(local_nv, fselem);
@@ -3431,7 +3575,7 @@ again:
case 1: {
/* promote it! */
nvlist_t *origin_nvfs;
- char *origin_fsname;
+ const char *origin_fsname;
origin_nvfs = fsavl_find(local_avl, originguid,
NULL);
@@ -3462,7 +3606,7 @@ again:
for (snapelem = nvlist_next_nvpair(snaps, NULL);
snapelem; snapelem = nextsnapelem) {
uint64_t thisguid;
- char *stream_snapname;
+ const char *stream_snapname;
nvlist_t *found, *props;
nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
@@ -3608,7 +3752,7 @@ again:
* new fs.
*/
if (parent != NULL) {
- char *pname;
+ const char *pname;
pname = fnvlist_lookup_string(parent, "name");
(void) snprintf(tryname, sizeof (tryname),
@@ -3659,8 +3803,8 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
{
nvlist_t *stream_nv = NULL;
avl_tree_t *stream_avl = NULL;
- char *fromsnap = NULL;
- char *sendsnap = NULL;
+ const char *fromsnap = NULL;
+ const char *sendsnap = NULL;
char *cp;
char tofs[ZFS_MAX_DATASET_NAME_LEN];
char sendfs[ZFS_MAX_DATASET_NAME_LEN];
@@ -4106,6 +4250,15 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
goto error;
}
+ /*
+ * For plain replicated send, we can ignore encryption
+ * properties other than first stream
+ */
+ if ((zfs_prop_encryption_key_param(prop) || prop ==
+ ZFS_PROP_ENCRYPTION) && !newfs && recursive && !raw) {
+ continue;
+ }
+
/* incremental streams can only exclude encryption properties */
if ((zfs_prop_encryption_key_param(prop) ||
prop == ZFS_PROP_ENCRYPTION) && !newfs &&
@@ -4140,7 +4293,7 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
*/
if (nvlist_exists(origprops, newname)) {
nvlist_t *attrs;
- char *source = NULL;
+ const char *source = NULL;
attrs = fnvlist_lookup_nvlist(origprops,
newname);
@@ -4207,7 +4360,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
if (cp != NULL)
*cp = '\0';
- if (!raw && zfs_crypto_create(hdl, namebuf, voprops, NULL,
+ if (!raw && !(!newfs && recursive) &&
+ zfs_crypto_create(hdl, namebuf, voprops, NULL,
B_FALSE, wkeydata_out, wkeylen_out) != 0) {
fnvlist_free(voprops);
ret = zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
@@ -4263,7 +4417,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zprop_errflags_t prop_errflags;
nvlist_t *prop_errors = NULL;
boolean_t recursive;
- char *snapname = NULL;
+ const char *snapname = NULL;
char destsnap[MAXPATHLEN * 2];
char origin[MAXNAMELEN] = {0};
char name[MAXPATHLEN];
@@ -4294,7 +4448,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
boolean_t holds = flags->holds && !flags->skipholds;
if (stream_avl != NULL) {
- char *keylocation = NULL;
+ const char *keylocation = NULL;
nvlist_t *lookup = NULL;
nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
&snapname);
@@ -4318,7 +4472,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
err = nvlist_lookup_string(rcvprops,
zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation);
if (err == 0) {
- strcpy(tmp_keylocation, keylocation);
+ strlcpy(tmp_keylocation, keylocation, MAXNAMELEN);
(void) nvlist_remove_all(rcvprops,
zfs_prop_to_name(ZFS_PROP_KEYLOCATION));
}
@@ -4374,7 +4528,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
* prepend a path separator.
*/
int len = strlen(drrb->drr_toname);
- cp = malloc(len + 2);
+ cp = umem_alloc(len + 2, UMEM_NOFAIL);
cp[0] = '/';
(void) strcpy(&cp[1], drrb->drr_toname);
chopprefix = cp;
@@ -4427,7 +4581,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
(void) strlcpy(destsnap, tosnap, sizeof (destsnap));
(void) strlcat(destsnap, chopprefix, sizeof (destsnap));
- free(cp);
+ if (cp != NULL)
+ umem_free(cp, strlen(cp) + 1);
if (!zfs_name_valid(destsnap, ZFS_TYPE_SNAPSHOT)) {
err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
goto out;
@@ -4485,18 +4640,20 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot receive new filesystem stream"));
- (void) strcpy(name, destsnap);
+ (void) strlcpy(name, destsnap, sizeof (name));
cp = strrchr(name, '/');
if (cp)
*cp = '\0';
if (cp &&
!zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
char suffix[ZFS_MAX_DATASET_NAME_LEN];
- (void) strcpy(suffix, strrchr(destsnap, '/'));
+ (void) strlcpy(suffix, strrchr(destsnap, '/'),
+ sizeof (suffix));
if (guid_to_name(hdl, name, parent_snapguid,
B_FALSE, destsnap) == 0) {
*strchr(destsnap, '@') = '\0';
- (void) strcat(destsnap, suffix);
+ (void) strlcat(destsnap, suffix,
+ sizeof (destsnap));
}
}
} else {
@@ -4514,7 +4671,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
"cannot receive incremental stream"));
}
- (void) strcpy(name, destsnap);
+ (void) strlcpy(name, destsnap, sizeof (name));
*strchr(name, '@') = '\0';
/*
@@ -4526,24 +4683,51 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
strlen(sendfs)) != '\0' && *chopprefix != '@')) &&
!zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
char snap[ZFS_MAX_DATASET_NAME_LEN];
- (void) strcpy(snap, strchr(destsnap, '@'));
+ (void) strlcpy(snap, strchr(destsnap, '@'),
+ sizeof (snap));
if (guid_to_name(hdl, name, drrb->drr_fromguid,
B_FALSE, destsnap) == 0) {
*strchr(destsnap, '@') = '\0';
- (void) strcat(destsnap, snap);
+ (void) strlcat(destsnap, snap,
+ sizeof (destsnap));
}
}
}
- (void) strcpy(name, destsnap);
+ (void) strlcpy(name, destsnap, sizeof (name));
*strchr(name, '@') = '\0';
redacted = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
DMU_BACKUP_FEATURE_REDACTED;
- if (zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
+ if (flags->heal) {
+ if (flags->isprefix || flags->istail || flags->force ||
+ flags->canmountoff || flags->resumable || flags->nomount ||
+ flags->skipholds) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "corrective recv can not be used when combined with"
+ " this flag"));
+ err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
+ goto out;
+ }
+ uint64_t guid =
+ get_snap_guid(hdl, name, strchr(destsnap, '@') + 1);
+ if (guid == 0) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "corrective recv must specify an existing snapshot"
+ " to heal"));
+ err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
+ goto out;
+ } else if (guid != drrb->drr_toguid) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "local snapshot doesn't match the snapshot"
+ " in the provided stream"));
+ err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf);
+ goto out;
+ }
+ } else if (zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
zfs_cmd_t zc = {"\0"};
- zfs_handle_t *zhp;
+ zfs_handle_t *zhp = NULL;
boolean_t encrypted;
(void) strcpy(zc.zc_name, name);
@@ -4600,6 +4784,33 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
goto out;
}
+ /*
+ * When receiving full/newfs on existing dataset, then it
+ * should be done with "-F" flag. Its enforced for initial
+ * receive in previous checks in this function.
+ * Similarly, on resuming full/newfs recv on existing dataset,
+ * it should be done with "-F" flag.
+ *
+ * When dataset doesn't exist, then full/newfs recv is done on
+ * newly created dataset and it's marked INCONSISTENT. But
+ * When receiving on existing dataset, recv is first done on
+ * %recv and its marked INCONSISTENT. Existing dataset is not
+ * marked INCONSISTENT.
+ * Resume of full/newfs receive with dataset not INCONSISTENT
+ * indicates that its resuming newfs on existing dataset. So,
+ * enforce "-F" flag in this case.
+ */
+ if (stream_resumingnewfs &&
+ !zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
+ !flags->force) {
+ zfs_close(zhp);
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Resuming recv on existing destination '%s'\n"
+ "must specify -F to overwrite it"), name);
+ err = zfs_error(hdl, EZFS_RESUME_EXISTS, errbuf);
+ goto out;
+ }
+
if (stream_wantsnewfs &&
zhp->zfs_dmustats.dds_origin[0]) {
zfs_close(zhp);
@@ -4737,8 +4948,9 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}
if (flags->verbose) {
- (void) printf("%s %s stream of %s into %s\n",
+ (void) printf("%s %s%s stream of %s into %s\n",
flags->dryrun ? "would receive" : "receiving",
+ flags->heal ? " corrective" : "",
drrb->drr_fromguid ? "incremental" : "full",
drrb->drr_toname, destsnap);
(void) fflush(stdout);
@@ -4808,10 +5020,17 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
goto out;
}
- err = ioctl_err = lzc_receive_with_cmdprops(destsnap, rcvprops,
- oxprops, wkeydata, wkeylen, origin, flags->force, flags->resumable,
- raw, infd, drr_noswap, -1, &read_bytes, &errflags,
- NULL, &prop_errors);
+ if (flags->heal) {
+ err = ioctl_err = lzc_receive_with_heal(destsnap, rcvprops,
+ oxprops, wkeydata, wkeylen, origin, flags->force,
+ flags->heal, flags->resumable, raw, infd, drr_noswap, -1,
+ &read_bytes, &errflags, NULL, &prop_errors);
+ } else {
+ err = ioctl_err = lzc_receive_with_cmdprops(destsnap, rcvprops,
+ oxprops, wkeydata, wkeylen, origin, flags->force,
+ flags->resumable, raw, infd, drr_noswap, -1, &read_bytes,
+ &errflags, NULL, &prop_errors);
+ }
ioctl_errno = ioctl_err;
prop_errflags = errflags;
@@ -4857,7 +5076,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
if (err == 0 && snapprops_nvlist) {
zfs_cmd_t zc = {"\0"};
- (void) strcpy(zc.zc_name, destsnap);
+ (void) strlcpy(zc.zc_name, destsnap, sizeof (zc.zc_name));
zc.zc_cookie = B_TRUE; /* received */
zcmd_write_src_nvlist(hdl, &zc, snapprops_nvlist);
(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
@@ -4933,7 +5152,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
(void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
break;
case EACCES:
- if (raw && stream_wantsnewfs) {
+ if (flags->heal) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "key must be loaded to do a non-raw "
+ "corrective recv on an encrypted "
+ "dataset."));
+ } else if (raw && stream_wantsnewfs) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"failed to create encryption key"));
} else if (raw && !stream_wantsnewfs) {
@@ -4960,21 +5184,27 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*cp = '@';
break;
case EINVAL:
- if (flags->resumable) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "kernel modules must be upgraded to "
- "receive this stream."));
- } else if (embedded && !raw) {
+ if (embedded && !raw) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"incompatible embedded data stream "
"feature with encrypted receive."));
+ } else if (flags->resumable) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "kernel modules must be upgraded to "
+ "receive this stream."));
}
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ECKSUM:
case ZFS_ERR_STREAM_TRUNCATED:
- recv_ecksum_set_aux(hdl, destsnap, flags->resumable,
- ioctl_err == ECKSUM);
+ if (flags->heal)
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "corrective receive was not able to "
+ "reconstruct the data needed for "
+ "healing."));
+ else
+ recv_ecksum_set_aux(hdl, destsnap,
+ flags->resumable, ioctl_err == ECKSUM);
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH:
@@ -4984,10 +5214,22 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ENOTSUP:
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "pool must be upgraded to receive this stream."));
+ if (flags->heal)
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "stream is not compatible with the "
+ "data in the pool."));
+ else
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "pool must be upgraded to receive this "
+ "stream."));
(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
break;
+ case ZFS_ERR_CRYPTO_NOTSUP:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "stream uses crypto parameters not compatible with "
+ "this pool"));
+ (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
+ break;
case EDQUOT:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"destination %s space quota exceeded."), name);
@@ -5015,6 +5257,27 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
"be updated."));
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
+ case ZFS_ERR_RESUME_EXISTS:
+ cp = strchr(destsnap, '@');
+ if (newfs) {
+ /* it's the containing fs that exists */
+ *cp = '\0';
+ }
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Resuming recv on existing dataset without force"));
+ (void) zfs_error_fmt(hdl, EZFS_RESUME_EXISTS,
+ dgettext(TEXT_DOMAIN, "cannot resume recv %s"),
+ destsnap);
+ *cp = '@';
+ break;
+ case E2BIG:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "zfs receive required kernel memory allocation "
+ "larger than the system can support. Please file "
+ "an issue at the OpenZFS issue tracker:\n"
+ "https://github.com/openzfs/zfs/issues/new"));
+ (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
+ break;
case EBUSY:
if (hastoken) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -5303,7 +5566,7 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
char *top_zfs = NULL;
int err;
struct stat sb;
- char *originsnap = NULL;
+ const char *originsnap = NULL;
/*
* The only way fstat can fail is if we do not have a valid file
diff --git a/lib/libzfs/libzfs_status.c b/lib/libzfs/libzfs_status.c
index 9f450806d78c..a2259eee91ca 100644
--- a/lib/libzfs/libzfs_status.c
+++ b/lib/libzfs/libzfs_status.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -168,7 +168,8 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
* later.
*/
if (ignore_replacing == B_TRUE) {
- char *type = fnvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE);
+ const char *type = fnvlist_lookup_string(vdev,
+ ZPOOL_CONFIG_TYPE);
if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
return (B_FALSE);
}
@@ -222,7 +223,6 @@ check_status(nvlist_t *config, boolean_t isimport,
{
pool_scan_stat_t *ps = NULL;
uint_t vsc, psc;
- uint64_t nerr;
uint64_t suspended;
uint64_t hostid = 0;
uint64_t errata = 0;
@@ -392,6 +392,7 @@ check_status(nvlist_t *config, boolean_t isimport,
* Persistent data errors.
*/
if (!isimport) {
+ uint64_t nerr;
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
&nerr) == 0 && nerr != 0)
return (ZPOOL_STATUS_CORRUPT_DATA);
diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c
index 4adaab86ecec..73ae0950ccb6 100644
--- a/lib/libzfs/libzfs_util.c
+++ b/lib/libzfs/libzfs_util.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2020 Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright (c) 2017 Datto Inc.
* Copyright (c) 2020 The FreeBSD Foundation
@@ -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"));
@@ -241,10 +243,20 @@ libzfs_error_description(libzfs_handle_t *hdl)
"into a new one"));
case EZFS_SCRUB_PAUSED:
return (dgettext(TEXT_DOMAIN, "scrub is paused; "
- "use 'zpool scrub' to resume"));
+ "use 'zpool scrub' to resume scrub"));
+ case EZFS_SCRUB_PAUSED_TO_CANCEL:
+ return (dgettext(TEXT_DOMAIN, "scrub is paused; "
+ "use 'zpool scrub' to resume or 'zpool scrub -s' to "
+ "cancel scrub"));
case EZFS_SCRUBBING:
return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
- "use 'zpool scrub -s' to cancel current scrub"));
+ "use 'zpool scrub -s' to cancel scrub"));
+ case EZFS_ERRORSCRUBBING:
+ return (dgettext(TEXT_DOMAIN, "currently error scrubbing; "
+ "use 'zpool scrub -s' to cancel error scrub"));
+ case EZFS_ERRORSCRUB_PAUSED:
+ return (dgettext(TEXT_DOMAIN, "error scrub is paused; "
+ "use 'zpool scrub -e' to resume error scrub"));
case EZFS_NO_SCRUB:
return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
case EZFS_DIFF:
@@ -302,6 +314,14 @@ libzfs_error_description(libzfs_handle_t *hdl)
case EZFS_NOT_USER_NAMESPACE:
return (dgettext(TEXT_DOMAIN, "the provided file "
"was not a user namespace file"));
+ case EZFS_RESUME_EXISTS:
+ return (dgettext(TEXT_DOMAIN, "Resuming recv on existing "
+ "dataset without force"));
+ case EZFS_RAIDZ_EXPAND_IN_PROGRESS:
+ return (dgettext(TEXT_DOMAIN, "raidz expansion in progress"));
+ case EZFS_ASHIFT_MISMATCH:
+ return (dgettext(TEXT_DOMAIN, "adding devices with "
+ "different physical sector sizes is not allowed"));
case EZFS_UNKNOWN:
return (dgettext(TEXT_DOMAIN, "unknown error"));
default:
@@ -396,6 +416,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);
@@ -492,7 +516,7 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
zfs_verror(hdl, EZFS_NOT_USER_NAMESPACE, fmt, ap);
break;
default:
- zfs_error_aux(hdl, "%s", strerror(error));
+ zfs_error_aux(hdl, "%s", zfs_strerror(error));
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
break;
}
@@ -679,7 +703,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,
@@ -744,8 +768,14 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
case ZFS_ERR_IOC_ARG_BADTYPE:
zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap);
break;
+ case ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS:
+ zfs_verror(hdl, EZFS_RAIDZ_EXPAND_IN_PROGRESS, fmt, ap);
+ break;
+ case ZFS_ERR_ASHIFT_MISMATCH:
+ zfs_verror(hdl, EZFS_ASHIFT_MISMATCH, fmt, ap);
+ break;
default:
- zfs_error_aux(hdl, "%s", strerror(error));
+ zfs_error_aux(hdl, "%s", zfs_strerror(error));
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
}
@@ -1240,7 +1270,7 @@ zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
static void
zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
{
- zprop_list_t *pl = cbp->cb_proplist;
+ zprop_list_t *pl;
int i;
char *title;
size_t len;
@@ -1586,13 +1616,13 @@ zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
*/
int
zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
- zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
+ zfs_type_t type, nvlist_t *ret, const char **svalp, uint64_t *ivalp,
const char *errbuf)
{
data_type_t datatype = nvpair_type(elem);
zprop_type_t proptype;
const char *propname;
- char *value;
+ const char *value;
boolean_t isnone = B_FALSE;
boolean_t isauto = B_FALSE;
int err = 0;
@@ -1673,6 +1703,20 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
}
/*
+ * Special handling for "checksum_*=none". In this case it's not
+ * 0 but UINT64_MAX.
+ */
+ if ((type & ZFS_TYPE_VDEV) && isnone &&
+ (prop == VDEV_PROP_CHECKSUM_N ||
+ prop == VDEV_PROP_CHECKSUM_T ||
+ prop == VDEV_PROP_IO_N ||
+ prop == VDEV_PROP_IO_T ||
+ prop == VDEV_PROP_SLOW_IO_N ||
+ prop == VDEV_PROP_SLOW_IO_T)) {
+ *ivalp = UINT64_MAX;
+ }
+
+ /*
* Special handling for setting 'refreservation' to 'auto'. Use
* UINT64_MAX to tell the caller to use zfs_fix_auto_resv().
* 'auto' is only allowed on volumes.
@@ -1753,6 +1797,7 @@ addlist(libzfs_handle_t *hdl, const char *propname, zprop_list_t **listp,
* a user-defined property.
*/
if (prop == ZPROP_USERPROP && ((type == ZFS_TYPE_POOL &&
+ !zfs_prop_user(propname) &&
!zpool_prop_feature(propname) &&
!zpool_prop_unsupported(propname)) ||
((type == ZFS_TYPE_DATASET) && !zfs_prop_user(propname) &&
@@ -1931,7 +1976,7 @@ zfs_version_print(void)
char *kver = zfs_version_kernel();
if (kver == NULL) {
fprintf(stderr, "zfs_version_kernel() failed: %s\n",
- strerror(errno));
+ zfs_strerror(errno));
return (-1);
}
@@ -1944,7 +1989,7 @@ zfs_version_print(void)
* Return 1 if the user requested ANSI color output, and our terminal supports
* it. Return 0 for no color.
*/
-static int
+int
use_color(void)
{
static int use_color = -1;
@@ -1990,10 +2035,11 @@ use_color(void)
}
/*
- * color_start() and color_end() are used for when you want to colorize a block
- * of text. For example:
+ * The functions color_start() and color_end() are used for when you want
+ * to colorize a block of text.
*
- * color_start(ANSI_RED_FG)
+ * For example:
+ * color_start(ANSI_RED)
* printf("hello");
* printf("world");
* color_end();
@@ -2001,18 +2047,25 @@ use_color(void)
void
color_start(const char *color)
{
- if (use_color())
+ if (color && use_color()) {
fputs(color, stdout);
+ fflush(stdout);
+ }
}
void
color_end(void)
{
- if (use_color())
+ if (use_color()) {
fputs(ANSI_RESET, stdout);
+ fflush(stdout);
+ }
+
}
-/* printf() with a color. If color is NULL, then do a normal printf. */
+/*
+ * printf() with a color. If color is NULL, then do a normal printf.
+ */
int
printf_color(const char *color, const char *format, ...)
{
@@ -2031,3 +2084,196 @@ printf_color(const char *color, const char *format, ...)
return (rc);
}
+
+/* PATH + 5 env vars + a NULL entry = 7 */
+#define ZPOOL_VDEV_SCRIPT_ENV_COUNT 7
+
+/*
+ * There's a few places where ZFS will call external scripts (like the script
+ * in zpool.d/ and `zfs_prepare_disk`). These scripts are called with a
+ * reduced $PATH, and some vdev specific environment vars set. This function
+ * will allocate an populate the environment variable array that is passed to
+ * these scripts. The user must free the arrays with zpool_vdev_free_env() when
+ * they are done.
+ *
+ * The following env vars will be set (but value could be blank):
+ *
+ * POOL_NAME
+ * VDEV_PATH
+ * VDEV_UPATH
+ * VDEV_ENC_SYSFS_PATH
+ *
+ * In addition, you can set an optional environment variable named 'opt_key'
+ * to 'opt_val' if you want.
+ *
+ * Returns allocated env[] array on success, NULL otherwise.
+ */
+char **
+zpool_vdev_script_alloc_env(const char *pool_name,
+ const char *vdev_path, const char *vdev_upath,
+ const char *vdev_enc_sysfs_path, const char *opt_key, const char *opt_val)
+{
+ char **env = NULL;
+ int rc;
+
+ env = calloc(ZPOOL_VDEV_SCRIPT_ENV_COUNT, sizeof (*env));
+ if (!env)
+ return (NULL);
+
+ env[0] = strdup("PATH=/bin:/sbin:/usr/bin:/usr/sbin");
+ if (!env[0])
+ goto error;
+
+ /* Setup our custom environment variables */
+ rc = asprintf(&env[1], "POOL_NAME=%s", pool_name ? pool_name : "");
+ if (rc == -1) {
+ env[1] = NULL;
+ goto error;
+ }
+
+ rc = asprintf(&env[2], "VDEV_PATH=%s", vdev_path ? vdev_path : "");
+ if (rc == -1) {
+ env[2] = NULL;
+ goto error;
+ }
+
+ rc = asprintf(&env[3], "VDEV_UPATH=%s", vdev_upath ? vdev_upath : "");
+ if (rc == -1) {
+ env[3] = NULL;
+ goto error;
+ }
+
+ rc = asprintf(&env[4], "VDEV_ENC_SYSFS_PATH=%s",
+ vdev_enc_sysfs_path ? vdev_enc_sysfs_path : "");
+ if (rc == -1) {
+ env[4] = NULL;
+ goto error;
+ }
+
+ if (opt_key != NULL) {
+ rc = asprintf(&env[5], "%s=%s", opt_key,
+ opt_val ? opt_val : "");
+ if (rc == -1) {
+ env[5] = NULL;
+ goto error;
+ }
+ }
+
+ return (env);
+
+error:
+ for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++)
+ free(env[i]);
+
+ free(env);
+
+ return (NULL);
+}
+
+/*
+ * Free the env[] array that was allocated by zpool_vdev_script_alloc_env().
+ */
+void
+zpool_vdev_script_free_env(char **env)
+{
+ for (int i = 0; i < ZPOOL_VDEV_SCRIPT_ENV_COUNT; i++)
+ free(env[i]);
+
+ free(env);
+}
+
+/*
+ * Prepare a disk by (optionally) running a program before labeling the disk.
+ * This can be useful for installing disk firmware or doing some pre-flight
+ * checks on the disk before it becomes part of the pool. The program run is
+ * located at ZFSEXECDIR/zfs_prepare_disk
+ * (E.x: /usr/local/libexec/zfs/zfs_prepare_disk).
+ *
+ * Return 0 on success, non-zero on failure.
+ */
+int
+zpool_prepare_disk(zpool_handle_t *zhp, nvlist_t *vdev_nv,
+ const char *prepare_str, char **lines[], int *lines_cnt)
+{
+ const char *script_path = ZFSEXECDIR "/zfs_prepare_disk";
+ const char *pool_name;
+ int rc = 0;
+
+ /* Path to script and a NULL entry */
+ char *argv[2] = {(char *)script_path};
+ char **env = NULL;
+ const char *path = NULL, *enc_sysfs_path = NULL;
+ char *upath;
+ *lines_cnt = 0;
+
+ if (access(script_path, X_OK) != 0) {
+ /* No script, nothing to do */
+ return (0);
+ }
+
+ (void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH, &path);
+ (void) nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
+ &enc_sysfs_path);
+
+ upath = zfs_get_underlying_path(path);
+ pool_name = zhp ? zpool_get_name(zhp) : NULL;
+
+ env = zpool_vdev_script_alloc_env(pool_name, path, upath,
+ enc_sysfs_path, "VDEV_PREPARE", prepare_str);
+
+ free(upath);
+
+ if (env == NULL) {
+ return (ENOMEM);
+ }
+
+ rc = libzfs_run_process_get_stdout(script_path, argv, env, lines,
+ lines_cnt);
+
+ zpool_vdev_script_free_env(env);
+
+ return (rc);
+}
+
+/*
+ * Optionally run a script and then label a disk. The script can be used to
+ * prepare a disk for inclusion into the pool. For example, it might update
+ * the disk's firmware or check its health.
+ *
+ * The 'name' provided is the short name, stripped of any leading
+ * /dev path, and is passed to zpool_label_disk. vdev_nv is the nvlist for
+ * the vdev. prepare_str is a string that gets passed as the VDEV_PREPARE
+ * env variable to the script.
+ *
+ * The following env vars are passed to the script:
+ *
+ * POOL_NAME: The pool name (blank during zpool create)
+ * VDEV_PREPARE: Reason why the disk is being prepared for inclusion:
+ * "create", "add", "replace", or "autoreplace"
+ * VDEV_PATH: Path to the disk
+ * VDEV_UPATH: One of the 'underlying paths' to the disk. This is
+ * useful for DM devices.
+ * VDEV_ENC_SYSFS_PATH: Path to the disk's enclosure sysfs path, if available.
+ *
+ * Note, some of these values can be blank.
+ *
+ * Return 0 on success, non-zero otherwise.
+ */
+int
+zpool_prepare_and_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp,
+ const char *name, nvlist_t *vdev_nv, const char *prepare_str,
+ char **lines[], int *lines_cnt)
+{
+ int rc;
+ char vdev_path[MAXPATHLEN];
+ (void) snprintf(vdev_path, sizeof (vdev_path), "%s/%s", DISK_ROOT,
+ name);
+
+ /* zhp will be NULL when creating a pool */
+ rc = zpool_prepare_disk(zhp, vdev_nv, prepare_str, lines, lines_cnt);
+ if (rc != 0)
+ return (rc);
+
+ rc = zpool_label_disk(hdl, zhp, name);
+ return (rc);
+}
diff --git a/lib/libzfs/os/freebsd/libzfs_compat.c b/lib/libzfs/os/freebsd/libzfs_compat.c
index b08b7e2c439b..2abf7755b518 100644
--- a/lib/libzfs/os/freebsd/libzfs_compat.c
+++ b/lib/libzfs/os/freebsd/libzfs_compat.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -38,7 +38,8 @@
#define ZFS_KMOD "openzfs"
#endif
-
+#ifndef HAVE_EXECVPE
+/* FreeBSD prior to 15 lacks execvpe */
static int
execvPe(const char *name, const char *path, char * const *argv,
char * const *envp)
@@ -192,6 +193,7 @@ execvpe(const char *name, char * const argv[], char * const envp[])
return (execvPe(name, path, argv, envp));
}
+#endif /* !HAVE_EXECVPE */
static __thread char errbuf[ERRBUFLEN];
@@ -204,11 +206,13 @@ libzfs_error_init(int error)
if (modfind("zfs") < 0) {
size_t len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN,
"Failed to load %s module: "), ZFS_KMOD);
+ if (len >= msglen)
+ len = msglen - 1;
msg += len;
msglen -= len;
}
- (void) snprintf(msg, msglen, "%s", strerror(error));
+ (void) snprintf(msg, msglen, "%s", zfs_strerror(error));
return (errbuf);
}
diff --git a/lib/libzfs/os/freebsd/libzfs_zmount.c b/lib/libzfs/os/freebsd/libzfs_zmount.c
index 6a26cae1e090..3c50daf471b7 100644
--- a/lib/libzfs/os/freebsd/libzfs_zmount.c
+++ b/lib/libzfs/os/freebsd/libzfs_zmount.c
@@ -28,9 +28,6 @@
* This file implements Solaris compatible zmount() function.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/uio.h>
@@ -73,33 +70,30 @@ build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
*iovlen = ++i;
}
-static int
-do_mount_(const char *spec, const char *dir, int mflag,
- char *dataptr, int datalen, const char *optptr, int optlen)
+int
+do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, int flags)
{
struct iovec *iov;
char *optstr, *p, *tofree;
int iovlen, rv;
+ const char *spec = zfs_get_name(zhp);
assert(spec != NULL);
- assert(dir != NULL);
- assert(dataptr == NULL), (void) dataptr;
- assert(datalen == 0), (void) datalen;
- assert(optptr != NULL);
- assert(optlen > 0), (void) optlen;
+ assert(mntpt != NULL);
+ assert(opts != NULL);
- tofree = optstr = strdup(optptr);
+ tofree = optstr = strdup(opts);
assert(optstr != NULL);
iov = NULL;
iovlen = 0;
if (strstr(optstr, MNTOPT_REMOUNT) != NULL)
build_iovec(&iov, &iovlen, "update", NULL, 0);
- if (mflag & MS_RDONLY)
+ if (flags & MS_RDONLY)
build_iovec(&iov, &iovlen, "ro", NULL, 0);
build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, MNTTYPE_ZFS),
(size_t)-1);
- build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, dir),
+ build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, mntpt),
(size_t)-1);
build_iovec(&iov, &iovlen, "from", __DECONST(char *, spec), (size_t)-1);
while ((p = strsep(&optstr, ",/")) != NULL)
@@ -109,14 +103,7 @@ do_mount_(const char *spec, const char *dir, int mflag,
if (rv < 0)
return (errno);
return (rv);
-}
-
-int
-do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, int flags)
-{
- return (do_mount_(zfs_get_name(zhp), mntpt, flags, NULL, 0,
- opts, sizeof (mntpt)));
}
int
diff --git a/lib/libzfs/os/linux/libzfs_mount_os.c b/lib/libzfs/os/linux/libzfs_mount_os.c
index 299d3a66e67e..f0bf3dcc6c6b 100644
--- a/lib/libzfs/os/linux/libzfs_mount_os.c
+++ b/lib/libzfs/os/linux/libzfs_mount_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -84,6 +84,13 @@ static const option_map_t option_map[] = {
{ MNTOPT_ACL, MS_POSIXACL, ZS_COMMENT },
{ MNTOPT_NOACL, MS_COMMENT, ZS_COMMENT },
{ MNTOPT_POSIXACL, MS_POSIXACL, ZS_COMMENT },
+ /*
+ * Case sensitive options are just listed here to silently
+ * ignore the error if passed with zfs mount command.
+ */
+ { MNTOPT_CASESENSITIVE, MS_COMMENT, ZS_COMMENT },
+ { MNTOPT_CASEINSENSITIVE, MS_COMMENT, ZS_COMMENT },
+ { MNTOPT_CASEMIXED, MS_COMMENT, ZS_COMMENT },
#ifdef MS_NOATIME
{ MNTOPT_NOATIME, MS_NOATIME, ZS_COMMENT },
{ MNTOPT_ATIME, MS_COMMENT, ZS_COMMENT },
diff --git a/lib/libzfs/os/linux/libzfs_pool_os.c b/lib/libzfs/os/linux/libzfs_pool_os.c
index b135e0146962..86eef3255bc2 100644
--- a/lib/libzfs/os/linux/libzfs_pool_os.c
+++ b/lib/libzfs/os/linux/libzfs_pool_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -96,7 +96,7 @@ zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg)
static int
read_efi_label(nvlist_t *config, diskaddr_t *sb)
{
- char *path;
+ const char *path;
int fd;
char diskname[MAXPATHLEN];
int err = -1;
@@ -273,6 +273,16 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
vtoc->efi_parts[0].p_start = start_block;
vtoc->efi_parts[0].p_size = slice_size;
+ if (vtoc->efi_parts[0].p_size * vtoc->efi_lbasize < SPA_MINDEVSIZE) {
+ (void) close(fd);
+ efi_free(vtoc);
+
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot "
+ "label '%s': partition would be less than the minimum "
+ "device size (64M)"), path);
+ return (zfs_error(hdl, EZFS_LABELFAILED, errbuf));
+ }
+
/*
* Why we use V_USR: V_BACKUP confuses users, and is considered
* disposable by some EFI utilities (since EFI doesn't have a backup
diff --git a/lib/libzfs/os/linux/libzfs_util_os.c b/lib/libzfs/os/linux/libzfs_util_os.c
index 712f8094755c..99faae66833e 100644
--- a/lib/libzfs/os/linux/libzfs_util_os.c
+++ b/lib/libzfs/os/linux/libzfs_util_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -145,8 +145,8 @@ libzfs_load_module(void)
if (pfds[0].revents & POLLIN) {
verify(read(ino, ev, evsz) >
sizeof (struct inotify_event));
- if (strcmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)])
- == 0) {
+ if (strncmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)],
+ ev->len) == 0) {
ret = 0;
break;
}
diff --git a/lib/libzfs_core/libzfs_core.abi b/lib/libzfs_core/libzfs_core.abi
index fae98469a04f..5b95c8f779db 100644
--- a/lib/libzfs_core/libzfs_core.abi
+++ b/lib/libzfs_core/libzfs_core.abi
@@ -1,7 +1,6 @@
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libzfs_core.so.3'>
<elf-needed>
<dependency name='libnvpair.so.3'/>
- <dependency name='libpthread.so.0'/>
<dependency name='libc.so.6'/>
<dependency name='ld-linux-x86-64.so.2'/>
</elf-needed>
@@ -181,12 +180,14 @@
<elf-symbol name='lzc_receive_resumable' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_receive_with_cmdprops' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_receive_with_header' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='lzc_receive_with_heal' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_redact' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_release' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_rename' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_reopen' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_rollback' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_rollback_to' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='lzc_scrub' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzc_send_resume' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -208,41 +209,50 @@
<elf-symbol name='membar_enter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_exit' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='membar_producer' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='membar_sync' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='mkdirp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='print_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
- <abi-instr address-size='64' path='assert.c' language='LANG_C99'>
- <type-decl name='variadic parameter type' id='2c1145c5'/>
- <function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
- <parameter type-id='c19b74c3' name='val'/>
+ <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
+ <class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
+ <function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
- <parameter type-id='80f4b756' name='file'/>
- <parameter type-id='80f4b756' name='func'/>
- <parameter type-id='95e97e5e' name='line'/>
- <parameter type-id='80f4b756' name='format'/>
- <parameter is-variadic='yes'/>
+ <function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b7f2d5e6'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
+ <parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='atomic.c' language='LANG_C99'>
- <type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
- <type-decl name='short int' size-in-bits='16' id='a2185560'/>
- <type-decl name='signed char' size-in-bits='8' id='28577a57'/>
- <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <abi-instr address-size='64' path='lib/libspl/atomic.c' language='LANG_C99'>
<typedef-decl name='ulong_t' type-id='7359adad' id='ee1f298e'/>
<typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
- <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
<typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
<typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
- <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
<typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
- <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
- <typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
<qualified-type-def type-id='149c6638' volatile='yes' id='5120c5f7'/>
<pointer-type-def type-id='5120c5f7' size-in-bits='64' id='93977ae7'/>
<qualified-type-def type-id='8f92235e' volatile='yes' id='430e0681'/>
@@ -305,11 +315,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_add_long' mangled-name='atomic_add_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_add_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_sub_ptr' mangled-name='atomic_sub_ptr' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_ptr'>
<parameter type-id='fe09dd29' name='target'/>
<parameter type-id='79a0948f' name='bits'/>
@@ -330,11 +335,6 @@
<parameter type-id='3ff5601b' name='bits'/>
<return type-id='48b5725f'/>
</function-decl>
- <function-decl name='atomic_sub_long' mangled-name='atomic_sub_long' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_sub_long'>
- <parameter type-id='64698d33' name='target'/>
- <parameter type-id='bd54fe1a' name='bits'/>
- <return type-id='48b5725f'/>
- </function-decl>
<function-decl name='atomic_or_8' mangled-name='atomic_or_8' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='atomic_or_8'>
<parameter type-id='aa323ea4' name='target'/>
<parameter type-id='b96825af' name='bits'/>
@@ -572,13 +572,18 @@
<return type-id='48b5725f'/>
</function-decl>
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
+ <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
</abi-instr>
- <abi-instr address-size='64' path='getexecname.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
</function-decl>
+ <function-decl name='getexecname_impl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
</abi-instr>
- <abi-instr address-size='64' path='list.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/list.c' language='LANG_C99'>
<typedef-decl name='list_node_t' type-id='b0b5e45e' id='b21843b2'/>
<typedef-decl name='list_t' type-id='e824dae9' id='0899125f'/>
<class-decl name='list_node' size-in-bits='128' is-struct='yes' visibility='default' id='b0b5e45e'>
@@ -600,7 +605,6 @@
<var-decl name='list_head' type-id='b0b5e45e' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
<pointer-type-def type-id='b0b5e45e' size-in-bits='64' id='b03eadb4'/>
<pointer-type-def type-id='b21843b2' size-in-bits='64' id='ccc38265'/>
<pointer-type-def type-id='0899125f' size-in-bits='64' id='352ec160'/>
@@ -690,33 +694,82 @@
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='mkdirp.c' language='LANG_C99'>
- <typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
+ <abi-instr address-size='64' path='lib/libspl/mkdirp.c' language='LANG_C99'>
<typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
+ <typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/>
+ <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/>
+ <qualified-type-def type-id='928221d2' const='yes' id='effb3702'/>
+ <pointer-type-def type-id='effb3702' size-in-bits='64' id='f077d3f8'/>
+ <qualified-type-def type-id='f077d3f8' restrict='yes' id='598aab80'/>
+ <pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/>
+ <qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/>
+ <function-decl name='calloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='access' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='f1358bc3'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='598aab80'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='e1c52942'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'>
<parameter type-id='80f4b756' name='d'/>
<parameter type-id='d50d396c' name='mode'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/gethostid.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/getexecname.c' language='LANG_C99'>
+ <function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
+ <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
+ <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
+ <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
+ <function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='3a47d82b'/>
+ </function-decl>
<function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
<return type-id='7359adad'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/getmntany.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
- <subrange length='3' type-id='7359adad' id='56f209d2'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
- <subrange length='1' type-id='7359adad' id='52f813b4'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
- <subrange length='20' type-id='7359adad' id='fdca39cf'/>
- </array-type-def>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
@@ -751,6 +804,26 @@
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
</data-member>
</class-decl>
+ <class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='mnt_type' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ </class-decl>
<class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
@@ -798,128 +871,46 @@
<var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
</data-member>
</class-decl>
- <typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
- <typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
- <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
<typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
- <typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
- <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
- <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
- <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
- <typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
- <typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
- <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
- <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
- <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='576'>
- <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='640'>
- <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='704'>
- <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='768'>
- <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='832'>
- <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='896'>
- <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='928'>
- <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='960'>
- <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1024'>
- <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1040'>
- <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1048'>
- <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1088'>
- <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1152'>
- <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1216'>
- <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1280'>
- <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1344'>
- <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1408'>
- <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1472'>
- <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1536'>
- <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='1568'>
- <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
- </data-member>
- </class-decl>
- <class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
- </data-member>
- </class-decl>
- <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
- <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
- <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
- <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
- <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
- <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
+ <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
+ <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
- <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
- <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
- <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
+ <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='3cad23cd'/>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='b6b61d2f'/>
+ </function-decl>
+ <function-decl name='feof' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f1cadedf'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'>
<parameter type-id='822cd80b' name='fp'/>
<parameter type-id='9d424d31' name='mgetp'/>
@@ -938,18 +929,28 @@
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/zone.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/os/linux/zone.c' language='LANG_C99'>
<typedef-decl name='zoneid_t' type-id='3502e3ff' id='4da03624'/>
+ <function-decl name='strtoul' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='7359adad'/>
+ </function-decl>
<function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'>
<return type-id='4da03624'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='page.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/page.c' language='LANG_C99'>
+ <function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='bd54fe1a'/>
+ </function-decl>
<function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
<return type-id='b59d7dce'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='strlcat.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libspl/strlcat.c' language='LANG_C99'>
<function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'>
<parameter type-id='26a90f95' name='dst'/>
<parameter type-id='80f4b756' name='src'/>
@@ -957,26 +958,123 @@
<return type-id='b59d7dce'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='strlcpy.c' language='LANG_C99'>
- <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
- <parameter type-id='26a90f95' name='dst'/>
- <parameter type-id='80f4b756' name='src'/>
- <parameter type-id='b59d7dce' name='len'/>
+ <abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
+ <typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
+ <class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='tm_min' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='tm_year' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='tm_zone' type-id='80f4b756' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
+ <qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/>
+ <pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/>
+ <qualified-type-def type-id='9f201474' restrict='yes' id='d6e2847c'/>
+ <qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/>
+ <pointer-type-def type-id='e824a34f' size-in-bits='64' id='d6ad37ff'/>
+ <qualified-type-def type-id='d6ad37ff' restrict='yes' id='f8c6051d'/>
+ <pointer-type-def type-id='c9d12d66' size-in-bits='64' id='b2eb2c3f'/>
+ <pointer-type-def type-id='dddf6ca2' size-in-bits='64' id='d915a820'/>
+ <qualified-type-def type-id='d915a820' restrict='yes' id='f099ad08'/>
+ <function-decl name='nl_langinfo' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='03b79a94'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='time' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b2eb2c3f'/>
+ <return type-id='c9d12d66'/>
+ </function-decl>
+ <function-decl name='strftime' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='266fe297'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='9d26089a'/>
+ <parameter type-id='f8c6051d'/>
<return type-id='b59d7dce'/>
</function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='timestamp.c' language='LANG_C99'>
+ <function-decl name='localtime_r' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='d6e2847c'/>
+ <parameter type-id='f099ad08'/>
+ <return type-id='d915a820'/>
+ </function-decl>
+ <function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='print_timestamp' mangled-name='print_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='print_timestamp'>
<parameter type-id='3502e3ff' name='timestamp_fmt'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
- <abi-instr address-size='64' path='libzfs_core.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libzfs_core/libzfs_core.c' language='LANG_C99'>
+ <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
+ <subrange length='3' type-id='7359adad' id='56f209d2'/>
+ </array-type-def>
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
+ <subrange length='1' type-id='7359adad' id='52f813b4'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='160' id='664ac0b7'>
+ <subrange length='20' type-id='7359adad' id='fdca39cf'/>
+ </array-type-def>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='2048' id='d1617432'>
<subrange length='256' type-id='7359adad' id='36e5b9fa'/>
</array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
+ <subrange length='4096' type-id='7359adad' id='bc1b5ddc'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='320' id='36c46961'>
+ <subrange length='40' type-id='7359adad' id='8f80b239'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'>
+ <subrange length='56' type-id='7359adad' id='f8137894'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='65536' id='163f6aa5'>
+ <subrange length='8192' type-id='7359adad' id='c88f397d'/>
+ </array-type-def>
+ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='infinite' id='e84913bd'>
+ <subrange length='infinite' type-id='7359adad' id='031f2035'/>
+ </array-type-def>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
+ <type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
+ <type-decl name='short int' size-in-bits='16' id='a2185560'/>
+ <type-decl name='signed char' size-in-bits='8' id='28577a57'/>
+ <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='128' id='c1c22e6c'>
+ <subrange length='2' type-id='7359adad' id='52efc4ef'/>
+ </array-type-def>
<array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='2176' id='8c2bcad1'>
<subrange length='34' type-id='7359adad' id='6a6a7e00'/>
</array-type-def>
@@ -1005,6 +1103,8 @@
<type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
+ <type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <type-decl name='variadic parameter type' id='2c1145c5'/>
<type-decl name='void' id='48b5725f'/>
<enum-decl name='lzc_dataset_type' id='bc9887f1'>
<underlying-type type-id='9cac1fee'/>
@@ -1107,6 +1207,33 @@
<enumerator name='DMU_OTN_ZAP_ENC_METADATA' value='228'/>
</enum-decl>
<typedef-decl name='dmu_object_type_t' type-id='04b3b0b9' id='5c9d8906'/>
+ <class-decl name='dmu_objset_stats' size-in-bits='2304' is-struct='yes' visibility='default' id='098f0221'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='dds_num_clones' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='dds_creation_txg' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='dds_guid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='dds_type' type-id='230f1e16' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='dds_is_snapshot' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='232'>
+ <var-decl name='dds_inconsistent' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='240'>
+ <var-decl name='dds_redacted' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='248'>
+ <var-decl name='dds_origin' type-id='d1617432' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='dmu_objset_stats_t' type-id='098f0221' id='b2c14f17'/>
<enum-decl name='dmu_objset_type' id='6b1b19f9'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='DMU_OST_NONE' value='0'/>
@@ -1123,7 +1250,8 @@
<enumerator name='POOL_INITIALIZE_START' value='0'/>
<enumerator name='POOL_INITIALIZE_CANCEL' value='1'/>
<enumerator name='POOL_INITIALIZE_SUSPEND' value='2'/>
- <enumerator name='POOL_INITIALIZE_FUNCS' value='3'/>
+ <enumerator name='POOL_INITIALIZE_UNINIT' value='3'/>
+ <enumerator name='POOL_INITIALIZE_FUNCS' value='4'/>
</enum-decl>
<typedef-decl name='pool_initialize_func_t' type-id='5c246ad4' id='7063e1ab'/>
<enum-decl name='pool_trim_func' id='54ed608a'>
@@ -1134,6 +1262,112 @@
<enumerator name='POOL_TRIM_FUNCS' value='3'/>
</enum-decl>
<typedef-decl name='pool_trim_func_t' type-id='54ed608a' id='b1146b8d'/>
+ <enum-decl name='zfs_ioc' id='12033f13'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='ZFS_IOC_FIRST' value='23040'/>
+ <enumerator name='ZFS_IOC' value='23040'/>
+ <enumerator name='ZFS_IOC_POOL_CREATE' value='23040'/>
+ <enumerator name='ZFS_IOC_POOL_DESTROY' value='23041'/>
+ <enumerator name='ZFS_IOC_POOL_IMPORT' value='23042'/>
+ <enumerator name='ZFS_IOC_POOL_EXPORT' value='23043'/>
+ <enumerator name='ZFS_IOC_POOL_CONFIGS' value='23044'/>
+ <enumerator name='ZFS_IOC_POOL_STATS' value='23045'/>
+ <enumerator name='ZFS_IOC_POOL_TRYIMPORT' value='23046'/>
+ <enumerator name='ZFS_IOC_POOL_SCAN' value='23047'/>
+ <enumerator name='ZFS_IOC_POOL_FREEZE' value='23048'/>
+ <enumerator name='ZFS_IOC_POOL_UPGRADE' value='23049'/>
+ <enumerator name='ZFS_IOC_POOL_GET_HISTORY' value='23050'/>
+ <enumerator name='ZFS_IOC_VDEV_ADD' value='23051'/>
+ <enumerator name='ZFS_IOC_VDEV_REMOVE' value='23052'/>
+ <enumerator name='ZFS_IOC_VDEV_SET_STATE' value='23053'/>
+ <enumerator name='ZFS_IOC_VDEV_ATTACH' value='23054'/>
+ <enumerator name='ZFS_IOC_VDEV_DETACH' value='23055'/>
+ <enumerator name='ZFS_IOC_VDEV_SETPATH' value='23056'/>
+ <enumerator name='ZFS_IOC_VDEV_SETFRU' value='23057'/>
+ <enumerator name='ZFS_IOC_OBJSET_STATS' value='23058'/>
+ <enumerator name='ZFS_IOC_OBJSET_ZPLPROPS' value='23059'/>
+ <enumerator name='ZFS_IOC_DATASET_LIST_NEXT' value='23060'/>
+ <enumerator name='ZFS_IOC_SNAPSHOT_LIST_NEXT' value='23061'/>
+ <enumerator name='ZFS_IOC_SET_PROP' value='23062'/>
+ <enumerator name='ZFS_IOC_CREATE' value='23063'/>
+ <enumerator name='ZFS_IOC_DESTROY' value='23064'/>
+ <enumerator name='ZFS_IOC_ROLLBACK' value='23065'/>
+ <enumerator name='ZFS_IOC_RENAME' value='23066'/>
+ <enumerator name='ZFS_IOC_RECV' value='23067'/>
+ <enumerator name='ZFS_IOC_SEND' value='23068'/>
+ <enumerator name='ZFS_IOC_INJECT_FAULT' value='23069'/>
+ <enumerator name='ZFS_IOC_CLEAR_FAULT' value='23070'/>
+ <enumerator name='ZFS_IOC_INJECT_LIST_NEXT' value='23071'/>
+ <enumerator name='ZFS_IOC_ERROR_LOG' value='23072'/>
+ <enumerator name='ZFS_IOC_CLEAR' value='23073'/>
+ <enumerator name='ZFS_IOC_PROMOTE' value='23074'/>
+ <enumerator name='ZFS_IOC_SNAPSHOT' value='23075'/>
+ <enumerator name='ZFS_IOC_DSOBJ_TO_DSNAME' value='23076'/>
+ <enumerator name='ZFS_IOC_OBJ_TO_PATH' value='23077'/>
+ <enumerator name='ZFS_IOC_POOL_SET_PROPS' value='23078'/>
+ <enumerator name='ZFS_IOC_POOL_GET_PROPS' value='23079'/>
+ <enumerator name='ZFS_IOC_SET_FSACL' value='23080'/>
+ <enumerator name='ZFS_IOC_GET_FSACL' value='23081'/>
+ <enumerator name='ZFS_IOC_SHARE' value='23082'/>
+ <enumerator name='ZFS_IOC_INHERIT_PROP' value='23083'/>
+ <enumerator name='ZFS_IOC_SMB_ACL' value='23084'/>
+ <enumerator name='ZFS_IOC_USERSPACE_ONE' value='23085'/>
+ <enumerator name='ZFS_IOC_USERSPACE_MANY' value='23086'/>
+ <enumerator name='ZFS_IOC_USERSPACE_UPGRADE' value='23087'/>
+ <enumerator name='ZFS_IOC_HOLD' value='23088'/>
+ <enumerator name='ZFS_IOC_RELEASE' value='23089'/>
+ <enumerator name='ZFS_IOC_GET_HOLDS' value='23090'/>
+ <enumerator name='ZFS_IOC_OBJSET_RECVD_PROPS' value='23091'/>
+ <enumerator name='ZFS_IOC_VDEV_SPLIT' value='23092'/>
+ <enumerator name='ZFS_IOC_NEXT_OBJ' value='23093'/>
+ <enumerator name='ZFS_IOC_DIFF' value='23094'/>
+ <enumerator name='ZFS_IOC_TMP_SNAPSHOT' value='23095'/>
+ <enumerator name='ZFS_IOC_OBJ_TO_STATS' value='23096'/>
+ <enumerator name='ZFS_IOC_SPACE_WRITTEN' value='23097'/>
+ <enumerator name='ZFS_IOC_SPACE_SNAPS' value='23098'/>
+ <enumerator name='ZFS_IOC_DESTROY_SNAPS' value='23099'/>
+ <enumerator name='ZFS_IOC_POOL_REGUID' value='23100'/>
+ <enumerator name='ZFS_IOC_POOL_REOPEN' value='23101'/>
+ <enumerator name='ZFS_IOC_SEND_PROGRESS' value='23102'/>
+ <enumerator name='ZFS_IOC_LOG_HISTORY' value='23103'/>
+ <enumerator name='ZFS_IOC_SEND_NEW' value='23104'/>
+ <enumerator name='ZFS_IOC_SEND_SPACE' value='23105'/>
+ <enumerator name='ZFS_IOC_CLONE' value='23106'/>
+ <enumerator name='ZFS_IOC_BOOKMARK' value='23107'/>
+ <enumerator name='ZFS_IOC_GET_BOOKMARKS' value='23108'/>
+ <enumerator name='ZFS_IOC_DESTROY_BOOKMARKS' value='23109'/>
+ <enumerator name='ZFS_IOC_RECV_NEW' value='23110'/>
+ <enumerator name='ZFS_IOC_POOL_SYNC' value='23111'/>
+ <enumerator name='ZFS_IOC_CHANNEL_PROGRAM' value='23112'/>
+ <enumerator name='ZFS_IOC_LOAD_KEY' value='23113'/>
+ <enumerator name='ZFS_IOC_UNLOAD_KEY' value='23114'/>
+ <enumerator name='ZFS_IOC_CHANGE_KEY' value='23115'/>
+ <enumerator name='ZFS_IOC_REMAP' value='23116'/>
+ <enumerator name='ZFS_IOC_POOL_CHECKPOINT' value='23117'/>
+ <enumerator name='ZFS_IOC_POOL_DISCARD_CHECKPOINT' value='23118'/>
+ <enumerator name='ZFS_IOC_POOL_INITIALIZE' value='23119'/>
+ <enumerator name='ZFS_IOC_POOL_TRIM' value='23120'/>
+ <enumerator name='ZFS_IOC_REDACT' value='23121'/>
+ <enumerator name='ZFS_IOC_GET_BOOKMARK_PROPS' value='23122'/>
+ <enumerator name='ZFS_IOC_WAIT' value='23123'/>
+ <enumerator name='ZFS_IOC_WAIT_FS' value='23124'/>
+ <enumerator name='ZFS_IOC_VDEV_GET_PROPS' value='23125'/>
+ <enumerator name='ZFS_IOC_VDEV_SET_PROPS' value='23126'/>
+ <enumerator name='ZFS_IOC_POOL_SCRUB' value='23127'/>
+ <enumerator name='ZFS_IOC_PLATFORM' value='23168'/>
+ <enumerator name='ZFS_IOC_EVENTS_NEXT' value='23169'/>
+ <enumerator name='ZFS_IOC_EVENTS_CLEAR' value='23170'/>
+ <enumerator name='ZFS_IOC_EVENTS_SEEK' value='23171'/>
+ <enumerator name='ZFS_IOC_NEXTBOOT' value='23172'/>
+ <enumerator name='ZFS_IOC_JAIL' value='23173'/>
+ <enumerator name='ZFS_IOC_USERNS_ATTACH' value='23173'/>
+ <enumerator name='ZFS_IOC_UNJAIL' value='23174'/>
+ <enumerator name='ZFS_IOC_USERNS_DETACH' value='23174'/>
+ <enumerator name='ZFS_IOC_SET_BOOTENV' value='23175'/>
+ <enumerator name='ZFS_IOC_GET_BOOTENV' value='23176'/>
+ <enumerator name='ZFS_IOC_LAST' value='23177'/>
+ </enum-decl>
+ <typedef-decl name='zfs_ioc_t' type-id='12033f13' id='5b35941c'/>
<enum-decl name='zpool_wait_activity_t' naming-typedef-id='73446457' id='849338e3'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZPOOL_WAIT_CKPT_DISCARD' value='0'/>
@@ -1144,7 +1378,8 @@
<enumerator name='ZPOOL_WAIT_RESILVER' value='5'/>
<enumerator name='ZPOOL_WAIT_SCRUB' value='6'/>
<enumerator name='ZPOOL_WAIT_TRIM' value='7'/>
- <enumerator name='ZPOOL_WAIT_NUM_ACTIVITIES' value='8'/>
+ <enumerator name='ZPOOL_WAIT_RAIDZ_EXPAND' value='8'/>
+ <enumerator name='ZPOOL_WAIT_NUM_ACTIVITIES' value='9'/>
</enum-decl>
<typedef-decl name='zpool_wait_activity_t' type-id='849338e3' id='73446457'/>
<enum-decl name='zfs_wait_activity_t' naming-typedef-id='3024501a' id='527d5dc6'>
@@ -1153,6 +1388,60 @@
<enumerator name='ZFS_WAIT_NUM_ACTIVITIES' value='1'/>
</enum-decl>
<typedef-decl name='zfs_wait_activity_t' type-id='527d5dc6' id='3024501a'/>
+ <enum-decl name='data_type_t' naming-typedef-id='8d0687d2' id='aeeae136'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='DATA_TYPE_DONTCARE' value='-1'/>
+ <enumerator name='DATA_TYPE_UNKNOWN' value='0'/>
+ <enumerator name='DATA_TYPE_BOOLEAN' value='1'/>
+ <enumerator name='DATA_TYPE_BYTE' value='2'/>
+ <enumerator name='DATA_TYPE_INT16' value='3'/>
+ <enumerator name='DATA_TYPE_UINT16' value='4'/>
+ <enumerator name='DATA_TYPE_INT32' value='5'/>
+ <enumerator name='DATA_TYPE_UINT32' value='6'/>
+ <enumerator name='DATA_TYPE_INT64' value='7'/>
+ <enumerator name='DATA_TYPE_UINT64' value='8'/>
+ <enumerator name='DATA_TYPE_STRING' value='9'/>
+ <enumerator name='DATA_TYPE_BYTE_ARRAY' value='10'/>
+ <enumerator name='DATA_TYPE_INT16_ARRAY' value='11'/>
+ <enumerator name='DATA_TYPE_UINT16_ARRAY' value='12'/>
+ <enumerator name='DATA_TYPE_INT32_ARRAY' value='13'/>
+ <enumerator name='DATA_TYPE_UINT32_ARRAY' value='14'/>
+ <enumerator name='DATA_TYPE_INT64_ARRAY' value='15'/>
+ <enumerator name='DATA_TYPE_UINT64_ARRAY' value='16'/>
+ <enumerator name='DATA_TYPE_STRING_ARRAY' value='17'/>
+ <enumerator name='DATA_TYPE_HRTIME' value='18'/>
+ <enumerator name='DATA_TYPE_NVLIST' value='19'/>
+ <enumerator name='DATA_TYPE_NVLIST_ARRAY' value='20'/>
+ <enumerator name='DATA_TYPE_BOOLEAN_VALUE' value='21'/>
+ <enumerator name='DATA_TYPE_INT8' value='22'/>
+ <enumerator name='DATA_TYPE_UINT8' value='23'/>
+ <enumerator name='DATA_TYPE_BOOLEAN_ARRAY' value='24'/>
+ <enumerator name='DATA_TYPE_INT8_ARRAY' value='25'/>
+ <enumerator name='DATA_TYPE_UINT8_ARRAY' value='26'/>
+ <enumerator name='DATA_TYPE_DOUBLE' value='27'/>
+ </enum-decl>
+ <typedef-decl name='data_type_t' type-id='aeeae136' id='8d0687d2'/>
+ <class-decl name='nvpair' size-in-bits='128' is-struct='yes' visibility='default' id='1c34e459'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='nvp_size' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='nvp_name_sz' type-id='23bd8cb5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='48'>
+ <var-decl name='nvp_reserve' type-id='23bd8cb5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='nvp_value_elem' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='nvp_type' type-id='8d0687d2' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='nvp_name' type-id='e84913bd' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='nvpair_t' type-id='1c34e459' id='57928edf'/>
<class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='nvl_version' type-id='3ff5601b' visibility='default'/>
@@ -1545,41 +1834,720 @@
</data-member>
</class-decl>
<typedef-decl name='dmu_replay_record_t' type-id='781a52d7' id='8b8fc893'/>
+ <class-decl name='zinject_record' size-in-bits='2816' is-struct='yes' visibility='default' id='3216f820'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zi_objset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='zi_object' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='zi_start' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='zi_end' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='zi_guid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='zi_level' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='352'>
+ <var-decl name='zi_error' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='zi_type' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='zi_freq' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='480'>
+ <var-decl name='zi_failfast' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='zi_func' type-id='d1617432' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2560'>
+ <var-decl name='zi_iotype' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2592'>
+ <var-decl name='zi_duration' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2624'>
+ <var-decl name='zi_timer' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2688'>
+ <var-decl name='zi_nlanes' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2752'>
+ <var-decl name='zi_cmd' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='2784'>
+ <var-decl name='zi_dvas' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zinject_record_t' type-id='3216f820' id='a4301ca6'/>
+ <class-decl name='zfs_share' size-in-bits='256' is-struct='yes' visibility='default' id='feb6f2da'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='z_exportdata' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='z_sharedata' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='z_sharetype' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='z_sharemax' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zfs_share_t' type-id='feb6f2da' id='ee5cec36'/>
+ <class-decl name='zfs_cmd' size-in-bits='109952' is-struct='yes' visibility='default' id='3522cd69'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zc_name' type-id='d16c6df4' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32768'>
+ <var-decl name='zc_nvlist_src' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32832'>
+ <var-decl name='zc_nvlist_src_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32896'>
+ <var-decl name='zc_nvlist_dst' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32960'>
+ <var-decl name='zc_nvlist_dst_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33024'>
+ <var-decl name='zc_nvlist_dst_filled' type-id='c19b74c3' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33056'>
+ <var-decl name='zc_pad2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33088'>
+ <var-decl name='zc_history' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='33152'>
+ <var-decl name='zc_value' type-id='163f6aa5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='98688'>
+ <var-decl name='zc_string' type-id='d1617432' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100736'>
+ <var-decl name='zc_guid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100800'>
+ <var-decl name='zc_nvlist_conf' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100864'>
+ <var-decl name='zc_nvlist_conf_size' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100928'>
+ <var-decl name='zc_cookie' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='100992'>
+ <var-decl name='zc_objset_type' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101056'>
+ <var-decl name='zc_perm_action' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101120'>
+ <var-decl name='zc_history_len' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101184'>
+ <var-decl name='zc_history_offset' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101248'>
+ <var-decl name='zc_obj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101312'>
+ <var-decl name='zc_iflags' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101376'>
+ <var-decl name='zc_share' type-id='ee5cec36' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='101632'>
+ <var-decl name='zc_objset_stats' type-id='b2c14f17' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='103936'>
+ <var-decl name='zc_begin_record' type-id='09fcdc01' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='106368'>
+ <var-decl name='zc_inject_record' type-id='a4301ca6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109184'>
+ <var-decl name='zc_defer_destroy' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109216'>
+ <var-decl name='zc_flags' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109248'>
+ <var-decl name='zc_action_handle' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109312'>
+ <var-decl name='zc_cleanup_fd' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109344'>
+ <var-decl name='zc_simple' type-id='b96825af' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109352'>
+ <var-decl name='zc_pad' type-id='d3490169' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109376'>
+ <var-decl name='zc_sendobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109440'>
+ <var-decl name='zc_fromobj' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109504'>
+ <var-decl name='zc_createtxg' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109568'>
+ <var-decl name='zc_stat' type-id='0371a9c7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='109888'>
+ <var-decl name='zc_zoneid' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='zfs_stat' size-in-bits='320' is-struct='yes' visibility='default' id='6417f0b9'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='zs_gen' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='zs_mode' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='zs_links' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='zs_ctime' type-id='c1c22e6c' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='zfs_stat_t' type-id='6417f0b9' id='0371a9c7'/>
<enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='B_FALSE' value='0'/>
<enumerator name='B_TRUE' value='1'/>
</enum-decl>
<typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/>
+ <typedef-decl name='uchar_t' type-id='002ac4a6' id='d8bf0010'/>
<typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
+ <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/>
+ <union-decl name='pthread_attr_t' size-in-bits='448' visibility='default' id='b63afacd'>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='6093ff7c' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_attr_t' type-id='b63afacd' id='7d8569fd'/>
+ <union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'>
+ <data-member access='public'>
+ <var-decl name='__data' type-id='4c734837' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__size' type-id='36c46961' visibility='default'/>
+ </data-member>
+ <data-member access='public'>
+ <var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
+ </data-member>
+ </union-decl>
+ <typedef-decl name='pthread_mutex_t' type-id='70681f9b' id='7a6844eb'/>
+ <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
<typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
<typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/>
<typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/>
<typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/>
+ <class-decl name='__pthread_mutex_s' size-in-bits='320' is-struct='yes' visibility='default' id='4c734837'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__lock' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='__count' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='__owner' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='96'>
+ <var-decl name='__nusers' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='__kind' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='__spins' type-id='a2185560' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='176'>
+ <var-decl name='__elision' type-id='a2185560' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='__list' type-id='518fb49c' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='stat' size-in-bits='1152' is-struct='yes' visibility='default' id='aafc373f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='st_ino' type-id='e43e523d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='st_nlink' type-id='80f0b9df' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='st_mode' type-id='e1c52942' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='224'>
+ <var-decl name='st_uid' type-id='cc5fcceb' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='st_gid' type-id='d94ec6d9' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='288'>
+ <var-decl name='__pad0' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='st_rdev' type-id='35ed8932' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='st_size' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='st_blksize' type-id='d3f10a7f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='st_blocks' type-id='dbc43803' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='st_atim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='st_mtim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='st_ctim' type-id='a9c79a1f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='__glibc_reserved' type-id='083f8d58' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='__pthread_internal_list' size-in-bits='128' is-struct='yes' visibility='default' id='0e01899c'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='__prev' type-id='4d98cd5a' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='__next' type-id='4d98cd5a' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='__pthread_list_t' type-id='0e01899c' id='518fb49c'/>
<typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
+ <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
<typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/>
<typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
<typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/>
+ <typedef-decl name='__dev_t' type-id='7359adad' id='35ed8932'/>
+ <typedef-decl name='__uid_t' type-id='f0981eeb' id='cc5fcceb'/>
+ <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
+ <typedef-decl name='__ino_t' type-id='7359adad' id='e43e523d'/>
+ <typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
+ <typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
+ <typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
+ <typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
+ <typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
+ <typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
+ <typedef-decl name='__blkcnt_t' type-id='bd54fe1a' id='dbc43803'/>
+ <typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
+ <typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
+ <typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
+ <typedef-decl name='_IO_lock_t' type-id='48b5725f' id='bb4788fa'/>
+ <class-decl name='_IO_FILE' size-in-bits='1728' is-struct='yes' visibility='default' id='ec1ed955'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='_IO_read_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='_IO_read_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='192'>
+ <var-decl name='_IO_read_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='256'>
+ <var-decl name='_IO_write_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='320'>
+ <var-decl name='_IO_write_ptr' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='384'>
+ <var-decl name='_IO_write_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='448'>
+ <var-decl name='_IO_buf_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='512'>
+ <var-decl name='_IO_buf_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='576'>
+ <var-decl name='_IO_save_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='_IO_backup_base' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='704'>
+ <var-decl name='_IO_save_end' type-id='26a90f95' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='768'>
+ <var-decl name='_markers' type-id='e4c6fa61' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='832'>
+ <var-decl name='_chain' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='896'>
+ <var-decl name='_fileno' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='928'>
+ <var-decl name='_flags2' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='960'>
+ <var-decl name='_old_offset' type-id='79989e9c' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1024'>
+ <var-decl name='_cur_column' type-id='8efea9e5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1040'>
+ <var-decl name='_vtable_offset' type-id='28577a57' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1048'>
+ <var-decl name='_shortbuf' type-id='89feb1ec' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1088'>
+ <var-decl name='_lock' type-id='cecf4ea7' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1152'>
+ <var-decl name='_offset' type-id='724e4de6' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1216'>
+ <var-decl name='_codecvt' type-id='570f8c59' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1280'>
+ <var-decl name='_wide_data' type-id='c65a1f29' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1344'>
+ <var-decl name='_freeres_list' type-id='dca988a5' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1408'>
+ <var-decl name='_freeres_buf' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1472'>
+ <var-decl name='__pad5' type-id='b59d7dce' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1536'>
+ <var-decl name='_mode' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='1568'>
+ <var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
+ <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
+ <pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
+ <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
+ <pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
+ <pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
+ <pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
+ <pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
+ <pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
+ <pointer-type-def type-id='724e4de6' size-in-bits='64' id='ecf845f9'/>
+ <pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
<pointer-type-def type-id='c19b74c3' size-in-bits='64' id='37e3bd22'/>
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
+ <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
<qualified-type-def type-id='8b8fc893' const='yes' id='9623bc03'/>
<pointer-type-def type-id='9623bc03' size-in-bits='64' id='8341348b'/>
<qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
<pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
+ <qualified-type-def type-id='57928edf' const='yes' id='642ee20f'/>
+ <pointer-type-def type-id='642ee20f' size-in-bits='64' id='dace003f'/>
+ <qualified-type-def type-id='7d8569fd' const='yes' id='e06dee2d'/>
+ <pointer-type-def type-id='e06dee2d' size-in-bits='64' id='540db505'/>
+ <qualified-type-def type-id='540db505' restrict='yes' id='e1815e87'/>
+ <qualified-type-def type-id='d8bf0010' const='yes' id='a9125480'/>
+ <pointer-type-def type-id='a9125480' size-in-bits='64' id='d1db479e'/>
+ <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
+ <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
<pointer-type-def type-id='c70fa2e8' size-in-bits='64' id='2e711a2a'/>
+ <pointer-type-def type-id='95e97e5e' size-in-bits='64' id='7292109c'/>
<pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
<pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
+ <pointer-type-def type-id='57928edf' size-in-bits='64' id='3fa542f0'/>
+ <pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/>
+ <pointer-type-def type-id='4051f5e7' size-in-bits='64' id='e01b5462'/>
+ <qualified-type-def type-id='e01b5462' restrict='yes' id='cc338b26'/>
+ <pointer-type-def type-id='b59d7dce' size-in-bits='64' id='78c01427'/>
+ <pointer-type-def type-id='aafc373f' size-in-bits='64' id='4330df87'/>
<pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
<pointer-type-def type-id='b96825af' size-in-bits='64' id='ae3e8ca6'/>
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
+ <pointer-type-def type-id='cd5d79f4' size-in-bits='64' id='5ad9edb6'/>
+ <qualified-type-def type-id='eaa32e2f' restrict='yes' id='1b7446cd'/>
+ <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
+ <pointer-type-def type-id='3522cd69' size-in-bits='64' id='b65f7fd1'/>
+ <class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
+ <class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
+ <class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <function-decl name='lzc_ioctl_fd' mangled-name='lzc_ioctl_fd' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_ioctl_fd'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7359adad'/>
+ <parameter type-id='b65f7fd1'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nvlist_unpack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_next_nvpair' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='dace003f'/>
+ <return type-id='3fa542f0'/>
+ </function-decl>
+ <function-decl name='nvpair_name' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='dace003f'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_pack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='78c01427'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='fnvlist_pack_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_unpack' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_int32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3ff5601b'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='d1db479e'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9f7200cf'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_boolean_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='fnvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
+ <parameter type-id='26a90f95'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__errno_location' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='7292109c'/>
+ </function-decl>
+ <function-decl name='pthread_create' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='cc338b26'/>
+ <parameter type-id='e1815e87'/>
+ <parameter type-id='5ad9edb6'/>
+ <parameter type-id='1b7446cd'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_join' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4051f5e7'/>
+ <parameter type-id='63e171df'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='18c91f9e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='getenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='close' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='pipe2' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='7292109c'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='splice' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='ecf845f9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='ecf845f9'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='f0981eeb'/>
+ <return type-id='41060289'/>
+ </function-decl>
+ <function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='b59d7dce'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='79a0948f'/>
+ </function-decl>
<function-decl name='libzfs_core_init' mangled-name='libzfs_core_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_core_init'>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libzfs_core_fini' mangled-name='libzfs_core_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_core_fini'>
<return type-id='48b5725f'/>
</function-decl>
+ <function-decl name='lzc_scrub' mangled-name='lzc_scrub' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_scrub'>
+ <parameter type-id='5b35941c' name='ioc'/>
+ <parameter type-id='80f4b756' name='name'/>
+ <parameter type-id='5ce45b60' name='source'/>
+ <parameter type-id='857bb57e' name='resultp'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='lzc_create' mangled-name='lzc_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_create'>
<parameter type-id='80f4b756' name='fsname'/>
<parameter type-id='bc9887f1' name='type'/>
@@ -1776,6 +2744,26 @@
<parameter type-id='857bb57e' name='errors'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='lzc_receive_with_heal' mangled-name='lzc_receive_with_heal' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_receive_with_heal'>
+ <parameter type-id='80f4b756' name='snapname'/>
+ <parameter type-id='5ce45b60' name='props'/>
+ <parameter type-id='5ce45b60' name='cmdprops'/>
+ <parameter type-id='ae3e8ca6' name='wkeydata'/>
+ <parameter type-id='3502e3ff' name='wkeylen'/>
+ <parameter type-id='80f4b756' name='origin'/>
+ <parameter type-id='c19b74c3' name='force'/>
+ <parameter type-id='c19b74c3' name='heal'/>
+ <parameter type-id='c19b74c3' name='resumable'/>
+ <parameter type-id='c19b74c3' name='raw'/>
+ <parameter type-id='95e97e5e' name='input_fd'/>
+ <parameter type-id='8341348b' name='begin_record'/>
+ <parameter type-id='95e97e5e' name='cleanup_fd'/>
+ <parameter type-id='5d6479ae' name='read_bytes'/>
+ <parameter type-id='5d6479ae' name='errflags'/>
+ <parameter type-id='5d6479ae' name='action_handle'/>
+ <parameter type-id='857bb57e' name='errors'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='lzc_rollback' mangled-name='lzc_rollback' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_rollback'>
<parameter type-id='80f4b756' name='fsname'/>
<parameter type-id='26a90f95' name='snapnamebuf'/>
@@ -1926,241 +2914,16 @@
<parameter type-id='eaa32e2f'/>
<return type-id='95e97e5e'/>
</function-type>
+ <function-type size-in-bits='64' id='cd5d79f4'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='eaa32e2f'/>
+ </function-type>
</abi-instr>
- <abi-instr address-size='64' path='os/linux/libzfs_core_ioctl.c' language='LANG_C99'>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
- <subrange length='4096' type-id='7359adad' id='bc1b5ddc'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='65536' id='163f6aa5'>
- <subrange length='8192' type-id='7359adad' id='c88f397d'/>
- </array-type-def>
- <array-type-def dimensions='1' type-id='9c313c2d' size-in-bits='128' id='c1c22e6c'>
- <subrange length='2' type-id='7359adad' id='52efc4ef'/>
- </array-type-def>
- <class-decl name='dmu_objset_stats' size-in-bits='2304' is-struct='yes' visibility='default' id='098f0221'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='dds_num_clones' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='dds_creation_txg' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='dds_guid' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='dds_type' type-id='230f1e16' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='224'>
- <var-decl name='dds_is_snapshot' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='232'>
- <var-decl name='dds_inconsistent' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='240'>
- <var-decl name='dds_redacted' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='248'>
- <var-decl name='dds_origin' type-id='d1617432' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='dmu_objset_stats_t' type-id='098f0221' id='b2c14f17'/>
- <class-decl name='zinject_record' size-in-bits='2816' is-struct='yes' visibility='default' id='3216f820'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zi_objset' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='zi_object' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='zi_start' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='zi_end' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='256'>
- <var-decl name='zi_guid' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='320'>
- <var-decl name='zi_level' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='352'>
- <var-decl name='zi_error' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='384'>
- <var-decl name='zi_type' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='448'>
- <var-decl name='zi_freq' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='480'>
- <var-decl name='zi_failfast' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='512'>
- <var-decl name='zi_func' type-id='d1617432' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2560'>
- <var-decl name='zi_iotype' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2592'>
- <var-decl name='zi_duration' type-id='3ff5601b' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2624'>
- <var-decl name='zi_timer' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2688'>
- <var-decl name='zi_nlanes' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2752'>
- <var-decl name='zi_cmd' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='2784'>
- <var-decl name='zi_dvas' type-id='8f92235e' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zinject_record_t' type-id='3216f820' id='a4301ca6'/>
- <class-decl name='zfs_share' size-in-bits='256' is-struct='yes' visibility='default' id='feb6f2da'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='z_exportdata' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='z_sharedata' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='z_sharetype' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='z_sharemax' type-id='9c313c2d' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zfs_share_t' type-id='feb6f2da' id='ee5cec36'/>
- <class-decl name='zfs_cmd' size-in-bits='109952' is-struct='yes' visibility='default' id='3522cd69'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zc_name' type-id='d16c6df4' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32768'>
- <var-decl name='zc_nvlist_src' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32832'>
- <var-decl name='zc_nvlist_src_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32896'>
- <var-decl name='zc_nvlist_dst' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='32960'>
- <var-decl name='zc_nvlist_dst_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33024'>
- <var-decl name='zc_nvlist_dst_filled' type-id='c19b74c3' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33056'>
- <var-decl name='zc_pad2' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33088'>
- <var-decl name='zc_history' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='33152'>
- <var-decl name='zc_value' type-id='163f6aa5' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='98688'>
- <var-decl name='zc_string' type-id='d1617432' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100736'>
- <var-decl name='zc_guid' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100800'>
- <var-decl name='zc_nvlist_conf' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100864'>
- <var-decl name='zc_nvlist_conf_size' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100928'>
- <var-decl name='zc_cookie' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='100992'>
- <var-decl name='zc_objset_type' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101056'>
- <var-decl name='zc_perm_action' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101120'>
- <var-decl name='zc_history_len' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101184'>
- <var-decl name='zc_history_offset' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101248'>
- <var-decl name='zc_obj' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101312'>
- <var-decl name='zc_iflags' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101376'>
- <var-decl name='zc_share' type-id='ee5cec36' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='101632'>
- <var-decl name='zc_objset_stats' type-id='b2c14f17' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='103936'>
- <var-decl name='zc_begin_record' type-id='09fcdc01' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='106368'>
- <var-decl name='zc_inject_record' type-id='a4301ca6' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109184'>
- <var-decl name='zc_defer_destroy' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109216'>
- <var-decl name='zc_flags' type-id='8f92235e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109248'>
- <var-decl name='zc_action_handle' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109312'>
- <var-decl name='zc_cleanup_fd' type-id='95e97e5e' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109344'>
- <var-decl name='zc_simple' type-id='b96825af' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109352'>
- <var-decl name='zc_pad' type-id='d3490169' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109376'>
- <var-decl name='zc_sendobj' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109440'>
- <var-decl name='zc_fromobj' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109504'>
- <var-decl name='zc_createtxg' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109568'>
- <var-decl name='zc_stat' type-id='0371a9c7' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='109888'>
- <var-decl name='zc_zoneid' type-id='9c313c2d' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zfs_cmd_t' type-id='3522cd69' id='a5559cdd'/>
- <class-decl name='zfs_stat' size-in-bits='320' is-struct='yes' visibility='default' id='6417f0b9'>
- <data-member access='public' layout-offset-in-bits='0'>
- <var-decl name='zs_gen' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='64'>
- <var-decl name='zs_mode' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='128'>
- <var-decl name='zs_links' type-id='9c313c2d' visibility='default'/>
- </data-member>
- <data-member access='public' layout-offset-in-bits='192'>
- <var-decl name='zs_ctime' type-id='c1c22e6c' visibility='default'/>
- </data-member>
- </class-decl>
- <typedef-decl name='zfs_stat_t' type-id='6417f0b9' id='0371a9c7'/>
- <pointer-type-def type-id='a5559cdd' size-in-bits='64' id='e4ec4540'/>
- <function-decl name='lzc_ioctl_fd' mangled-name='lzc_ioctl_fd' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_ioctl_fd'>
- <parameter type-id='95e97e5e' name='fd'/>
- <parameter type-id='7359adad' name='request'/>
- <parameter type-id='e4ec4540' name='zc'/>
+ <abi-instr address-size='64' path='lib/libzfs_core/os/linux/libzfs_core_ioctl.c' language='LANG_C99'>
+ <function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='7359adad'/>
+ <parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c
index 681fd8c7ba5e..01d803e21db0 100644
--- a/lib/libzfs_core/libzfs_core.c
+++ b/lib/libzfs_core/libzfs_core.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,10 +22,10 @@
/*
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
- * Copyright (c) 2017 Datto Inc.
* Copyright 2017 RackTop Systems.
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
* Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
+ * Copyright (c) 2019 Datto Inc.
*/
/*
@@ -235,7 +235,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);
}
@@ -248,6 +248,13 @@ out:
}
int
+lzc_scrub(zfs_ioc_t ioc, const char *name,
+ nvlist_t *source, nvlist_t **resultp)
+{
+ return (lzc_ioctl(ioc, name, source, resultp));
+}
+
+int
lzc_create(const char *fsname, enum lzc_dataset_type type, nvlist_t *props,
uint8_t *wkeydata, uint_t wkeylen)
{
@@ -643,10 +650,12 @@ send_worker(void *arg)
unsigned int bufsiz = max_pipe_buffer(ctx->from);
ssize_t rd;
- while ((rd = splice(ctx->from, NULL, ctx->to, NULL, bufsiz,
- SPLICE_F_MOVE | SPLICE_F_MORE)) > 0)
- ;
-
+ for (;;) {
+ rd = splice(ctx->from, NULL, ctx->to, NULL, bufsiz,
+ SPLICE_F_MOVE | SPLICE_F_MORE);
+ if ((rd == -1 && errno != EINTR) || rd == 0)
+ break;
+ }
int err = (rd == -1) ? errno : 0;
close(ctx->from);
return ((void *)(uintptr_t)err);
@@ -986,7 +995,7 @@ recv_read(int fd, void *buf, int ilen)
static int
recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
uint8_t *wkeydata, uint_t wkeylen, const char *origin, boolean_t force,
- boolean_t resumable, boolean_t raw, int input_fd,
+ boolean_t heal, boolean_t resumable, boolean_t raw, int input_fd,
const dmu_replay_record_t *begin_record, uint64_t *read_bytes,
uint64_t *errflags, nvlist_t **errors)
{
@@ -1041,7 +1050,7 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
/*
* All receives with a payload should use the new interface.
*/
- if (resumable || raw || wkeydata != NULL || payload) {
+ if (resumable || heal || raw || wkeydata != NULL || payload) {
nvlist_t *outnvl = NULL;
nvlist_t *innvl = fnvlist_alloc();
@@ -1081,6 +1090,8 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops,
if (resumable)
fnvlist_add_boolean(innvl, "resumable");
+ if (heal)
+ fnvlist_add_boolean(innvl, "heal");
error = lzc_ioctl(ZFS_IOC_RECV_NEW, fsname, innvl, &outnvl);
@@ -1103,7 +1114,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);
@@ -1112,14 +1124,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;
}
@@ -1154,8 +1166,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);
}
@@ -1180,7 +1194,7 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, boolean_t raw, int fd)
{
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
- B_FALSE, raw, fd, NULL, NULL, NULL, NULL));
+ B_FALSE, B_FALSE, raw, fd, NULL, NULL, NULL, NULL));
}
/*
@@ -1194,7 +1208,7 @@ lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, boolean_t raw, int fd)
{
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
- B_TRUE, raw, fd, NULL, NULL, NULL, NULL));
+ B_FALSE, B_TRUE, raw, fd, NULL, NULL, NULL, NULL));
}
/*
@@ -1217,7 +1231,7 @@ lzc_receive_with_header(const char *snapname, nvlist_t *props,
return (EINVAL);
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
- resumable, raw, fd, begin_record, NULL, NULL, NULL));
+ B_FALSE, resumable, raw, fd, begin_record, NULL, NULL, NULL));
}
/*
@@ -1247,7 +1261,7 @@ lzc_receive_one(const char *snapname, nvlist_t *props,
{
(void) action_handle, (void) cleanup_fd;
return (recv_impl(snapname, props, NULL, NULL, 0, origin, force,
- resumable, raw, input_fd, begin_record,
+ B_FALSE, resumable, raw, input_fd, begin_record,
read_bytes, errflags, errors));
}
@@ -1269,7 +1283,27 @@ lzc_receive_with_cmdprops(const char *snapname, nvlist_t *props,
{
(void) action_handle, (void) cleanup_fd;
return (recv_impl(snapname, props, cmdprops, wkeydata, wkeylen, origin,
- force, resumable, raw, input_fd, begin_record,
+ force, B_FALSE, resumable, raw, input_fd, begin_record,
+ read_bytes, errflags, errors));
+}
+
+/*
+ * Like lzc_receive_with_cmdprops, but allows the caller to pass an additional
+ * 'heal' argument.
+ *
+ * The heal arguments tells us to heal the provided snapshot using the provided
+ * send stream
+ */
+int lzc_receive_with_heal(const char *snapname, nvlist_t *props,
+ nvlist_t *cmdprops, uint8_t *wkeydata, uint_t wkeylen, const char *origin,
+ boolean_t force, boolean_t heal, boolean_t resumable, boolean_t raw,
+ int input_fd, const dmu_replay_record_t *begin_record, int cleanup_fd,
+ uint64_t *read_bytes, uint64_t *errflags, uint64_t *action_handle,
+ nvlist_t **errors)
+{
+ (void) action_handle, (void) cleanup_fd;
+ return (recv_impl(snapname, props, cmdprops, wkeydata, wkeylen, origin,
+ force, heal, resumable, raw, input_fd, begin_record,
read_bytes, errflags, errors));
}
diff --git a/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c b/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c
index b8394886d034..76778b36521c 100644
--- a/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c
+++ b/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -38,7 +38,7 @@ get_zfs_ioctl_version(void)
int ver = ZFS_IOCVER_NONE;
ver_size = sizeof (ver);
- sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0);
+ (void) sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0);
return (ver);
}
@@ -46,8 +46,11 @@ get_zfs_ioctl_version(void)
static int
zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
{
- int newrequest, ret;
+ int ret;
+#ifdef ZFS_LEGACY_SUPPORT
+ int newrequest;
void *zc_c = NULL;
+#endif
unsigned long ncmd;
zfs_iocparm_t zp;
@@ -58,6 +61,7 @@ zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
zp.zfs_cmd_size = sizeof (zfs_cmd_t);
zp.zfs_ioctl_version = ZFS_IOCVER_OZFS;
break;
+#ifdef ZFS_LEGACY_SUPPORT
case ZFS_CMD_COMPAT_LEGACY:
newrequest = zfs_ioctl_ozfs_to_legacy(request);
ncmd = _IOWR('Z', newrequest, zfs_iocparm_t);
@@ -67,6 +71,7 @@ zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
zp.zfs_cmd_size = sizeof (zfs_cmd_legacy_t);
zp.zfs_ioctl_version = ZFS_IOCVER_LEGACY;
break;
+#endif
default:
abort();
return (EINVAL);
@@ -74,14 +79,18 @@ zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
ret = ioctl(fd, ncmd, &zp);
if (ret) {
+#ifdef ZFS_LEGACY_SUPPORT
if (zc_c)
free(zc_c);
+#endif
return (ret);
}
+#ifdef ZFS_LEGACY_SUPPORT
if (zc_c) {
zfs_cmd_legacy_to_ozfs(zc_c, zc);
free(zc_c);
}
+#endif
return (ret);
}
@@ -100,9 +109,11 @@ lzc_ioctl_fd(int fd, unsigned long request, zfs_cmd_t *zc)
zfs_ioctl_version = get_zfs_ioctl_version();
switch (zfs_ioctl_version) {
+#ifdef ZFS_LEGACY_SUPPORT
case ZFS_IOCVER_LEGACY:
cflag = ZFS_CMD_COMPAT_LEGACY;
break;
+#endif
case ZFS_IOCVER_OZFS:
cflag = ZFS_CMD_COMPAT_NONE;
break;
diff --git a/lib/libzfs_core/os/linux/libzfs_core_ioctl.c b/lib/libzfs_core/os/linux/libzfs_core_ioctl.c
index 9b44a4e3be0d..116cddfc45d3 100644
--- a/lib/libzfs_core/os/linux/libzfs_core_ioctl.c
+++ b/lib/libzfs_core/os/linux/libzfs_core_ioctl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzfsbootenv/libzfsbootenv.abi b/lib/libzfsbootenv/libzfsbootenv.abi
index 86ec25cf8470..5903d5dcbe21 100644
--- a/lib/libzfsbootenv/libzfsbootenv.abi
+++ b/lib/libzfsbootenv/libzfsbootenv.abi
@@ -14,69 +14,8 @@
<elf-symbol name='lzbe_remove_pair' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='lzbe_set_boot_device' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
- <abi-instr address-size='64' path='lzbe_device.c' language='LANG_C99'>
+ <abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_device.c' language='LANG_C99'>
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
- <type-decl name='int' size-in-bits='32' id='95e97e5e'/>
- <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
- <type-decl name='void' id='48b5725f'/>
- <enum-decl name='lzbe_flags' id='2b77720b'>
- <underlying-type type-id='9cac1fee'/>
- <enumerator name='lzbe_add' value='0'/>
- <enumerator name='lzbe_replace' value='1'/>
- </enum-decl>
- <typedef-decl name='lzbe_flags_t' type-id='2b77720b' id='a1936f04'/>
- <pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
- <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
- <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
- <pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
- <function-decl name='lzbe_set_boot_device' mangled-name='lzbe_set_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_set_boot_device'>
- <parameter type-id='80f4b756' name='pool'/>
- <parameter type-id='a1936f04' name='flag'/>
- <parameter type-id='80f4b756' name='device'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='lzbe_get_boot_device' mangled-name='lzbe_get_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_get_boot_device'>
- <parameter type-id='80f4b756' name='pool'/>
- <parameter type-id='9b23c9ad' name='device'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lzbe_pair.c' language='LANG_C99'>
- <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
- <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
- <pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
- <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
- <function-decl name='lzbe_nvlist_get' mangled-name='lzbe_nvlist_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_get'>
- <parameter type-id='80f4b756' name='pool'/>
- <parameter type-id='80f4b756' name='key'/>
- <parameter type-id='63e171df' name='ptr'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='lzbe_nvlist_set' mangled-name='lzbe_nvlist_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_set'>
- <parameter type-id='80f4b756' name='pool'/>
- <parameter type-id='80f4b756' name='key'/>
- <parameter type-id='eaa32e2f' name='ptr'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='lzbe_nvlist_free' mangled-name='lzbe_nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_free'>
- <parameter type-id='eaa32e2f' name='ptr'/>
- <return type-id='48b5725f'/>
- </function-decl>
- <function-decl name='lzbe_add_pair' mangled-name='lzbe_add_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_add_pair'>
- <parameter type-id='eaa32e2f' name='ptr'/>
- <parameter type-id='80f4b756' name='key'/>
- <parameter type-id='80f4b756' name='type'/>
- <parameter type-id='eaa32e2f' name='value'/>
- <parameter type-id='b59d7dce' name='size'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- <function-decl name='lzbe_remove_pair' mangled-name='lzbe_remove_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_remove_pair'>
- <parameter type-id='eaa32e2f' name='ptr'/>
- <parameter type-id='80f4b756' name='key'/>
- <return type-id='95e97e5e'/>
- </function-decl>
- </abi-instr>
- <abi-instr address-size='64' path='lzbe_util.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
<subrange length='1' type-id='7359adad' id='52f813b4'/>
</array-type-def>
@@ -86,9 +25,55 @@
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <class-decl name='libzfs_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='c8a9d9d8'/>
+ <class-decl name='zpool_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='67002a8a'/>
+ <type-decl name='int' size-in-bits='32' id='95e97e5e'/>
<type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
<type-decl name='signed char' size-in-bits='8' id='28577a57'/>
+ <type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
+ <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
+ <type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
<type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
+ <type-decl name='variadic parameter type' id='2c1145c5'/>
+ <type-decl name='void' id='48b5725f'/>
+ <typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/>
+ <typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/>
+ <enum-decl name='lzbe_flags' id='2b77720b'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='lzbe_add' value='0'/>
+ <enumerator name='lzbe_replace' value='1'/>
+ </enum-decl>
+ <typedef-decl name='lzbe_flags_t' type-id='2b77720b' id='a1936f04'/>
+ <class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='nvl_version' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='32'>
+ <var-decl name='nvl_nvflag' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='nvl_priv' type-id='9c313c2d' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='nvl_flag' type-id='8f92235e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='160'>
+ <var-decl name='nvl_pad' type-id='3ff5601b' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='nvlist_t' type-id='ac266fd9' id='8e8d4be3'/>
+ <enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='B_FALSE' value='0'/>
+ <enumerator name='B_TRUE' value='1'/>
+ </enum-decl>
+ <typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/>
+ <typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
+ <typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/>
+ <typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/>
+ <typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/>
+ <typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
+ <typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/>
<typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
<typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
<typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
@@ -182,15 +167,413 @@
<var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
</data-member>
</class-decl>
+ <typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
+ <qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
<pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
<pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
+ <pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
+ <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
+ <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
+ <qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
+ <pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
+ <qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
+ <pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/>
+ <qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
+ <pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
+ <pointer-type-def type-id='95942d0c' size-in-bits='64' id='b0382bb3'/>
+ <pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
+ <pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
+ <pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
+ <pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
+ <pointer-type-def type-id='b1efc708' size-in-bits='64' id='4c81de99'/>
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
+ <class-decl name='libzfs_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='c8a9d9d8'/>
+ <class-decl name='zpool_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='67002a8a'/>
+ <function-decl name='libzfs_init' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='b0382bb3'/>
+ </function-decl>
+ <function-decl name='libzfs_fini' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='libzfs_error_description' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='zpool_open' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='b0382bb3'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='4c81de99'/>
+ </function-decl>
+ <function-decl name='zpool_close' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4c81de99'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='zpool_set_bootenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='22cce67b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_get_bootenv' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='4c81de99'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='5d6479ae'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='7d3cd834'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_exists' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='5ce45b60'/>
+ </function-decl>
+ <function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b59d7dce'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
+ <function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='b59d7dce'/>
+ </function-decl>
+ <function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='e75a27e9'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_set_boot_device' mangled-name='lzbe_set_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_set_boot_device'>
+ <parameter type-id='80f4b756' name='pool'/>
+ <parameter type-id='a1936f04' name='flag'/>
+ <parameter type-id='80f4b756' name='device'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_get_boot_device' mangled-name='lzbe_get_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_get_boot_device'>
+ <parameter type-id='80f4b756' name='pool'/>
+ <parameter type-id='9b23c9ad' name='device'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_pair.c' language='LANG_C99'>
+ <type-decl name='short int' size-in-bits='16' id='a2185560'/>
+ <type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
+ <typedef-decl name='uchar_t' type-id='002ac4a6' id='d8bf0010'/>
+ <typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
+ <typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
+ <typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
+ <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
+ <typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/>
+ <typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
+ <typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
+ <typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
+ <typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
+ <typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
+ <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
+ <qualified-type-def type-id='c19b74c3' const='yes' id='12373e33'/>
+ <pointer-type-def type-id='12373e33' size-in-bits='64' id='c5f6c15b'/>
+ <qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
+ <pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
+ <qualified-type-def type-id='23bd8cb5' const='yes' id='75f7b0c5'/>
+ <pointer-type-def type-id='75f7b0c5' size-in-bits='64' id='a3eb883d'/>
+ <qualified-type-def type-id='3ff5601b' const='yes' id='922df12b'/>
+ <pointer-type-def type-id='922df12b' size-in-bits='64' id='1f526493'/>
+ <qualified-type-def type-id='9da381c4' const='yes' id='f07b7694'/>
+ <pointer-type-def type-id='f07b7694' size-in-bits='64' id='505bed1a'/>
+ <qualified-type-def type-id='ee31ee44' const='yes' id='721c32d4'/>
+ <pointer-type-def type-id='721c32d4' size-in-bits='64' id='a06445da'/>
+ <qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/>
+ <pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/>
+ <qualified-type-def type-id='d8bf0010' const='yes' id='a9125480'/>
+ <pointer-type-def type-id='a9125480' size-in-bits='64' id='d1db479e'/>
+ <qualified-type-def type-id='149c6638' const='yes' id='b01a5ac8'/>
+ <pointer-type-def type-id='b01a5ac8' size-in-bits='64' id='1b7d11c6'/>
+ <qualified-type-def type-id='8f92235e' const='yes' id='b9930aae'/>
+ <pointer-type-def type-id='b9930aae' size-in-bits='64' id='a6798dcc'/>
+ <qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/>
+ <pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/>
+ <qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
+ <pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
+ <pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
+ <function-decl name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='3502e3ff'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_dup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='22cce67b'/>
+ <parameter type-id='857bb57e'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c19b74c3'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_byte' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='d8bf0010'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int8' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='ee31ee44'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint8' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='b96825af'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int16' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='23bd8cb5'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint16' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='149c6638'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3ff5601b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint32' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='8f92235e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9da381c4'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9c313c2d'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='22cce67b'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='c5f6c15b'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='d1db479e'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a06445da'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='9f7200cf'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a3eb883d'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='1b7d11c6'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='1f526493'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='a6798dcc'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='505bed1a'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='713a56f5'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_string_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='13956559'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='3bbfee2e'/>
+ <parameter type-id='3502e3ff'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='5ce45b60'/>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='857bb57e'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_nvlist_get' mangled-name='lzbe_nvlist_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_get'>
+ <parameter type-id='80f4b756' name='pool'/>
+ <parameter type-id='80f4b756' name='key'/>
+ <parameter type-id='63e171df' name='ptr'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_nvlist_set' mangled-name='lzbe_nvlist_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_set'>
+ <parameter type-id='80f4b756' name='pool'/>
+ <parameter type-id='80f4b756' name='key'/>
+ <parameter type-id='eaa32e2f' name='ptr'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_nvlist_free' mangled-name='lzbe_nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_free'>
+ <parameter type-id='eaa32e2f' name='ptr'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='lzbe_add_pair' mangled-name='lzbe_add_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_add_pair'>
+ <parameter type-id='eaa32e2f' name='ptr'/>
+ <parameter type-id='80f4b756' name='key'/>
+ <parameter type-id='80f4b756' name='type'/>
+ <parameter type-id='eaa32e2f' name='value'/>
+ <parameter type-id='b59d7dce' name='size'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='lzbe_remove_pair' mangled-name='lzbe_remove_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_remove_pair'>
+ <parameter type-id='eaa32e2f' name='ptr'/>
+ <parameter type-id='80f4b756' name='key'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ </abi-instr>
+ <abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_util.c' language='LANG_C99'>
+ <function-decl name='nvlist_print' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <parameter type-id='5ce45b60'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='lzbe_bootenv_print' mangled-name='lzbe_bootenv_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_bootenv_print'>
<parameter type-id='80f4b756' name='pool'/>
<parameter type-id='80f4b756' name='nvlist'/>
diff --git a/lib/libzfsbootenv/lzbe_device.c b/lib/libzfsbootenv/lzbe_device.c
index 39e33324b315..894471a9bf35 100644
--- a/lib/libzfsbootenv/lzbe_device.c
+++ b/lib/libzfsbootenv/lzbe_device.c
@@ -74,6 +74,7 @@ lzbe_set_boot_device(const char *pool, lzbe_flags_t flag, const char *device)
/* version is mandatory */
fnvlist_add_uint64(nv, BOOTENV_VERSION, VB_NVLIST);
+ rv = 0;
/*
* If device name is empty, remove boot device configuration.
*/
@@ -95,8 +96,8 @@ lzbe_set_boot_device(const char *pool, lzbe_flags_t flag, const char *device)
rv = ENOMEM;
}
}
-
- rv = zpool_set_bootenv(zphdl, nv);
+ if (rv == 0)
+ rv = zpool_set_bootenv(zphdl, nv);
if (rv != 0)
fprintf(stderr, "%s\n", libzfs_error_description(hdl));
@@ -115,7 +116,7 @@ lzbe_get_boot_device(const char *pool, char **device)
libzfs_handle_t *hdl;
zpool_handle_t *zphdl;
nvlist_t *nv;
- char *val;
+ const char *val;
int rv = -1;
if (pool == NULL || *pool == '\0' || device == NULL)
@@ -139,14 +140,13 @@ lzbe_get_boot_device(const char *pool, char **device)
* we only do need dataset name.
*/
if (strncmp(val, "zfs:", 4) == 0) {
- val += 4;
- val = strdup(val);
- if (val != NULL) {
- size_t len = strlen(val);
-
- if (val[len - 1] == ':')
- val[len - 1] = '\0';
- *device = val;
+ char *tmp = strdup(val + 4);
+ if (tmp != NULL) {
+ size_t len = strlen(tmp);
+
+ if (tmp[len - 1] == ':')
+ tmp[len - 1] = '\0';
+ *device = tmp;
} else {
rv = ENOMEM;
}
diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am
index eaa920e56106..42f3404db5a9 100644
--- a/lib/libzpool/Makefile.am
+++ b/lib/libzpool/Makefile.am
@@ -43,6 +43,7 @@ nodist_libzpool_la_SOURCES = \
module/os/linux/zfs/arc_os.c \
module/os/linux/zfs/trace.c \
module/os/linux/zfs/vdev_file.c \
+ module/os/linux/zfs/vdev_label_os.c \
module/os/linux/zfs/zfs_debug.c \
module/os/linux/zfs/zfs_racct.c \
module/os/linux/zfs/zfs_znode.c \
@@ -74,9 +75,11 @@ nodist_libzpool_la_SOURCES = \
module/zfs/bptree.c \
module/zfs/bqueue.c \
module/zfs/btree.c \
+ module/zfs/brt.c \
module/zfs/dbuf.c \
module/zfs/dbuf_stats.c \
module/zfs/ddt.c \
+ module/zfs/ddt_stats.c \
module/zfs/ddt_zap.c \
module/zfs/dmu.c \
module/zfs/dmu_diff.c \
@@ -118,10 +121,9 @@ nodist_libzpool_la_SOURCES = \
module/zfs/refcount.c \
module/zfs/rrwlock.c \
module/zfs/sa.c \
- module/zfs/sha256.c \
+ module/zfs/sha2_zfs.c \
module/zfs/skein_zfs.c \
module/zfs/spa.c \
- module/zfs/spa_boot.c \
module/zfs/spa_checkpoint.c \
module/zfs/spa_config.c \
module/zfs/spa_errlog.c \
@@ -135,7 +137,6 @@ nodist_libzpool_la_SOURCES = \
module/zfs/uberblock.c \
module/zfs/unique.c \
module/zfs/vdev.c \
- module/zfs/vdev_cache.c \
module/zfs/vdev_draid.c \
module/zfs/vdev_draid_rand.c \
module/zfs/vdev_indirect.c \
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
index 05c278f91940..a3930ee07f73 100644
--- a/lib/libzpool/kernel.c
+++ b/lib/libzpool/kernel.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <libzutil.h>
#include <sys/crypto/icp.h>
#include <sys/processor.h>
@@ -91,7 +92,8 @@ zk_thread_wrapper(void *arg)
}
kthread_t *
-zk_thread_create(void (*func)(void *), void *arg, size_t stksize, int state)
+zk_thread_create(const char *name, void (*func)(void *), void *arg,
+ size_t stksize, int state)
{
pthread_attr_t attr;
pthread_t tid;
@@ -139,6 +141,8 @@ zk_thread_create(void (*func)(void *), void *arg, size_t stksize, int state)
VERIFY0(pthread_create(&tid, &attr, zk_thread_wrapper, ztw));
VERIFY0(pthread_attr_destroy(&attr));
+ pthread_setname_np(tid, name);
+
return ((void *)(uintptr_t)tid);
}
@@ -205,6 +209,15 @@ mutex_enter(kmutex_t *mp)
}
int
+mutex_enter_check_return(kmutex_t *mp)
+{
+ int error = pthread_mutex_lock(&mp->m_lock);
+ if (error == 0)
+ mp->m_owner = pthread_self();
+ return (error);
+}
+
+int
mutex_tryenter(kmutex_t *mp)
{
int error = pthread_mutex_trylock(&mp->m_lock);
@@ -769,10 +782,8 @@ random_get_pseudo_bytes(uint8_t *ptr, size_t len)
int
ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
{
- (void) nptr;
- char *end;
-
- *result = strtoull(str, &end, base);
+ errno = 0;
+ *result = strtoull(str, nptr, base);
if (*result == 0)
return (errno);
return (0);
@@ -956,6 +967,35 @@ kmem_asprintf(const char *fmt, ...)
return (buf);
}
+/*
+ * kmem_scnprintf() will return the number of characters that it would have
+ * printed whenever it is limited by value of the size variable, rather than
+ * the number of characters that it did print. This can cause misbehavior on
+ * subsequent uses of the return value, so we define a safe version that will
+ * return the number of characters actually printed, minus the NULL format
+ * character. Subsequent use of this by the safe string functions is safe
+ * whether it is snprintf(), strlcat() or strlcpy().
+ */
+int
+kmem_scnprintf(char *restrict str, size_t size, const char *restrict fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ /* Make the 0 case a no-op so that we do not return -1 */
+ if (size == 0)
+ return (0);
+
+ va_start(ap, fmt);
+ n = vsnprintf(str, size, fmt, ap);
+ va_end(ap);
+
+ if (n >= size)
+ n = size - 1;
+
+ return (n);
+}
+
zfs_file_t *
zfs_onexit_fd_hold(int fd, minor_t *minorp)
{
@@ -972,7 +1012,7 @@ zfs_onexit_fd_rele(zfs_file_t *fp)
int
zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
- uint64_t *action_handle)
+ uintptr_t *action_handle)
{
(void) minor, (void) func, (void) data, (void) action_handle;
return (0);
diff --git a/lib/libzpool/taskq.c b/lib/libzpool/taskq.c
index 2531b341f442..5fb2283cf0b1 100644
--- a/lib/libzpool/taskq.c
+++ b/lib/libzpool/taskq.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -276,7 +276,7 @@ taskq_create(const char *name, int nthreads, pri_t pri,
cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL);
- (void) strncpy(tq->tq_name, name, TASKQ_NAMELEN);
+ (void) strlcpy(tq->tq_name, name, sizeof (tq->tq_name));
tq->tq_flags = flags | TASKQ_ACTIVE;
tq->tq_active = nthreads;
tq->tq_nthreads = nthreads;
@@ -295,8 +295,8 @@ taskq_create(const char *name, int nthreads, pri_t pri,
}
for (t = 0; t < nthreads; t++)
- VERIFY((tq->tq_threadlist[t] = thread_create(NULL, 0,
- taskq_thread, tq, 0, &p0, TS_RUN, pri)) != NULL);
+ VERIFY((tq->tq_threadlist[t] = thread_create_named(tq->tq_name,
+ NULL, 0, taskq_thread, tq, 0, &p0, TS_RUN, pri)) != NULL);
return (tq);
}
@@ -319,7 +319,9 @@ taskq_destroy(taskq_t *tq)
tq->tq_minalloc = 0;
while (tq->tq_nalloc != 0) {
ASSERT(tq->tq_freelist != NULL);
- task_free(tq, task_alloc(tq, KM_SLEEP));
+ taskq_ent_t *tqent_nexttq = tq->tq_freelist->tqent_next;
+ task_free(tq, tq->tq_freelist);
+ tq->tq_freelist = tqent_nexttq;
}
mutex_exit(&tq->tq_lock);
@@ -335,6 +337,36 @@ taskq_destroy(taskq_t *tq)
kmem_free(tq, sizeof (taskq_t));
}
+/*
+ * Create a taskq with a specified number of pool threads. Allocate
+ * and return an array of nthreads kthread_t pointers, one for each
+ * thread in the pool. The array is not ordered and must be freed
+ * by the caller.
+ */
+taskq_t *
+taskq_create_synced(const char *name, int nthreads, pri_t pri,
+ int minalloc, int maxalloc, uint_t flags, kthread_t ***ktpp)
+{
+ taskq_t *tq;
+ kthread_t **kthreads = kmem_zalloc(sizeof (*kthreads) * nthreads,
+ KM_SLEEP);
+
+ (void) pri; (void) minalloc; (void) maxalloc;
+
+ flags &= ~(TASKQ_DYNAMIC | TASKQ_THREADS_CPU_PCT | TASKQ_DC_BATCH);
+
+ tq = taskq_create(name, nthreads, minclsyspri, nthreads, INT_MAX,
+ flags | TASKQ_PREPOPULATE);
+ VERIFY(tq != NULL);
+ VERIFY(tq->tq_nthreads == nthreads);
+
+ for (int i = 0; i < nthreads; i++) {
+ kthreads[i] = tq->tq_threadlist[i];
+ }
+ *ktpp = kthreads;
+ return (tq);
+}
+
int
taskq_member(taskq_t *tq, kthread_t *t)
{
diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c
index 9a6326e425ff..b9503d4e56d0 100644
--- a/lib/libzpool/util.c
+++ b/lib/libzpool/util.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -65,7 +65,7 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
if (desc != NULL) {
const char *suffix = "";
- char *bias = NULL;
+ const char *bias = NULL;
char bias_suffix[32];
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
@@ -113,12 +113,13 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
for (c = 0; c < children; c++) {
nvlist_t *cnv = child[c];
- char *cname = NULL, *tname;
+ const char *cname = NULL;
+ char *tname;
uint64_t np;
int len;
if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) &&
nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname))
- cname = (char *)"<unknown>";
+ cname = "<unknown>";
len = strlen(cname) + 2;
tname = umem_zalloc(len, UMEM_NOFAIL);
(void) strlcpy(tname, cname, len);
@@ -133,7 +134,7 @@ void
show_pool_stats(spa_t *spa)
{
nvlist_t *config, *nvroot;
- char *name;
+ const char *name;
VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0);
@@ -174,12 +175,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);
}
@@ -228,13 +230,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);
@@ -259,7 +262,9 @@ pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
(void) unused, (void) guid;
zfs_iocparm_t zp;
zfs_cmd_t *zc = NULL;
+#ifdef ZFS_LEGACY_SUPPORT
zfs_cmd_legacy_t *zcl = NULL;
+#endif
unsigned long request;
int ret;
@@ -294,6 +299,7 @@ pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
umem_free(zc, sizeof (zfs_cmd_t));
break;
+#ifdef ZFS_LEGACY_SUPPORT
case ZFS_IOCVER_LEGACY:
zcl = umem_zalloc(sizeof (zfs_cmd_legacy_t), UMEM_NOFAIL);
@@ -309,6 +315,7 @@ pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive)
umem_free(zcl, sizeof (zfs_cmd_legacy_t));
break;
+#endif
default:
fprintf(stderr, "unrecognized zfs ioctl version %d", ver);
exit(1);
@@ -349,7 +356,7 @@ pool_active(void *unused, const char *name, uint64_t guid,
}
#endif
-const pool_config_ops_t libzpool_config_ops = {
+pool_config_ops_t libzpool_config_ops = {
.pco_refresh_config = refresh_config,
.pco_pool_active = pool_active,
};
diff --git a/lib/libzutil/Makefile.am b/lib/libzutil/Makefile.am
index ecdf940508b2..519906235f7f 100644
--- a/lib/libzutil/Makefile.am
+++ b/lib/libzutil/Makefile.am
@@ -17,6 +17,7 @@ libzutil_la_SOURCES = \
if BUILD_LINUX
libzutil_la_SOURCES += \
+ %D%/os/linux/zutil_setproctitle.c \
%D%/os/linux/zutil_device_path_os.c \
%D%/os/linux/zutil_import_os.c
endif
diff --git a/lib/libzutil/os/freebsd/zutil_device_path_os.c b/lib/libzutil/os/freebsd/zutil_device_path_os.c
index f93ab9ad7538..9c67d3af085a 100644
--- a/lib/libzutil/os/freebsd/zutil_device_path_os.c
+++ b/lib/libzutil/os/freebsd/zutil_device_path_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzutil/os/freebsd/zutil_import_os.c b/lib/libzutil/os/freebsd/zutil_import_os.c
index da9a7ded936a..049710d3985f 100644
--- a/lib/libzutil/os/freebsd/zutil_import_os.c
+++ b/lib/libzutil/os/freebsd/zutil_import_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -250,7 +250,24 @@ zfs_dev_flush(int fd)
}
void
+update_vdev_config_dev_sysfs_path(nvlist_t *nv, const char *path,
+ const char *key)
+{
+ (void) nv;
+ (void) path;
+ (void) key;
+}
+
+void
update_vdevs_config_dev_sysfs_path(nvlist_t *config)
{
(void) config;
}
+
+int
+zpool_disk_wait(const char *path)
+{
+
+ (void) path;
+ return (ENOTSUP);
+}
diff --git a/lib/libzutil/os/linux/zutil_device_path_os.c b/lib/libzutil/os/linux/zutil_device_path_os.c
index cfd4bfbf1e2c..900d5e5bacd2 100644
--- a/lib/libzutil/os/linux/zutil_device_path_os.c
+++ b/lib/libzutil/os/linux/zutil_device_path_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -273,7 +273,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;
@@ -345,6 +344,8 @@ zfs_get_enclosure_sysfs_path(const char *dev_name)
if (strstr(ep->d_name, "enclosure_device") == NULL)
continue;
+ if (tmp2 != NULL)
+ free(tmp2);
if (asprintf(&tmp2, "%s/%s", tmp1, ep->d_name) == -1) {
tmp2 = NULL;
break;
@@ -373,14 +374,13 @@ zfs_get_enclosure_sysfs_path(const char *dev_name)
if (tmp3 == NULL)
break;
+ if (path != NULL)
+ free(path);
if (asprintf(&path, "/sys/class/%s", tmp3) == -1) {
/* If asprintf() fails, 'path' is undefined */
path = NULL;
break;
}
-
- if (path == NULL)
- break;
}
end:
@@ -428,7 +428,6 @@ dm_get_underlying_path(const char *dm_name)
char *tmp = NULL;
char *path = NULL;
char *dev_str;
- int size;
char *first_path = NULL;
char *enclosure_path;
@@ -450,7 +449,7 @@ dm_get_underlying_path(const char *dm_name)
else
dev_str = tmp;
- if ((size = asprintf(&tmp, "/sys/block/%s/slaves/", dev_str)) == -1) {
+ if (asprintf(&tmp, "/sys/block/%s/slaves/", dev_str) == -1) {
tmp = NULL;
goto end;
}
@@ -479,8 +478,7 @@ dm_get_underlying_path(const char *dm_name)
if (!enclosure_path)
continue;
- if ((size = asprintf(
- &path, "/dev/%s", ep->d_name)) == -1)
+ if (asprintf(&path, "/dev/%s", ep->d_name) == -1)
path = NULL;
free(enclosure_path);
break;
@@ -499,7 +497,7 @@ end:
* enclosure devices. Throw up out hands and return the first
* underlying path.
*/
- if ((size = asprintf(&path, "/dev/%s", first_path)) == -1)
+ if (asprintf(&path, "/dev/%s", first_path) == -1)
path = NULL;
}
diff --git a/lib/libzutil/os/linux/zutil_import_os.c b/lib/libzutil/os/linux/zutil_import_os.c
index 85f367237996..bb91dec5acff 100644
--- a/lib/libzutil/os/linux/zutil_import_os.c
+++ b/lib/libzutil/os/linux/zutil_import_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -168,27 +168,19 @@ zpool_open_func(void *arg)
* Add additional entries for paths described by this label.
*/
if (rn->rn_labelpaths) {
- char *path = NULL;
- char *devid = NULL;
- char *env = NULL;
+ const char *path = NULL;
+ const char *devid = NULL;
rdsk_node_t *slice;
avl_index_t where;
- int timeout;
int error;
if (label_paths(rn->rn_hdl, rn->rn_config, &path, &devid))
return;
- env = getenv("ZPOOL_IMPORT_UDEV_TIMEOUT_MS");
- if ((env == NULL) || sscanf(env, "%d", &timeout) != 1 ||
- timeout < 0) {
- timeout = DISK_LABEL_WAIT;
- }
-
/*
* Allow devlinks to stabilize so all paths are available.
*/
- zpool_label_disk_wait(rn->rn_name, timeout);
+ zpool_disk_wait(rn->rn_name);
if (path != NULL) {
slice = zutil_alloc(hdl, sizeof (rdsk_node_t));
@@ -582,9 +574,8 @@ zfs_device_get_physical(struct udev_device *dev, char *bufptr, size_t buflen)
* Wait up to timeout_ms for udev to set up the device node. The device is
* considered ready when libudev determines it has been initialized, all of
* the device links have been verified to exist, and it has been allowed to
- * settle. At this point the device the device can be accessed reliably.
- * Depending on the complexity of the udev rules this process could take
- * several seconds.
+ * settle. At this point the device can be accessed reliably. Depending on
+ * the complexity of the udev rules this process could take several seconds.
*/
int
zpool_label_disk_wait(const char *path, int timeout_ms)
@@ -684,6 +675,20 @@ zpool_label_disk_wait(const char *path, int timeout_ms)
}
/*
+ * Simplified version of zpool_label_disk_wait() where we wait for a device
+ * to appear using the default timeouts.
+ */
+int
+zpool_disk_wait(const char *path)
+{
+ int timeout;
+ timeout = zpool_getenv_int("ZPOOL_IMPORT_UDEV_TIMEOUT_MS",
+ DISK_LABEL_WAIT);
+
+ return (zpool_label_disk_wait(path, timeout));
+}
+
+/*
* Encode the persistent devices strings
* used for the vdev disk label
*/
@@ -767,20 +772,37 @@ no_dev:
* Rescan the enclosure sysfs path for turning on enclosure LEDs and store it
* in the nvlist * (if applicable). Like:
* vdev_enc_sysfs_path: '/sys/class/enclosure/11:0:1:0/SLOT 4'
+ *
+ * If an old path was in the nvlist, and the rescan can not find a new path,
+ * then keep the old path, since the disk may have been removed.
+ *
+ * path: The vdev path (value from ZPOOL_CONFIG_PATH)
+ * key: The nvlist_t name (like ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH)
*/
-static void
-update_vdev_config_dev_sysfs_path(nvlist_t *nv, char *path)
+void
+update_vdev_config_dev_sysfs_path(nvlist_t *nv, const char *path,
+ const char *key)
{
char *upath, *spath;
+ const char *oldpath = NULL;
+
+ (void) nvlist_lookup_string(nv, key, &oldpath);
/* Add enclosure sysfs path (if disk is in an enclosure). */
upath = zfs_get_underlying_path(path);
spath = zfs_get_enclosure_sysfs_path(upath);
if (spath) {
- nvlist_add_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, spath);
+ (void) nvlist_add_string(nv, key, spath);
} else {
- nvlist_remove_all(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
+ /*
+ * We couldn't dynamically scan the disk's enclosure sysfs path.
+ * This could be because the disk went away. If there's an old
+ * enclosure sysfs path in the nvlist, then keep using it.
+ */
+ if (!oldpath) {
+ (void) nvlist_remove_all(nv, key);
+ }
}
free(upath);
@@ -795,12 +817,13 @@ sysfs_path_pool_vdev_iter_f(void *hdl_data, nvlist_t *nv, void *data)
{
(void) hdl_data, (void) data;
- char *path = NULL;
+ const char *path = NULL;
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
return (1);
/* Rescan our enclosure sysfs path for this vdev */
- update_vdev_config_dev_sysfs_path(nv, path);
+ update_vdev_config_dev_sysfs_path(nv, path,
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
return (0);
}
@@ -841,7 +864,7 @@ void
update_vdev_config_dev_strs(nvlist_t *nv)
{
vdev_dev_strs_t vds;
- char *env, *type, *path;
+ const char *env, *type, *path;
uint64_t wholedisk = 0;
/*
@@ -889,7 +912,8 @@ update_vdev_config_dev_strs(nvlist_t *nv)
(void) nvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
vds.vds_devphys);
}
- update_vdev_config_dev_sysfs_path(nv, path);
+ update_vdev_config_dev_sysfs_path(nv, path,
+ ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
} else {
/* Clear out any stale entries. */
(void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
diff --git a/lib/libzutil/os/linux/zutil_setproctitle.c b/lib/libzutil/os/linux/zutil_setproctitle.c
new file mode 100644
index 000000000000..e63acceb4f8e
--- /dev/null
+++ b/lib/libzutil/os/linux/zutil_setproctitle.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright © 2013 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/param.h>
+#include <libzutil.h>
+
+static struct {
+ /* Original value. */
+ const char *arg0;
+
+ /* Title space available. */
+ char *base, *end;
+
+ /* Pointer to original nul character within base. */
+ char *nul;
+
+ boolean_t warned;
+ boolean_t reset;
+ int error;
+} SPT;
+
+#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/')
+#define SPT_MAXTITLE 255
+
+extern const char *__progname;
+
+static const char *
+getprogname(void)
+{
+ return (__progname);
+}
+
+static void
+setprogname(const char *progname)
+{
+ size_t i;
+
+ for (i = strlen(progname); i > 0; i--) {
+ if (LIBBSD_IS_PATHNAME_SEPARATOR(progname[i - 1])) {
+ __progname = progname + i;
+ return;
+ }
+ }
+ __progname = progname;
+}
+
+
+static inline size_t
+spt_min(size_t a, size_t b)
+{
+ return ((a < b) ? a : b);
+}
+
+static int
+spt_copyenv(int envc, char *envp[])
+{
+ char **envcopy;
+ char *eq;
+ int envsize;
+ int i, error = 0;
+
+ if (environ != envp)
+ return (0);
+
+ /*
+ * Make a copy of the old environ array of pointers, in case
+ * clearenv() or setenv() is implemented to free the internal
+ * environ array, because we will need to access the old environ
+ * contents to make the new copy.
+ */
+ envsize = (envc + 1) * sizeof (char *);
+ envcopy = malloc(envsize);
+ if (envcopy == NULL)
+ return (errno);
+ memcpy(envcopy, envp, envsize);
+
+ environ = NULL;
+
+ for (i = 0; envcopy[i]; i++) {
+ eq = strchr(envcopy[i], '=');
+ if (eq == NULL)
+ continue;
+
+ *eq = '\0';
+ if (setenv(envcopy[i], eq + 1, 1) < 0)
+ error = errno;
+ *eq = '=';
+
+ if (error) {
+ clearenv();
+ environ = envp;
+ free(envcopy);
+ return (error);
+ }
+ }
+
+ /*
+ * Dispose of the shallow copy, now that we've finished transfering
+ * the old environment.
+ */
+ free(envcopy);
+
+ return (0);
+}
+
+static int
+spt_copyargs(int argc, char *argv[])
+{
+ char *tmp;
+ int i;
+
+ for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
+ if (argv[i] == NULL)
+ continue;
+
+ tmp = strdup(argv[i]);
+ if (tmp == NULL)
+ return (errno);
+
+ argv[i] = tmp;
+ }
+
+ return (0);
+}
+
+void
+zfs_setproctitle_init(int argc, char *argv[], char *envp[])
+{
+ char *base, *end, *nul, *tmp;
+ int i, envc, error;
+
+ /* Try to make sure we got called with main() arguments. */
+ if (argc < 0)
+ return;
+
+ base = argv[0];
+ if (base == NULL)
+ return;
+
+ nul = base + strlen(base);
+ end = nul + 1;
+
+ for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
+ if (argv[i] == NULL || argv[i] != end)
+ continue;
+
+ end = argv[i] + strlen(argv[i]) + 1;
+ }
+
+ for (i = 0; envp[i]; i++) {
+ if (envp[i] != end)
+ continue;
+
+ end = envp[i] + strlen(envp[i]) + 1;
+ }
+ envc = i;
+
+ SPT.arg0 = strdup(argv[0]);
+ if (SPT.arg0 == NULL) {
+ SPT.error = errno;
+ return;
+ }
+
+ tmp = strdup(getprogname());
+ if (tmp == NULL) {
+ SPT.error = errno;
+ return;
+ }
+ setprogname(tmp);
+
+ error = spt_copyenv(envc, envp);
+ if (error) {
+ SPT.error = error;
+ return;
+ }
+
+ error = spt_copyargs(argc, argv);
+ if (error) {
+ SPT.error = error;
+ return;
+ }
+
+ SPT.nul = nul;
+ SPT.base = base;
+ SPT.end = end;
+}
+
+void
+zfs_setproctitle(const char *fmt, ...)
+{
+ /* Use buffer in case argv[0] is passed. */
+ char buf[SPT_MAXTITLE + 1];
+ va_list ap;
+ char *nul;
+ int len;
+ if (SPT.base == NULL) {
+ if (!SPT.warned) {
+ warnx("setproctitle not initialized, please"
+ "call zfs_setproctitle_init()");
+ SPT.warned = B_TRUE;
+ }
+ return;
+ }
+
+ if (fmt) {
+ if (fmt[0] == '-') {
+ /* Skip program name prefix. */
+ fmt++;
+ len = 0;
+ } else {
+ /* Print program name heading for grep. */
+ snprintf(buf, sizeof (buf), "%s: ", getprogname());
+ len = strlen(buf);
+ }
+
+ va_start(ap, fmt);
+ len += vsnprintf(buf + len, sizeof (buf) - len, fmt, ap);
+ va_end(ap);
+ } else {
+ len = snprintf(buf, sizeof (buf), "%s", SPT.arg0);
+ }
+
+ if (len <= 0) {
+ SPT.error = errno;
+ return;
+ }
+
+ if (!SPT.reset) {
+ memset(SPT.base, 0, SPT.end - SPT.base);
+ SPT.reset = B_TRUE;
+ } else {
+ memset(SPT.base, 0, spt_min(sizeof (buf), SPT.end - SPT.base));
+ }
+
+ len = spt_min(len, spt_min(sizeof (buf), SPT.end - SPT.base) - 1);
+ memcpy(SPT.base, buf, len);
+ nul = SPT.base + len;
+
+ if (nul < SPT.nul) {
+ *SPT.nul = '.';
+ } else if (nul == SPT.nul && nul + 1 < SPT.end) {
+ *SPT.nul = ' ';
+ *++nul = '\0';
+ }
+}
diff --git a/lib/libzutil/zutil_device_path.c b/lib/libzutil/zutil_device_path.c
index 6a8c8869edf1..0425018e1022 100644
--- a/lib/libzutil/zutil_device_path.c
+++ b/lib/libzutil/zutil_device_path.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c
index 26fba2cadf74..06705ff4d9b4 100644
--- a/lib/libzutil/zutil_import.c
+++ b/lib/libzutil/zutil_import.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -71,6 +71,30 @@
#include "zutil_import.h"
+const char *
+libpc_error_description(libpc_handle_t *hdl)
+{
+ if (hdl->lpc_desc[0] != '\0')
+ return (hdl->lpc_desc);
+
+ switch (hdl->lpc_error) {
+ case LPC_BADCACHE:
+ return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
+ case LPC_BADPATH:
+ return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
+ case LPC_NOMEM:
+ return (dgettext(TEXT_DOMAIN, "out of memory"));
+ case LPC_EACCESS:
+ return (dgettext(TEXT_DOMAIN, "some devices require root "
+ "privileges"));
+ case LPC_UNKNOWN:
+ return (dgettext(TEXT_DOMAIN, "unknown error"));
+ default:
+ assert(hdl->lpc_error == 0);
+ return (dgettext(TEXT_DOMAIN, "no error"));
+ }
+}
+
static __attribute__((format(printf, 2, 3))) void
zutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...)
{
@@ -85,28 +109,27 @@ zutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...)
}
static void
-zutil_verror(libpc_handle_t *hdl, const char *error, const char *fmt,
+zutil_verror(libpc_handle_t *hdl, lpc_error_t error, const char *fmt,
va_list ap)
{
char action[1024];
(void) vsnprintf(action, sizeof (action), fmt, ap);
+ hdl->lpc_error = error;
if (hdl->lpc_desc_active)
hdl->lpc_desc_active = B_FALSE;
else
hdl->lpc_desc[0] = '\0';
- if (hdl->lpc_printerr) {
- if (hdl->lpc_desc[0] != '\0')
- error = hdl->lpc_desc;
-
- (void) fprintf(stderr, "%s: %s\n", action, error);
- }
+ if (hdl->lpc_printerr)
+ (void) fprintf(stderr, "%s: %s\n", action,
+ libpc_error_description(hdl));
}
static __attribute__((format(printf, 3, 4))) int
-zutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...)
+zutil_error_fmt(libpc_handle_t *hdl, lpc_error_t error,
+ const char *fmt, ...)
{
va_list ap;
@@ -120,7 +143,7 @@ zutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...)
}
static int
-zutil_error(libpc_handle_t *hdl, const char *error, const char *msg)
+zutil_error(libpc_handle_t *hdl, lpc_error_t error, const char *msg)
{
return (zutil_error_fmt(hdl, error, "%s", msg));
}
@@ -128,7 +151,7 @@ zutil_error(libpc_handle_t *hdl, const char *error, const char *msg)
static int
zutil_no_memory(libpc_handle_t *hdl)
{
- zutil_error(hdl, EZFS_NOMEM, "internal error");
+ zutil_error(hdl, LPC_NOMEM, "internal error");
exit(1);
}
@@ -210,7 +233,7 @@ fix_paths(libpc_handle_t *hdl, nvlist_t *nv, name_entry_t *names)
uint_t c, children;
uint64_t guid;
name_entry_t *ne, *best;
- char *path;
+ const char *path;
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0) {
@@ -474,15 +497,13 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok,
uint_t i, nspares, nl2cache;
boolean_t config_seen;
uint64_t best_txg;
- char *name, *hostname = NULL;
+ const char *name, *hostname = NULL;
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;
@@ -490,7 +511,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;
@@ -569,8 +591,8 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok,
* hostname (if available)
*/
uint64_t state, version;
- char *comment = NULL;
- char *compatibility = NULL;
+ const char *comment = NULL;
+ const char *compatibility = NULL;
version = fnvlist_lookup_uint64(tmp,
ZPOOL_CONFIG_VERSION);
@@ -912,7 +934,6 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels)
vdev_phys_t *label;
nvlist_t *expected_config = NULL;
uint64_t expected_guid = 0, size;
- int error;
*config = NULL;
@@ -920,8 +941,9 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels)
return (0);
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
- error = posix_memalign((void **)&label, PAGESIZE, sizeof (*label));
- if (error)
+ label = (vdev_phys_t *)umem_alloc_aligned(sizeof (*label), PAGESIZE,
+ UMEM_DEFAULT);
+ if (label == NULL)
return (-1);
for (l = 0; l < VDEV_LABELS; l++) {
@@ -970,7 +992,7 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels)
if (num_labels != NULL)
*num_labels = count;
- free(label);
+ umem_free_aligned(label, sizeof (*label));
*config = expected_config;
return (0);
@@ -1001,9 +1023,9 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels)
return (0);
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
- error = posix_memalign((void **)&labels, PAGESIZE,
- VDEV_LABELS * sizeof (*labels));
- if (error)
+ labels = (vdev_phys_t *)umem_alloc_aligned(
+ VDEV_LABELS * sizeof (*labels), PAGESIZE, UMEM_DEFAULT);
+ if (labels == NULL)
return (-1);
memset(aiocbs, 0, sizeof (aiocbs));
@@ -1034,10 +1056,21 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels)
case EINVAL:
break;
case EINPROGRESS:
- // This shouldn't be possible to
- // encounter, die if we do.
+ /*
+ * This shouldn't be possible to
+ * encounter, die if we do.
+ */
ASSERT(B_FALSE);
zfs_fallthrough;
+ case EREMOTEIO:
+ /*
+ * May be returned by an NVMe device
+ * which is visible in /dev/ but due
+ * to a low-level format change, or
+ * other error, needs to be rescanned.
+ * Try the slow method.
+ */
+ zfs_fallthrough;
case EOPNOTSUPP:
case ENOSYS:
do_slow = B_TRUE;
@@ -1056,7 +1089,7 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels)
error = zpool_read_label_slow(fd, config, num_labels);
saved_errno = errno;
}
- free(labels);
+ umem_free_aligned(labels, VDEV_LABELS * sizeof (*labels));
errno = saved_errno;
return (error);
}
@@ -1105,7 +1138,7 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels)
if (num_labels != NULL)
*num_labels = count;
- free(labels);
+ umem_free_aligned(labels, VDEV_LABELS * sizeof (*labels));
*config = expected_config;
return (0);
@@ -1139,12 +1172,12 @@ slice_cache_compare(const void *arg1, const void *arg2)
static int
label_paths_impl(libpc_handle_t *hdl, nvlist_t *nvroot, uint64_t pool_guid,
- uint64_t vdev_guid, char **path, char **devid)
+ uint64_t vdev_guid, const char **path, const char **devid)
{
nvlist_t **child;
uint_t c, children;
uint64_t guid;
- char *val;
+ const char *val;
int error;
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
@@ -1182,18 +1215,32 @@ label_paths_impl(libpc_handle_t *hdl, nvlist_t *nvroot, uint64_t pool_guid,
* The returned pointers are only valid as long as label remains valid.
*/
int
-label_paths(libpc_handle_t *hdl, nvlist_t *label, char **path, char **devid)
+label_paths(libpc_handle_t *hdl, nvlist_t *label, const char **path,
+ const char **devid)
{
nvlist_t *nvroot;
uint64_t pool_guid;
uint64_t vdev_guid;
+ uint64_t state;
*path = NULL;
*devid = NULL;
+ if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid) != 0)
+ return (ENOENT);
+
+ /*
+ * In case of spare or l2cache, we directly return path/devid from the
+ * label.
+ */
+ if (!(nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_STATE, &state)) &&
+ (state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE)) {
+ (void) nvlist_lookup_string(label, ZPOOL_CONFIG_PATH, path);
+ (void) nvlist_lookup_string(label, ZPOOL_CONFIG_DEVID, devid);
+ return (0);
+ }
if (nvlist_lookup_nvlist(label, ZPOOL_CONFIG_VDEV_TREE, &nvroot) ||
- nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid) ||
- nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid))
+ nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid))
return (ENOENT);
return (label_paths_impl(hdl, nvroot, pool_guid, vdev_guid, path,
@@ -1243,18 +1290,18 @@ zpool_find_import_scan_dir(libpc_handle_t *hdl, pthread_mutex_t *lock,
if (error == ENOENT)
return (0);
- zutil_error_aux(hdl, "%s", strerror(error));
- (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext(
- TEXT_DOMAIN, "cannot resolve path '%s'"), dir);
+ zutil_error_aux(hdl, "%s", zfs_strerror(error));
+ (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN,
+ "cannot resolve path '%s'"), dir);
return (error);
}
dirp = opendir(path);
if (dirp == NULL) {
error = errno;
- zutil_error_aux(hdl, "%s", strerror(error));
- (void) zutil_error_fmt(hdl, EZFS_BADPATH,
- dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
+ zutil_error_aux(hdl, "%s", zfs_strerror(error));
+ (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN,
+ "cannot open '%s'"), path);
return (error);
}
@@ -1314,9 +1361,9 @@ zpool_find_import_scan_path(libpc_handle_t *hdl, pthread_mutex_t *lock,
goto out;
}
- zutil_error_aux(hdl, "%s", strerror(error));
- (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext(
- TEXT_DOMAIN, "cannot resolve path '%s'"), dir);
+ zutil_error_aux(hdl, "%s", zfs_strerror(error));
+ (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN,
+ "cannot resolve path '%s'"), dir);
goto out;
}
@@ -1352,8 +1399,8 @@ zpool_find_import_scan(libpc_handle_t *hdl, pthread_mutex_t *lock,
if (error == ENOENT)
continue;
- zutil_error_aux(hdl, "%s", strerror(error));
- (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext(
+ zutil_error_aux(hdl, "%s", zfs_strerror(error));
+ (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(
TEXT_DOMAIN, "cannot resolve path '%s'"), dir[i]);
goto error;
}
@@ -1451,7 +1498,7 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg,
}
if (iarg->poolname != NULL && !aux) {
- char *pname;
+ const char *pname;
matched = nvlist_lookup_string(config,
ZPOOL_CONFIG_POOL_NAME, &pname) == 0 &&
@@ -1525,7 +1572,7 @@ static int
discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
avl_tree_t *cache, pthread_mutex_t *lock)
{
- char *path = NULL;
+ const char *path = NULL;
ssize_t dl;
uint_t children;
nvlist_t **child;
@@ -1542,12 +1589,21 @@ discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
* our directory cache.
*/
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
- if ((dl = zfs_dirnamelen(path)) == -1)
- path = (char *)".";
- else
- path[dl] = '\0';
- return (zpool_find_import_scan_dir(hdl, lock, cache,
- path, 0));
+ int ret;
+ char c = '\0';
+ if ((dl = zfs_dirnamelen(path)) == -1) {
+ path = ".";
+ } else {
+ c = path[dl];
+ ((char *)path)[dl] = '\0';
+
+ }
+ ret = zpool_find_import_scan_dir(hdl, lock, cache,
+ path, 0);
+ if (c != '\0')
+ ((char *)path)[dl] = c;
+
+ return (ret);
}
return (0);
}
@@ -1566,24 +1622,24 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
nvlist_t *raw, *src, *dst;
nvlist_t *pools;
nvpair_t *elem;
- char *name;
+ const char *name;
uint64_t this_guid;
boolean_t active;
verify(iarg->poolname == NULL || iarg->guid == 0);
if ((fd = open(iarg->cachefile, O_RDONLY | O_CLOEXEC)) < 0) {
- zutil_error_aux(hdl, "%s", strerror(errno));
- (void) zutil_error(hdl, EZFS_BADCACHE,
- dgettext(TEXT_DOMAIN, "failed to open cache file"));
+ zutil_error_aux(hdl, "%s", zfs_strerror(errno));
+ (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN,
+ "failed to open cache file"));
return (NULL);
}
if (fstat64(fd, &statbuf) != 0) {
- zutil_error_aux(hdl, "%s", strerror(errno));
+ zutil_error_aux(hdl, "%s", zfs_strerror(errno));
(void) close(fd);
- (void) zutil_error(hdl, EZFS_BADCACHE,
- dgettext(TEXT_DOMAIN, "failed to get size of cache file"));
+ (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN,
+ "failed to get size of cache file"));
return (NULL);
}
@@ -1595,8 +1651,7 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
(void) close(fd);
free(buf);
- (void) zutil_error(hdl, EZFS_BADCACHE,
- dgettext(TEXT_DOMAIN,
+ (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN,
"failed to read cache file contents"));
return (NULL);
}
@@ -1605,8 +1660,7 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) {
free(buf);
- (void) zutil_error(hdl, EZFS_BADCACHE,
- dgettext(TEXT_DOMAIN,
+ (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN,
"invalid or corrupt cache file contents"));
return (NULL);
}
@@ -1694,6 +1748,8 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
* caller.
*/
nvpair_t *pair = nvlist_next_nvpair(nv, NULL);
+ if (pair == NULL)
+ continue;
fnvlist_add_nvlist(pools, nvpair_name(pair),
fnvpair_value_nvlist(pair));
@@ -1775,26 +1831,20 @@ zpool_find_import(libpc_handle_t *hdl, importargs_t *iarg)
nvlist_t *
-zpool_search_import(void *hdl, importargs_t *import,
- const pool_config_ops_t *pco)
+zpool_search_import(libpc_handle_t *hdl, importargs_t *import)
{
- libpc_handle_t handle = { 0 };
nvlist_t *pools = NULL;
- handle.lpc_lib_handle = hdl;
- handle.lpc_ops = pco;
- handle.lpc_printerr = B_TRUE;
-
verify(import->poolname == NULL || import->guid == 0);
if (import->cachefile != NULL)
- pools = zpool_find_import_cached(&handle, import);
+ pools = zpool_find_import_cached(hdl, import);
else
- pools = zpool_find_import(&handle, import);
+ pools = zpool_find_import(hdl, import);
if ((pools == NULL || nvlist_empty(pools)) &&
- handle.lpc_open_access_error && geteuid() != 0) {
- (void) zutil_error(&handle, EZFS_EACESS, dgettext(TEXT_DOMAIN,
+ hdl->lpc_open_access_error && geteuid() != 0) {
+ (void) zutil_error(hdl, LPC_EACCESS, dgettext(TEXT_DOMAIN,
"no pools found"));
}
@@ -1802,10 +1852,10 @@ zpool_search_import(void *hdl, importargs_t *import,
}
static boolean_t
-pool_match(nvlist_t *cfg, char *tgt)
+pool_match(nvlist_t *cfg, const char *tgt)
{
uint64_t v, guid = strtoull(tgt, NULL, 0);
- char *s;
+ const char *s;
if (guid != 0) {
if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0)
@@ -1818,8 +1868,8 @@ pool_match(nvlist_t *cfg, char *tgt)
}
int
-zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
- importargs_t *args, const pool_config_ops_t *pco)
+zpool_find_config(libpc_handle_t *hdl, const char *target, nvlist_t **configp,
+ importargs_t *args)
{
nvlist_t *pools;
nvlist_t *match = NULL;
@@ -1828,12 +1878,15 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
int count = 0;
char *targetdup = strdup(target);
+ if (targetdup == NULL)
+ return (ENOMEM);
+
*configp = NULL;
if ((sepp = strpbrk(targetdup, "/@")) != NULL)
*sepp = '\0';
- pools = zpool_search_import(hdl, args, pco);
+ pools = zpool_search_import(hdl, args);
if (pools != NULL) {
nvpair_t *elem = NULL;
@@ -1869,6 +1922,104 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
return (0);
}
+/* Return if a vdev is a leaf vdev. Note: draid spares are leaf vdevs. */
+static boolean_t
+vdev_is_leaf(nvlist_t *nv)
+{
+ uint_t children = 0;
+ nvlist_t **child;
+
+ (void) nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
+ &child, &children);
+
+ return (children == 0);
+}
+
+/* Return if a vdev is a leaf vdev and a real device (disk or file) */
+static boolean_t
+vdev_is_real_leaf(nvlist_t *nv)
+{
+ const char *type = NULL;
+ if (!vdev_is_leaf(nv))
+ return (B_FALSE);
+
+ (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type);
+ if ((strcmp(type, VDEV_TYPE_DISK) == 0) ||
+ (strcmp(type, VDEV_TYPE_FILE) == 0)) {
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+/*
+ * This function is called by our FOR_EACH_VDEV() macros.
+ *
+ * state: State machine status (stored inside of a (nvlist_t *))
+ * nv: The current vdev nvlist_t we are iterating over.
+ * last_nv: The previous vdev nvlist_t we returned to the user in
+ * the last iteration of FOR_EACH_VDEV(). We use it
+ * to find the next vdev nvlist_t we should return.
+ * real_leaves_only: Only return leaf vdevs.
+ *
+ * Returns 1 if we found the next vdev nvlist_t for this iteration. 0 if
+ * we're still searching for it.
+ */
+static int
+__for_each_vdev_macro_helper_func(void *state, nvlist_t *nv, void *last_nv,
+ boolean_t real_leaves_only)
+{
+ enum {FIRST_NV = 0, NEXT_IS_MATCH = 1, STOP_LOOKING = 2};
+
+ /* The very first entry in the NV list is a special case */
+ if (*((nvlist_t **)state) == (nvlist_t *)FIRST_NV) {
+ if (real_leaves_only && !vdev_is_real_leaf(nv))
+ return (0);
+
+ *((nvlist_t **)last_nv) = nv;
+ *((nvlist_t **)state) = (nvlist_t *)STOP_LOOKING;
+ return (1);
+ }
+
+ /*
+ * We came across our last_nv, meaning the next one is the one we
+ * want
+ */
+ if (nv == *((nvlist_t **)last_nv)) {
+ /* Next iteration of this function will return the nvlist_t */
+ *((nvlist_t **)state) = (nvlist_t *)NEXT_IS_MATCH;
+ return (0);
+ }
+
+ /*
+ * We marked NEXT_IS_MATCH on the previous iteration, so this is the one
+ * we want.
+ */
+ if (*(nvlist_t **)state == (nvlist_t *)NEXT_IS_MATCH) {
+ if (real_leaves_only && !vdev_is_real_leaf(nv))
+ return (0);
+
+ *((nvlist_t **)last_nv) = nv;
+ *((nvlist_t **)state) = (nvlist_t *)STOP_LOOKING;
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+for_each_vdev_macro_helper_func(void *state, nvlist_t *nv, void *last_nv)
+{
+ return (__for_each_vdev_macro_helper_func(state, nv, last_nv, B_FALSE));
+}
+
+int
+for_each_real_leaf_vdev_macro_helper_func(void *state, nvlist_t *nv,
+ void *last_nv)
+{
+ return (__for_each_vdev_macro_helper_func(state, nv, last_nv, B_TRUE));
+}
+
/*
* Internal function for iterating over the vdevs.
*
@@ -1887,7 +2038,7 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func,
uint_t c, children;
int ret = 0;
int i;
- char *type;
+ const char *type;
const char *list[] = {
ZPOOL_CONFIG_SPARES,
@@ -1898,9 +2049,8 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func,
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
return (ret);
- /* Don't run our function on root or indirect vdevs */
- if ((strcmp(type, VDEV_TYPE_ROOT) != 0) &&
- (strcmp(type, VDEV_TYPE_INDIRECT) != 0)) {
+ /* Don't run our function on indirect vdevs */
+ if (strcmp(type, VDEV_TYPE_INDIRECT) != 0) {
ret |= func(zhp, nv, data);
}
diff --git a/lib/libzutil/zutil_import.h b/lib/libzutil/zutil_import.h
index 0108eb45c5cf..da7941fa5307 100644
--- a/lib/libzutil/zutil_import.h
+++ b/lib/libzutil/zutil_import.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,28 +28,13 @@
#ifndef _LIBZUTIL_ZUTIL_IMPORT_H_
#define _LIBZUTIL_ZUTIL_IMPORT_H_
-#define EZFS_BADCACHE "invalid or missing cache file"
-#define EZFS_BADPATH "must be an absolute path"
-#define EZFS_NOMEM "out of memory"
-#define EZFS_EACESS "some devices require root privileges"
-
#define IMPORT_ORDER_PREFERRED_1 1
#define IMPORT_ORDER_PREFERRED_2 2
#define IMPORT_ORDER_SCAN_OFFSET 10
#define IMPORT_ORDER_DEFAULT 100
-typedef struct libpc_handle {
- boolean_t lpc_printerr;
- boolean_t lpc_open_access_error;
- boolean_t lpc_desc_active;
- char lpc_desc[1024];
- const pool_config_ops_t *lpc_ops;
- void *lpc_lib_handle;
-} libpc_handle_t;
-
-
-int label_paths(libpc_handle_t *hdl, nvlist_t *label, char **path,
- char **devid);
+int label_paths(libpc_handle_t *hdl, nvlist_t *label, const char **path,
+ const char **devid);
int zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock,
avl_tree_t **slice_cache);
diff --git a/lib/libzutil/zutil_nicenum.c b/lib/libzutil/zutil_nicenum.c
index 4dcac1f855ff..e05bcb40a8ce 100644
--- a/lib/libzutil/zutil_nicenum.c
+++ b/lib/libzutil/zutil_nicenum.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/lib/libzutil/zutil_pool.c b/lib/libzutil/zutil_pool.c
index 21dc1f9d9458..86460de3fc61 100644
--- a/lib/libzutil/zutil_pool.c
+++ b/lib/libzutil/zutil_pool.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,6 +28,7 @@
#include <string.h>
#include <sys/nvpair.h>
#include <sys/fs/zfs.h>
+#include <math.h>
#include <libzutil.h>
@@ -144,3 +145,33 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
*leftover = bytes_read;
return (0);
}
+
+/*
+ * Floating point sleep(). Allows you to pass in a floating point value for
+ * seconds.
+ */
+void
+fsleep(float sec)
+{
+ struct timespec req;
+ req.tv_sec = floor(sec);
+ req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
+ nanosleep(&req, NULL);
+}
+
+/*
+ * Get environment variable 'env' and return it as an integer.
+ * If 'env' is not set, then return 'default_val' instead.
+ */
+int
+zpool_getenv_int(const char *env, int default_val)
+{
+ char *str;
+ int val;
+ str = getenv(env);
+ if ((str == NULL) || sscanf(str, "%d", &val) != 1 ||
+ val < 0) {
+ val = default_val;
+ }
+ return (val);
+}
diff --git a/man/Makefile.am b/man/Makefile.am
index 12f818372f37..43bb014ddd32 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -15,6 +15,7 @@ dist_man_MANS = \
%D%/man4/zfs.4 \
\
%D%/man7/dracut.zfs.7 \
+ %D%/man7/vdevprops.7 \
%D%/man7/zfsconcepts.7 \
%D%/man7/zfsprops.7 \
%D%/man7/zpool-features.7 \
@@ -37,7 +38,6 @@ dist_man_MANS = \
%D%/man8/zfs-groupspace.8 \
%D%/man8/zfs-hold.8 \
%D%/man8/zfs-inherit.8 \
- %D%/man8/zfs-jail.8 \
%D%/man8/zfs-list.8 \
%D%/man8/zfs-load-key.8 \
%D%/man8/zfs-mount.8 \
@@ -56,14 +56,11 @@ dist_man_MANS = \
%D%/man8/zfs-share.8 \
%D%/man8/zfs-snapshot.8 \
%D%/man8/zfs-unallow.8 \
- %D%/man8/zfs-unjail.8 \
%D%/man8/zfs-unload-key.8 \
%D%/man8/zfs-unmount.8 \
- %D%/man8/zfs-unzone.8 \
%D%/man8/zfs-upgrade.8 \
%D%/man8/zfs-userspace.8 \
%D%/man8/zfs-wait.8 \
- %D%/man8/zfs-zone.8 \
%D%/man8/zfs_ids_to_path.8 \
%D%/man8/zgenhostid.8 \
%D%/man8/zinject.8 \
@@ -103,9 +100,22 @@ dist_man_MANS = \
%D%/man8/zstreamdump.8 \
%D%/man8/zpool_influxdb.8
+if BUILD_FREEBSD
+dist_man_MANS += \
+ %D%/man8/zfs-jail.8 \
+ %D%/man8/zfs-unjail.8
+endif
+
+if BUILD_LINUX
+dist_man_MANS += \
+ %D%/man8/zfs-unzone.8 \
+ %D%/man8/zfs-zone.8
+endif
+
nodist_man_MANS = \
%D%/man8/zed.8 \
- %D%/man8/zfs-mount-generator.8
+ %D%/man8/zfs-mount-generator.8 \
+ %D%/man8/zfs_prepare_disk.8
dist_noinst_DATA += $(dist_noinst_man_MANS) $(dist_man_MANS)
diff --git a/man/man1/arcstat.1 b/man/man1/arcstat.1
index a69cd8937bdf..82358fa686b9 100644
--- a/man/man1/arcstat.1
+++ b/man/man1/arcstat.1
@@ -12,7 +12,7 @@
.\" Copyright (c) 2015 by Delphix. All rights reserved.
.\" Copyright (c) 2020 by AJ Jordan. All rights reserved.
.\"
-.Dd May 26, 2021
+.Dd December 23, 2022
.Dt ARCSTAT 1
.Os
.
@@ -35,33 +35,83 @@ prints various ZFS ARC and L2ARC statistics in vmstat-like fashion:
.It Sy c
ARC target size
.It Sy dh%
-Demand data hit percentage
+Demand hit percentage
+.It Sy di%
+Demand I/O hit percentage
.It Sy dm%
+Demand miss percentage
+.It Sy ddh%
+Demand data hit percentage
+.It Sy ddi%
+Demand data I/O hit percentage
+.It Sy ddm%
Demand data miss percentage
+.It Sy dmh%
+Demand metadata hit percentage
+.It Sy dmi%
+Demand metadata I/O hit percentage
+.It Sy dmm%
+Demand metadata miss percentage
.It Sy mfu
MFU list hits per second
.It Sy mh%
Metadata hit percentage
+.It Sy mi%
+Metadata I/O hit percentage
.It Sy mm%
Metadata miss percentage
.It Sy mru
MRU list hits per second
.It Sy ph%
Prefetch hits percentage
+.It Sy pi%
+Prefetch I/O hits percentage
.It Sy pm%
Prefetch miss percentage
+.It Sy pdh%
+Prefetch data hits percentage
+.It Sy pdi%
+Prefetch data I/O hits percentage
+.It Sy pdm%
+Prefetch data miss percentage
+.It Sy pmh%
+Prefetch metadata hits percentage
+.It Sy pmi%
+Prefetch metadata I/O hits percentage
+.It Sy pmm%
+Prefetch metadata miss percentage
.It Sy dhit
-Demand data hits per second
+Demand hits per second
+.It Sy dioh
+Demand I/O hits per second
.It Sy dmis
+Demand misses per second
+.It Sy ddhit
+Demand data hits per second
+.It Sy ddioh
+Demand data I/O hits per second
+.It Sy ddmis
Demand data misses per second
+.It Sy dmhit
+Demand metadata hits per second
+.It Sy dmioh
+Demand metadata I/O hits per second
+.It Sy dmmis
+Demand metadata misses per second
.It Sy hit%
ARC hit percentage
.It Sy hits
-ARC reads per second
+ARC hits per second
+.It Sy ioh%
+ARC I/O hits percentage
+.It Sy iohs
+ARC I/O hits per second
.It Sy mfug
MFU ghost list hits per second
.It Sy mhit
Metadata hits per second
+.It Sy mioh
+Metadata I/O hits per second
.It Sy miss
ARC misses per second
.It Sy mmis
@@ -70,8 +120,22 @@ Metadata misses per second
MRU ghost list hits per second
.It Sy phit
Prefetch hits per second
+.It Sy pioh
+Prefetch I/O hits per second
.It Sy pmis
Prefetch misses per second
+.It Sy pdhit
+Prefetch data hits per second
+.It Sy pdioh
+Prefetch data I/O hits per second
+.It Sy pdmis
+Prefetch data misses per second
+.It Sy pmhit
+Prefetch metadata hits per second
+.It Sy pmioh
+Prefetch metadata I/O hits per second
+.It Sy pmmis
+Prefetch metadata misses per second
.It Sy read
Total ARC accesses per second
.It Sy time
@@ -81,8 +145,14 @@ ARC size
.It Sy arcsz
Alias for
.Sy size
+.It Sy unc
+Uncached list hits per second
.It Sy dread
+Demand accesses per second
+.It Sy ddread
Demand data accesses per second
+.It Sy dmread
+Demand metadata accesses per second
.It Sy eskip
evict_skip per second
.It Sy miss%
@@ -91,6 +161,10 @@ ARC miss percentage
Metadata accesses per second
.It Sy pread
Prefetch accesses per second
+.It Sy pdread
+Prefetch data accesses per second
+.It Sy pmread
+Prefetch metadata accesses per second
.It Sy l2hit%
L2ARC access hit percentage
.It Sy l2hits
@@ -134,7 +208,8 @@ ARC grow disabled
.It Sy need
ARC reclaim needed
.It Sy free
-The ARC's idea of how much free memory there is, which includes evictable memory in the page cache.
+The ARC's idea of how much free memory there is, which includes evictable memory
+in the page cache.
Since the ARC tries to keep
.Sy avail
above zero,
@@ -142,7 +217,8 @@ above zero,
is usually more instructive to observe than
.Sy free .
.It Sy avail
-The ARC's idea of how much free memory is available to it, which is a bit less than
+The ARC's idea of how much free memory is available to it, which is a bit less
+than
.Sy free .
May temporarily be negative, in which case the ARC will reduce the target size
.Sy c .
diff --git a/man/man1/cstyle.1 b/man/man1/cstyle.1
index e8f30f1f5950..726db298437e 100644
--- a/man/man1/cstyle.1
+++ b/man/man1/cstyle.1
@@ -8,7 +8,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man1/raidz_test.1 b/man/man1/raidz_test.1
index 5281d2b86db9..d027230d0dc9 100644
--- a/man/man1/raidz_test.1
+++ b/man/man1/raidz_test.1
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man1/test-runner.1 b/man/man1/test-runner.1
index b823aaa3e1a0..5bdb4d887e10 100644
--- a/man/man1/test-runner.1
+++ b/man/man1/test-runner.1
@@ -99,7 +99,8 @@ one directory.
The options specified on the command line or in a
.Ar runfile
apply to individual tests in the group.
-The exception is options pertaining to pre and post scripts, which act on all tests as a group.
+The exception is options pertaining to pre and post scripts, which act on all
+tests as a group.
Rather than running before and after each test,
these scripts are run only once each at the start and end of the test group.
.Ss Test Execution
@@ -254,7 +255,7 @@ Execute the post script as
.
.Sh EXAMPLES
.Bl -tag -width "-h"
-.It Sy Example 1 : No Running ad-hoc tests.
+.It Sy Example 1 : No Running ad-hoc tests .
This example demonstrates the simplest invocation of
.Nm .
.Bd -literal
@@ -270,7 +271,7 @@ Running Time: 00:00:07
Percent passed: 100.0%
Log directory: /var/tmp/test_results/20120923T180654
.Ed
-.It Sy Example 2 : No Creating a Ar runfile No for future use.
+.It Sy Example 2 : No Creating a Ar runfile No for future use .
This example demonstrates creating a
.Ar runfile
with non-default options.
diff --git a/man/man1/zhack.1 b/man/man1/zhack.1
index b03b87a1bdab..937f1e9168c2 100644
--- a/man/man1/zhack.1
+++ b/man/man1/zhack.1
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -98,9 +98,29 @@ feature is now required to read the pool MOS.
.It Xo
.Nm zhack
.Cm label repair
+.Op Fl cu
.Ar device
.Xc
-Repair corrupted labels by rewriting the checksum using the presumed valid contents of the label.
+Repair labels of a specified
+.Ar device
+according to options.
+.Pp
+Flags may be combined to do their functions simultaneously.
+.
+.Pp
+The
+.Fl c
+flag repairs corrupted label checksums
+.
+.Pp
+The
+.Fl u
+flag restores the label on a detached device
+.Pp
+Example:
+.Nm zhack Cm label repair Fl cu Ar device
+ Fix checksums and undetach a device
+.
.El
.
.Sh GLOBAL OPTIONS
diff --git a/man/man1/ztest.1 b/man/man1/ztest.1
index 9e44eb4579f9..bbbe751ca01d 100644
--- a/man/man1/ztest.1
+++ b/man/man1/ztest.1
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -52,6 +52,16 @@
.Op Fl T Ar time
.Op Fl z Ar zil_failure_rate
.
+.Nm
+.Fl X
+.Op Fl VG
+.Op Fl s Ar size_of_each_vdev
+.Op Fl a Ar alignment_shift
+.Op Fl r Ar raidz_disks
+.Op Fl R Ar raid_parity
+.Op Fl d Ar datasets
+.Op Fl t Ar threads
+.
.Sh DESCRIPTION
.Nm
was written by the ZFS Developers as a ZFS unit test.
@@ -114,19 +124,25 @@ Print a help summary.
Number of vdevs.
.It Fl s , -vdev-size Ns = (default: Sy 64M )
Size of each vdev.
-.It Fl a , -alignment-shift Ns = (default: Sy 9 ) No (use Sy 0 No for random)
+.It Fl a , -alignment-shift Ns = (default: Sy 9 ) No (use Sy 0 No for random )
Alignment shift used in test.
.It Fl m , -mirror-copies Ns = (default: Sy 2 )
Number of mirror copies.
-.It Fl r , -raid-disks Ns = (default: Sy 4 No for raidz/ Ns Sy 16 No for draid)
+.It Fl r , -raid-disks Ns = (default: Sy 4 No for raidz/ Ns Sy 16 No for draid )
Number of raidz/draid disks.
.It Fl R , -raid-parity Ns = (default: Sy 1 )
Raid parity (raidz & draid).
-.It Fl K , -raid-kind Ns = Ns Sy raidz Ns | Ns Sy draid Ns | Ns Sy random No (default: Sy random )
+.It Xo
+.Fl K , -raid-kind Ns = Ns
+.Sy raidz Ns | Ns Sy eraidz Ns | Ns Sy draid Ns | Ns Sy random
+(default:
+.Sy random Ns
+)
+.Xc
The kind of RAID config to use.
With
.Sy random
-the kind alternates between raidz and draid.
+the kind alternates between raidz, eraidz (expandable raidz) and draid.
.It Fl D , -draid-data Ns = (default: Sy 4 )
Number of data disks in a dRAID redundancy group.
.It Fl S , -draid-spares Ns = (default: Sy 1 )
@@ -159,7 +175,8 @@ Max loops in
.It Fl B , -alt-ztest Ns =
Path to alternate ("older")
.Nm ztest
-to drive, which will be used to initialise the pool, and, a stochastic half the time, to run the tests.
+to drive, which will be used to initialise the pool, and, a stochastic half the
+time, to run the tests.
The parallel
.Pa lib
directory is prepended to
@@ -168,7 +185,7 @@ i.e. given
.Fl B Pa ./chroots/lenny/usr/bin/ Ns Nm ,
.Pa ./chroots/lenny/usr/lib
will be loaded.
-.It Fl C , -vdev-class-state Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Sy random No (default: Sy random )
+.It Fl C , -vdev-class-state Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Sy random No (default : Sy random )
The vdev allocation class state.
.It Fl o , -option Ns = Ns Ar variable Ns = Ns Ar value
Set global
@@ -180,6 +197,8 @@ to an unsigned 32-bit integer
Dump zfs_dbgmsg buffer before exiting due to an error.
.It Fl V , -verbose
Verbose (use multiple times for ever more verbosity).
+.It Fl X , -raidz-expansion
+Perform a dedicated raidz expansion test.
.El
.
.Sh EXAMPLES
diff --git a/man/man4/spl.4 b/man/man4/spl.4
index 11cde14ae5ca..5cc12764e18c 100644
--- a/man/man4/spl.4
+++ b/man/man4/spl.4
@@ -2,7 +2,7 @@
.\" The contents of this file are subject to the terms of the Common Development
.\" and Distribution License (the "License"). You may not use this file except
.\" in compliance with the License. You can obtain a copy of the license at
-.\" usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
+.\" usr/src/OPENSOLARIS.LICENSE or https://opensource.org/licenses/CDDL-1.0.
.\"
.\" See the License for the specific language governing permissions and
.\" limitations under the License. When distributing Covered Code, include this
@@ -31,14 +31,6 @@ for use by the kmem caches.
For the majority of systems and workloads only a small number of threads are
required.
.
-.It Sy spl_kmem_cache_reclaim Ns = Ns Sy 0 Pq uint
-When this is set it prevents Linux from being able to rapidly reclaim all the
-memory held by the kmem caches.
-This may be useful in circumstances where it's preferable that Linux
-reclaim memory from some other subsystem first.
-Setting this will increase the likelihood out of memory events on a memory
-constrained system.
-.
.It Sy spl_kmem_cache_obj_per_slab Ns = Ns Sy 8 Pq uint
The preferred number of objects per slab in the cache.
In general, a larger value will increase the caches memory footprint
@@ -177,7 +169,8 @@ This is used to control
how quickly taskqs ramp up the number of threads processing the queue.
Because Linux thread creation and destruction are relatively inexpensive a
small default value has been selected.
-This means that normally threads will be created aggressively which is desirable.
+This means that normally threads will be created aggressively which is
+desirable.
Increasing this value will
result in a slower thread creation rate which may be preferable for some
configurations.
@@ -192,4 +185,9 @@ The proc file will walk the lists with lock held,
reading it could cause a lock-up if the list grow too large
without limiting the output.
"(truncated)" will be shown if the list is larger than the limit.
+.
+.It Sy spl_taskq_thread_timeout_ms Ns = Ns Sy 5000 Pq uint
+Minimum idle threads exit interval for dynamic taskqs.
+Smaller values allow idle threads exit more often and potentially be
+respawned again on demand, causing more churn.
.El
diff --git a/man/man4/zfs.4 b/man/man4/zfs.4
index a7e5408e5e37..5edd80659e08 100644
--- a/man/man4/zfs.4
+++ b/man/man4/zfs.4
@@ -2,10 +2,11 @@
.\" Copyright (c) 2013 by Turbo Fredriksson <turbo@bayour.com>. All rights reserved.
.\" Copyright (c) 2019, 2021 by Delphix. All rights reserved.
.\" Copyright (c) 2019 Datto Inc.
+.\" Copyright (c) 2023, 2024 Klara, Inc.
.\" The contents of this file are subject to the terms of the Common Development
.\" and Distribution License (the "License"). You may not use this file except
.\" in compliance with the License. You can obtain a copy of the license at
-.\" usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
+.\" usr/src/OPENSOLARIS.LICENSE or https://opensource.org/licenses/CDDL-1.0.
.\"
.\" See the License for the specific language governing permissions and
.\" limitations under the License. When distributing Covered Code, include this
@@ -15,7 +16,7 @@
.\" own identifying information:
.\" Portions Copyright [yyyy] [name of copyright owner]
.\"
-.Dd June 1, 2021
+.Dd February 14, 2024
.Dt ZFS 4
.Os
.
@@ -26,7 +27,7 @@
.Sh DESCRIPTION
The ZFS module supports these parameters:
.Bl -tag -width Ds
-.It Sy dbuf_cache_max_bytes Ns = Ns Sy ULONG_MAX Ns B Pq ulong
+.It Sy dbuf_cache_max_bytes Ns = Ns Sy UINT64_MAX Ns B Pq u64
Maximum size in bytes of the dbuf cache.
The target size is determined by the MIN versus
.No 1/2^ Ns Sy dbuf_cache_shift Pq 1/32nd
@@ -36,7 +37,7 @@ can be observed via the
.Pa /proc/spl/kstat/zfs/dbufstats
kstat.
.
-.It Sy dbuf_metadata_cache_max_bytes Ns = Ns Sy ULONG_MAX Ns B Pq ulong
+.It Sy dbuf_metadata_cache_max_bytes Ns = Ns Sy UINT64_MAX Ns B Pq u64
Maximum size in bytes of the metadata dbuf cache.
The target size is determined by the MIN versus
.No 1/2^ Ns Sy dbuf_metadata_cache_shift Pq 1/64th
@@ -56,21 +57,27 @@ The percentage below
.Sy dbuf_cache_max_bytes
when the evict thread stops evicting dbufs.
.
-.It Sy dbuf_cache_shift Ns = Ns Sy 5 Pq int
+.It Sy dbuf_cache_shift Ns = Ns Sy 5 Pq uint
Set the size of the dbuf cache
.Pq Sy dbuf_cache_max_bytes
to a log2 fraction of the target ARC size.
.
-.It Sy dbuf_metadata_cache_shift Ns = Ns Sy 6 Pq int
+.It Sy dbuf_metadata_cache_shift Ns = Ns Sy 6 Pq uint
Set the size of the dbuf metadata cache
.Pq Sy dbuf_metadata_cache_max_bytes
to a log2 fraction of the target ARC size.
.
-.It Sy dmu_object_alloc_chunk_shift Ns = Ns Sy 7 Po 128 Pc Pq int
+.It Sy dbuf_mutex_cache_shift Ns = Ns Sy 0 Pq uint
+Set the size of the mutex array for the dbuf cache.
+When set to
+.Sy 0
+the array is dynamically sized based on total system memory.
+.
+.It Sy dmu_object_alloc_chunk_shift Ns = Ns Sy 7 Po 128 Pc Pq uint
dnode slots allocated in a single operation as a power of 2.
The default value minimizes lock contention for the bulk operation performed.
.
-.It Sy dmu_prefetch_max Ns = Ns Sy 134217728 Ns B Po 128 MiB Pc Pq int
+.It Sy dmu_prefetch_max Ns = Ns Sy 134217728 Ns B Po 128 MiB Pc Pq uint
Limit the amount we can prefetch with one call to this amount in bytes.
This helps to limit the amount of memory that can be used by prefetching.
.
@@ -82,16 +89,16 @@ Alias for
Turbo L2ARC warm-up.
When the L2ARC is cold the fill interval will be set as fast as possible.
.
-.It Sy l2arc_feed_min_ms Ns = Ns Sy 200 Pq ulong
+.It Sy l2arc_feed_min_ms Ns = Ns Sy 200 Pq u64
Min feed interval in milliseconds.
Requires
.Sy l2arc_feed_again Ns = Ns Ar 1
and only applicable in related situations.
.
-.It Sy l2arc_feed_secs Ns = Ns Sy 1 Pq ulong
+.It Sy l2arc_feed_secs Ns = Ns Sy 1 Pq u64
Seconds between L2ARC writing.
.
-.It Sy l2arc_headroom Ns = Ns Sy 2 Pq ulong
+.It Sy l2arc_headroom Ns = Ns Sy 8 Pq u64
How far through the ARC lists to search for L2ARC cacheable content,
expressed as a multiplier of
.Sy l2arc_write_max .
@@ -100,7 +107,7 @@ by setting this parameter to
.Sy 0 ,
allowing the full length of ARC lists to be searched for cacheable content.
.
-.It Sy l2arc_headroom_boost Ns = Ns Sy 200 Ns % Pq ulong
+.It Sy l2arc_headroom_boost Ns = Ns Sy 200 Ns % Pq u64
Scales
.Sy l2arc_headroom
by this percentage when L2ARC contents are being successfully compressed
@@ -149,14 +156,14 @@ provided by the
arcstats can be used to decide if toggling this option is appropriate
for the current workload.
.
-.It Sy l2arc_meta_percent Ns = Ns Sy 33 Ns % Pq int
+.It Sy l2arc_meta_percent Ns = Ns Sy 33 Ns % Pq uint
Percent of ARC size allowed for L2ARC-only headers.
Since L2ARC buffers are not evicted on memory pressure,
too many headers on a system with an irrationally large L2ARC
can render it slow or unusable.
This parameter limits L2ARC writes and rebuilds to achieve the target.
.
-.It Sy l2arc_trim_ahead Ns = Ns Sy 0 Ns % Pq ulong
+.It Sy l2arc_trim_ahead Ns = Ns Sy 0 Ns % Pq u64
Trims ahead of the current write size
.Pq Sy l2arc_write_max
on L2ARC devices by this percentage of write size if we have filled the device.
@@ -194,12 +201,12 @@ to enable caching/reading prefetches to/from L2ARC.
.It Sy l2arc_norw Ns = Ns Sy 0 Ns | Ns 1 Pq int
No reads during writes.
.
-.It Sy l2arc_write_boost Ns = Ns Sy 8388608 Ns B Po 8 MiB Pc Pq ulong
+.It Sy l2arc_write_boost Ns = Ns Sy 33554432 Ns B Po 32 MiB Pc Pq u64
Cold L2ARC devices will have
.Sy l2arc_write_max
increased by this amount while they remain cold.
.
-.It Sy l2arc_write_max Ns = Ns Sy 8388608 Ns B Po 8 MiB Pc Pq ulong
+.It Sy l2arc_write_max Ns = Ns Sy 33554432 Ns B Po 32 MiB Pc Pq u64
Max write bytes per interval.
.
.It Sy l2arc_rebuild_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
@@ -209,7 +216,7 @@ or attaching an L2ARC device (e.g. the L2ARC device is slow
in reading stored log metadata, or the metadata
has become somehow fragmented/unusable).
.
-.It Sy l2arc_rebuild_blocks_min_l2size Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq ulong
+.It Sy l2arc_rebuild_blocks_min_l2size Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq u64
Mininum size of an L2ARC device required in order to write log blocks in it.
The log blocks are used upon importing the pool to rebuild the persistent L2ARC.
.Pp
@@ -218,7 +225,7 @@ For L2ARC devices less than 1 GiB, the amount of data
evicts is significant compared to the amount of restored L2ARC data.
In this case, do not write log blocks in L2ARC in order not to waste space.
.
-.It Sy metaslab_aliquot Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq ulong
+.It Sy metaslab_aliquot Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq u64
Metaslab granularity, in bytes.
This is roughly similar to what would be referred to as the "stripe size"
in traditional RAID arrays.
@@ -229,11 +236,45 @@ before moving on to the next top-level vdev.
Enable metaslab group biasing based on their vdevs' over- or under-utilization
relative to the pool.
.
-.It Sy metaslab_force_ganging Ns = Ns Sy 16777217 Ns B Po 16 MiB + 1 B Pc Pq ulong
+.It Sy metaslab_force_ganging Ns = Ns Sy 16777217 Ns B Po 16 MiB + 1 B Pc Pq u64
Make some blocks above a certain size be gang blocks.
This option is used by the test suite to facilitate testing.
.
-.It Sy zfs_history_output_max Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq int
+.It Sy metaslab_force_ganging_pct Ns = Ns Sy 3 Ns % Pq uint
+For blocks that could be forced to be a gang block (due to
+.Sy metaslab_force_ganging ) ,
+force this many of them to be gang blocks.
+.
+.It Sy brt_zap_prefetch Ns = Ns Sy 1 Ns | Ns 0 Pq int
+Controls prefetching BRT records for blocks which are going to be cloned.
+.
+.It Sy brt_zap_default_bs Ns = Ns Sy 12 Po 4 KiB Pc Pq int
+Default BRT ZAP data block size as a power of 2. Note that changing this after
+creating a BRT on the pool will not affect existing BRTs, only newly created
+ones.
+.
+.It Sy brt_zap_default_ibs Ns = Ns Sy 12 Po 4 KiB Pc Pq int
+Default BRT ZAP indirect block size as a power of 2. Note that changing this
+after creating a BRT on the pool will not affect existing BRTs, only newly
+created ones.
+.
+.It Sy ddt_zap_default_bs Ns = Ns Sy 15 Po 32 KiB Pc Pq int
+Default DDT ZAP data block size as a power of 2. Note that changing this after
+creating a DDT on the pool will not affect existing DDTs, only newly created
+ones.
+.
+.It Sy ddt_zap_default_ibs Ns = Ns Sy 15 Po 32 KiB Pc Pq int
+Default DDT ZAP indirect block size as a power of 2. Note that changing this
+after creating a DDT on the pool will not affect existing DDTs, only newly
+created ones.
+.
+.It Sy zfs_default_bs Ns = Ns Sy 9 Po 512 B Pc Pq int
+Default dnode block size as a power of 2.
+.
+.It Sy zfs_default_ibs Ns = Ns Sy 17 Po 128 KiB Pc Pq int
+Default dnode indirect block size as a power of 2.
+.
+.It Sy zfs_history_output_max Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq u64
When attempting to log an output nvlist of an ioctl in the on-disk history,
the output will not be stored if it is larger than this size (in bytes).
This must be less than
@@ -261,7 +302,7 @@ Prevent metaslabs from being unloaded.
.It Sy metaslab_fragmentation_factor_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
Enable use of the fragmentation metric in computing metaslab weights.
.
-.It Sy metaslab_df_max_search Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
+.It Sy metaslab_df_max_search Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq uint
Maximum distance to search forward from the last offset.
Without this limit, fragmented pools can see
.Em >100`000
@@ -293,7 +334,7 @@ this tunable controls which segment is used.
If set, we will use the largest free segment.
If unset, we will use a segment of at least the requested size.
.
-.It Sy zfs_metaslab_max_size_cache_sec Ns = Ns Sy 3600 Ns s Po 1 hour Pc Pq ulong
+.It Sy zfs_metaslab_max_size_cache_sec Ns = Ns Sy 3600 Ns s Po 1 hour Pc Pq u64
When we unload a metaslab, we cache the size of the largest free chunk.
We use that cached size to determine whether or not to load a metaslab
for a given allocation.
@@ -303,7 +344,7 @@ After a number of seconds controlled by this tunable,
we stop considering the cached max size and start
considering only the histogram instead.
.
-.It Sy zfs_metaslab_mem_limit Ns = Ns Sy 25 Ns % Pq int
+.It Sy zfs_metaslab_mem_limit Ns = Ns Sy 25 Ns % Pq uint
When we are loading a new metaslab, we check the amount of memory being used
to store metaslab range trees.
If it is over a threshold, we attempt to unload the least recently used metaslab
@@ -335,26 +376,33 @@ If that fails we will do a "try hard" gang allocation.
If that fails then we will have a multi-layer gang block.
.El
.
-.It Sy zfs_metaslab_find_max_tries Ns = Ns Sy 100 Pq int
+.It Sy zfs_metaslab_find_max_tries Ns = Ns Sy 100 Pq uint
When not trying hard, we only consider this number of the best metaslabs.
This improves performance, especially when there are many metaslabs per vdev
and the allocation can't actually be satisfied
(so we would otherwise iterate all metaslabs).
.
-.It Sy zfs_vdev_default_ms_count Ns = Ns Sy 200 Pq int
+.It Sy zfs_vdev_default_ms_count Ns = Ns Sy 200 Pq uint
When a vdev is added, target this number of metaslabs per top-level vdev.
.
-.It Sy zfs_vdev_default_ms_shift Ns = Ns Sy 29 Po 512 MiB Pc Pq int
-Default limit for metaslab size.
+.It Sy zfs_vdev_default_ms_shift Ns = Ns Sy 29 Po 512 MiB Pc Pq uint
+Default lower limit for metaslab size.
+.
+.It Sy zfs_vdev_max_ms_shift Ns = Ns Sy 34 Po 16 GiB Pc Pq uint
+Default upper limit for metaslab size.
.
-.It Sy zfs_vdev_max_auto_ashift Ns = Ns Sy ASHIFT_MAX Po 16 Pc Pq ulong
-Maximum ashift used when optimizing for logical \[->] physical sector size on new
+.It Sy zfs_vdev_max_auto_ashift Ns = Ns Sy 14 Pq uint
+Maximum ashift used when optimizing for logical \[->] physical sector size on
+new
top-level vdevs.
+May be increased up to
+.Sy ASHIFT_MAX Po 16 Pc ,
+but this may negatively impact pool space efficiency.
.
-.It Sy zfs_vdev_min_auto_ashift Ns = Ns Sy ASHIFT_MIN Po 9 Pc Pq ulong
+.It Sy zfs_vdev_min_auto_ashift Ns = Ns Sy ASHIFT_MIN Po 9 Pc Pq uint
Minimum ashift used when creating new top-level vdevs.
.
-.It Sy zfs_vdev_min_ms_count Ns = Ns Sy 16 Pq int
+.It Sy zfs_vdev_min_ms_count Ns = Ns Sy 16 Pq uint
Minimum number of metaslabs to create in a top-level vdev.
.
.It Sy vdev_validate_skip Ns = Ns Sy 0 Ns | Ns 1 Pq int
@@ -362,33 +410,53 @@ Skip label validation steps during pool import.
Changing is not recommended unless you know what you're doing
and are recovering a damaged label.
.
-.It Sy zfs_vdev_ms_count_limit Ns = Ns Sy 131072 Po 128k Pc Pq int
+.It Sy zfs_vdev_ms_count_limit Ns = Ns Sy 131072 Po 128k Pc Pq uint
Practical upper limit of total metaslabs per top-level vdev.
.
.It Sy metaslab_preload_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
Enable metaslab group preloading.
.
+.It Sy metaslab_preload_limit Ns = Ns Sy 10 Pq uint
+Maximum number of metaslabs per group to preload
+.
+.It Sy metaslab_preload_pct Ns = Ns Sy 50 Pq uint
+Percentage of CPUs to run a metaslab preload taskq
+.
.It Sy metaslab_lba_weighting_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
Give more weight to metaslabs with lower LBAs,
assuming they have greater bandwidth,
as is typically the case on a modern constant angular velocity disk drive.
.
-.It Sy metaslab_unload_delay Ns = Ns Sy 32 Pq int
+.It Sy metaslab_unload_delay Ns = Ns Sy 32 Pq uint
After a metaslab is used, we keep it loaded for this many TXGs, to attempt to
reduce unnecessary reloading.
Note that both this many TXGs and
.Sy metaslab_unload_delay_ms
milliseconds must pass before unloading will occur.
.
-.It Sy metaslab_unload_delay_ms Ns = Ns Sy 600000 Ns ms Po 10 min Pc Pq int
+.It Sy metaslab_unload_delay_ms Ns = Ns Sy 600000 Ns ms Po 10 min Pc Pq uint
After a metaslab is used, we keep it loaded for this many milliseconds,
to attempt to reduce unnecessary reloading.
Note, that both this many milliseconds and
.Sy metaslab_unload_delay
TXGs must pass before unloading will occur.
.
+.It Sy reference_history Ns = Ns Sy 3 Pq uint
+Maximum reference holders being tracked when reference_tracking_enable is
+active.
+.It Sy raidz_expand_max_copy_bytes Ns = Ns Sy 160MB Pq ulong
+Max amount of memory to use for RAID-Z expansion I/O.
+This limits how much I/O can be outstanding at once.
+.
+.It Sy raidz_expand_max_reflow_bytes Ns = Ns Sy 0 Pq ulong
+For testing, pause RAID-Z expansion when reflow amount reaches this value.
+.
+.It Sy raidz_io_aggregate_rows Ns = Ns Sy 4 Pq ulong
+For expanded RAID-Z, aggregate reads that have more rows than this.
+.
.It Sy reference_history Ns = Ns Sy 3 Pq int
-Maximum reference holders being tracked when reference_tracking_enable is active.
+Maximum reference holders being tracked when reference_tracking_enable is
+active.
.
.It Sy reference_tracking_enable Ns = Ns Sy 0 Ns | Ns 1 Pq int
Track reference holders to
@@ -406,7 +474,7 @@ This is useful if you suspect your datasets are affected by a bug in
.It Sy spa_config_path Ns = Ns Pa /etc/zfs/zpool.cache Pq charp
SPA config file.
.
-.It Sy spa_asize_inflation Ns = Ns Sy 24 Pq int
+.It Sy spa_asize_inflation Ns = Ns Sy 24 Pq uint
Multiplication factor used to estimate actual disk consumption from the
size of data being written.
The default value is a worst case estimate,
@@ -416,7 +484,8 @@ may wish to specify a more realistic inflation factor,
particularly if they operate close to quota or capacity limits.
.
.It Sy spa_load_print_vdev_tree Ns = Ns Sy 0 Ns | Ns 1 Pq int
-Whether to print the vdev tree in the debugging message buffer during pool import.
+Whether to print the vdev tree in the debugging message buffer during pool
+import.
.
.It Sy spa_load_verify_data Ns = Ns Sy 1 Ns | Ns 0 Pq int
Whether to traverse data blocks during an "extreme rewind"
@@ -439,7 +508,7 @@ blocks in the pool for verification.
If this parameter is unset, the traversal is not performed.
It can be toggled once the import has started to stop or start the traversal.
.
-.It Sy spa_load_verify_shift Ns = Ns Sy 4 Po 1/16th Pc Pq int
+.It Sy spa_load_verify_shift Ns = Ns Sy 4 Po 1/16th Pc Pq uint
Sets the maximum number of bytes to consume during pool import to the log2
fraction of the target ARC size.
.
@@ -454,6 +523,20 @@ If we have less than this amount of free space,
most ZPL operations (e.g. write, create) will return
.Sy ENOSPC .
.
+.It Sy spa_num_allocators Ns = Ns Sy 4 Pq int
+Determines the number of block alloctators to use per spa instance.
+Capped by the number of actual CPUs in the system via
+.Sy spa_cpus_per_allocator .
+.Pp
+Note that setting this value too high could result in performance
+degredation and/or excess fragmentation.
+Set value only applies to pools imported/created after that.
+.
+.It Sy spa_cpus_per_allocator Ns = Ns Sy 4 Pq int
+Determines the minimum number of CPUs in a system for block alloctator
+per spa instance.
+Set value only applies to pools imported/created after that.
+.
.It Sy spa_upgrade_errlog_limit Ns = Ns Sy 0 Pq uint
Limits the number of on-disk error log entries that will be converted to the
new format when enabling the
@@ -461,7 +544,7 @@ new format when enabling the
feature.
The default is to convert all log entries.
.
-.It Sy vdev_removal_max_span Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq int
+.It Sy vdev_removal_max_span Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq uint
During top-level vdev removal, chunks of data are copied from the vdev
which may include free space in order to trade bandwidth for IOPS.
This parameter determines the maximum span of free space, in bytes,
@@ -472,10 +555,10 @@ The default value here was chosen to align with
which is a similar concept when doing
regular reads (but there's no reason it has to be the same).
.
-.It Sy vdev_file_logical_ashift Ns = Ns Sy 9 Po 512 B Pc Pq ulong
+.It Sy vdev_file_logical_ashift Ns = Ns Sy 9 Po 512 B Pc Pq u64
Logical ashift for file-based devices.
.
-.It Sy vdev_file_physical_ashift Ns = Ns Sy 9 Po 512 B Pc Pq ulong
+.It Sy vdev_file_physical_ashift Ns = Ns Sy 9 Po 512 B Pc Pq u64
Physical ashift for file-based devices.
.
.It Sy zap_iterate_prefetch Ns = Ns Sy 1 Ns | Ns 0 Pq int
@@ -484,8 +567,12 @@ prefetch the entire object (all leaf blocks).
However, this is limited by
.Sy dmu_prefetch_max .
.
-.It Sy zfetch_array_rd_sz Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq ulong
-If prefetching is enabled, disable prefetching for reads larger than this size.
+.It Sy zap_micro_max_size Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq int
+Maximum micro ZAP size.
+A micro ZAP is upgraded to a fat ZAP, once it grows beyond the specified size.
+.
+.It Sy zap_shrink_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
+If set, adjacent empty ZAP blocks will be collapsed, reducing disk space.
.
.It Sy zfetch_min_distance Ns = Ns Sy 4194304 Ns B Po 4 MiB Pc Pq uint
Min bytes to prefetch per stream.
@@ -501,6 +588,13 @@ Max bytes to prefetch per stream.
.It Sy zfetch_max_idistance Ns = Ns Sy 67108864 Ns B Po 64 MiB Pc Pq uint
Max bytes to prefetch indirects for per stream.
.
+.It Sy zfetch_max_reorder Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq uint
+Requests within this byte distance from the current prefetch stream position
+are considered parts of the stream, reordered due to parallel processing.
+Such requests do not advance the stream position immediately unless
+.Sy zfetch_hole_shift
+fill threshold is reached, but saved to fill holes in the stream later.
+.
.It Sy zfetch_max_streams Ns = Ns Sy 8 Pq uint
Max number of streams per zfetch (prefetch streams per file).
.
@@ -528,7 +622,7 @@ depends on kernel configuration.
This is the minimum allocation size that will use scatter (page-based) ABDs.
Smaller allocations will use linear ABDs.
.
-.It Sy zfs_arc_dnode_limit Ns = Ns Sy 0 Ns B Pq ulong
+.It Sy zfs_arc_dnode_limit Ns = Ns Sy 0 Ns B Pq u64
When the number of bytes consumed by dnodes in the ARC exceeds this number of
bytes, try to unpin some of it in response to demand for non-metadata.
This value acts as a ceiling to the amount of dnode metadata, and defaults to
@@ -536,27 +630,19 @@ This value acts as a ceiling to the amount of dnode metadata, and defaults to
which indicates that a percent which is based on
.Sy zfs_arc_dnode_limit_percent
of the ARC meta buffers that may be used for dnodes.
-.Pp
-Also see
-.Sy zfs_arc_meta_prune
-which serves a similar purpose but is used
-when the amount of metadata in the ARC exceeds
-.Sy zfs_arc_meta_limit
-rather than in response to overall demand for non-metadata.
-.
-.It Sy zfs_arc_dnode_limit_percent Ns = Ns Sy 10 Ns % Pq ulong
+.It Sy zfs_arc_dnode_limit_percent Ns = Ns Sy 10 Ns % Pq u64
Percentage that can be consumed by dnodes of ARC meta buffers.
.Pp
See also
.Sy zfs_arc_dnode_limit ,
which serves a similar purpose but has a higher priority if nonzero.
.
-.It Sy zfs_arc_dnode_reduce_percent Ns = Ns Sy 10 Ns % Pq ulong
+.It Sy zfs_arc_dnode_reduce_percent Ns = Ns Sy 10 Ns % Pq u64
Percentage of ARC dnodes to try to scan in response to demand for non-metadata
when the number of bytes consumed by dnodes exceeds
.Sy zfs_arc_dnode_limit .
.
-.It Sy zfs_arc_average_blocksize Ns = Ns Sy 8192 Ns B Po 8 KiB Pc Pq int
+.It Sy zfs_arc_average_blocksize Ns = Ns Sy 8192 Ns B Po 8 KiB Pc Pq uint
The ARC's buffer hash table is sized based on the assumption of an average
block size of this value.
This works out to roughly 1 MiB of hash table per 1 GiB of physical memory
@@ -564,7 +650,7 @@ with 8-byte pointers.
For configurations with a known larger average block size,
this value can be increased to reduce the memory footprint.
.
-.It Sy zfs_arc_eviction_pct Ns = Ns Sy 200 Ns % Pq int
+.It Sy zfs_arc_eviction_pct Ns = Ns Sy 200 Ns % Pq uint
When
.Fn arc_is_overflowing ,
.Fn arc_get_data_impl
@@ -582,12 +668,12 @@ Since this is finite, it ensures that allocations can still happen,
even during the potentially long time that
.Sy arc_size No is more than Sy arc_c .
.
-.It Sy zfs_arc_evict_batch_limit Ns = Ns Sy 10 Pq int
+.It Sy zfs_arc_evict_batch_limit Ns = Ns Sy 10 Pq uint
Number ARC headers to evict per sub-list before proceeding to another sub-list.
This batch-style operation prevents entire sub-lists from being evicted at once
but comes at a cost of additional unlocking and locking.
.
-.It Sy zfs_arc_grow_retry Ns = Ns Sy 0 Ns s Pq int
+.It Sy zfs_arc_grow_retry Ns = Ns Sy 0 Ns s Pq uint
If set to a non zero value, it will replace the
.Sy arc_grow_retry
value with this value.
@@ -604,15 +690,12 @@ Setting this value to
.Sy 0
will disable the throttle.
.
-.It Sy zfs_arc_max Ns = Ns Sy 0 Ns B Pq ulong
+.It Sy zfs_arc_max Ns = Ns Sy 0 Ns B Pq u64
Max size of ARC in bytes.
If
.Sy 0 ,
then the max size of ARC is determined by the amount of system memory installed.
-Under Linux, half of system memory will be used as the limit.
-Under
-.Fx ,
-the larger of
+The larger of
.Sy all_system_memory No \- Sy 1 GiB
and
.Sy 5/8 No \(mu Sy all_system_memory
@@ -626,63 +709,12 @@ It cannot be set back to
while running, and reducing it below the current ARC size will not cause
the ARC to shrink without memory pressure to induce shrinking.
.
-.It Sy zfs_arc_meta_adjust_restarts Ns = Ns Sy 4096 Pq ulong
-The number of restart passes to make while scanning the ARC attempting
-the free buffers in order to stay below the
-.Sy fs_arc_meta_limit .
-This value should not need to be tuned but is available to facilitate
-performance analysis.
-.
-.It Sy zfs_arc_meta_limit Ns = Ns Sy 0 Ns B Pq ulong
-The maximum allowed size in bytes that metadata buffers are allowed to
-consume in the ARC.
-When this limit is reached, metadata buffers will be reclaimed,
-even if the overall
-.Sy arc_c_max
-has not been reached.
-It defaults to
-.Sy 0 ,
-which indicates that a percentage based on
-.Sy zfs_arc_meta_limit_percent
-of the ARC may be used for metadata.
-.Pp
-This value my be changed dynamically, except that must be set to an explicit value
-.Pq cannot be set back to Sy 0 .
+.It Sy zfs_arc_meta_balance Ns = Ns Sy 500 Pq uint
+Balance between metadata and data on ghost hits.
+Values above 100 increase metadata caching by proportionally reducing effect
+of ghost data hits on target data/metadata rate.
.
-.It Sy zfs_arc_meta_limit_percent Ns = Ns Sy 75 Ns % Pq ulong
-Percentage of ARC buffers that can be used for metadata.
-.Pp
-See also
-.Sy zfs_arc_meta_limit ,
-which serves a similar purpose but has a higher priority if nonzero.
-.
-.It Sy zfs_arc_meta_min Ns = Ns Sy 0 Ns B Pq ulong
-The minimum allowed size in bytes that metadata buffers may consume in
-the ARC.
-.
-.It Sy zfs_arc_meta_prune Ns = Ns Sy 10000 Pq int
-The number of dentries and inodes to be scanned looking for entries
-which can be dropped.
-This may be required when the ARC reaches the
-.Sy zfs_arc_meta_limit
-because dentries and inodes can pin buffers in the ARC.
-Increasing this value will cause to dentry and inode caches
-to be pruned more aggressively.
-Setting this value to
-.Sy 0
-will disable pruning the inode and dentry caches.
-.
-.It Sy zfs_arc_meta_strategy Ns = Ns Sy 1 Ns | Ns 0 Pq int
-Define the strategy for ARC metadata buffer eviction (meta reclaim strategy):
-.Bl -tag -compact -offset 4n -width "0 (META_ONLY)"
-.It Sy 0 Pq META_ONLY
-evict only the ARC metadata buffers
-.It Sy 1 Pq BALANCED
-additional data buffers may be evicted if required
-to evict the required number of metadata buffers.
-.El
-.
-.It Sy zfs_arc_min Ns = Ns Sy 0 Ns B Pq ulong
+.It Sy zfs_arc_min Ns = Ns Sy 0 Ns B Pq u64
Min size of ARC in bytes.
.No If set to Sy 0 , arc_c_min
will default to consuming the larger of
@@ -690,10 +722,10 @@ will default to consuming the larger of
and
.Sy all_system_memory No / Sy 32 .
.
-.It Sy zfs_arc_min_prefetch_ms Ns = Ns Sy 0 Ns ms Ns Po Ns ≡ Ns 1s Pc Pq int
+.It Sy zfs_arc_min_prefetch_ms Ns = Ns Sy 0 Ns ms Ns Po Ns ≡ Ns 1s Pc Pq uint
Minimum time prefetched blocks are locked in the ARC.
.
-.It Sy zfs_arc_min_prescient_prefetch_ms Ns = Ns Sy 0 Ns ms Ns Po Ns ≡ Ns 6s Pc Pq int
+.It Sy zfs_arc_min_prescient_prefetch_ms Ns = Ns Sy 0 Ns ms Ns Po Ns ≡ Ns 6s Pc Pq uint
Minimum time "prescient prefetched" blocks are locked in the ARC.
These blocks are meant to be prefetched fairly aggressively ahead of
the code that may use them.
@@ -709,7 +741,7 @@ but that was not proven to be useful.
Number of missing top-level vdevs which will be allowed during
pool import (only in read-only mode).
.
-.It Sy zfs_max_nvlist_src_size Ns = Sy 0 Pq ulong
+.It Sy zfs_max_nvlist_src_size Ns = Sy 0 Pq u64
Maximum size in bytes allowed to be passed as
.Sy zc_nvlist_src_size
for ioctls on
@@ -730,7 +762,7 @@ and to
.Sy 134217728 Ns B Pq 128 MiB
under Linux.
.
-.It Sy zfs_multilist_num_sublists Ns = Ns Sy 0 Pq int
+.It Sy zfs_multilist_num_sublists Ns = Ns Sy 0 Pq uint
To allow more fine-grained locking, each ARC state contains a series
of lists for both data and metadata objects.
Locking is performed at the level of these "sub-lists".
@@ -763,21 +795,7 @@ causes the ARC to start reclamation if it exceeds the target size by
of the target size, and block allocations by
.Em 0.6% .
.
-.It Sy zfs_arc_p_min_shift Ns = Ns Sy 0 Pq int
-If nonzero, this will update
-.Sy arc_p_min_shift Pq default Sy 4
-with the new value.
-.Sy arc_p_min_shift No is used as a shift of Sy arc_c
-when calculating the minumum
-.Sy arc_p No size.
-.
-.It Sy zfs_arc_p_dampener_disable Ns = Ns Sy 1 Ns | Ns 0 Pq int
-Disable
-.Sy arc_p
-adapt dampener, which reduces the maximum single adjustment to
-.Sy arc_p .
-.
-.It Sy zfs_arc_shrink_shift Ns = Ns Sy 0 Pq int
+.It Sy zfs_arc_shrink_shift Ns = Ns Sy 0 Pq uint
If nonzero, this will update
.Sy arc_shrink_shift Pq default Sy 7
with the new value.
@@ -813,7 +831,7 @@ even with a small average compressed block size of ~8 KiB.
The parameter can be set to 0 (zero) to disable the limit,
and only applies on Linux.
.
-.It Sy zfs_arc_sys_free Ns = Ns Sy 0 Ns B Pq ulong
+.It Sy zfs_arc_sys_free Ns = Ns Sy 0 Ns B Pq u64
The target number of bytes the ARC should leave as free memory on the system.
If zero, equivalent to the bigger of
.Sy 512 KiB No and Sy all_system_memory/64 .
@@ -828,7 +846,7 @@ Note that this should not be set below the ZED thresholds
(currently 10 checksums over 10 seconds)
or else the daemon may not trigger any action.
.
-.It Sy zfs_commit_timeout_pct Ns = Ns Sy 5 Ns % Pq int
+.It Sy zfs_commit_timeout_pct Ns = Ns Sy 10 Ns % Pq uint
This controls the amount of time that a ZIL block (lwb) will remain "open"
when it isn't "full", and it has a thread waiting for it to be committed to
stable storage.
@@ -841,8 +859,9 @@ Vdev indirection layer (used for device removal) sleeps for this many
milliseconds during mapping generation.
Intended for use with the test suite to throttle vdev removal speed.
.
-.It Sy zfs_condense_indirect_obsolete_pct Ns = Ns Sy 25 Ns % Pq int
-Minimum percent of obsolete bytes in vdev mapping required to attempt to condense
+.It Sy zfs_condense_indirect_obsolete_pct Ns = Ns Sy 25 Ns % Pq uint
+Minimum percent of obsolete bytes in vdev mapping required to attempt to
+condense
.Pq see Sy zfs_condense_indirect_vdevs_enable .
Intended for use with the test suite
to facilitate triggering condensing as needed.
@@ -855,14 +874,15 @@ if the mapping uses more than
bytes of memory and if the obsolete space map object uses more than
.Sy zfs_condense_max_obsolete_bytes
bytes on-disk.
-The condensing process is an attempt to save memory by removing obsolete mappings.
+The condensing process is an attempt to save memory by removing obsolete
+mappings.
.
-.It Sy zfs_condense_max_obsolete_bytes Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq ulong
+.It Sy zfs_condense_max_obsolete_bytes Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq u64
Only attempt to condense indirect vdev mappings if the on-disk size
of the obsolete space map object is greater than this number of bytes
.Pq see Sy zfs_condense_indirect_vdevs_enable .
.
-.It Sy zfs_condense_min_mapping_bytes Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq ulong
+.It Sy zfs_condense_min_mapping_bytes Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq u64
Minimum size vdev mapping to attempt to condense
.Pq see Sy zfs_condense_indirect_vdevs_enable .
.
@@ -878,7 +898,7 @@ to the file clears the log.
This setting does not influence debug prints due to
.Sy zfs_flags .
.
-.It Sy zfs_dbgmsg_maxsize Ns = Ns Sy 4194304 Ns B Po 4 MiB Pc Pq int
+.It Sy zfs_dbgmsg_maxsize Ns = Ns Sy 4194304 Ns B Po 4 MiB Pc Pq uint
Maximum size of the internal ZFS debug log.
.
.It Sy zfs_dbuf_state_index Ns = Ns Sy 0 Pq int
@@ -918,21 +938,21 @@ This can be used to facilitate automatic fail-over
to a properly configured fail-over partner.
.El
.
-.It Sy zfs_deadman_checktime_ms Ns = Ns Sy 60000 Ns ms Po 1 min Pc Pq int
+.It Sy zfs_deadman_checktime_ms Ns = Ns Sy 60000 Ns ms Po 1 min Pc Pq u64
Check time in milliseconds.
This defines the frequency at which we check for hung I/O requests
and potentially invoke the
.Sy zfs_deadman_failmode
behavior.
.
-.It Sy zfs_deadman_synctime_ms Ns = Ns Sy 600000 Ns ms Po 10 min Pc Pq ulong
+.It Sy zfs_deadman_synctime_ms Ns = Ns Sy 600000 Ns ms Po 10 min Pc Pq u64
Interval in milliseconds after which the deadman is triggered and also
the interval after which a pool sync operation is considered to be "hung".
Once this limit is exceeded the deadman will be invoked every
.Sy zfs_deadman_checktime_ms
milliseconds until the pool sync completes.
.
-.It Sy zfs_deadman_ziotime_ms Ns = Ns Sy 300000 Ns ms Po 5 min Pc Pq ulong
+.It Sy zfs_deadman_ziotime_ms Ns = Ns Sy 300000 Ns ms Po 5 min Pc Pq u64
Interval in milliseconds after which the deadman is triggered and an
individual I/O operation is considered to be "hung".
As long as the operation remains "hung",
@@ -943,7 +963,7 @@ milliseconds until the operation completes.
.It Sy zfs_dedup_prefetch Ns = Ns Sy 0 Ns | Ns 1 Pq int
Enable prefetching dedup-ed blocks which are going to be freed.
.
-.It Sy zfs_delay_min_dirty_percent Ns = Ns Sy 60 Ns % Pq int
+.It Sy zfs_delay_min_dirty_percent Ns = Ns Sy 60 Ns % Pq uint
Start to delay each transaction once there is this amount of dirty data,
expressed as a percentage of
.Sy zfs_dirty_data_max .
@@ -982,18 +1002,19 @@ will result in objects waiting when there is not actually contention on the
same object.
.
.It Sy zfs_slow_io_events_per_second Ns = Ns Sy 20 Ns /s Pq int
-Rate limit delay and deadman zevents (which report slow I/O operations) to this many per
+Rate limit delay and deadman zevents (which report slow I/O operations) to this
+many per
second.
.
-.It Sy zfs_unflushed_max_mem_amt Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq ulong
+.It Sy zfs_unflushed_max_mem_amt Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq u64
Upper-bound limit for unflushed metadata changes to be held by the
log spacemap in memory, in bytes.
.
-.It Sy zfs_unflushed_max_mem_ppm Ns = Ns Sy 1000 Ns ppm Po 0.1% Pc Pq ulong
+.It Sy zfs_unflushed_max_mem_ppm Ns = Ns Sy 1000 Ns ppm Po 0.1% Pc Pq u64
Part of overall system memory that ZFS allows to be used
for unflushed metadata changes by the log spacemap, in millionths.
.
-.It Sy zfs_unflushed_log_block_max Ns = Ns Sy 131072 Po 128k Pc Pq ulong
+.It Sy zfs_unflushed_log_block_max Ns = Ns Sy 131072 Po 128k Pc Pq u64
Describes the maximum number of log spacemap blocks allowed for each pool.
The default value means that the space in all the log spacemaps
can add up to no more than
@@ -1021,17 +1042,17 @@ one extra logical I/O issued.
This is the reason why this tunable is exposed in terms of blocks rather
than space used.
.
-.It Sy zfs_unflushed_log_block_min Ns = Ns Sy 1000 Pq ulong
+.It Sy zfs_unflushed_log_block_min Ns = Ns Sy 1000 Pq u64
If the number of metaslabs is small and our incoming rate is high,
we could get into a situation that we are flushing all our metaslabs every TXG.
Thus we always allow at least this many log blocks.
.
-.It Sy zfs_unflushed_log_block_pct Ns = Ns Sy 400 Ns % Pq ulong
+.It Sy zfs_unflushed_log_block_pct Ns = Ns Sy 400 Ns % Pq u64
Tunable used to determine the number of blocks that can be used for
the spacemap log, expressed as a percentage of the total number of
unflushed metaslabs in the pool.
.
-.It Sy zfs_unflushed_log_txg_max Ns = Ns Sy 1000 Pq ulong
+.It Sy zfs_unflushed_log_txg_max Ns = Ns Sy 1000 Pq u64
Tunable limiting maximum time in TXGs any metaslab may remain unflushed.
It effectively limits maximum number of unflushed per-TXG spacemap logs
that need to be read after unclean pool export.
@@ -1050,7 +1071,9 @@ Files containing more than
will be deleted asynchronously, while smaller files are deleted synchronously.
Decreasing this value will reduce the time spent in an
.Xr unlink 2
-system call, at the expense of a longer delay before the freed space is available.
+system call, at the expense of a longer delay before the freed space is
+available.
+This only applies on Linux.
.
.It Sy zfs_dirty_data_max Ns = Pq int
Determines the dirty space limit in bytes.
@@ -1076,9 +1099,12 @@ This parameter takes precedence over
.No See Sx ZFS TRANSACTION DELAY .
.Pp
Defaults to
-.Sy physical_ram/4 ,
+.Sy min(physical_ram/4, 4GiB) ,
+or
+.Sy min(physical_ram/4, 1GiB)
+for 32-bit systems.
.
-.It Sy zfs_dirty_data_max_max_percent Ns = Ns Sy 25 Ns % Pq int
+.It Sy zfs_dirty_data_max_max_percent Ns = Ns Sy 25 Ns % Pq uint
Maximum allowable value of
.Sy zfs_dirty_data_max ,
expressed as a percentage of physical RAM.
@@ -1090,7 +1116,7 @@ The parameter
takes precedence over this one.
.No See Sx ZFS TRANSACTION DELAY .
.
-.It Sy zfs_dirty_data_max_percent Ns = Ns Sy 10 Ns % Pq int
+.It Sy zfs_dirty_data_max_percent Ns = Ns Sy 10 Ns % Pq uint
Determines the dirty space limit, expressed as a percentage of all memory.
Once this limit is exceeded, new writes are halted until space frees up.
The parameter
@@ -1101,7 +1127,7 @@ takes precedence over this one.
Subject to
.Sy zfs_dirty_data_max_max .
.
-.It Sy zfs_dirty_data_sync_percent Ns = Ns Sy 20 Ns % Pq int
+.It Sy zfs_dirty_data_sync_percent Ns = Ns Sy 20 Ns % Pq uint
Start syncing out a transaction group if there's at least this much dirty data
.Pq as a percentage of Sy zfs_dirty_data_max .
This should be less than
@@ -1113,7 +1139,7 @@ Write operations are throttled when approaching the limit until log data is
cleared out after transaction group sync.
Because of some overhead, it should be set at least 2 times the size of
.Sy zfs_dirty_data_max
-.No to prevent harming normal write throughput.
+.No to prevent harming normal write throughput .
It also should be smaller than the size of the slog device if slog is present.
.Pp
Defaults to
@@ -1159,24 +1185,52 @@ Selecting any option other than
results in vector instructions
from the respective CPU instruction set being used.
.
+.It Sy zfs_bclone_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
+Enable the experimental block cloning feature.
+If this setting is 0, then even if feature@block_cloning is enabled,
+attempts to clone blocks will act as though the feature is disabled.
+.
+.It Sy zfs_bclone_wait_dirty Ns = Ns Sy 0 Ns | Ns 1 Pq int
+When set to 1 the FICLONE and FICLONERANGE ioctls wait for dirty data to be
+written to disk.
+This allows the clone operation to reliably succeed when a file is
+modified and then immediately cloned.
+For small files this may be slower than making a copy of the file.
+Therefore, this setting defaults to 0 which causes a clone operation to
+immediately fail when encountering a dirty block.
+.
+.It Sy zfs_blake3_impl Ns = Ns Sy fastest Pq string
+Select a BLAKE3 implementation.
+.Pp
+Supported selectors are:
+.Sy cycle , fastest , generic , sse2 , sse41 , avx2 , avx512 .
+All except
+.Sy cycle , fastest No and Sy generic
+require instruction set extensions to be available,
+and will only appear if ZFS detects that they are present at runtime.
+If multiple implementations of BLAKE3 are available, the
+.Sy fastest will be chosen using a micro benchmark. You can see the
+benchmark results by reading this kstat file:
+.Pa /proc/spl/kstat/zfs/chksum_bench .
+.
.It Sy zfs_free_bpobj_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
Enable/disable the processing of the free_bpobj object.
.
-.It Sy zfs_async_block_max_blocks Ns = Ns Sy ULONG_MAX Po unlimited Pc Pq ulong
+.It Sy zfs_async_block_max_blocks Ns = Ns Sy UINT64_MAX Po unlimited Pc Pq u64
Maximum number of blocks freed in a single TXG.
.
-.It Sy zfs_max_async_dedup_frees Ns = Ns Sy 100000 Po 10^5 Pc Pq ulong
+.It Sy zfs_max_async_dedup_frees Ns = Ns Sy 100000 Po 10^5 Pc Pq u64
Maximum number of dedup blocks freed in a single TXG.
.
-.It Sy zfs_vdev_async_read_max_active Ns = Ns Sy 3 Pq int
+.It Sy zfs_vdev_async_read_max_active Ns = Ns Sy 3 Pq uint
Maximum asynchronous read I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_async_read_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_async_read_min_active Ns = Ns Sy 1 Pq uint
Minimum asynchronous read I/O operation active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_async_write_active_max_dirty_percent Ns = Ns Sy 60 Ns % Pq int
+.It Sy zfs_vdev_async_write_active_max_dirty_percent Ns = Ns Sy 60 Ns % Pq uint
When the pool has more than this much dirty data, use
.Sy zfs_vdev_async_write_max_active
to limit active async writes.
@@ -1184,7 +1238,7 @@ If the dirty data is between the minimum and maximum,
the active I/O limit is linearly interpolated.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_async_write_active_min_dirty_percent Ns = Ns Sy 30 Ns % Pq int
+.It Sy zfs_vdev_async_write_active_min_dirty_percent Ns = Ns Sy 30 Ns % Pq uint
When the pool has less than this much dirty data, use
.Sy zfs_vdev_async_write_min_active
to limit active async writes.
@@ -1193,11 +1247,11 @@ the active I/O limit is linearly
interpolated.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_async_write_max_active Ns = Ns Sy 30 Pq int
+.It Sy zfs_vdev_async_write_max_active Ns = Ns Sy 10 Pq uint
Maximum asynchronous write I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_async_write_min_active Ns = Ns Sy 2 Pq int
+.It Sy zfs_vdev_async_write_min_active Ns = Ns Sy 2 Pq uint
Minimum asynchronous write I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.Pp
@@ -1211,69 +1265,76 @@ A value of
has been shown to improve resilver performance further at a cost of
further increasing latency.
.
-.It Sy zfs_vdev_initializing_max_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_initializing_max_active Ns = Ns Sy 1 Pq uint
Maximum initializing I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_initializing_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_initializing_min_active Ns = Ns Sy 1 Pq uint
Minimum initializing I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_max_active Ns = Ns Sy 1000 Pq int
+.It Sy zfs_vdev_max_active Ns = Ns Sy 1000 Pq uint
The maximum number of I/O operations active to each device.
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_rebuild_max_active Ns = Ns Sy 3 Pq int
+.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 uint
Maximum sequential resilver I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_rebuild_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_rebuild_min_active Ns = Ns Sy 1 Pq uint
Minimum sequential resilver I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_removal_max_active Ns = Ns Sy 2 Pq int
+.It Sy zfs_vdev_removal_max_active Ns = Ns Sy 2 Pq uint
Maximum removal I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_removal_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_removal_min_active Ns = Ns Sy 1 Pq uint
Minimum removal I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_scrub_max_active Ns = Ns Sy 2 Pq int
+.It Sy zfs_vdev_scrub_max_active Ns = Ns Sy 2 Pq uint
Maximum scrub I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_scrub_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_scrub_min_active Ns = Ns Sy 1 Pq uint
Minimum scrub I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_sync_read_max_active Ns = Ns Sy 10 Pq int
+.It Sy zfs_vdev_sync_read_max_active Ns = Ns Sy 10 Pq uint
Maximum synchronous read I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_sync_read_min_active Ns = Ns Sy 10 Pq int
+.It Sy zfs_vdev_sync_read_min_active Ns = Ns Sy 10 Pq uint
Minimum synchronous read I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_sync_write_max_active Ns = Ns Sy 10 Pq int
+.It Sy zfs_vdev_sync_write_max_active Ns = Ns Sy 10 Pq uint
Maximum synchronous write I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_sync_write_min_active Ns = Ns Sy 10 Pq int
+.It Sy zfs_vdev_sync_write_min_active Ns = Ns Sy 10 Pq uint
Minimum synchronous write I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_trim_max_active Ns = Ns Sy 2 Pq int
+.It Sy zfs_vdev_trim_max_active Ns = Ns Sy 2 Pq uint
Maximum trim/discard I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_trim_min_active Ns = Ns Sy 1 Pq int
+.It Sy zfs_vdev_trim_min_active Ns = Ns Sy 1 Pq uint
Minimum trim/discard I/O operations active to each device.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_nia_delay Ns = Ns Sy 5 Pq int
+.It Sy zfs_vdev_nia_delay Ns = Ns Sy 5 Pq uint
For non-interactive I/O (scrub, resilver, removal, initialize and rebuild),
the number of concurrently-active I/O operations is limited to
.Sy zfs_*_min_active ,
@@ -1287,7 +1348,7 @@ and the number of concurrently-active non-interactive operations is increased to
.Sy zfs_*_max_active .
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_nia_credit Ns = Ns Sy 5 Pq int
+.It Sy zfs_vdev_nia_credit Ns = Ns Sy 5 Pq uint
Some HDDs tend to prioritize sequential I/O so strongly, that concurrent
random I/O latency reaches several seconds.
On some HDDs this happens even if sequential I/O operations
@@ -1302,7 +1363,7 @@ This enforced wait ensures the HDD services the interactive I/O
within a reasonable amount of time.
.No See Sx ZFS I/O SCHEDULER .
.
-.It Sy zfs_vdev_queue_depth_pct Ns = Ns Sy 1000 Ns % Pq int
+.It Sy zfs_vdev_queue_depth_pct Ns = Ns Sy 1000 Ns % Pq uint
Maximum number of queued allocations per top-level vdev expressed as
a percentage of
.Sy zfs_vdev_async_write_max_active ,
@@ -1314,6 +1375,47 @@ as fuller devices will tend to be slower than empty devices.
Also see
.Sy zio_dva_throttle_enabled .
.
+.It Sy zfs_vdev_def_queue_depth Ns = Ns Sy 32 Pq uint
+Default queue depth for each vdev IO allocator.
+Higher values allow for better coalescing of sequential writes before sending
+them to the disk, but can increase transaction commit times.
+.
+.It Sy zfs_vdev_failfast_mask Ns = Ns Sy 1 Pq uint
+Defines if the driver should retire on a given error type.
+The following options may be bitwise-ored together:
+.TS
+box;
+lbz r l l .
+ Value Name Description
+_
+ 1 Device No driver retries on device errors
+ 2 Transport No driver retries on transport errors.
+ 4 Driver No driver retries on driver errors.
+.TE
+.
+.It Sy zfs_vdev_disk_max_segs Ns = Ns Sy 0 Pq uint
+Maximum number of segments to add to a BIO (min 4).
+If this is higher than the maximum allowed by the device queue or the kernel
+itself, it will be clamped.
+Setting it to zero will cause the kernel's ideal size to be used.
+This parameter only applies on Linux.
+This parameter is ignored if
+.Sy zfs_vdev_disk_classic Ns = Ns Sy 1 .
+.
+.It Sy zfs_vdev_disk_classic Ns = Ns Sy 0 Ns | Ns 1 Pq uint
+If set to 1, OpenZFS will submit IO to Linux using the method it used in 2.2
+and earlier.
+This "classic" method has known issues with highly fragmented IO requests and
+is slower on many workloads, but it has been in use for many years and is known
+to be very stable.
+If you set this parameter, please also open a bug report why you did so,
+including the workload involved and any error messages.
+.Pp
+This parameter and the classic submission method will be removed once we have
+total confidence in the new method.
+.Pp
+This parameter only applies on Linux, and can only be set at module load time.
+.
.It Sy zfs_expire_snapshot Ns = Ns Sy 300 Ns s Pq int
Time before expiring
.Pa .zfs/snapshot .
@@ -1333,13 +1435,13 @@ The following flags may be bitwise-ored together:
.TS
box;
lbz r l l .
- Value Symbolic Name Description
+ Value Name Description
_
1 ZFS_DEBUG_DPRINTF Enable dprintf entries in the debug log.
* 2 ZFS_DEBUG_DBUF_VERIFY Enable extra dbuf verifications.
* 4 ZFS_DEBUG_DNODE_VERIFY Enable extra dnode verifications.
8 ZFS_DEBUG_SNAPNAMES Enable snapshot name verification.
- 16 ZFS_DEBUG_MODIFY Check for illegally modified ARC buffers.
+* 16 ZFS_DEBUG_MODIFY Check for illegally modified ARC buffers.
64 ZFS_DEBUG_ZIO_FREE Enable verification of block frees.
128 ZFS_DEBUG_HISTOGRAM_VERIFY Enable extra spacemap histogram verifications.
256 ZFS_DEBUG_METASLAB_VERIFY Verify space accounting on disk matches in-memory \fBrange_trees\fP.
@@ -1349,7 +1451,23 @@ _
4096 ZFS_DEBUG_LOG_SPACEMAP Verify that the log summary is consistent with the spacemap log
and enable \fBzfs_dbgmsgs\fP for metaslab loading and flushing.
.TE
-.Sy \& * No Requires debug build.
+.Sy \& * No Requires debug build .
+.
+.It Sy zfs_btree_verify_intensity Ns = Ns Sy 0 Pq uint
+Enables btree verification.
+The following settings are culminative:
+.TS
+box;
+lbz r l l .
+ Value Description
+
+ 1 Verify height.
+ 2 Verify pointers from children to parent.
+ 3 Verify element counts.
+ 4 Verify element order. (expensive)
+* 5 Verify unused memory is poisoned. (expensive)
+.TE
+.Sy \& * No Requires debug build .
.
.It Sy zfs_free_leak_on_eio Ns = Ns Sy 0 Ns | Ns 1 Pq int
If destroy encounters an
@@ -1392,7 +1510,7 @@ but we chose the more conservative approach of not setting it,
so that there is no possibility of
leaking space in the "partial temporary" failure case.
.
-.It Sy zfs_free_min_time_ms Ns = Ns Sy 1000 Ns ms Po 1s Pc Pq int
+.It Sy zfs_free_min_time_ms Ns = Ns Sy 1000 Ns ms Po 1s Pc Pq uint
During a
.Nm zfs Cm destroy
operation using the
@@ -1400,27 +1518,27 @@ operation using the
feature,
a minimum of this much time will be spent working on freeing blocks per TXG.
.
-.It Sy zfs_obsolete_min_time_ms Ns = Ns Sy 500 Ns ms Pq int
+.It Sy zfs_obsolete_min_time_ms Ns = Ns Sy 500 Ns ms Pq uint
Similar to
.Sy zfs_free_min_time_ms ,
but for cleanup of old indirection records for removed vdevs.
.
-.It Sy zfs_immediate_write_sz Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq long
+.It Sy zfs_immediate_write_sz Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq s64
Largest data block to write to the ZIL.
Larger blocks will be treated as if the dataset being written to had the
.Sy logbias Ns = Ns Sy throughput
property set.
.
-.It Sy zfs_initialize_value Ns = Ns Sy 16045690984833335022 Po 0xDEADBEEFDEADBEEE Pc Pq ulong
+.It Sy zfs_initialize_value Ns = Ns Sy 16045690984833335022 Po 0xDEADBEEFDEADBEEE Pc Pq u64
Pattern written to vdev free space by
.Xr zpool-initialize 8 .
.
-.It Sy zfs_initialize_chunk_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq ulong
+.It Sy zfs_initialize_chunk_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq u64
Size of writes used by
.Xr zpool-initialize 8 .
This option is used by the test suite.
.
-.It Sy zfs_livelist_max_entries Ns = Ns Sy 500000 Po 5*10^5 Pc Pq ulong
+.It Sy zfs_livelist_max_entries Ns = Ns Sy 500000 Po 5*10^5 Pc Pq u64
The threshold size (in block pointers) at which we create a new sub-livelist.
Larger sublists are more costly from a memory perspective but the fewer
sublists there are, the lower the cost of insertion.
@@ -1459,11 +1577,11 @@ executing the open context condensing work in
.Fn spa_livelist_condense_cb .
This option is used by the test suite to trigger race conditions.
.
-.It Sy zfs_lua_max_instrlimit Ns = Ns Sy 100000000 Po 10^8 Pc Pq ulong
+.It Sy zfs_lua_max_instrlimit Ns = Ns Sy 100000000 Po 10^8 Pc Pq u64
The maximum execution time limit that can be set for a ZFS channel program,
specified as a number of Lua instructions.
.
-.It Sy zfs_lua_max_memlimit Ns = Ns Sy 104857600 Po 100 MiB Pc Pq ulong
+.It Sy zfs_lua_max_memlimit Ns = Ns Sy 104857600 Po 100 MiB Pc Pq u64
The maximum memory limit that can be set for a ZFS channel program, specified
in bytes.
.
@@ -1472,14 +1590,14 @@ The maximum depth of nested datasets.
This value can be tuned temporarily to
fix existing datasets that exceed the predefined limit.
.
-.It Sy zfs_max_log_walking Ns = Ns Sy 5 Pq ulong
+.It Sy zfs_max_log_walking Ns = Ns Sy 5 Pq u64
The number of past TXGs that the flushing algorithm of the log spacemap
feature uses to estimate incoming log blocks.
.
-.It Sy zfs_max_logsm_summary_length Ns = Ns Sy 10 Pq ulong
+.It Sy zfs_max_logsm_summary_length Ns = Ns Sy 10 Pq u64
Maximum number of rows allowed in the summary of the spacemap log.
.
-.It Sy zfs_max_recordsize Ns = Ns Sy 16777216 Po 16 MiB Pc Pq int
+.It Sy zfs_max_recordsize Ns = Ns Sy 16777216 Po 16 MiB Pc Pq uint
We currently support block sizes from
.Em 512 Po 512 B Pc No to Em 16777216 Po 16 MiB Pc .
The benefits of larger blocks, and thus larger I/O,
@@ -1495,16 +1613,16 @@ regardless of this setting.
Allow datasets received with redacted send/receive to be mounted.
Normally disabled because these datasets may be missing key data.
.
-.It Sy zfs_min_metaslabs_to_flush Ns = Ns Sy 1 Pq ulong
+.It Sy zfs_min_metaslabs_to_flush Ns = Ns Sy 1 Pq u64
Minimum number of metaslabs to flush per dirty TXG.
.
-.It Sy zfs_metaslab_fragmentation_threshold Ns = Ns Sy 70 Ns % Pq int
+.It Sy zfs_metaslab_fragmentation_threshold Ns = Ns Sy 70 Ns % Pq uint
Allow metaslabs to keep their active state as long as their fragmentation
percentage is no more than this value.
An active metaslab that exceeds this threshold
will no longer keep its active status allowing better metaslabs to be selected.
.
-.It Sy zfs_mg_fragmentation_threshold Ns = Ns Sy 95 Ns % Pq int
+.It Sy zfs_mg_fragmentation_threshold Ns = Ns Sy 95 Ns % Pq uint
Metaslab groups are considered eligible for allocations if their
fragmentation metric (measured as a percentage) is less than or equal to
this value.
@@ -1512,7 +1630,7 @@ If a metaslab group exceeds this threshold then it will be
skipped unless all metaslab groups within the metaslab class have also
crossed this threshold.
.
-.It Sy zfs_mg_noalloc_threshold Ns = Ns Sy 0 Ns % Pq int
+.It Sy zfs_mg_noalloc_threshold Ns = Ns Sy 0 Ns % Pq uint
Defines a threshold at which metaslab groups should be eligible for allocations.
The value is expressed as a percentage of free space
beyond which a metaslab group is always eligible for allocations.
@@ -1523,7 +1641,8 @@ Once all groups have reached the threshold, all groups are allowed to accept
allocations.
The default value of
.Sy 0
-disables the feature and causes all metaslab groups to be eligible for allocations.
+disables the feature and causes all metaslab groups to be eligible for
+allocations.
.Pp
This parameter allows one to deal with pools having heavily imbalanced
vdevs such as would be the case when a new vdev has been added.
@@ -1541,11 +1660,12 @@ If enabled, ZFS will place DDT data into the special allocation class.
If enabled, ZFS will place user data indirect blocks
into the special allocation class.
.
-.It Sy zfs_multihost_history Ns = Ns Sy 0 Pq int
-Historical statistics for this many latest multihost updates will be available in
+.It Sy zfs_multihost_history Ns = Ns Sy 0 Pq uint
+Historical statistics for this many latest multihost updates will be available
+in
.Pa /proc/spl/kstat/zfs/ Ns Ao Ar pool Ac Ns Pa /multihost .
.
-.It Sy zfs_multihost_interval Ns = Ns Sy 1000 Ns ms Po 1 s Pc Pq ulong
+.It Sy zfs_multihost_interval Ns = Ns Sy 1000 Ns ms Po 1 s Pc Pq u64
Used to control the frequency of multihost writes which are performed when the
.Sy multihost
pool property is on.
@@ -1632,16 +1752,16 @@ The number of bytes which should be prefetched during a pool traversal, like
.Nm zfs Cm send
or other data crawling operations.
.
-.It Sy zfs_traverse_indirect_prefetch_limit Ns = Ns Sy 32 Pq int
+.It Sy zfs_traverse_indirect_prefetch_limit Ns = Ns Sy 32 Pq uint
The number of blocks pointed by indirect (non-L0) block which should be
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 u64
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.
+.Sy 0 No disables this throttle .
.
.It Sy zfs_prefetch_disable Ns = Ns Sy 0 Ns | Ns 1 Pq int
Disable predictive prefetch.
@@ -1666,17 +1786,17 @@ Disable QAT hardware acceleration for AES-GCM encryption.
May be unset after the ZFS modules have been loaded to initialize the QAT
hardware as long as support is compiled in and the QAT driver is present.
.
-.It Sy zfs_vnops_read_chunk_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq long
+.It Sy zfs_vnops_read_chunk_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq u64
Bytes to read per chunk.
.
-.It Sy zfs_read_history Ns = Ns Sy 0 Pq int
+.It Sy zfs_read_history Ns = Ns Sy 0 Pq uint
Historical statistics for this many latest reads will be available in
.Pa /proc/spl/kstat/zfs/ Ns Ao Ar pool Ac Ns Pa /reads .
.
.It Sy zfs_read_history_hits Ns = Ns Sy 0 Ns | Ns 1 Pq int
Include cache hits in read history
.
-.It Sy zfs_rebuild_max_segment Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq ulong
+.It Sy zfs_rebuild_max_segment Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq u64
Maximum read segment size to issue when sequentially resilvering a
top-level vdev.
.
@@ -1686,7 +1806,7 @@ completes in order to verify the checksums of all blocks which have been
resilvered.
This is enabled by default and strongly recommended.
.
-.It Sy zfs_rebuild_vdev_limit Ns = Ns Sy 33554432 Ns B Po 32 MiB Pc Pq ulong
+.It Sy zfs_rebuild_vdev_limit Ns = Ns Sy 67108864 Ns B Po 64 MiB Pc Pq u64
Maximum amount of I/O that can be concurrently issued for a sequential
resilver per leaf device, given in bytes.
.
@@ -1714,11 +1834,11 @@ and is hence not recommended.
This should only be used as a last resort when the
pool cannot be returned to a healthy state prior to removing the device.
.
-.It Sy zfs_removal_suspend_progress Ns = Ns Sy 0 Ns | Ns 1 Pq int
+.It Sy zfs_removal_suspend_progress Ns = Ns Sy 0 Ns | Ns 1 Pq uint
This is used by the test suite so that it can ensure that certain actions
happen while in the middle of a removal.
.
-.It Sy zfs_remove_max_segment Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
+.It Sy zfs_remove_max_segment Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq uint
The largest contiguous segment that we will attempt to allocate when removing
a device.
If there is a performance problem with attempting to allocate large blocks,
@@ -1731,7 +1851,7 @@ Ignore the
feature, causing an operation that would start a resilver to
immediately restart the one in progress.
.
-.It Sy zfs_resilver_min_time_ms Ns = Ns Sy 3000 Ns ms Po 3 s Pc Pq int
+.It Sy zfs_resilver_min_time_ms Ns = Ns Sy 3000 Ns ms Po 3 s Pc Pq uint
Resilvers are processed by the sync thread.
While resilvering, it will spend at least this much time
working on a resilver between TXG flushes.
@@ -1742,25 +1862,35 @@ even if there were unrepairable errors.
Intended to be used during pool repair or recovery to
stop resilvering when the pool is next imported.
.
-.It Sy zfs_scrub_min_time_ms Ns = Ns Sy 1000 Ns ms Po 1 s Pc Pq int
+.It Sy zfs_scrub_after_expand Ns = Ns Sy 1 Ns | Ns 0 Pq int
+Automatically start a pool scrub after a RAIDZ expansion completes
+in order to verify the checksums of all blocks which have been
+copied during the expansion.
+This is enabled by default and strongly recommended.
+.
+.It Sy zfs_scrub_min_time_ms Ns = Ns Sy 1000 Ns ms Po 1 s Pc Pq uint
Scrubs are processed by the sync thread.
While scrubbing, it will spend at least this much time
working on a scrub between TXG flushes.
.
-.It Sy zfs_scan_checkpoint_intval Ns = Ns Sy 7200 Ns s Po 2 hour Pc Pq int
+.It Sy zfs_scrub_error_blocks_per_txg Ns = Ns Sy 4096 Pq uint
+Error blocks to be scrubbed in one txg.
+.
+.It Sy zfs_scan_checkpoint_intval Ns = Ns Sy 7200 Ns s Po 2 hour Pc Pq uint
To preserve progress across reboots, the sequential scan algorithm periodically
needs to stop metadata scanning and issue all the verification I/O to disk.
The frequency of this flushing is determined by this tunable.
.
-.It Sy zfs_scan_fill_weight Ns = Ns Sy 3 Pq int
+.It Sy zfs_scan_fill_weight Ns = Ns Sy 3 Pq uint
This tunable affects how scrub and resilver I/O segments are ordered.
A higher number indicates that we care more about how filled in a segment is,
while a lower number indicates we care more about the size of the extent without
considering the gaps within a segment.
This value is only tunable upon module insertion.
-Changing the value afterwards will have no effect on scrub or resilver performance.
+Changing the value afterwards will have no effect on scrub or resilver
+performance.
.
-.It Sy zfs_scan_issue_strategy Ns = Ns Sy 0 Pq int
+.It Sy zfs_scan_issue_strategy Ns = Ns Sy 0 Pq uint
Determines the order that data will be verified while scrubbing or resilvering:
.Bl -tag -compact -offset 4n -width "a"
.It Sy 1
@@ -1774,7 +1904,7 @@ By deferring scrubbing of small segments, we may later find adjacent data
to coalesce and increase the segment size.
.It Sy 0
.No Use strategy Sy 1 No during normal verification
-.No and strategy Sy 2 No while taking a checkpoint.
+.No and strategy Sy 2 No while taking a checkpoint .
.El
.
.It Sy zfs_scan_legacy Ns = Ns Sy 0 Ns | Ns 1 Pq int
@@ -1790,21 +1920,29 @@ that will still be considered sequential for sorting purposes.
Changing this value will not
affect scrubs or resilvers that are already in progress.
.
-.It Sy zfs_scan_mem_lim_fact Ns = Ns Sy 20 Ns ^-1 Pq int
+.It Sy zfs_scan_mem_lim_fact Ns = Ns Sy 20 Ns ^-1 Pq uint
Maximum fraction of RAM used for I/O sorting by sequential scan algorithm.
This tunable determines the hard limit for I/O sorting memory usage.
When the hard limit is reached we stop scanning metadata and start issuing
data verification I/O.
This is done until we get below the soft limit.
.
-.It Sy zfs_scan_mem_lim_soft_fact Ns = Ns Sy 20 Ns ^-1 Pq int
+.It Sy zfs_scan_mem_lim_soft_fact Ns = Ns Sy 20 Ns ^-1 Pq uint
The fraction of the hard limit used to determined the soft limit for I/O sorting
by the sequential scan algorithm.
When we cross this limit from below no action is taken.
-When we cross this limit from above it is because we are issuing verification I/O.
+When we cross this limit from above it is because we are issuing verification
+I/O.
In this case (unless the metadata scan is done) we stop issuing verification I/O
and start scanning metadata again until we get to the hard limit.
.
+.It Sy zfs_scan_report_txgs Ns = Ns Sy 0 Ns | Ns 1 Pq uint
+When reporting resilver throughput and estimated completion time use the
+performance observed over roughly the last
+.Sy zfs_scan_report_txgs
+TXGs.
+When set to zero performance is calculated over the time between checkpoints.
+.
.It Sy zfs_scan_strict_mem_lim Ns = Ns Sy 0 Ns | Ns 1 Pq int
Enforce tight memory limits on pool scans when a sequential scan is in progress.
When disabled, the memory limit may be exceeded by fast disks.
@@ -1813,7 +1951,7 @@ When disabled, the memory limit may be exceeded by fast disks.
Freezes a scrub/resilver in progress without actually pausing it.
Intended for testing/debugging.
.
-.It Sy zfs_scan_vdev_limit Ns = Ns Sy 4194304 Ns B Po 4 MiB Pc Pq int
+.It Sy zfs_scan_vdev_limit Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
Maximum amount of data that can be concurrently issued at once for scrubs and
resilvers per leaf device, given in bytes.
.
@@ -1827,41 +1965,41 @@ remove the spill block from an existing object.
Including unmodified copies of the spill blocks creates a backwards-compatible
stream which will recreate a spill block if it was incorrectly removed.
.
-.It Sy zfs_send_no_prefetch_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq int
+.It Sy zfs_send_no_prefetch_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq uint
The fill fraction of the
.Nm zfs Cm send
internal queues.
The fill fraction controls the timing with which internal threads are woken up.
.
-.It Sy zfs_send_no_prefetch_queue_length Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq int
+.It Sy zfs_send_no_prefetch_queue_length Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq uint
The maximum number of bytes allowed in
.Nm zfs Cm send Ns 's
internal queues.
.
-.It Sy zfs_send_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq int
+.It Sy zfs_send_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq uint
The fill fraction of the
.Nm zfs Cm send
prefetch queue.
The fill fraction controls the timing with which internal threads are woken up.
.
-.It Sy zfs_send_queue_length Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
+.It Sy zfs_send_queue_length Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq uint
The maximum number of bytes allowed that will be prefetched by
.Nm zfs Cm send .
This value must be at least twice the maximum block size in use.
.
-.It Sy zfs_recv_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq int
+.It Sy zfs_recv_queue_ff Ns = Ns Sy 20 Ns ^\-1 Pq uint
The fill fraction of the
.Nm zfs Cm receive
queue.
The fill fraction controls the timing with which internal threads are woken up.
.
-.It Sy zfs_recv_queue_length Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
+.It Sy zfs_recv_queue_length Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq uint
The maximum number of bytes allowed in the
.Nm zfs Cm receive
queue.
This value must be at least twice the maximum block size in use.
.
-.It Sy zfs_recv_write_batch_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq int
+.It Sy zfs_recv_write_batch_size Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq uint
The maximum amount of data, in bytes, that
.Nm zfs Cm receive
will write in one DMU transaction.
@@ -1870,7 +2008,18 @@ This setting will not reduce the write size below a single block.
Capped at a maximum of
.Sy 32 MiB .
.
-.It Sy zfs_override_estimate_recordsize Ns = Ns Sy 0 Ns | Ns 1 Pq ulong
+.It Sy zfs_recv_best_effort_corrective Ns = Ns Sy 0 Pq int
+When this variable is set to non-zero a corrective receive:
+.Bl -enum -compact -offset 4n -width "1."
+.It
+Does not enforce the restriction of source & destination snapshot GUIDs
+matching.
+.It
+If there is an error during healing, the healing receive is not
+terminated instead it moves on to the next record.
+.El
+.
+.It Sy zfs_override_estimate_recordsize Ns = Ns Sy 0 Ns | Ns 1 Pq uint
Setting this variable overrides the default logic for estimating block
sizes when doing a
.Nm zfs Cm send .
@@ -1879,7 +2028,7 @@ will be the current recordsize.
Override this value if most data in your dataset is not of that size
and you require accurate zfs send size estimates.
.
-.It Sy zfs_sync_pass_deferred_free Ns = Ns Sy 2 Pq int
+.It Sy zfs_sync_pass_deferred_free Ns = Ns Sy 2 Pq uint
Flushing of data to disk is done in passes.
Defer frees starting in this pass.
.
@@ -1887,13 +2036,14 @@ Defer frees starting in this pass.
Maximum memory used for prefetching a checkpoint's space map on each
vdev while discarding the checkpoint.
.
-.It Sy zfs_special_class_metadata_reserve_pct Ns = Ns Sy 25 Ns % Pq int
+.It Sy zfs_special_class_metadata_reserve_pct Ns = Ns Sy 25 Ns % Pq uint
Only allow small data blocks to be allocated on the special and dedup vdev
-types when the available free space percentage on these vdevs exceeds this value.
+types when the available free space percentage on these vdevs exceeds this
+value.
This ensures reserved space is available for pool metadata as the
special vdevs approach capacity.
.
-.It Sy zfs_sync_pass_dont_compress Ns = Ns Sy 8 Pq int
+.It Sy zfs_sync_pass_dont_compress Ns = Ns Sy 8 Pq uint
Starting in this sync pass, disable compression (including of metadata).
With the default setting, in practice, we don't have this many sync passes,
so this has no effect.
@@ -1911,22 +2061,17 @@ because these will not be compressed.
The
.Em 128 KiB
allocations are especially detrimental to performance
-on highly fragmented systems, which may have very few free segments of this size,
+on highly fragmented systems, which may have very few free segments of this
+size,
and may need to load new metaslabs to satisfy these allocations.
.
-.It Sy zfs_sync_pass_rewrite Ns = Ns Sy 2 Pq int
+.It Sy zfs_sync_pass_rewrite Ns = Ns Sy 2 Pq uint
Rewrite new block pointers starting in this pass.
.
-.It Sy zfs_sync_taskq_batch_pct Ns = Ns Sy 75 Ns % Pq int
-This controls the number of threads used by
-.Sy dp_sync_taskq .
-The default value of
-.Sy 75%
-will create a maximum of one thread per CPU.
-.
.It Sy zfs_trim_extent_bytes_max Ns = Ns Sy 134217728 Ns B Po 128 MiB Pc Pq uint
Maximum size of TRIM command.
-Larger ranges will be split into chunks no larger than this value before issuing.
+Larger ranges will be split into chunks no larger than this value before
+issuing.
.
.It Sy zfs_trim_extent_bytes_min Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq uint
Minimum size of TRIM commands.
@@ -1937,7 +2082,8 @@ to negatively impact overall performance.
.
.It Sy zfs_trim_metaslab_skip Ns = Ns Sy 0 Ns | Ns 1 Pq uint
Skip uninitialized metaslabs during the TRIM process.
-This option is useful for pools constructed from large thinly-provisioned devices
+This option is useful for pools constructed from large thinly-provisioned
+devices
where TRIM operations are slow.
As a pool ages, an increasing fraction of the pool's metaslabs
will be initialized, progressively degrading the usefulness of this option.
@@ -1957,46 +2103,27 @@ more efficient TRIM operations and the delay
before the recently trimmed space is available for use by the device.
.Pp
Increasing this value will allow frees to be aggregated for a longer time.
-This will result is larger TRIM operations and potentially increased memory usage.
+This will result is larger TRIM operations and potentially increased memory
+usage.
Decreasing this value will have the opposite effect.
The default of
.Sy 32
was determined to be a reasonable compromise.
.
-.It Sy zfs_txg_history Ns = Ns Sy 0 Pq int
+.It Sy zfs_txg_history Ns = Ns Sy 0 Pq uint
Historical statistics for this many latest TXGs will be available in
.Pa /proc/spl/kstat/zfs/ Ns Ao Ar pool Ac Ns Pa /TXGs .
.
-.It Sy zfs_txg_timeout Ns = Ns Sy 5 Ns s Pq int
-Flush dirty data to disk at least every this many seconds (maximum TXG duration).
-.
-.It Sy zfs_vdev_aggregate_trim Ns = Ns Sy 0 Ns | Ns 1 Pq int
-Allow TRIM I/O operations to be aggregated.
-This is normally not helpful because the extents to be trimmed
-will have been already been aggregated by the metaslab.
-This option is provided for debugging and performance analysis.
+.It Sy zfs_txg_timeout Ns = Ns Sy 5 Ns s Pq uint
+Flush dirty data to disk at least every this many seconds (maximum TXG
+duration).
.
-.It Sy zfs_vdev_aggregation_limit Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq int
+.It Sy zfs_vdev_aggregation_limit Ns = Ns Sy 1048576 Ns B Po 1 MiB Pc Pq uint
Max vdev I/O aggregation size.
.
-.It Sy zfs_vdev_aggregation_limit_non_rotating Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq int
+.It Sy zfs_vdev_aggregation_limit_non_rotating Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq uint
Max vdev I/O aggregation size for non-rotating media.
.
-.It Sy zfs_vdev_cache_bshift Ns = Ns Sy 16 Po 64 KiB Pc Pq int
-Shift size to inflate reads to.
-.
-.It Sy zfs_vdev_cache_max Ns = Ns Sy 16384 Ns B Po 16 KiB Pc Pq int
-Inflate reads smaller than this value to meet the
-.Sy zfs_vdev_cache_bshift
-size
-.Pq default Sy 64 KiB .
-.
-.It Sy zfs_vdev_cache_size Ns = Ns Sy 0 Pq int
-Total size of the per-disk cache in bytes.
-.Pp
-Currently this feature is disabled, as it has been found to not be helpful
-for performance and in some cases harmful.
-.
.It Sy zfs_vdev_mirror_rotating_inc Ns = Ns Sy 0 Pq int
A number by which the balancing algorithm increments the load calculation for
the purpose of selecting the least busy mirror member when an I/O operation
@@ -2023,17 +2150,18 @@ when I/O operations do not immediately follow one another.
.
.It Sy zfs_vdev_mirror_non_rotating_seek_inc Ns = Ns Sy 1 Pq int
A number by which the balancing algorithm increments the load calculation for
-the purpose of selecting the least busy mirror member when an I/O operation lacks
+the purpose of selecting the least busy mirror member when an I/O operation
+lacks
locality as defined by the
.Sy zfs_vdev_mirror_rotating_seek_offset .
Operations within this that are not immediately following the previous operation
are incremented by half.
.
-.It Sy zfs_vdev_read_gap_limit Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq int
+.It Sy zfs_vdev_read_gap_limit Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq uint
Aggregate read I/O operations if the on-disk gap between them is within this
threshold.
.
-.It Sy zfs_vdev_write_gap_limit Ns = Ns Sy 4096 Ns B Po 4 KiB Pc Pq int
+.It Sy zfs_vdev_write_gap_limit Ns = Ns Sy 4096 Ns B Po 4 KiB Pc Pq uint
Aggregate write I/O operations if the on-disk gap between them is within this
threshold.
.
@@ -2070,7 +2198,7 @@ powerpc_altivec Altivec PowerPC
.Sy DEPRECATED .
Prints warning to kernel log for compatibility.
.
-.It Sy zfs_zevent_len_max Ns = Ns Sy 512 Pq int
+.It Sy zfs_zevent_len_max Ns = Ns Sy 512 Pq uint
Max event queue length.
Events in the queue can be viewed with
.Xr zpool-events 8 .
@@ -2100,12 +2228,17 @@ The default value of
.Sy 100%
will create a maximum of one thread per cpu.
.
-.It Sy zil_maxblocksize Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq int
+.It Sy zil_maxblocksize Ns = Ns Sy 131072 Ns B Po 128 KiB Pc Pq uint
This sets the maximum block size used by the ZIL.
On very fragmented pools, lowering this
.Pq typically to Sy 36 KiB
can improve performance.
.
+.It Sy zil_maxcopied Ns = Ns Sy 7680 Ns B Po 7.5 KiB Pc Pq uint
+This sets the maximum number of write bytes logged via WR_COPIED.
+It tunes a tradeoff between additional memory copy and possibly worse log
+space efficiency vs additional range lock/unlock.
+.
.It Sy zil_nocacheflush Ns = Ns Sy 0 Ns | Ns 1 Pq int
Disable the cache flush commands that are normally sent to disk by
the ZIL after an LWB write has completed.
@@ -2116,7 +2249,7 @@ if a volatile out-of-order write cache is enabled.
Disable intent logging replay.
Can be disabled for recovery from corrupted ZIL.
.
-.It Sy zil_slog_bulk Ns = Ns Sy 786432 Ns B Po 768 KiB Pc Pq ulong
+.It Sy zil_slog_bulk Ns = Ns Sy 67108864 Ns B Po 64 MiB Pc Pq u64
Limit SLOG write size per commit executed with synchronous priority.
Any writes above that will be executed with lower (asynchronous) priority
to limit potential SLOG device abuse by single active ZIL writer.
@@ -2131,19 +2264,20 @@ This would only be necessary to work around bugs in the ZIL logging or replay
code for this record type.
The tunable has no effect if the feature is disabled.
.
-.It Sy zfs_embedded_slog_min_ms Ns = Ns Sy 64 Pq int
+.It Sy zfs_embedded_slog_min_ms Ns = Ns Sy 64 Pq uint
Usually, one metaslab from each normal-class vdev is dedicated for use by
the ZIL to log synchronous writes.
However, if there are fewer than
.Sy zfs_embedded_slog_min_ms
metaslabs in the vdev, this functionality is disabled.
-This ensures that we don't set aside an unreasonable amount of space for the ZIL.
+This ensures that we don't set aside an unreasonable amount of space for the
+ZIL.
.
-.It Sy zstd_earlyabort_pass Ns = Ns Sy 1 Pq int
+.It Sy zstd_earlyabort_pass Ns = Ns Sy 1 Pq uint
Whether heuristic for detection of incompressible data with zstd levels >= 3
using LZ4 and zstd-1 passes is enabled.
.
-.It Sy zstd_abort_size Ns = Ns Sy 131072 Pq int
+.It Sy zstd_abort_size Ns = Ns Sy 131072 Pq uint
Minimal uncompressed size (inclusive) of a record before the early abort
heuristic will be attempted.
.
@@ -2199,8 +2333,8 @@ Prioritize requeued I/O.
.
.It Sy zio_taskq_batch_pct Ns = Ns Sy 80 Ns % Pq uint
Percentage of online CPUs which will run a worker thread for I/O.
-These workers are responsible for I/O work such as compression and
-checksum calculations.
+These workers are responsible for I/O work such as compression, encryption,
+checksum and parity calculations.
Fractional number of CPUs will be rounded down.
.Pp
The default value of
@@ -2208,15 +2342,36 @@ The default value of
was chosen to avoid using all CPUs which can result in
latency issues and inconsistent application performance,
especially when slower compression and/or checksumming is enabled.
+Set value only applies to pools imported/created after that.
.
.It Sy zio_taskq_batch_tpq Ns = Ns Sy 0 Pq uint
Number of worker threads per taskq.
-Lower values improve I/O ordering and CPU utilization,
-while higher reduces lock contention.
+Higher values improve I/O ordering and CPU utilization,
+while lower reduce lock contention.
+Set value only applies to pools imported/created after that.
.Pp
If
.Sy 0 ,
generate a system-dependent value close to 6 threads per taskq.
+Set value only applies to pools imported/created after that.
+.
+.It Sy zio_taskq_write_tpq Ns = Ns Sy 16 Pq uint
+Determines the minumum number of threads per write issue taskq.
+Higher values improve CPU utilization on high throughput,
+while lower reduce taskq locks contention on high IOPS.
+Set value only applies to pools imported/created after that.
+.
+.It Sy zio_taskq_read Ns = Ns Sy fixed,1,8 null scale null Pq charp
+Set the queue and thread configuration for the IO read queues.
+This is an advanced debugging parameter.
+Don't change this unless you understand what it does.
+Set values only apply to pools imported/created after that.
+.
+.It Sy zio_taskq_write Ns = Ns Sy sync fixed,1,5 scale fixed,1,5 Pq charp
+Set the queue and thread configuration for the IO write queues.
+This is an advanced debugging parameter.
+Don't change this unless you understand what it does.
+Set values only apply to pools imported/created after that.
.
.It Sy zvol_inhibit_dev Ns = Ns Sy 0 Ns | Ns 1 Pq uint
Do not create zvol device nodes.
@@ -2226,7 +2381,7 @@ systems with a very large number of zvols.
.It Sy zvol_major Ns = Ns Sy 230 Pq uint
Major number for zvol block devices.
.
-.It Sy zvol_max_discard_blocks Ns = Ns Sy 16384 Pq ulong
+.It Sy zvol_max_discard_blocks Ns = Ns Sy 16384 Pq long
Discard (TRIM) operations done on zvols will be done in batches of this
many blocks, where block size is determined by the
.Sy volblocksize
@@ -2252,6 +2407,13 @@ The number of requests which can be handled concurrently is controlled by
is ignored when running on a kernel that supports block multiqueue
.Pq Li blk-mq .
.
+.It Sy zvol_num_taskqs Ns = Ns Sy 0 Pq uint
+Number of zvol taskqs.
+If
+.Sy 0
+(the default) then scaling is done internally to prefer 6 threads per taskq.
+This only applies on Linux.
+.
.It Sy zvol_threads Ns = Ns Sy 0 Pq uint
The number of system wide threads to use for processing zvol block IOs.
If
@@ -2328,6 +2490,10 @@ Defines zvol block devices behaviour when
.It Sy 3
.No equivalent to Sy none
.El
+.
+.It Sy zvol_enforce_quotas Ns = Ns Sy 0 Ns | Ns 1 Pq uint
+Enable strict ZVOL quota enforcement.
+The strict quota enforcement may have a performance impact.
.El
.
.Sh ZFS I/O SCHEDULER
@@ -2360,7 +2526,8 @@ the scheduler looks for classes whose maximum has not been satisfied.
Iteration through the I/O classes is done in the order specified above.
No further operations are issued
if the aggregate maximum number of concurrent operations has been hit,
-or if there are no operations queued for an I/O class that has not hit its maximum.
+or if there are no operations queued for an I/O class that has not hit its
+maximum.
Every time an I/O operation is queued or an operation completes,
the scheduler looks for new operations to issue.
.Pp
@@ -2391,10 +2558,10 @@ the I/O scheduler changes the maximum number of active async write operations
according to the amount of dirty data in the pool.
Since both throughput and latency typically increase with the number of
concurrent operations issued to physical devices, reducing the
-burstiness in the number of concurrent operations also stabilizes the
-response time of operations from other – and in particular synchronous – queues.
+burstiness in the number of simultaneous operations also stabilizes the
+response time of operations from other queues, in particular synchronous ones.
In broad strokes, the I/O scheduler will issue more concurrent operations
-from the async write queue as there's more dirty data in the pool.
+from the async write queue as there is more dirty data in the pool.
.
.Ss Async Writes
The number of concurrent operations issued for the async write I/O class
@@ -2459,7 +2626,8 @@ so that we only start to delay after writing at full speed
has failed to keep up with the incoming write rate.
The scale of the curve is defined by
.Sy zfs_delay_scale .
-Roughly speaking, this variable determines the amount of delay at the midpoint of the curve.
+Roughly speaking, this variable determines the amount of delay at the midpoint
+of the curve.
.Bd -literal
delay
10ms +-------------------------------------------------------------*+
diff --git a/man/man7/dracut.zfs.7 b/man/man7/dracut.zfs.7
index 0f446fe2fe3f..c1475c695e83 100644
--- a/man/man7/dracut.zfs.7
+++ b/man/man7/dracut.zfs.7
@@ -1,6 +1,6 @@
.\" SPDX-License-Identifier: 0BSD
.\"
-.Dd April 4, 2022
+.Dd March 28, 2023
.Dt DRACUT.ZFS 7
.Os
.
@@ -28,13 +28,13 @@ zfs-import-scan.service \(da \(da | zfs-import-c
zfs-import.target \(-> dracut-pre-mount.service
| \(ua |
| dracut-zfs-generator |
- | ____________________/|
+ | _____________________/|
|/ \(da
- | sysroot.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em dracut-zfs-generator
- | | \(da |
- | \(da sysroot-{usr,etc,lib,&c.}.mount |
- | initrd-root-fs.target \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em or \(da
- | | zfs-nonroot-necessities.service
+ | sysroot.mount \(<-\(em\(em\(em dracut-zfs-generator
+ | |
+ | \(da
+ | initrd-root-fs.target \(<-\(em zfs-nonroot-necessities.service
+ | | |
| \(da |
\(da dracut-mount.service |
zfs-snapshot-bootfs.service | |
@@ -42,7 +42,7 @@ zfs-import-scan.service \(da \(da | zfs-import-c
\(da … |
zfs-rollback-bootfs.service | |
| \(da |
- | sysroot-usr.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
+ | /sysroot/{usr,etc,lib,&c.} \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
| |
| \(da
| initrd-fs.target
@@ -71,7 +71,8 @@ module.
.Pp
Booting into a ZFS dataset requires
.Sy mountpoint Ns = Ns Pa /
-to be set on the dataset containing the root filesystem (henceforth "the boot dataset") and at the very least either the
+to be set on the dataset containing the root filesystem (henceforth "the boot
+dataset") and at the very least either the
.Sy bootfs
property to be set to that dataset, or the
.Sy root=
@@ -86,7 +87,8 @@ matching
globs are deemed essential and will be mounted as well.
.Pp
.Xr zfs-mount-generator 8
-is recommended for proper functioning of the system afterward (correct mount properties, remounting, &c.).
+is recommended for proper functioning of the system afterward (correct mount
+properties, remounting, &c.).
.
.Sh CMDLINE
.Ss Standard
@@ -122,7 +124,8 @@ cf.\&
.Sx Temporary Mount Point Properties
in
.Xr zfsprops 7 .
-These properties will not last, since all filesystems will be re-mounted from the real root.
+These properties will not last, since all filesystems will be re-mounted from
+the real root.
.
.It Sy debug
If specified,
@@ -263,7 +266,8 @@ Does nothing on
.Nm systemd
systems
.Pq if Pa dracut-zfs-generator No succeeded .
-Otherwise, loads encryption key for the boot dataset from the console or via plymouth.
+Otherwise, loads encryption key for the boot dataset from the console or via
+plymouth.
It may not work at all!
.El
.
diff --git a/man/man7/vdevprops.7 b/man/man7/vdevprops.7
index ab6c77064194..5ec37df179de 100644
--- a/man/man7/vdevprops.7
+++ b/man/man7/vdevprops.7
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -20,7 +20,7 @@
.\"
.\" Copyright (c) 2021 Klara, Inc.
.\"
-.Dd November 27, 2021
+.Dd October 30, 2022
.Dt VDEVPROPS 7
.Os
.
@@ -43,7 +43,8 @@ section, below.
.Ss Native Properties
Every vdev has a set of properties that export statistics about the vdev
as well as control various behaviors.
-Properties are NOT inherited from top-level vdevs.
+Properties are not inherited from top-level vdevs, with the exception of
+checksum_n, checksum_t, io_n, io_t, slow_io_n, and slow_io_t.
.Pp
The values of numeric properties can be specified using human-readable suffixes
.Po for example,
@@ -114,13 +115,32 @@ The cumulative size of all operations of each type performed by this vdev
If this device is currently being removed from the pool
.El
.Pp
-The following native properties can be used to change the behavior of a ZFS
-dataset.
+The following native properties can be used to change the behavior of a vdev.
.Bl -tag -width "allocating"
+.It Sy checksum_n , checksum_t , io_n , io_t , slow_io_n , slow_io_t
+Tune the fault management daemon by specifying checksum/io thresholds of <N>
+errors in <T> seconds, respectively.
+These properties can be set on leaf and top-level vdevs.
+When the property is set on the leaf and top-level vdev, the value of the leaf
+vdev will be used.
+If the property is only set on the top-level vdev, this value will be used.
+The value of these properties do not persist across vdev replacement.
+For this reason, it is advisable to set the property on the top-level vdev -
+not on the leaf vdev itself.
+The default values for
+.Sy OpenZFS on Linux
+are 10 errors in 600 seconds.
+For
+.Sy OpenZFS on FreeBSD
+defaults see
+.Xr zfsd 8 .
.It Sy comment
A text comment up to 8192 characters long
.It Sy bootsize
The amount of space to reserve for the EFI system partition
+.It Sy failfast
+If this device should propage BIO errors back to ZFS, used to disable
+failfast.
.It Sy path
The path to the device for this vdev
.It Sy allocating
diff --git a/man/man7/zfsconcepts.7 b/man/man7/zfsconcepts.7
index 0e5b21d54c78..1be3d961c3d7 100644
--- a/man/man7/zfsconcepts.7
+++ b/man/man7/zfsconcepts.7
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -28,8 +28,9 @@
.\" Copyright 2019 Richard Laager. All rights reserved.
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
+.\" Copyright 2023 Klara, Inc.
.\"
-.Dd June 30, 2019
+.Dd October 6, 2023
.Dt ZFSCONCEPTS 7
.Os
.
@@ -81,7 +82,8 @@ Bookmarks can be created extremely quickly, compared to snapshots, and they
consume no additional space within the pool.
Bookmarks can also have arbitrary names, much like snapshots.
.Pp
-Unlike snapshots, bookmarks can not be accessed through the filesystem in any way.
+Unlike snapshots, bookmarks can not be accessed through the filesystem in any
+way.
From a storage standpoint a bookmark just provides a way to reference
when a snapshot was created as a distinct object.
Bookmarks are initially tied to a snapshot, not the filesystem or volume,
@@ -204,3 +206,40 @@ practices, such as regular backups.
Consider using the
.Sy compression
property as a less resource-intensive alternative.
+.Ss Block cloning
+Block cloning is a facility that allows a file (or parts of a file) to be
+.Qq cloned ,
+that is, a shallow copy made where the existing data blocks are referenced
+rather than copied.
+Later modifications to the data will cause a copy of the data block to be taken
+and that copy modified.
+This facility is used to implement
+.Qq reflinks
+or
+.Qq file-level copy-on-write .
+.Pp
+Cloned blocks are tracked in a special on-disk structure called the Block
+Reference Table
+.Po BRT
+.Pc .
+Unlike deduplication, this table has minimal overhead, so can be enabled at all
+times.
+.Pp
+Also unlike deduplication, cloning must be requested by a user program.
+Many common file copying programs, including newer versions of
+.Nm /bin/cp ,
+will try to create clones automatically.
+Look for
+.Qq clone ,
+.Qq dedupe
+or
+.Qq reflink
+in the documentation for more information.
+.Pp
+There are some limitations to block cloning.
+Only whole blocks can be cloned, and blocks can not be cloned if they are not
+yet written to disk, or if they are encrypted, or the source and destination
+.Sy recordsize
+properties differ.
+The OS may add additional restrictions;
+for example, most versions of Linux will not allow clones across datasets.
diff --git a/man/man7/zfsprops.7 b/man/man7/zfsprops.7
index 4d6fc613c851..9ff0236f4d74 100644
--- a/man/man7/zfsprops.7
+++ b/man/man7/zfsprops.7
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -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 August 8, 2023
.Dt ZFSPROPS 7
.Os
.
@@ -79,7 +80,9 @@ for zettabyte
The following are all valid
.Pq and equal
specifications:
-.Li 1536M, 1.5g, 1.50GB .
+.Li 1536M ,
+.Li 1.5g ,
+.Li 1.50GB .
.Pp
The values of non-numeric properties are case sensitive and must be lowercase,
except for
@@ -191,7 +194,8 @@ and
.It Sy guid
The 64 bit GUID of this dataset or bookmark which does not change over its
entire lifetime.
-When a snapshot is sent to another pool, the received snapshot has the same GUID.
+When a snapshot is sent to another pool, the received snapshot has the same
+GUID.
Thus, the
.Sy guid
is suitable to identify a snapshot across pools.
@@ -258,7 +262,8 @@ this opaque token can be provided to
to resume and complete the
.Nm zfs Cm receive .
.It Sy redact_snaps
-For bookmarks, this is the list of snapshot guids the bookmark contains a redaction
+For bookmarks, this is the list of snapshot guids the bookmark contains a
+redaction
list for.
For snapshots, this is the list of snapshot guids the snapshot is redacted with
respect to.
@@ -519,6 +524,16 @@ The root user, or a user who has been granted the
privilege with
.Nm zfs allow ,
can access all projects' objects usage.
+.It Sy snapshots_changed
+Provides a mechanism to quickly determine whether snapshot list has
+changed without having to mount a dataset or iterate the snapshot list.
+Specifies the time at which a snapshot for a dataset was last
+created or deleted.
+.Pp
+This allows us to be more efficient how often we query snapshots.
+The property is persistent across mount and unmount operations only if the
+.Sy extensible_dataset
+feature is enabled.
.It Sy volblocksize
For volumes, specifies the block size of the volume.
The
@@ -787,7 +802,8 @@ Controls the compression algorithm used for this dataset.
.Pp
When set to
.Sy on
-(the default), indicates that the current default compression algorithm should be used.
+(the default), indicates that the current default compression algorithm should
+be used.
The default balances compression and decompression speed, with compression ratio
and is expected to work well on a wide variety of workloads.
Unlike all other settings for this property,
@@ -850,7 +866,8 @@ is equivalent to
.Pp
The
.Sy zstd
-compression algorithm provides both high compression ratios and good performance.
+compression algorithm provides both high compression ratios and good
+performance.
You can specify the
.Sy zstd
level by using the value
@@ -905,7 +922,8 @@ after compression, otherwise the compression will not be considered worthwhile
and the block saved uncompressed.
Note that when the logical block is less than
8 times the disk sector size this effectively reduces the necessary compression
-ratio; for example, 8 KiB blocks on disks with 4 KiB disk sectors must compress to 1/2
+ratio; for example, 8 KiB blocks on disks with 4 KiB disk sectors must compress
+to 1/2
or less of their original size.
.It Xo
.Sy context Ns = Ns Sy none Ns | Ns
@@ -1029,7 +1047,7 @@ file system.
The default value is
.Sy legacy .
Setting this property to a value other than
-.Sy legacy No requires the Sy large_dnode No pool feature to be enabled.
+.Sy legacy No requires the Sy large_dnode No pool feature to be enabled .
.Pp
Consider setting
.Sy dnodesize
@@ -1052,7 +1070,7 @@ if you need to receive a send stream of this dataset on a pool that doesn't
enable the
.Sy large_dnode
feature, or if you need to import this pool on a system that doesn't support the
-.Sy large_dnode No feature.
+.Sy large_dnode No feature .
.Pp
This property can also be referred to by its shortened column name,
.Sy dnsize .
@@ -1121,14 +1139,16 @@ is selected ZFS will ask for the key at the command prompt when it is required
to access the encrypted data (see
.Nm zfs Cm load-key
for details).
-This setting will also allow the key to be passed in via the standard input stream,
+This setting will also allow the key to be passed in via the standard input
+stream,
but users should be careful not to place keys which should be kept secret on
the command line.
If a file URI is selected, the key will be loaded from the
specified absolute file path.
If an HTTPS or HTTP URL is selected, it will be GETted using
.Xr fetch 3 ,
-libcurl, or nothing, depending on compile-time configuration and run-time availability.
+libcurl, or nothing, depending on compile-time configuration and run-time
+availability.
The
.Sy SSL_CA_CERT_FILE
environment variable can be set to set the location
@@ -1177,6 +1197,18 @@ are equivalent to the
and
.Sy noexec
mount options.
+.It Sy volthreading Ns = Ns Sy on Ns | Ns Sy off
+Controls internal zvol threading.
+The value
+.Sy off
+disables zvol threading, and zvol relies on application threads.
+The default value is
+.Sy on ,
+which enables threading within a zvol.
+Please note that this property will be overridden by
+.Sy zvol_request_sync
+module parameter.
+This property is only applicable to Linux.
.It Sy filesystem_limit Ns = Ns Ar count Ns | Ns Sy none
Limits the number of filesystems and volumes that can exist under this point in
the dataset tree.
@@ -1228,18 +1260,28 @@ Otherwise, they are automatically remounted in the new location if the property
was previously
.Sy legacy
or
-.Sy none ,
-or if they were mounted before the property was changed.
+.Sy none .
In addition, any shared file systems are unshared and shared in the new
location.
+.Pp
+When the
+.Sy mountpoint
+property is set with
+.Nm zfs Cm set Fl u
+, the
+.Sy mountpoint
+property is updated but dataset is not mounted or unmounted and remains
+as it was before.
.It Sy nbmand Ns = Ns Sy on Ns | Ns Sy off
Controls whether the file system should be mounted with
.Sy nbmand
.Pq Non-blocking mandatory locks .
-This is used for SMB clients.
Changes to this property only take effect when the file system is umounted and
remounted.
-Support for these locks is scarce and not described by POSIX.
+This was only supported by Linux prior to 5.15, and was buggy there,
+and is not supported by
+.Fx .
+On Solaris it's used for SMB clients.
.It Sy overlay Ns = Ns Sy on Ns | Ns Sy off
Allow mounting on a busy directory or a directory which already contains
files or directories.
@@ -1444,7 +1486,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.
@@ -1476,7 +1518,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
@@ -1485,6 +1527,18 @@ 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
@@ -1538,7 +1592,7 @@ Access time is only updated if the previous
access time was earlier than the current modify or change time or if the
existing access time hasn't been updated within the past 24 hours.
The default value is
-.Sy off .
+.Sy on .
The values
.Sy on
and
@@ -1571,6 +1625,23 @@ If this property is set to
then only metadata is cached.
The default value is
.Sy all .
+.It Sy prefetch Ns = Ns Sy all Ns | Ns Sy none Ns | Ns Sy metadata
+Controls what speculative prefetch does.
+If this property is set to
+.Sy all ,
+then both user data and metadata are prefetched.
+If this property is set to
+.Sy none ,
+then neither user data nor metadata are prefetched.
+If this property is set to
+.Sy metadata ,
+then only metadata are prefetched.
+The default value is
+.Sy all .
+.Pp
+Please note that the module parameter zfs_disable_prefetch=1 can
+be used to totally disable speculative prefetch, bypassing anything
+this property does.
.It Sy setuid Ns = Ns Sy on Ns | Ns Sy off
Controls whether the setuid bit is respected for the file system.
The default value is
@@ -1620,7 +1691,15 @@ LDAP- or
.Xr smbpasswd 5 Ns -based )
by default.
This means that any additional access control
-(disallow specific user specific access etc) must be done on the underlying file system.
+(disallow specific user specific access etc) must be done on the underlying file
+system.
+.Pp
+When the
+.Sy sharesmb
+property is updated with
+.Nm zfs Cm set Fl u
+, the property is set to desired value, but the operation to share, reshare
+or unshare the the dataset is not performed.
.It Sy sharenfs Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Ar opts
Controls whether the file system is shared via NFS, and what options are to be
used.
@@ -1664,6 +1743,13 @@ or if they were shared before the property was changed.
If the new property is
.Sy off ,
the file systems are unshared.
+.Pp
+When the
+.Sy sharenfs
+property is updated with
+.Nm zfs Cm set Fl u
+, the property is set to desired value, but the operation to share, reshare
+or unshare the the dataset is not performed.
.It Sy logbias Ns = Ns Sy latency Ns | Ns Sy throughput
Provide a hint to ZFS about handling of synchronous requests in this dataset.
If
@@ -1881,13 +1967,15 @@ See
for more information.
Jails are a
.Fx
-feature and are not relevant on other platforms.
-The default value is
-.Sy off .
-.It Sy zoned Ns = Ns Sy on Ns | Ns Sy off
+feature and this property is not available on other platforms.
+.It Sy zoned Ns = Ns Sy off Ns | Ns Sy on
Controls whether the dataset is managed from a non-global zone or namespace.
-The default value is
-.Sy off .
+See
+.Xr zfs-zone 8
+for more information.
+Zoning is a
+Linux
+feature and this property is not available on other platforms.
.El
.Pp
The following three properties cannot be changed after the file system is
diff --git a/man/man7/zpool-features.7 b/man/man7/zpool-features.7
index ed5cd419d6d0..ea3c68dc6083 100644
--- a/man/man7/zpool-features.7
+++ b/man/man7/zpool-features.7
@@ -5,7 +5,7 @@
.\" The contents of this file are subject to the terms of the Common Development
.\" and Distribution License (the "License"). You may not use this file except
.\" in compliance with the License. You can obtain a copy of the license at
-.\" usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
+.\" usr/src/OPENSOLARIS.LICENSE or https://opensource.org/licenses/CDDL-1.0.
.\"
.\" See the License for the specific language governing permissions and
.\" limitations under the License. When distributing Covered Code, include this
@@ -62,7 +62,8 @@ Refer to the documentation for the ZFS
implementation that created the pool for information about those features.
.Pp
Each supported feature also has a short name.
-By convention a feature's short name is the portion of its GUID which follows the
+By convention a feature's short name is the portion of its GUID which follows
+the
.Sq \&:
.Po
i.e.
@@ -167,7 +168,8 @@ separated by whitespace and/or commas.
Only features present in all files are enabled.
.Pp
Simple sanity checks are applied to the files:
-they must be between 1 B and 16 KiB in size, and must end with a newline character.
+they must be between 1 B and 16 KiB in size, and must end with a newline
+character.
.Pp
The requested features are applied when a pool is created using
.Nm zpool Cm create Fl o Sy compatibility Ns = Ns Ar …
@@ -217,8 +219,11 @@ to the end of the line is ignored.
.Bd -literal -compact -offset 4n
.No example# Nm cat Pa /usr/share/zfs/compatibility.d/grub2
# Features which are supported by GRUB2
+allocation_classes
async_destroy
+block_cloning
bookmarks
+device_rebuild
embedded_data
empty_bpobj
enabled_txg
@@ -226,8 +231,16 @@ extensible_dataset
filesystem_limits
hole_birth
large_blocks
+livelist
+log_spacemap
lz4_compress
+project_quota
+resilver_defer
spacemap_histogram
+spacemap_v2
+userobj_accounting
+zilsaxattr
+zpool_checkpoint
.No example# Nm zpool Cm create Fl o Sy compatibility Ns = Ns Ar grub2 Ar bootpool Ar vdev
.Ed
@@ -268,7 +281,7 @@ or when a new file is created under that filesystem. \
The upgrade can also be triggered on filesystems via \
Nm zfs Cm set Sy version Ns = Ns Sy current Ar fs . \
No The upgrade process runs in the background and may take a while to complete \
-for filesystems containing large amounts of files.
+for filesystems containing large amounts of files .
.
.de checksum-spiel
When the
@@ -339,11 +352,29 @@ while
is non-zero.
.
.feature org.openzfs blake3 no extensible_dataset
-This feature enables the use of the BLAKE3 hash algorithm for checksum and dedup.
+This feature enables the use of the BLAKE3 hash algorithm for checksum and
+dedup.
BLAKE3 is a secure hash algorithm focused on high performance.
.Pp
.checksum-spiel blake3
.
+.feature com.fudosecurity block_cloning yes
+When this feature is enabled ZFS will use block cloning for operations like
+.Fn copy_file_range 2 .
+Block cloning allows to create multiple references to a single block.
+It is much faster than copying the data (as the actual data is neither read nor
+written) and takes no additional space.
+Blocks can be cloned across datasets under some conditions (like equal
+.Nm recordsize ,
+the same master encryption key, etc.).
+ZFS tries its best to clone across datasets including encrypted ones.
+This is limited for various (nontrivial) reasons depending on the OS
+and/or ZFS internals.
+.Pp
+This feature becomes
+.Sy active
+when first block is cloned.
+When the last cloned block is freed, it goes back to the enabled state.
.feature com.delphix bookmarks yes extensible_dataset
This feature enables use of the
.Nm zfs Cm bookmark
@@ -548,6 +579,9 @@ and keyed by the head id.
With this feature enabled, every dataset affected by an error block is listed
in the output of
.Nm zpool Cm status .
+In case of encrypted filesystems with unloaded keys we are unable to check
+their snapshots or clones for errors and these will not be reported.
+An "access denied" error will be reported.
.Pp
\*[instant-never]
.
@@ -745,6 +779,14 @@ as soon as it is enabled and will never return to being
.Sy disabled .
\*[remount-upgrade]
.
+.feature org.openzfs raidz_expansion no none
+This feature enables the
+.Nm zpool Cm attach
+subcommand to attach a new device to a RAID-Z group, expanding the total
+amount usable space in the pool.
+See
+.Xr zpool-attach 8 .
+.
.feature com.delphix redaction_bookmarks no bookmarks extensible_dataset
This feature enables the use of redacted
.Nm zfs Cm send Ns s ,
@@ -762,6 +804,18 @@ and so cannot be safely mounted, and their contents cannot be safely read.
For more information about redacted receives, see
.Xr zfs-send 8 .
.
+.feature com.delphix redaction_list_spill no redaction_bookmarks
+This feature enables the redaction list created by zfs redact to store
+many more entries.
+It becomes
+.Sy active
+when a redaction list is created with more than 36 entries,
+and returns to being
+.Sy enabled
+when no long redaction lists remain in the pool.
+For more information about redacted sends, see
+.Xr zfs-send 8 .
+.
.feature com.datto resilver_defer yes
This feature allows ZFS to postpone new resilvers if an existing one is already
in progress.
@@ -837,6 +891,22 @@ by user and group.
\*[instant-never]
\*[remount-upgrade]
.
+.feature com.klarasystems vdev_zaps_v2 no
+This feature creates a ZAP object for the root vdev.
+.Pp
+This feature becomes active after the next
+.Nm zpool Cm import
+or
+.Nm zpool reguid .
+.
+Properties can be retrieved or set on the root vdev using
+.Nm zpool Cm get
+and
+.Nm zpool Cm set
+with
+.Sy root
+as the vdev name which is an alias for
+.Sy root-0 .
.feature org.openzfs zilsaxattr yes extensible_dataset
This feature enables
.Sy xattr Ns = Ns Sy sa
diff --git a/man/man7/zpoolconcepts.7 b/man/man7/zpoolconcepts.7
index ea2b783f32a7..18dfca6dc8ac 100644
--- a/man/man7/zpoolconcepts.7
+++ b/man/man7/zpoolconcepts.7
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -26,7 +26,7 @@
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\"
-.Dd June 2, 2021
+.Dd April 7, 2023
.Dt ZPOOLCONCEPTS 7
.Os
.
@@ -36,7 +36,7 @@
.
.Sh DESCRIPTION
.Ss Virtual Devices (vdevs)
-A "virtual device" describes a single device or a collection of devices
+A "virtual device" describes a single device or a collection of devices,
organized according to certain performance and fault characteristics.
The following virtual devices are supported:
.Bl -tag -width "special"
@@ -66,13 +66,14 @@ A mirror of two or more devices.
Data is replicated in an identical fashion across all components of a mirror.
A mirror with
.Em N No disks of size Em X No can hold Em X No bytes and can withstand Em N-1
-devices failing without losing data.
+devices failing, without losing data.
.It Sy raidz , raidz1 , raidz2 , raidz3
-A variation on RAID-5 that allows for better distribution of parity and
-eliminates the RAID-5
-.Qq write hole
+A distributed-parity layout, similar to RAID-5/6, with improved distribution of
+parity, and which does not suffer from the RAID-5/6
+.Qq write hole ,
.Pq in which data and parity become inconsistent after a power loss .
-Data and parity is striped across all disks within a raidz group.
+Data and parity is striped across all disks within a raidz group, though not
+necessarily in a consistent stripe width.
.Pp
A raidz group can have single, double, or triple parity, meaning that the
raidz group can sustain one, two, or three failures, respectively, without
@@ -91,26 +92,26 @@ vdev type is an alias for
.Pp
A raidz group with
.Em N No disks of size Em X No with Em P No parity disks can hold approximately
-.Em (N-P)*X No bytes and can withstand Em P No devices failing without losing data.
+.Em (N-P)*X No bytes and can withstand Em P No devices failing without losing data .
The minimum number of devices in a raidz group is one more than the number of
parity disks.
The recommended number is between 3 and 9 to help increase performance.
.It Sy draid , draid1 , draid2 , draid3
-A variant of raidz that provides integrated distributed hot spares which
-allows for faster resilvering while retaining the benefits of raidz.
+A variant of raidz that provides integrated distributed hot spares, allowing
+for faster resilvering, while retaining the benefits of raidz.
A dRAID vdev is constructed from multiple internal raidz groups, each with
-.Em D No data devices and Em P No parity devices.
+.Em D No data devices and Em P No parity devices .
These groups are distributed over all of the children in order to fully
utilize the available disk performance.
.Pp
Unlike raidz, dRAID uses a fixed stripe width (padding as necessary with
zeros) to allow fully sequential resilvering.
-This fixed stripe width significantly effects both usable capacity and IOPS.
+This fixed stripe width significantly affects both usable capacity and IOPS.
For example, with the default
.Em D=8 No and Em 4 KiB No disk sectors the minimum allocation size is Em 32 KiB .
If using compression, this relatively large allocation size can reduce the
effective compression ratio.
-When using ZFS volumes and dRAID, the default of the
+When using ZFS volumes (zvols) and dRAID, the default of the
.Sy volblocksize
property is increased to account for the allocation size.
If a dRAID pool will hold a significant amount of small blocks, it is
@@ -118,8 +119,8 @@ recommended to also add a mirrored
.Sy special
vdev to store those blocks.
.Pp
-In regards to I/O, performance is similar to raidz since for any read all
-.Em D No data disks must be accessed.
+In regards to I/O, performance is similar to raidz since, for any read, all
+.Em D No data disks must be accessed .
Delivered random IOPS can be reasonably approximated as
.Sy floor((N-S)/(D+P))*single_drive_IOPS .
.Pp
@@ -136,7 +137,7 @@ vdev type is an alias for
.Sy draid1 .
.Pp
A dRAID with
-.Em N No disks of size Em X , D No data disks per redundancy group, Em P
+.Em N No disks of size Em X , D No data disks per redundancy group , Em P
.No parity level, and Em S No distributed hot spares can hold approximately
.Em (N-S)*(D/(D+P))*X No bytes and can withstand Em P
devices failing without losing data.
@@ -151,7 +152,7 @@ The parity level (1-3).
.It Ar data
The number of data devices per redundancy group.
In general, a smaller value of
-.Em D No will increase IOPS, improve the compression ratio,
+.Em D No will increase IOPS, improve the compression ratio ,
and speed up resilvering at the expense of total usable capacity.
Defaults to
.Em 8 , No unless Em N-P-S No is less than Em 8 .
@@ -178,7 +179,7 @@ For more information, see the
.Sx Intent Log
section.
.It Sy dedup
-A device dedicated solely for deduplication tables.
+A device solely dedicated for deduplication tables.
The redundancy of this device should match the redundancy of the other normal
devices in the pool.
If more than one dedup device is specified, then
@@ -202,11 +203,9 @@ For more information, see the
section.
.El
.Pp
-Virtual devices cannot be nested, so a mirror or raidz virtual device can only
-contain files or disks.
-Mirrors of mirrors
-.Pq or other combinations
-are not allowed.
+Virtual devices cannot be nested arbitrarily.
+A mirror, raidz or draid virtual device can only be created with files or disks.
+Mirrors of mirrors or other such combinations are not allowed.
.Pp
A pool can have any number of virtual devices at the top of the configuration
.Po known as
@@ -230,7 +229,7 @@ each a mirror of two disks:
ZFS supports a rich set of mechanisms for handling device failure and data
corruption.
All metadata and data is checksummed, and ZFS automatically repairs bad data
-from a good copy when corruption is detected.
+from a good copy, when corruption is detected.
.Pp
In order to take advantage of these features, a pool must make use of some form
of redundancy, using either mirrored or raidz groups.
@@ -247,7 +246,7 @@ A faulted pool has corrupted metadata, or one or more faulted devices, and
insufficient replicas to continue functioning.
.Pp
The health of the top-level vdev, such as a mirror or raidz device,
-is potentially impacted by the state of its associated vdevs,
+is potentially impacted by the state of its associated vdevs
or component devices.
A top-level vdev or component device is in one of the following states:
.Bl -tag -width "DEGRADED"
@@ -261,8 +260,8 @@ sufficient replicas exist to continue functioning.
The underlying conditions are as follows:
.Bl -bullet -compact
.It
-The number of checksum errors exceeds acceptable levels and the device is
-degraded as an indication that something may be wrong.
+The number of checksum errors or slow I/Os exceeds acceptable levels and the
+device is degraded as an indication that something may be wrong.
ZFS continues to use the device as necessary.
.It
The number of I/O errors exceeds acceptable levels.
@@ -319,14 +318,15 @@ In this case, checksum errors are reported for all disks on which the block
is stored.
.Pp
If a device is removed and later re-attached to the system,
-ZFS attempts online the device automatically.
+ZFS attempts to bring the device online automatically.
Device attachment detection is hardware-dependent
and might not be supported on all platforms.
.
.Ss Hot Spares
ZFS allows devices to be associated with pools as
.Qq hot spares .
-These devices are not actively used in the pool, but when an active device
+These devices are not actively used in the pool.
+But, when an active device
fails, it is automatically replaced by a hot spare.
To create a pool with hot spares, specify a
.Sy spare
@@ -343,10 +343,10 @@ Once a spare replacement is initiated, a new
.Sy spare
vdev is created within the configuration that will remain there until the
original device is replaced.
-At this point, the hot spare becomes available again if another device fails.
+At this point, the hot spare becomes available again, if another device fails.
.Pp
-If a pool has a shared spare that is currently being used, the pool can not be
-exported since other pools may use this shared spare, which may lead to
+If a pool has a shared spare that is currently being used, the pool cannot be
+exported, since other pools may use this shared spare, which may lead to
potential data corruption.
.Pp
Shared spares add some risk.
@@ -390,7 +390,7 @@ See the
.Sx EXAMPLES
section for an example of mirroring multiple log devices.
.Pp
-Log devices can be added, replaced, attached, detached and removed.
+Log devices can be added, replaced, attached, detached, and removed.
In addition, log devices are imported and exported as part of the pool
that contains them.
Mirrored devices can be removed by specifying the top-level mirror vdev.
@@ -423,8 +423,8 @@ This can be disabled by setting
.Sy l2arc_rebuild_enabled Ns = Ns Sy 0 .
For cache devices smaller than
.Em 1 GiB ,
-we do not write the metadata structures
-required for rebuilding the L2ARC in order not to waste space.
+ZFS does not write the metadata structures
+required for rebuilding the L2ARC, to conserve space.
This can be changed with
.Sy l2arc_rebuild_blocks_min_l2size .
The cache device header
@@ -435,21 +435,21 @@ Setting
will result in scanning the full-length ARC lists for cacheable content to be
written in L2ARC (persistent ARC).
If a cache device is added with
-.Nm zpool Cm add
-its label and header will be overwritten and its contents are not going to be
+.Nm zpool Cm add ,
+its label and header will be overwritten and its contents will not be
restored in L2ARC, even if the device was previously part of the pool.
If a cache device is onlined with
-.Nm zpool Cm online
+.Nm zpool Cm online ,
its contents will be restored in L2ARC.
-This is useful in case of memory pressure
+This is useful in case of memory pressure,
where the contents of the cache device are not fully restored in L2ARC.
-The user can off- and online the cache device when there is less memory pressure
-in order to fully restore its contents to L2ARC.
+The user can off- and online the cache device when there is less memory
+pressure, to fully restore its contents to L2ARC.
.
.Ss Pool checkpoint
Before starting critical procedures that include destructive actions
.Pq like Nm zfs Cm destroy ,
-an administrator can checkpoint the pool's state and in the case of a
+an administrator can checkpoint the pool's state and, in the case of a
mistake or failure, rewind the entire pool back to the checkpoint.
Otherwise, the checkpoint can be discarded when the procedure has completed
successfully.
@@ -485,7 +485,7 @@ current state of the pool won't be scanned during a scrub.
.
.Ss Special Allocation Class
Allocations in the special class are dedicated to specific block types.
-By default this includes all metadata, the indirect blocks of user data, and
+By default, this includes all metadata, the indirect blocks of user data, and
any deduplication tables.
The class can also be provisioned to accept small file blocks.
.Pp
diff --git a/man/man7/zpoolprops.7 b/man/man7/zpoolprops.7
index 944fbf2b8d29..5428ab8d3076 100644
--- a/man/man7/zpoolprops.7
+++ b/man/man7/zpoolprops.7
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -26,8 +26,9 @@
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
+.\" Copyright (c) 2023, Klara Inc.
.\"
-.Dd May 27, 2021
+.Dd January 2, 2024
.Dt ZPOOLPROPS 7
.Os
.
@@ -40,15 +41,34 @@ Each pool has several properties associated with it.
Some properties are read-only statistics while others are configurable and
change the behavior of the pool.
.Pp
+User properties have no effect on ZFS behavior.
+Use them to annotate pools in a way that is meaningful in your environment.
+For more information about user properties, see the
+.Sx User Properties
+section.
+.Pp
The following are read-only properties:
.Bl -tag -width "unsupported@guid"
-.It Cm allocated
+.It Sy allocated
Amount of storage used within the pool.
See
.Sy fragmentation
and
.Sy free
for more information.
+.It Sy bcloneratio
+The ratio of the total amount of storage that would be required to store all
+the cloned blocks without cloning to the actual storage used.
+The
+.Sy bcloneratio
+property is calculated as:
+.Pp
+.Sy ( ( bclonesaved + bcloneused ) * 100 ) / bcloneused
+.It Sy bclonesaved
+The amount of additional storage that would be required if block cloning
+was not used.
+.It Sy bcloneused
+The amount of storage used by cloned blocks.
.It Sy capacity
Percentage of pool space used.
This property can also be referred to by its shortened column name,
@@ -82,11 +102,13 @@ By contrast, the
property describes how much new data can be written to ZFS filesystems/volumes.
The zpool
.Sy free
-property is not generally useful for this purpose, and can be substantially more than the zfs
+property is not generally useful for this purpose, and can be substantially more
+than the zfs
.Sy available
space.
This discrepancy is due to several factors, including raidz parity;
-zfs reservation, quota, refreservation, and refquota properties; and space set aside by
+zfs reservation, quota, refreservation, and refquota properties; and space set
+aside by
.Sy spa_slop_shift
(see
.Xr zfs 4
@@ -101,16 +123,16 @@ Over time
will decrease while
.Sy free
increases.
-.It Sy leaked
-Space not released while
-.Sy freeing
-due to corruption, now permanently leaked into the pool.
+.It Sy guid
+A unique identifier for the pool.
.It Sy health
The current health of the pool.
Health can be one of
.Sy ONLINE , DEGRADED , FAULTED , OFFLINE, REMOVED , UNAVAIL .
-.It Sy guid
-A unique identifier for the pool.
+.It Sy leaked
+Space not released while
+.Sy freeing
+due to corruption, now permanently leaked into the pool.
.It Sy load_guid
A unique identifier for the pool.
Unlike the
@@ -177,7 +199,7 @@ changed with the
.Nm zpool Cm set
command:
.Bl -tag -width Ds
-.It Sy ashift Ns = Ns Sy ashift
+.It Sy ashift Ns = Ns Ar ashift
Pool sector size exponent, to the power of
.Sy 2
(internally referred to as
@@ -272,7 +294,8 @@ using the
command.
.It Sy bootfs Ns = Ns Sy (unset) Ns | Ns Ar pool Ns Op / Ns Ar dataset
Identifies the default bootable dataset for the root pool.
-This property is expected to be set mainly by the installation and upgrade programs.
+This property is expected to be set mainly by the installation and upgrade
+programs.
Not all Linux distribution boot processes use the bootfs property.
.It Sy cachefile Ns = Ns Ar path Ns | Ns Sy none
Controls the location of where the pool configuration is cached.
@@ -308,7 +331,7 @@ Specifies that the pool maintain compatibility with specific feature sets.
When set to
.Sy off
(or unset) compatibility is disabled (all features may be enabled); when set to
-.Sy legacy Ns
+.Sy legacy
no features may be enabled.
When set to a comma-separated list of filenames
(each filename may either be an absolute path, or relative to
@@ -415,3 +438,49 @@ backwards compatibility.
Once feature flags are enabled on a pool this property will no longer have a
value.
.El
+.
+.Ss User Properties
+In addition to the standard native properties, ZFS supports arbitrary user
+properties.
+User properties have no effect on ZFS behavior, but applications or
+administrators can use them to annotate pools.
+.Pp
+User property names must contain a colon
+.Pq Qq Sy \&:
+character to distinguish them from native properties.
+They may contain lowercase letters, numbers, and the following punctuation
+characters: colon
+.Pq Qq Sy \&: ,
+dash
+.Pq Qq Sy - ,
+period
+.Pq Qq Sy \&. ,
+and underscore
+.Pq Qq Sy _ .
+The expected convention is that the property name is divided into two portions
+such as
+.Ar module : Ns Ar property ,
+but this namespace is not enforced by ZFS.
+User property names can be at most 256 characters, and cannot begin with a dash
+.Pq Qq Sy - .
+.Pp
+When making programmatic use of user properties, it is strongly suggested to use
+a reversed DNS domain name for the
+.Ar module
+component of property names to reduce the chance that two
+independently-developed packages use the same property name for different
+purposes.
+.Pp
+The values of user properties are arbitrary strings and
+are never validated.
+All of the commands that operate on properties
+.Po Nm zpool Cm list ,
+.Nm zpool Cm get ,
+.Nm zpool Cm set ,
+and so forth
+.Pc
+can be used to manipulate both native properties and user properties.
+Use
+.Nm zpool Cm set Ar name Ns =
+to clear a user property.
+Property values are limited to 8192 bytes.
diff --git a/man/man8/.gitignore b/man/man8/.gitignore
index f2fc702147e9..a468f9cbf9d3 100644
--- a/man/man8/.gitignore
+++ b/man/man8/.gitignore
@@ -1,2 +1,3 @@
/zed.8
/zfs-mount-generator.8
+/zfs_prepare_disk.8
diff --git a/man/man8/fsck.zfs.8 b/man/man8/fsck.zfs.8
index 0ce7576ebe63..57d41f61d299 100644
--- a/man/man8/fsck.zfs.8
+++ b/man/man8/fsck.zfs.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -34,7 +34,8 @@
.
.Sh DESCRIPTION
.Nm
-is a thin shell wrapper that at most checks the status of a dataset's container pool.
+is a thin shell wrapper that at most checks the status of a dataset's container
+pool.
It is installed by OpenZFS because some Linux
distributions expect a fsck helper for all filesystems.
.Pp
diff --git a/man/man8/mount.zfs.8 b/man/man8/mount.zfs.8
index 2101f70cd595..0840ac531c63 100644
--- a/man/man8/mount.zfs.8
+++ b/man/man8/mount.zfs.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/vdev_id.8 b/man/man8/vdev_id.8
index 2b327b3192a6..96f8d9c08543 100644
--- a/man/man8/vdev_id.8
+++ b/man/man8/vdev_id.8
@@ -30,8 +30,10 @@ is an udev helper which parses
to map a physical path in a storage topology to a channel name.
The channel name is combined with a disk enclosure slot number to create
an alias that reflects the physical location of the drive.
-This is particularly helpful when it comes to tasks like replacing failed drives.
-Slot numbers may also be remapped in case the default numbering is unsatisfactory.
+This is particularly helpful when it comes to tasks like replacing failed
+drives.
+Slot numbers may also be remapped in case the default numbering is
+unsatisfactory.
The drive aliases will be created as symbolic links in
.Pa /dev/disk/by-vdev .
.Pp
diff --git a/man/man8/zdb.8 b/man/man8/zdb.8
index 31ee601538ce..d7f66d917ac7 100644
--- a/man/man8/zdb.8
+++ b/man/man8/zdb.8
@@ -14,7 +14,7 @@
.\" Copyright (c) 2017 Lawrence Livermore National Security, LLC.
.\" Copyright (c) 2017 Intel Corporation.
.\"
-.Dd October 7, 2020
+.Dd November 18, 2023
.Dt ZDB 8
.Os
.
@@ -23,25 +23,35 @@
.Nd display ZFS storage pool debugging and consistency information
.Sh SYNOPSIS
.Nm
-.Op Fl AbcdDFGhikLMNPsvXYy
+.Op Fl AbcdDFGhikLMNPsTvXYy
.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns …
.Op Fl I Ar inflight-I/O-ops
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns …
.Op Fl t Ar txg
.Op Fl U Ar cache
.Op Fl x Ar dumpdir
+.Op Fl K Ar key
.Op Ar poolname Ns Op / Ns Ar dataset Ns | Ns Ar objset-ID
.Op Ar object Ns | Ns Ar range Ns …
.Nm
.Op Fl AdiPv
.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns …
.Op Fl U Ar cache
+.Op Fl K Ar key
.Ar poolname Ns Op Ar / Ns Ar dataset Ns | Ns Ar objset-ID
.Op Ar object Ns | Ns Ar range Ns …
.Nm
+.Fl B
+.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns …
+.Op Fl U Ar cache
+.Op Fl K Ar key
+.Ar poolname Ns Ar / Ns Ar objset-ID
+.Op Ar backup-flags
+.Nm
.Fl C
.Op Fl A
.Op Fl U Ar cache
+.Op Ar poolname
.Nm
.Fl E
.Op Fl A
@@ -59,9 +69,11 @@
.Ar poolname Op Ar vdev Oo Ar metaslab Oc Ns …
.Nm
.Fl O
+.Op Fl K Ar key
.Ar dataset path
.Nm
.Fl r
+.Op Fl K Ar key
.Ar dataset path destination
.Nm
.Fl R
@@ -103,6 +115,12 @@ characters, it is interpreted as a pool name.
The root dataset can be specified as
.Qq Ar pool Ns / .
.Pp
+.Nm
+is an
+.Qq offline
+tool; it accesses the block devices underneath the pools directly from
+userspace and does not care if the pool is imported or datasets are mounted
+(or even if the system understands ZFS at all).
When operating on an imported and active pool it is possible, though unlikely,
that zdb may interpret inconsistent pool data and behave erratically.
.
@@ -113,6 +131,22 @@ Display options:
Display statistics regarding the number, size
.Pq logical, physical and allocated
and deduplication of blocks.
+.It Fl B , -backup
+Generate a backup stream, similar to
+.Nm zfs Cm send ,
+but for the numeric objset ID, and without opening the dataset.
+This can be useful in recovery scenarios if dataset metadata has become
+corrupted but the dataset itself is readable.
+The optional
+.Ar flags
+argument is a string of one or more of the letters
+.Sy e ,
+.Sy L ,
+.Sy c ,
+and
+.Sy w ,
+which correspond to the same flags in
+.Xr zfs-send 8 .
.It Fl c , -checksum
Verify the checksum of all metadata blocks while printing block statistics
.Po see
@@ -174,7 +208,8 @@ negates the effect of the flag that follows it and has no effect unless
preceded by the
.Ar A
flag.
-For example, the range 0:-1:A-d will dump all object types except for directories.
+For example, the range 0:-1:A-d will dump all object types except for
+directories.
.Pp
.Bl -tag -compact -width Ds
.It Sy A
@@ -274,7 +309,8 @@ the percentage of free space in each space map.
.It Fl mmmm
Display every spacemap record.
.It Fl M , -metaslab-groups
-Display all "normal" vdev metaslab group information - per-vdev metaslab count, fragmentation,
+Display all "normal" vdev metaslab group information - per-vdev metaslab count,
+fragmentation,
and free space histogram, as well as overall pool fragmentation and histogram.
.It Fl MM
"Special" vdevs are added to -M's normal output.
@@ -367,6 +403,13 @@ Display operation counts, bandwidth, and error counts of I/O to the pool from
Simulate the effects of deduplication, constructing a DDT and then display
that DDT as with
.Fl DD .
+.It Fl T , -brt-stats
+Display block reference table (BRT) statistics, including the size of uniques
+blocks cloned, the space saving as a result of cloning, and the saving ratio.
+.It Fl TT
+Display the per-vdev BRT statistics, including total references.
+.It Fl TTT
+Dump the contents of the block reference tables.
.It Fl u , -uberblock
Display the current uberblock.
.El
@@ -410,6 +453,24 @@ The default value is 200.
This option affects the performance of the
.Fl c
option.
+.It Fl K , -key Ns = Ns Ar key
+Decryption key needed to access an encrypted dataset.
+This will cause
+.Nm
+to attempt to unlock the dataset using the encryption root, key format and other
+encryption parameters on the given dataset.
+.Nm
+can still inspect pool and dataset structures on encrypted datasets without
+unlocking them, but will not be able to access file names and attributes and
+object contents. \fBWARNING:\fP The raw decryption key and any decrypted data
+will be in user memory while
+.Nm
+is running.
+Other user programs may be able to extract it by inspecting
+.Nm
+as it runs.
+Exercise extreme caution when using this option in shared or uncontrolled
+environments.
.It Fl o , -option Ns = Ns Ar var Ns = Ns Ar value Ns …
Set the given global libzpool variable to the provided value.
The value must be an unsigned 32-bit integer.
diff --git a/man/man8/zed.8.in b/man/man8/zed.8.in
index 6c51f10695cc..1bbca05e385d 100644
--- a/man/man8/zed.8.in
+++ b/man/man8/zed.8.in
@@ -27,6 +27,7 @@
.Op Fl P Ar path
.Op Fl s Ar statefile
.Op Fl j Ar jobs
+.Op Fl b Ar buflen
.
.Sh DESCRIPTION
The
@@ -60,8 +61,10 @@ Lock all current and future pages in the virtual memory address space.
This may help the daemon remain responsive when the system is under heavy
memory pressure.
.It Fl I
-Request that the daemon idle rather than exit when the kernel modules are not loaded.
-Processing of events will start, or resume, when the kernel modules are (re)loaded.
+Request that the daemon idle rather than exit when the kernel modules are not
+loaded.
+Processing of events will start, or resume, when the kernel modules are
+(re)loaded.
Under Linux the kernel modules cannot be unloaded while the daemon is running.
.It Fl Z
Zero the daemon's state, thereby allowing zevents still within the kernel
@@ -74,12 +77,14 @@ Write the daemon's process ID to the specified file.
Custom
.Ev $PATH
for zedlets to use.
-Normally zedlets run in a locked-down environment, with hardcoded paths to the ZFS commands
+Normally zedlets run in a locked-down environment, with hardcoded paths to the
+ZFS commands
.Pq Ev $ZFS , $ZPOOL , $ZED , … ,
and a hard-coded
.Ev $PATH .
This is done for security reasons.
-However, the ZFS test suite uses a custom PATH for its ZFS commands, and passes it to
+However, the ZFS test suite uses a custom PATH for its ZFS commands, and passes
+it to
.Nm
with
.Fl P .
@@ -96,10 +101,22 @@ ZEDLETs to run concurrently,
delaying execution of new ones until they finish.
Defaults to
.Sy 16 .
+.It Fl b Ar buflen
+Cap kernel event buffer growth to
+.Ar buflen
+entries.
+This buffer is grown when the daemon misses an event, but results in
+unreclaimable memory use in the kernel.
+A value of
+.Sy 0
+removes the cap.
+Defaults to
+.Sy 1048576 .
.El
.Sh ZEVENTS
A zevent is comprised of a list of nvpairs (name/value pairs).
-Each zevent contains an EID (Event IDentifier) that uniquely identifies it throughout
+Each zevent contains an EID (Event IDentifier) that uniquely identifies it
+throughout
the lifetime of the loaded ZFS kernel module; this EID is a monotonically
increasing integer that resets to 1 each time the kernel module is loaded.
Each zevent also contains a class string that identifies the type of event.
@@ -205,7 +222,8 @@ The ZFS release the daemon is part of.
.El
.Pp
ZEDLETs may need to call other ZFS commands.
-The installation paths of the following executables are defined as environment variables:
+The installation paths of the following executables are defined as environment
+variables:
.Sy ZDB ,
.Sy ZED ,
.Sy ZFS ,
diff --git a/man/man8/zfs-allow.8 b/man/man8/zfs-allow.8
index 52b7c43f44ba..d26984317c2e 100644
--- a/man/man8/zfs-allow.8
+++ b/man/man8/zfs-allow.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -411,7 +411,7 @@ mount point permission is set to 755 by default, user
will be unable to mount file systems under
.Ar tank/cindys .
Add an ACE similar to the following syntax to provide mount point access:
-.Dl # Cm chmod No A+user: Ns Ar cindys Ns :add_subdirectory:allow Ar /tank/cindys
+.Dl # Cm chmod No A+user : Ns Ar cindys Ns :add_subdirectory:allow Ar /tank/cindys
.
.Ss Example 2 : No Delegating Create Time Permissions on a ZFS Dataset
The following example shows how to grant anyone in the group
diff --git a/man/man8/zfs-bookmark.8 b/man/man8/zfs-bookmark.8
index 8b268b714385..01364b0f5052 100644
--- a/man/man8/zfs-bookmark.8
+++ b/man/man8/zfs-bookmark.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-clone.8 b/man/man8/zfs-clone.8
index 305748a8cd0f..fee629951c36 100644
--- a/man/man8/zfs-clone.8
+++ b/man/man8/zfs-clone.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-create.8 b/man/man8/zfs-create.8
index f302493e0ab3..b3997d32767c 100644
--- a/man/man8/zfs-create.8
+++ b/man/man8/zfs-create.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -234,14 +234,11 @@ if the volume is not sparse.
Print verbose information about the created dataset.
.El
.El
-.Ss ZFS Volumes as Swap
-ZFS volumes may be used as swap devices.
-After creating the volume with the
-.Nm zfs Cm create Fl V
-enable the swap area using the
-.Xr swapon 8
-command.
-Swapping to files on ZFS filesystems is not supported.
+.Ss ZFS for Swap
+Swapping to a ZFS volume is prone to deadlock and not recommended.
+See OpenZFS FAQ.
+.Pp
+Swapping to a file on a ZFS filesystem is not supported.
.
.Sh EXAMPLES
.\" These are, respectively, examples 1, 10 from zfs.8
diff --git a/man/man8/zfs-destroy.8 b/man/man8/zfs-destroy.8
index 26926d8dcbb8..fe4f19d18e9f 100644
--- a/man/man8/zfs-destroy.8
+++ b/man/man8/zfs-destroy.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-diff.8 b/man/man8/zfs-diff.8
index f82735b38e4e..16aa20969f91 100644
--- a/man/man8/zfs-diff.8
+++ b/man/man8/zfs-diff.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-hold.8 b/man/man8/zfs-hold.8
index 5e4652092e80..4bc36cb47fc2 100644
--- a/man/man8/zfs-hold.8
+++ b/man/man8/zfs-hold.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -43,7 +43,7 @@
.Ar tag Ar snapshot Ns …
.Nm zfs
.Cm holds
-.Op Fl rH
+.Op Fl rHp
.Ar snapshot Ns …
.Nm zfs
.Cm release
@@ -76,7 +76,7 @@ of all descendent file systems.
.It Xo
.Nm zfs
.Cm holds
-.Op Fl rH
+.Op Fl rHp
.Ar snapshot Ns …
.Xc
Lists all existing user references for the given snapshot or snapshots.
@@ -86,6 +86,8 @@ Lists the holds that are set on the named descendent snapshots, in addition to
listing the holds on the named snapshot.
.It Fl H
Do not print headers, use tab-delimited output.
+.It Fl p
+Prints holds timestamps as unix epoch timestamps.
.El
.It Xo
.Nm zfs
diff --git a/man/man8/zfs-jail.8 b/man/man8/zfs-jail.8
index 4f9faaea9bf5..53a1ccef7746 100644
--- a/man/man8/zfs-jail.8
+++ b/man/man8/zfs-jail.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -97,7 +97,8 @@ property cannot be changed from within a jail.
After a dataset is attached to a jail and the
.Sy jailed
property is set, a jailed file system cannot be mounted outside the jail,
-since the jail administrator might have set the mount point to an unacceptable value.
+since the jail administrator might have set the mount point to an unacceptable
+value.
.Pp
See
.Xr jail 8
diff --git a/man/man8/zfs-list.8 b/man/man8/zfs-list.8
index 2b4c13d0e3a3..85bd3fbafced 100644
--- a/man/man8/zfs-list.8
+++ b/man/man8/zfs-list.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -29,7 +29,7 @@
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
.\"
-.Dd March 16, 2022
+.Dd February 8, 2024
.Dt ZFS-LIST 8
.Os
.
@@ -155,6 +155,15 @@ or
For example, specifying
.Fl t Sy snapshot
displays only snapshots.
+.Sy fs ,
+.Sy snap ,
+or
+.Sy vol
+can be used as aliases for
+.Sy filesystem ,
+.Sy snapshot ,
+or
+.Sy volume .
.El
.
.Sh EXAMPLES
diff --git a/man/man8/zfs-load-key.8 b/man/man8/zfs-load-key.8
index b12a79e0150a..f68d6e985a78 100644
--- a/man/man8/zfs-load-key.8
+++ b/man/man8/zfs-load-key.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -236,7 +236,8 @@ Key rotation is managed by ZFS.
Changing the user's key (e.g. a passphrase)
does not require re-encrypting the entire dataset.
Datasets can be scrubbed,
-resilvered, renamed, and deleted without the encryption keys being loaded (see the
+resilvered, renamed, and deleted without the encryption keys being loaded (see
+the
.Cm load-key
subcommand for more info on key loading).
.Pp
@@ -291,9 +292,11 @@ Encrypted datasets may not have
since the implementation stores some encryption metadata where the third copy
would normally be.
Since compression is applied before encryption, datasets may
-be vulnerable to a CRIME-like attack if applications accessing the data allow for it.
+be vulnerable to a CRIME-like attack if applications accessing the data allow
+for it.
Deduplication with encryption will leak information about which blocks
-are equivalent in a dataset and will incur an extra CPU cost for each block written.
+are equivalent in a dataset and will incur an extra CPU cost for each block
+written.
.
.Sh SEE ALSO
.Xr zfsprops 7 ,
diff --git a/man/man8/zfs-mount-generator.8.in b/man/man8/zfs-mount-generator.8.in
index ae8937038e67..be60ea68f960 100644
--- a/man/man8/zfs-mount-generator.8.in
+++ b/man/man8/zfs-mount-generator.8.in
@@ -49,7 +49,7 @@ units for configured ZFS datasets.
.No Skipped if Sy off .
.No Skipped if only Sy noauto
datasets exist for a given mountpoint and there's more than one.
-.No Datasets with Sy yes No take precedence over ones with Sy noauto No for the same mountpoint.
+.No Datasets with Sy yes No take precedence over ones with Sy noauto No for the same mountpoint .
.No Sets logical Em noauto No flag if Sy noauto .
Encryption roots always generate
.Sy zfs-load-key@ Ns Ar root Ns Sy .service ,
@@ -94,14 +94,15 @@ as the mount unit.
.No Sets Sy After Ns = for the mount unit.
.
.It Sy org.openzfs.systemd:wanted-by Ns = Ns Pa unit Ns Oo " " Ns Pa unit Oc Ns …
-.No Sets logical Em noauto No flag (see below).
+.No Sets logical Em noauto No flag (see below) .
.No If not Sy none , No sets Sy WantedBy Ns = for the mount unit.
.It Sy org.openzfs.systemd:required-by Ns = Ns Pa unit Ns Oo " " Ns Pa unit Oc Ns …
-.No Sets logical Em noauto No flag (see below).
+.No Sets logical Em noauto No flag (see below) .
.No If not Sy none , No sets Sy RequiredBy Ns = for the mount unit.
.
.It Sy org.openzfs.systemd:nofail Ns = Ns (unset) Ns | Ns Sy on Ns | Ns Sy off
-Waxes or wanes strength of default reverse dependencies of the mount unit, see below.
+Waxes or wanes strength of default reverse dependencies of the mount unit, see
+below.
.
.It Sy org.openzfs.systemd:ignore Ns = Ns Sy on Ns | Ns Sy off
.No Skip if Sy on .
diff --git a/man/man8/zfs-mount.8 b/man/man8/zfs-mount.8
index 42ce6b5ca155..20dbe4d0e648 100644
--- a/man/man8/zfs-mount.8
+++ b/man/man8/zfs-mount.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -43,7 +43,7 @@
.Cm mount
.Op Fl Oflv
.Op Fl o Ar options
-.Fl a Ns | Ns Ar filesystem
+.Fl a Ns | Ns Fl R Ar filesystem Ns | Ns Ar filesystem
.Nm zfs
.Cm unmount
.Op Fl fu
@@ -61,7 +61,7 @@ Displays all ZFS file systems currently mounted.
.Cm mount
.Op Fl Oflv
.Op Fl o Ar options
-.Fl a Ns | Ns Ar filesystem
+.Fl a Ns | Ns Fl R Ar filesystem Ns | Ns Ar filesystem
.Xc
Mount ZFS filesystem on a path described by its
.Sy mountpoint
@@ -83,6 +83,8 @@ for more information.
.It Fl a
Mount all available ZFS file systems.
Invoked automatically as part of the boot process if configured.
+.It Fl R
+Mount the specified filesystems along with all their children.
.It Ar filesystem
Mount the specified filesystem.
.It Fl o Ar options
@@ -104,7 +106,8 @@ this will cause the terminal to interactively block after asking for the key.
.It Fl v
Report mount progress.
.It Fl f
-Attempt to force mounting of all filesystems, even those that couldn't normally be mounted (e.g. redacted datasets).
+Attempt to force mounting of all filesystems, even those that couldn't normally
+be mounted (e.g. redacted datasets).
.El
.It Xo
.Nm zfs
diff --git a/man/man8/zfs-program.8 b/man/man8/zfs-program.8
index 06415b2190eb..928620362be7 100644
--- a/man/man8/zfs-program.8
+++ b/man/man8/zfs-program.8
@@ -424,6 +424,19 @@ To enable taking snapshots from ZCP scripts, the pool must be upgraded.
.It Ar dataset Pq string
Name of snapshot to create.
.El
+.It Fn zfs.sync.rename_snapshot dataset oldsnapname newsnapname
+Rename a snapshot of a filesystem or a volume.
+Returns 0 if the snapshot was successfully renamed,
+and a nonzero error code otherwise.
+.Pp
+.Bl -tag -compact -width "newbookmark (string)"
+.It Ar dataset Pq string
+Name of the snapshot's parent dataset.
+.It Ar oldsnapname Pq string
+Original name of the snapshot.
+.It Ar newsnapname Pq string
+New name of the snapshot.
+.El
.It Fn zfs.sync.bookmark source newbookmark
Create a bookmark of an existing source snapshot or bookmark.
Returns 0 if the new bookmark was successfully created,
diff --git a/man/man8/zfs-project.8 b/man/man8/zfs-project.8
index 0edaad0820d7..12f503124038 100644
--- a/man/man8/zfs-project.8
+++ b/man/man8/zfs-project.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -99,7 +99,8 @@ Clear subdirectories' flags recursively.
.Ar file Ns | Ns Ar directory Ns …
.Xc
Check project ID and inherit flag on the files and directories:
-report entries without the project inherit flag, or with project IDs different from the
+report entries without the project inherit flag, or with project IDs different
+from the
target directory's project ID or the one specified with
.Fl p .
.Bl -tag -width "-p id"
diff --git a/man/man8/zfs-promote.8 b/man/man8/zfs-promote.8
index 3cb896887330..cdb04d05de18 100644
--- a/man/man8/zfs-promote.8
+++ b/man/man8/zfs-promote.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -44,7 +44,8 @@
.Sh DESCRIPTION
The
.Nm zfs Cm promote
-command makes it possible to destroy the dataset that the clone was created from.
+command makes it possible to destroy the dataset that the clone was created
+from.
The clone parent-child dependency relationship is reversed, so that the origin
dataset becomes a clone of the specified dataset.
.Pp
diff --git a/man/man8/zfs-receive.8 b/man/man8/zfs-receive.8
index 8d99c7ee58dc..a15f2cbe9450 100644
--- a/man/man8/zfs-receive.8
+++ b/man/man8/zfs-receive.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -29,7 +29,7 @@
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
.\"
-.Dd March 16, 2022
+.Dd March 12, 2023
.Dt ZFS-RECEIVE 8
.Os
.
@@ -56,6 +56,11 @@
.Cm receive
.Fl A
.Ar filesystem Ns | Ns Ar volume
+.Nm zfs
+.Cm receive
+.Fl c
+.Op Fl vn
+.Ar filesystem Ns | Ns Ar snapshot
.
.Sh DESCRIPTION
.Bl -tag -width ""
@@ -393,6 +398,24 @@ restrictions (e.g. set-once) apply equally to
Abort an interrupted
.Nm zfs Cm receive Fl s ,
deleting its saved partially received state.
+.It Xo
+.Nm zfs
+.Cm receive
+.Fl c
+.Op Fl vn
+.Ar filesystem Ns | Ns Ar snapshot
+.Xc
+Attempt to repair data corruption in the specified dataset,
+by using the provided stream as the source of healthy data.
+This method of healing can only heal data blocks present in the stream.
+Metadata can not be healed by corrective receive.
+Running a scrub is recommended post-healing to ensure all data corruption was
+repaired.
+.Pp
+It's important to consider why corruption has happened in the first place.
+If you have slowly failing hardware - periodically repairing the data
+is not going to save you from data loss later on when the hardware fails
+completely.
.El
.
.Sh EXAMPLES
diff --git a/man/man8/zfs-rename.8 b/man/man8/zfs-rename.8
index 01c58087371e..cb1dfc995d5b 100644
--- a/man/man8/zfs-rename.8
+++ b/man/man8/zfs-rename.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-rollback.8 b/man/man8/zfs-rollback.8
index 0ec612888584..c12c564ef671 100644
--- a/man/man8/zfs-rollback.8
+++ b/man/man8/zfs-rollback.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-send.8 b/man/man8/zfs-send.8
index 137deb94e20d..ba604bf77855 100644
--- a/man/man8/zfs-send.8
+++ b/man/man8/zfs-send.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -29,7 +29,7 @@
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
.\"
-.Dd March 16, 2022
+.Dd July 27, 2023
.Dt ZFS-SEND 8
.Os
.
@@ -39,29 +39,29 @@
.Sh SYNOPSIS
.Nm zfs
.Cm send
-.Op Fl DLPbcehnpsvw
+.Op Fl DLPVbcehnpsvw
.Op Fl R Op Fl X Ar dataset Ns Oo , Ns Ar dataset Oc Ns …
.Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot
.Ar snapshot
.Nm zfs
.Cm send
-.Op Fl DLPcensvw
+.Op Fl DLPVcensvw
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm zfs
.Cm send
.Fl -redact Ar redaction_bookmark
-.Op Fl DLPcenpv
+.Op Fl DLPVcenpv
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar snapshot
.Nm zfs
.Cm send
-.Op Fl Penv
+.Op Fl PVenv
.Fl t
.Ar receive_resume_token
.Nm zfs
.Cm send
-.Op Fl Pnv
+.Op Fl PVnv
.Fl S Ar filesystem
.Nm zfs
.Cm redact
@@ -73,7 +73,7 @@
.It Xo
.Nm zfs
.Cm send
-.Op Fl DLPbcehnpsvw
+.Op Fl DLPVbcehnpsvw
.Op Fl R Op Fl X Ar dataset Ns Oo , Ns Ar dataset Oc Ns …
.Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot
.Ar snapshot
@@ -142,6 +142,8 @@ If the
flag is used to send encrypted datasets, then
.Fl w
must also be specified.
+.It Fl V , -proctitle
+Set the process title to a per-second report of how much data has been sent.
.It Fl X , -exclude Ar dataset Ns Oo , Ns Ar dataset Oc Ns …
With
.Fl R ,
@@ -215,7 +217,8 @@ compress on the receiver, unless you specify
.Fl o Sy compress Ns = Em off .
.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.
+This allows backups to be taken even if encryption keys are not currently
+loaded.
The backup may then be received on an untrusted machine since that machine will
not have the encryption keys to read the protected data or alter it without
being detected.
@@ -286,13 +289,20 @@ when using this flag.
Allows sending a replication stream even when there are snapshots missing in the
hierarchy.
When a snapshot is missing, instead of throwing an error and aborting the send,
-a warning is printed to the standard error stream and the dataset to which it belongs
+a warning is printed to the standard error stream and the dataset to which it
+belongs
and its descendents are skipped.
This flag can only be used in conjunction with
.Fl R .
.It Fl v , -verbose
Print verbose information about the stream package generated.
This information includes a per-second report of how much data has been sent.
+The same report can be requested by sending
+.Dv SIGINFO
+or
+.Dv SIGUSR1 ,
+regardless of
+.Fl v .
.Pp
The format of the stream is committed.
You will be able to receive your streams on future versions of ZFS.
@@ -300,7 +310,7 @@ You will be able to receive your streams on future versions of ZFS.
.It Xo
.Nm zfs
.Cm send
-.Op Fl DLPcenvw
+.Op Fl DLPVcenvw
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
@@ -354,7 +364,8 @@ then the data will be decompressed before sending so it can be split into
smaller block sizes.
.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.
+This allows backups to be taken even if encryption keys are not currently
+loaded.
The backup may then be received on an untrusted machine since that machine will
not have the encryption keys to read the protected data or alter it without
being detected.
@@ -386,7 +397,8 @@ If the
.Sy lz4_compress
feature is active on the sending system, then the receiving system must have
that feature enabled as well.
-Datasets that are sent with this flag may not be received as an encrypted dataset,
+Datasets that are sent with this flag may not be received as an encrypted
+dataset,
since encrypted datasets cannot use the
.Sy embedded_data
feature.
@@ -427,12 +439,18 @@ and the verbose output goes to standard error
.It Fl v , -verbose
Print verbose information about the stream package generated.
This information includes a per-second report of how much data has been sent.
+The same report can be requested by sending
+.Dv SIGINFO
+or
+.Dv SIGUSR1 ,
+regardless of
+.Fl v .
.El
.It Xo
.Nm zfs
.Cm send
.Fl -redact Ar redaction_bookmark
-.Op Fl DLPcenpv
+.Op Fl DLPVcenpv
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar snapshot
.Xc
@@ -445,7 +463,7 @@ included in the redaction list contained in the bookmark specified by the
flag.
The resulting send stream is said to be redacted with respect to the snapshots
the bookmark specified by the
-.Fl -redact No flag was created with.
+.Fl -redact No flag was created with .
The bookmark must have been created by running
.Nm zfs Cm redact
on the snapshot being sent.
@@ -526,7 +544,7 @@ raw sends and redacted sends cannot be combined at this time.
.It Xo
.Nm zfs
.Cm send
-.Op Fl Penv
+.Op Fl PVenv
.Fl t
.Ar receive_resume_token
.Xc
@@ -541,7 +559,7 @@ for more details.
.It Xo
.Nm zfs
.Cm send
-.Op Fl Pnv
+.Op Fl PVnv
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Fl S
.Ar filesystem
@@ -629,7 +647,8 @@ snapshots themselves.
In order to make the purpose of the feature more clear, an example is provided.
Consider a zfs filesystem containing four files.
These files represent information for an online shopping service.
-One file contains a list of usernames and passwords, another contains purchase histories,
+One file contains a list of usernames and passwords, another contains purchase
+histories,
a third contains click tracking data, and a fourth contains user preferences.
The owner of this data wants to make it available for their development teams to
test against, and their market research teams to do analysis on.
@@ -641,7 +660,8 @@ However, because all of this data is stored in one ZFS filesystem,
it must all be sent and received together.
In addition, the owner of the data
wants to take advantage of features like compression, checksumming, and
-snapshots, so they do want to continue to use ZFS to store and transmit their data.
+snapshots, so they do want to continue to use ZFS to store and transmit their
+data.
Redaction can help them do so.
First, they would make two clones of a snapshot of the data on the source.
In one clone, they create the setup they want their market research team to see;
@@ -654,12 +674,17 @@ They would then create a redaction bookmark on the parent snapshot,
using snapshots on the two clones as redaction snapshots.
The parent can then be sent, redacted, to the target
server where the research and development teams have access.
-Finally, incremental sends from the parent snapshot to each of the clones can be sent
+Finally, incremental sends from the parent snapshot to each of the clones can be
+sent
to and received on the target server; these snapshots are identical to the
ones on the source, and are ready to be used, while the parent snapshot on the
target contains none of the username and password data present on the source,
because it was removed by the redacted send operation.
.
+.Sh SIGNALS
+See
+.Fl v .
+.
.Sh EXAMPLES
.\" These are, respectively, examples 12, 13 from zfs.8
.\" Make sure to update them bidirectionally
diff --git a/man/man8/zfs-set.8 b/man/man8/zfs-set.8
index 9d0c437df217..8cc19caf3f00 100644
--- a/man/man8/zfs-set.8
+++ b/man/man8/zfs-set.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -29,7 +29,7 @@
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
.\"
-.Dd March 16, 2022
+.Dd April 20, 2024
.Dt ZFS-SET 8
.Os
.
@@ -39,6 +39,7 @@
.Sh SYNOPSIS
.Nm zfs
.Cm set
+.Op Fl u
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns …
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns …
.Nm zfs
@@ -60,6 +61,7 @@
.It Xo
.Nm zfs
.Cm set
+.Op Fl u
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns …
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns …
.Xc
@@ -79,6 +81,11 @@ For more information, see the
.Em User Properties
section of
.Xr zfsprops 7 .
+.Bl -tag -width "-u"
+.It Fl u
+Update mountpoint, sharenfs, sharesmb property but do not mount or share the
+dataset.
+.El
.It Xo
.Nm zfs
.Cm get
@@ -151,6 +158,15 @@ A comma-separated list of types to display, where
.Ar type
is one of
.Sy filesystem , snapshot , volume , bookmark , No or Sy all .
+.Sy fs ,
+.Sy snap ,
+or
+.Sy vol
+can be used as aliases for
+.Sy filesystem ,
+.Sy snapshot ,
+or
+.Sy volume .
.El
.It Xo
.Nm zfs
diff --git a/man/man8/zfs-share.8 b/man/man8/zfs-share.8
index 89121ead0958..52087f0b9220 100644
--- a/man/man8/zfs-share.8
+++ b/man/man8/zfs-share.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-snapshot.8 b/man/man8/zfs-snapshot.8
index 771b52099ec1..a0c164dd02cb 100644
--- a/man/man8/zfs-snapshot.8
+++ b/man/man8/zfs-snapshot.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -44,13 +44,21 @@
.Ar dataset Ns @ Ns Ar snapname Ns …
.
.Sh DESCRIPTION
-All previous modifications by successful system calls to the file system are
-part of the snapshots.
-Snapshots are taken atomically, so that all snapshots correspond to the same
-moment in time.
+Creates a snapshot of a dataset or multiple snapshots of different
+datasets.
+.Pp
+Snapshots are created atomically.
+That is, a snapshot is a consistent image of a dataset at a specific
+point in time; it includes all modifications to the dataset made by
+system calls that have successfully completed before that point in time.
+Recursive snapshots created through the
+.Fl r
+option are all created at the same time.
+.Pp
.Nm zfs Cm snap
can be used as an alias for
.Nm zfs Cm snapshot .
+.Pp
See the
.Sx Snapshots
section of
diff --git a/man/man8/zfs-upgrade.8 b/man/man8/zfs-upgrade.8
index f3620faa6135..2744b07424d5 100644
--- a/man/man8/zfs-upgrade.8
+++ b/man/man8/zfs-upgrade.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-userspace.8 b/man/man8/zfs-userspace.8
index b7bd61b5709a..4bd7bb7cbef6 100644
--- a/man/man8/zfs-userspace.8
+++ b/man/man8/zfs-userspace.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -73,7 +73,8 @@
.Oo Fl t Ar type Ns Oo , Ns Ar type Oc Ns … Oc
.Ar filesystem Ns | Ns Ar snapshot Ns | Ns Ar path
.Xc
-Displays space consumed by, and quotas on, each user in the specified filesystem,
+Displays space consumed by, and quotas on, each user in the specified
+filesystem,
snapshot, or path.
If a path is given, the filesystem that contains that path will be used.
This corresponds to the
diff --git a/man/man8/zfs-wait.8 b/man/man8/zfs-wait.8
index 81bc15636541..9d1f24f195b7 100644
--- a/man/man8/zfs-wait.8
+++ b/man/man8/zfs-wait.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs-zone.8 b/man/man8/zfs-zone.8
index 2f975dde6799..0ee4409a2f17 100644
--- a/man/man8/zfs-zone.8
+++ b/man/man8/zfs-zone.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs.8 b/man/man8/zfs.8
index eaa93e0ea75c..dd578cb74aac 100644
--- a/man/man8/zfs.8
+++ b/man/man8/zfs.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -737,6 +737,12 @@ command will be undone if the share is ever unshared (like via a reboot).
.
.Sh ENVIRONMENT VARIABLES
.Bl -tag -width "ZFS_MODULE_TIMEOUT"
+.It Sy ZFS_COLOR
+Use ANSI color in
+.Nm zfs Cm diff
+and
+.Nm zfs Cm list
+output.
.It Sy ZFS_MOUNT_HELPER
Cause
.Nm zfs Cm mount
diff --git a/man/man8/zfs_ids_to_path.8 b/man/man8/zfs_ids_to_path.8
index d5b74678b29c..ba093d1cf913 100644
--- a/man/man8/zfs_ids_to_path.8
+++ b/man/man8/zfs_ids_to_path.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zfs_prepare_disk.8.in b/man/man8/zfs_prepare_disk.8.in
new file mode 100644
index 000000000000..2a741531e415
--- /dev/null
+++ b/man/man8/zfs_prepare_disk.8.in
@@ -0,0 +1,70 @@
+.\"
+.\" Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
+.\" Copyright (C) 2023 Lawrence Livermore National Security, LLC.
+.\" Refer to the OpenZFS git commit log for authoritative copyright attribution.
+.\"
+.\" The contents of this file are subject to the terms of the
+.\" Common Development and Distribution License Version 1.0 (CDDL-1.0).
+.\" You can obtain a copy of the license from the top-level file
+.\" "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
+.\" You may not use this file except in compliance with the license.
+.\"
+.\" Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049)
+.\"
+.Dd August 30, 2023
+.Dt ZFS_PREPARE_DISK 8
+.Os
+.
+.Sh NAME
+.Nm zfs_prepare_disk
+.Nd special script that gets run before bringing a disk into a pool
+.Sh DESCRIPTION
+.Nm
+is an optional script that gets called by libzfs before bringing a disk into a
+pool.
+It can be modified by the user to run whatever commands are necessary to prepare
+a disk for inclusion into the pool.
+For example, users can add lines to
+.Nm zfs_prepare_disk
+to do things like update the drive's firmware or check the drive's health.
+.Nm zfs_prepare_disk
+is optional and can be removed if not needed.
+libzfs will look for the script at @zfsexecdir@/zfs_prepare_disk.
+.
+.Ss Properties
+.Nm zfs_prepare_disk
+will be passed the following environment variables:
+.sp
+.Bl -tag -compact -width "VDEV_ENC_SYSFS_PATH"
+.
+.It Nm POOL_NAME
+.No Name of the pool
+.It Nm VDEV_PATH
+.No Path to the disk (like /dev/sda)
+.It Nm VDEV_PREPARE
+.No Reason why the disk is being prepared for inclusion
+('create', 'add', 'replace', or 'autoreplace').
+This can be useful if you only want the script to be run under certain actions.
+.It Nm VDEV_UPATH
+.No Path to one of the underlying devices for the
+disk.
+For multipath this would return one of the /dev/sd* paths to the disk.
+If the device is not a device mapper device, then
+.Nm VDEV_UPATH
+just returns the same value as
+.Nm VDEV_PATH
+.It Nm VDEV_ENC_SYSFS_PATH
+.No Path to the disk's enclosure sysfs path, if available
+.El
+.Pp
+Note that some of these variables may have a blank value.
+.Nm POOL_NAME
+is blank at pool creation time, for example.
+.Sh ENVIRONMENT
+.Nm zfs_prepare_disk
+runs with a limited $PATH.
+.Sh EXIT STATUS
+.Nm zfs_prepare_disk
+should return 0 on success, non-zero otherwise.
+If non-zero is returned, the disk will not be included in the pool.
+.
diff --git a/man/man8/zgenhostid.8 b/man/man8/zgenhostid.8
index e157578cf0bb..f7f2bdb4ac53 100644
--- a/man/man8/zgenhostid.8
+++ b/man/man8/zgenhostid.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zinject.8 b/man/man8/zinject.8
index 1cd8aa85e3cd..ad9e7a42bfac 100644
--- a/man/man8/zinject.8
+++ b/man/man8/zinject.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -19,10 +19,11 @@
.\" CDDL HEADER END
.\"
.\" Copyright 2013 Darik Horn <dajhorn@vanadac.com>. All rights reserved.
+.\" Copyright (c) 2024, Klara Inc.
.\"
.\" lint-ok: WARNING: sections out of conventional order: Sh SYNOPSIS
.\"
-.Dd May 26, 2021
+.Dd April 4, 2024
.Dt ZINJECT 8
.Os
.
@@ -69,6 +70,7 @@ Force a vdev into the DEGRADED or FAULTED state.
.Nm zinject
.Fl d Ar vdev
.Fl D Ar latency : Ns Ar lanes
+.Op Fl T Ar read|write
.Ar pool
.Xc
Add an artificial delay to I/O requests on a particular
@@ -127,6 +129,14 @@ Force a vdev error.
.
.It Xo
.Nm zinject
+.Fl i Ar seconds
+.Ar pool
+.Xc
+Add an artificial delay during the future import of a pool.
+This injector is automatically cleared after the import is finished.
+.
+.It Xo
+.Nm zinject
.Fl I
.Op Fl s Ar seconds Ns | Ns Fl g Ar txgs
.Ar pool
@@ -188,7 +198,7 @@ Each number is in hexadecimal, and only one block can be specified.
.It Fl C Ar dvas
Inject the given error only into specific DVAs.
The mask should be specified as a list of 0-indexed DVAs separated by commas
-.No (e.g. Ar 0,2 Ns No ).
+.No (e.g . Ar 0,2 Ns No ).
This option is not applicable to logical data errors such as
.Sy decompress
and
@@ -209,9 +219,11 @@ to flip a bit in the data after a read,
.It Sy dtl
for an ECHILD error,
.It Sy io
-for an EIO error where reopening the device will succeed, or
+for an EIO error where reopening the device will succeed,
.It Sy nxio
-for an ENXIO error where reopening the device will fail.
+for an ENXIO error where reopening the device will fail, or
+.It Sy noop
+to drop the IO without executing it, and return success.
.El
.Pp
For EIO and ENXIO, the "failed" reads or writes still occur.
@@ -256,6 +268,7 @@ Run for this many seconds before reporting failure.
.It Fl T Ar failure
Set the failure type to one of
.Sy all ,
+.Sy ioctl ,
.Sy claim ,
.Sy free ,
.Sy read ,
diff --git a/man/man8/zpool-add.8 b/man/man8/zpool-add.8
index 04171ae0264b..60b35f1a511a 100644
--- a/man/man8/zpool-add.8
+++ b/man/man8/zpool-add.8
@@ -5,7 +5,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -24,8 +24,9 @@
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+.\" Copyright (c) 2024 by Delphix. All Rights Reserved.
.\"
-.Dd March 16, 2022
+.Dd March 8, 2024
.Dt ZPOOL-ADD 8
.Os
.
@@ -36,6 +37,7 @@
.Nm zpool
.Cm add
.Op Fl fgLnP
+.Op Fl -allow-in-use -allow-replication-mismatch -allow-ashift-mismatch
.Oo Fl o Ar property Ns = Ns Ar value Oc
.Ar pool vdev Ns …
.
@@ -56,7 +58,8 @@ subcommand.
.It Fl f
Forces use of
.Ar vdev Ns s ,
-even if they appear in use or specify a conflicting replication level.
+even if they appear in use, have conflicting ashift values, or specify
+a conflicting replication level.
Not all devices can be overridden in this manner.
.It Fl g
Display
@@ -91,6 +94,17 @@ See the
manual page for a list of valid properties that can be set.
The only property supported at the moment is
.Sy ashift .
+.It Fl -allow-ashift-mismatch
+Disable the ashift validation which allows mismatched ashift values in the
+pool.
+Adding top-level
+.Ar vdev Ns s
+with different sector sizes will prohibit future device removal operations, see
+.Xr zpool-remove 8 .
+.It Fl -allow-in-use
+Allow vdevs to be added even if they might be in use in another pool.
+.It Fl -allow-replication-mismatch
+Allow vdevs with conflicting replication levels to be added to the pool.
.El
.
.Sh EXAMPLES
diff --git a/man/man8/zpool-attach.8 b/man/man8/zpool-attach.8
index 9dfa35a107d3..22b1369b6853 100644
--- a/man/man8/zpool-attach.8
+++ b/man/man8/zpool-attach.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -26,7 +26,7 @@
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\"
-.Dd May 15, 2020
+.Dd June 28, 2023
.Dt ZPOOL-ATTACH 8
.Os
.
@@ -45,7 +45,15 @@ Attaches
.Ar new_device
to the existing
.Ar device .
-The existing device cannot be part of a raidz configuration.
+The behavior differs depending on if the existing
+.Ar device
+is a RAID-Z device, or a mirror/plain device.
+.Pp
+If the existing device is a mirror or plain device
+.Pq e.g. specified as Qo Li sda Qc or Qq Li mirror-7 ,
+the new device will be mirrored with the existing device, a resilver will be
+initiated, and the new device will contribute to additional redundancy once the
+resilver completes.
If
.Ar device
is not currently part of a mirrored configuration,
@@ -62,6 +70,42 @@ creates a three-way mirror, and so on.
In either case,
.Ar new_device
begins to resilver immediately and any running scrub is cancelled.
+.Pp
+If the existing device is a RAID-Z device
+.Pq e.g. specified as Qq Ar raidz2-0 ,
+the new device will become part of that RAID-Z group.
+A "raidz expansion" will be initiated, and once the expansion completes,
+the new device will contribute additional space to the RAID-Z group.
+The expansion entails reading all allocated space from existing disks in the
+RAID-Z group, and rewriting it to the new disks in the RAID-Z group (including
+the newly added
+.Ar device ) .
+Its progress can be monitored with
+.Nm zpool Cm status .
+.Pp
+Data redundancy is maintained during and after the expansion.
+If a disk fails while the expansion is in progress, the expansion pauses until
+the health of the RAID-Z vdev is restored (e.g. by replacing the failed disk
+and waiting for reconstruction to complete).
+Expansion does not change the number of failures that can be tolerated
+without data loss (e.g. a RAID-Z2 is still a RAID-Z2 even after expansion).
+A RAID-Z vdev can be expanded multiple times.
+.Pp
+After the expansion completes, old blocks retain their old data-to-parity
+ratio
+.Pq e.g. 5-wide RAID-Z2 has 3 data and 2 parity
+but distributed among the larger set of disks.
+New blocks will be written with the new data-to-parity ratio (e.g. a 5-wide
+RAID-Z2 which has been expanded once to 6-wide, has 4 data and 2 parity).
+However, the vdev's assumed parity ratio does not change, so slightly less
+space than is expected may be reported for newly-written blocks, according to
+.Nm zfs Cm list ,
+.Nm df ,
+.Nm ls Fl s ,
+and similar tools.
+.Pp
+A pool-wide scrub is initiated at the end of the expansion in order to verify
+the checksums of all blocks which have been copied during the expansion.
.Bl -tag -width Ds
.It Fl f
Forces use of
@@ -76,16 +120,15 @@ manual page for a list of valid properties that can be set.
The only property supported at the moment is
.Sy ashift .
.It Fl s
-The
+When attaching to a mirror or plain device, the
.Ar new_device
is reconstructed sequentially to restore redundancy as quickly as possible.
Checksums are not verified during sequential reconstruction so a scrub is
started when the resilver completes.
-Sequential reconstruction is not supported for raidz configurations.
.It Fl w
Waits until
.Ar new_device
-has finished resilvering before returning.
+has finished resilvering or expanding before returning.
.El
.
.Sh SEE ALSO
diff --git a/man/man8/zpool-checkpoint.8 b/man/man8/zpool-checkpoint.8
index d5add14aed2f..7900b323822f 100644
--- a/man/man8/zpool-checkpoint.8
+++ b/man/man8/zpool-checkpoint.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-clear.8 b/man/man8/zpool-clear.8
index 0b256b28bd21..3e448be87fc2 100644
--- a/man/man8/zpool-clear.8
+++ b/man/man8/zpool-clear.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -36,6 +36,7 @@
.Sh SYNOPSIS
.Nm zpool
.Cm clear
+.Op Fl -power
.Ar pool
.Oo Ar device Oc Ns …
.
@@ -49,9 +50,20 @@ If the pool was suspended it will be brought back online provided the
devices can be accessed.
Pools with
.Sy multihost
-enabled which have been suspended cannot be resumed.
-While the pool was suspended, it may have been imported on
-another host, and resuming I/O could result in pool damage.
+enabled which have been suspended cannot be resumed when there is evidence
+that the pool was imported by another host.
+The same checks performed during an import will be applied before the clear
+proceeds.
+.Bl -tag -width Ds
+.It Fl -power
+Power on the devices's slot in the storage enclosure and wait for the device
+to show up before attempting to clear errors.
+This is done on all the devices specified.
+Alternatively, you can set the
+.Sy ZPOOL_AUTO_POWER_ON_SLOT
+environment variable to always enable this behavior.
+Note: This flag currently works on Linux only.
+.El
.
.Sh SEE ALSO
.Xr zdb 8 ,
diff --git a/man/man8/zpool-create.8 b/man/man8/zpool-create.8
index c1d1c7d564c2..8449520944fb 100644
--- a/man/man8/zpool-create.8
+++ b/man/man8/zpool-create.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -87,12 +87,13 @@ currently in use by another subsystem.
However this check is not robust enough
to detect simultaneous attempts to use a new device in different pools, even if
.Sy multihost Ns = Sy enabled .
-The administrator must ensure, that simultaneous invocations of any combination of
+The administrator must ensure that simultaneous invocations of any combination
+of
.Nm zpool Cm replace ,
.Nm zpool Cm create ,
.Nm zpool Cm add ,
or
-.Nm zpool Cm labelclear ,
+.Nm zpool Cm labelclear
do not refer to the same device.
Using the same device in two pools will result in pool corruption.
.Pp
diff --git a/man/man8/zpool-destroy.8 b/man/man8/zpool-destroy.8
index a98acf46f85a..b1ac18c8b4fd 100644
--- a/man/man8/zpool-destroy.8
+++ b/man/man8/zpool-destroy.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-detach.8 b/man/man8/zpool-detach.8
index 952dd7882a90..3d5ca9f146ad 100644
--- a/man/man8/zpool-detach.8
+++ b/man/man8/zpool-detach.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-events.8 b/man/man8/zpool-events.8
index 55f7babae2bd..ef20ef4e003c 100644
--- a/man/man8/zpool-events.8
+++ b/man/man8/zpool-events.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -25,8 +25,9 @@
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+.\" Copyright (c) 2024, Klara Inc.
.\"
-.Dd May 27, 2021
+.Dd February 28, 2024
.Dt ZPOOL-EVENTS 8
.Os
.
@@ -108,7 +109,8 @@ Issued when a pool is exported.
.It Sy zpool.import
Issued when a pool is imported.
.It Sy zpool.reguid
-Issued when a REGUID (new unique identifier for the pool have been regenerated) have been detected.
+Issued when a REGUID (new unique identifier for the pool have been regenerated)
+have been detected.
.It Sy vdev.unknown
Issued when the vdev is unknown.
Such as trying to clear device errors on a vdev that have failed/been kicked
@@ -226,7 +228,8 @@ ID of vdev (if any).
.It Sy vdev_fru
Physical FRU location.
.It Sy vdev_state
-State of vdev (0=uninitialized, 1=closed, 2=offline, 3=removed, 4=failed to open, 5=faulted, 6=degraded, 7=healthy).
+State of vdev (0=uninitialized, 1=closed, 2=offline, 3=removed, 4=failed to
+open, 5=faulted, 6=degraded, 7=healthy).
.It Sy vdev_ashift
The ashift value of the vdev.
.It Sy vdev_complete_ts
@@ -303,10 +306,6 @@ The time when a given I/O request was submitted.
The time required to service a given I/O request.
.It Sy prev_state
The previous state of the vdev.
-.It Sy cksum_expected
-The expected checksum value for the block.
-.It Sy cksum_actual
-The actual checksum value for an errant block.
.It Sy cksum_algorithm
Checksum algorithm used.
See
@@ -360,28 +359,12 @@ Like
but contains
.Pq Ar good data No & ~( Ns Ar bad data ) ;
that is, the bits set in the good data which are cleared in the bad data.
-.It Sy bad_set_histogram
-If this field exists, it is an array of counters.
-Each entry counts bits set in a particular bit of a big-endian uint64 type.
-The first entry counts bits
-set in the high-order bit of the first byte, the 9th byte, etc, and the last
-entry counts bits set of the low-order bit of the 8th byte, the 16th byte, etc.
-This information is useful for observing a stuck bit in a parallel data path,
-such as IDE or parallel SCSI.
-.It Sy bad_cleared_histogram
-If this field exists, it is an array of counters.
-Each entry counts bit clears in a particular bit of a big-endian uint64 type.
-The first entry counts bits
-clears of the high-order bit of the first byte, the 9th byte, etc, and the
-last entry counts clears of the low-order bit of the 8th byte, the 16th byte, etc.
-This information is useful for observing a stuck bit in a parallel data
-path, such as IDE or parallel SCSI.
.El
.
.Sh I/O STAGES
The ZFS I/O pipeline is comprised of various stages which are defined below.
The individual stages are used to construct these basic I/O
-operations: Read, Write, Free, Claim, and Ioctl.
+operations: Read, Write, Free, Claim, Flush and Trim.
These stages may be
set on an event to describe the life cycle of a given I/O request.
.Pp
@@ -390,41 +373,43 @@ tab(:);
l l l .
Stage:Bit Mask:Operations
_:_:_
-ZIO_STAGE_OPEN:0x00000001:RWFCI
+ZIO_STAGE_OPEN:0x00000001:RWFCXT
-ZIO_STAGE_READ_BP_INIT:0x00000002:R----
-ZIO_STAGE_WRITE_BP_INIT:0x00000004:-W---
-ZIO_STAGE_FREE_BP_INIT:0x00000008:--F--
-ZIO_STAGE_ISSUE_ASYNC:0x00000010:RWF--
-ZIO_STAGE_WRITE_COMPRESS:0x00000020:-W---
+ZIO_STAGE_READ_BP_INIT:0x00000002:R-----
+ZIO_STAGE_WRITE_BP_INIT:0x00000004:-W----
+ZIO_STAGE_FREE_BP_INIT:0x00000008:--F---
+ZIO_STAGE_ISSUE_ASYNC:0x00000010:-WF--T
+ZIO_STAGE_WRITE_COMPRESS:0x00000020:-W----
-ZIO_STAGE_ENCRYPT:0x00000040:-W---
-ZIO_STAGE_CHECKSUM_GENERATE:0x00000080:-W---
+ZIO_STAGE_ENCRYPT:0x00000040:-W----
+ZIO_STAGE_CHECKSUM_GENERATE:0x00000080:-W----
-ZIO_STAGE_NOP_WRITE:0x00000100:-W---
+ZIO_STAGE_NOP_WRITE:0x00000100:-W----
-ZIO_STAGE_DDT_READ_START:0x00000200:R----
-ZIO_STAGE_DDT_READ_DONE:0x00000400:R----
-ZIO_STAGE_DDT_WRITE:0x00000800:-W---
-ZIO_STAGE_DDT_FREE:0x00001000:--F--
+ZIO_STAGE_BRT_FREE:0x00000200:--F---
-ZIO_STAGE_GANG_ASSEMBLE:0x00002000:RWFC-
-ZIO_STAGE_GANG_ISSUE:0x00004000:RWFC-
+ZIO_STAGE_DDT_READ_START:0x00000400:R-----
+ZIO_STAGE_DDT_READ_DONE:0x00000800:R-----
+ZIO_STAGE_DDT_WRITE:0x00001000:-W----
+ZIO_STAGE_DDT_FREE:0x00002000:--F---
-ZIO_STAGE_DVA_THROTTLE:0x00008000:-W---
-ZIO_STAGE_DVA_ALLOCATE:0x00010000:-W---
-ZIO_STAGE_DVA_FREE:0x00020000:--F--
-ZIO_STAGE_DVA_CLAIM:0x00040000:---C-
+ZIO_STAGE_GANG_ASSEMBLE:0x00004000:RWFC--
+ZIO_STAGE_GANG_ISSUE:0x00008000:RWFC--
-ZIO_STAGE_READY:0x00080000:RWFCI
+ZIO_STAGE_DVA_THROTTLE:0x00010000:-W----
+ZIO_STAGE_DVA_ALLOCATE:0x00020000:-W----
+ZIO_STAGE_DVA_FREE:0x00040000:--F---
+ZIO_STAGE_DVA_CLAIM:0x00080000:---C--
-ZIO_STAGE_VDEV_IO_START:0x00100000:RW--I
-ZIO_STAGE_VDEV_IO_DONE:0x00200000:RW--I
-ZIO_STAGE_VDEV_IO_ASSESS:0x00400000:RW--I
+ZIO_STAGE_READY:0x00100000:RWFCIT
-ZIO_STAGE_CHECKSUM_VERIFY:0x00800000:R----
+ZIO_STAGE_VDEV_IO_START:0x00200000:RW--XT
+ZIO_STAGE_VDEV_IO_DONE:0x00400000:RW--XT
+ZIO_STAGE_VDEV_IO_ASSESS:0x00800000:RW--XT
-ZIO_STAGE_DONE:0x01000000:RWFCI
+ZIO_STAGE_CHECKSUM_VERIFY:0x01000000:R-----
+
+ZIO_STAGE_DONE:0x02000000:RWFCXT
.TE
.
.Sh I/O FLAGS
@@ -451,7 +436,6 @@ ZIO_FLAG_CANFAIL:0x00000080
ZIO_FLAG_SPECULATIVE:0x00000100
ZIO_FLAG_CONFIG_WRITER:0x00000200
ZIO_FLAG_DONT_RETRY:0x00000400
-ZIO_FLAG_DONT_CACHE:0x00000800
ZIO_FLAG_NODATA:0x00001000
ZIO_FLAG_INDUCE_DAMAGE:0x00002000
diff --git a/man/man8/zpool-export.8 b/man/man8/zpool-export.8
index 14d737fa5444..4fed98cfe278 100644
--- a/man/man8/zpool-export.8
+++ b/man/man8/zpool-export.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -61,7 +61,8 @@ the disks.
.It Fl a
Exports all pools imported on the system.
.It Fl f
-Forcefully unmount all datasets, and allow export of pools with active shared spares.
+Forcefully unmount all datasets, and allow export of pools with active shared
+spares.
.Pp
This command will forcefully export the pool even if it has a shared spare that
is currently being used.
diff --git a/man/man8/zpool-get.8 b/man/man8/zpool-get.8
index 4ef9a1b5ec44..78a39b07d749 100644
--- a/man/man8/zpool-get.8
+++ b/man/man8/zpool-get.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-history.8 b/man/man8/zpool-history.8
index 2a2d500b8b8c..c6aa8884e598 100644
--- a/man/man8/zpool-history.8
+++ b/man/man8/zpool-history.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-import.8 b/man/man8/zpool-import.8
index b23d7dabdb55..dab6e1f55771 100644
--- a/man/man8/zpool-import.8
+++ b/man/man8/zpool-import.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-initialize.8 b/man/man8/zpool-initialize.8
index 0a108180dbbe..a9c8fd35aec9 100644
--- a/man/man8/zpool-initialize.8
+++ b/man/man8/zpool-initialize.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -36,7 +36,7 @@
.Sh SYNOPSIS
.Nm zpool
.Cm initialize
-.Op Fl c Ns | Ns Fl s
+.Op Fl c Ns | Ns Fl s | Ns Fl u
.Op Fl w
.Ar pool
.Oo Ar device Oc Ns …
@@ -60,6 +60,14 @@ initialized, the command will fail and no suspension will occur on any device.
Initializing can then be resumed by running
.Nm zpool Cm initialize
with no flags on the relevant target devices.
+.It Fl u , -uninit
+Clears the initialization state on the specified devices, or all eligible
+devices if none are specified.
+If the devices are being actively initialized the command will fail.
+After being cleared
+.Nm zpool Cm initialize
+with no flags can be used to re-initialize all unallocoated regions on
+the relevant target devices.
.It Fl w , -wait
Wait until the devices have finished initializing before returning.
.El
diff --git a/man/man8/zpool-iostat.8 b/man/man8/zpool-iostat.8
index b0c0565c4efa..e1d2a4b4ff1c 100644
--- a/man/man8/zpool-iostat.8
+++ b/man/man8/zpool-iostat.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -66,7 +66,8 @@ If
is specified, the command exits after
.Ar count
reports are printed.
-The first report printed is always the statistics since boot regardless of whether
+The first report printed is always the statistics since boot regardless of
+whether
.Ar interval
and
.Ar count
@@ -117,7 +118,7 @@ If
is passed without a script name, it prints a list of all scripts.
.Fl c
also sets verbose mode
-.No \&( Ns Fl v Ns No \&).
+.No \&( Ns Fl v Ns No \&) .
.Pp
Script output should be in the form of "name=value".
The column name is set to "name" and the value is set to "value".
@@ -145,7 +146,7 @@ Specify
.Sy u
for a printed representation of the internal representation of time.
See
-.Xr time 2 .
+.Xr time 1 .
Specify
.Sy d
for standard date format.
diff --git a/man/man8/zpool-labelclear.8 b/man/man8/zpool-labelclear.8
index 912adb0700a7..3d7b60b5587d 100644
--- a/man/man8/zpool-labelclear.8
+++ b/man/man8/zpool-labelclear.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-list.8 b/man/man8/zpool-list.8
index 88183b4dce1a..c60c47f5eb3d 100644
--- a/man/man8/zpool-list.8
+++ b/man/man8/zpool-list.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -95,7 +95,7 @@ Specify
.Sy u
for a printed representation of the internal representation of time.
See
-.Xr time 2 .
+.Xr time 1 .
Specify
.Sy d
for standard date format.
diff --git a/man/man8/zpool-offline.8 b/man/man8/zpool-offline.8
index 9b2cf59cf414..1b6095d63709 100644
--- a/man/man8/zpool-offline.8
+++ b/man/man8/zpool-offline.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -36,12 +36,13 @@
.Sh SYNOPSIS
.Nm zpool
.Cm offline
-.Op Fl ft
+.Op Fl Sy -power Ns | Ns Op Fl Sy ft
.Ar pool
.Ar device Ns …
.Nm zpool
.Cm online
-.Op Fl e
+.Op Fl Sy -power
+.Op Fl Sy e
.Ar pool
.Ar device Ns …
.
@@ -50,7 +51,7 @@
.It Xo
.Nm zpool
.Cm offline
-.Op Fl ft
+.Op Fl Sy -power Ns | Ns Op Fl Sy ft
.Ar pool
.Ar device Ns …
.Xc
@@ -60,6 +61,9 @@ While the
is offline, no attempt is made to read or write to the device.
This command is not applicable to spares.
.Bl -tag -width Ds
+.It Fl -power
+Power off the device's slot in the storage enclosure.
+This flag currently works on Linux only
.It Fl f
Force fault.
Instead of offlining the disk, put it into a faulted state.
@@ -73,6 +77,7 @@ Upon reboot, the specified physical device reverts to its previous state.
.It Xo
.Nm zpool
.Cm online
+.Op Fl -power
.Op Fl e
.Ar pool
.Ar device Ns …
@@ -80,6 +85,13 @@ Upon reboot, the specified physical device reverts to its previous state.
Brings the specified physical device online.
This command is not applicable to spares.
.Bl -tag -width Ds
+.It Fl -power
+Power on the device's slot in the storage enclosure and wait for the device
+to show up before attempting to online it.
+Alternatively, you can set the
+.Sy ZPOOL_AUTO_POWER_ON_SLOT
+environment variable to always enable this behavior.
+This flag currently works on Linux only
.It Fl e
Expand the device to use all available space.
If the device is part of a mirror or raidz then all devices must be expanded
diff --git a/man/man8/zpool-reguid.8 b/man/man8/zpool-reguid.8
index 7bb7c1c726b2..1fd4ddd9a77d 100644
--- a/man/man8/zpool-reguid.8
+++ b/man/man8/zpool-reguid.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-remove.8 b/man/man8/zpool-remove.8
index ec476ec88572..b5cc6e4fc57e 100644
--- a/man/man8/zpool-remove.8
+++ b/man/man8/zpool-remove.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -75,9 +75,11 @@ The
feature flag must be enabled to remove a top-level vdev, see
.Xr zpool-features 7 .
.Pp
-A mirrored top-level device (log or data) can be removed by specifying the top-level mirror for the
+A mirrored top-level device (log or data) can be removed by specifying the top-
+level mirror for the
same.
-Non-log devices or data devices that are part of a mirrored configuration can be removed using
+Non-log devices or data devices that are part of a mirrored configuration can be
+removed using
the
.Nm zpool Cm detach
command.
@@ -137,11 +139,11 @@ config:
.Ed
.Pp
The command to remove the mirrored log
-.Ar mirror-2 No is:
+.Ar mirror-2 No is :
.Dl # Nm zpool Cm remove Ar tank mirror-2
.Pp
The command to remove the mirrored data
-.Ar mirror-1 No is:
+.Ar mirror-1 No is :
.Dl # Nm zpool Cm remove Ar tank mirror-1
.
.Sh SEE ALSO
diff --git a/man/man8/zpool-reopen.8 b/man/man8/zpool-reopen.8
index f1f8606f12c7..5cf7c8635211 100644
--- a/man/man8/zpool-reopen.8
+++ b/man/man8/zpool-reopen.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-replace.8 b/man/man8/zpool-replace.8
index cc61fa3ea37e..ba897ea704b9 100644
--- a/man/man8/zpool-replace.8
+++ b/man/man8/zpool-replace.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-resilver.8 b/man/man8/zpool-resilver.8
index 1ef316ac1825..420f9bcb5608 100644
--- a/man/man8/zpool-resilver.8
+++ b/man/man8/zpool-resilver.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -40,7 +40,8 @@
.
.Sh DESCRIPTION
Starts a resilver of the specified pools.
-If an existing resilver is already running it will be restarted from the beginning.
+If an existing resilver is already running it will be restarted from the
+beginning.
Any drives that were scheduled for a deferred
resilver will be added to the new one.
This requires the
diff --git a/man/man8/zpool-scrub.8 b/man/man8/zpool-scrub.8
index 1c13d9b9b2a4..03f3ad4991f9 100644
--- a/man/man8/zpool-scrub.8
+++ b/man/man8/zpool-scrub.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -26,7 +26,7 @@
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\"
-.Dd July 25, 2021
+.Dd June 22, 2023
.Dt ZPOOL-SCRUB 8
.Os
.
@@ -38,6 +38,7 @@
.Cm scrub
.Op Fl s Ns | Ns Fl p
.Op Fl w
+.Op Fl e
.Ar pool Ns …
.
.Sh DESCRIPTION
@@ -62,6 +63,13 @@ device
whereas scrubbing examines all data to discover silent errors due to hardware
faults or disk failure.
.Pp
+When scrubbing a pool with encrypted filesystems the keys do not need to be
+loaded.
+However, if the keys are not loaded and an unrepairable checksum error is
+detected the file name cannot be included in the
+.Nm zpool Cm status Fl v
+verbose error report.
+.Pp
Because scrubbing and resilvering are I/O-intensive operations, ZFS only allows
one at a time.
.Pp
@@ -92,17 +100,30 @@ Once resumed the scrub will pick up from the place where it was last
checkpointed to disk.
To resume a paused scrub issue
.Nm zpool Cm scrub
+or
+.Nm zpool Cm scrub
+.Fl e
again.
.It Fl w
Wait until scrub has completed before returning.
+.It Fl e
+Only scrub files with known data errors as reported by
+.Nm zpool Cm status Fl v .
+The pool must have been scrubbed at least once with the
+.Sy head_errlog
+feature enabled to use this option.
+Error scrubbing cannot be run simultaneously with regular scrubbing or
+resilvering, nor can it be run when a regular scrub is paused.
.El
.Sh EXAMPLES
-.Ss Example 1 : No Status of pool with ongoing scrub:
+.Ss Example 1
+Status of pool with ongoing scrub:
+.sp
.Bd -literal -compact
.No # Nm zpool Cm status
...
scan: scrub in progress since Sun Jul 25 16:07:49 2021
- 403M scanned at 100M/s, 68.4M issued at 10.0M/s, 405M total
+ 403M / 405M scanned at 100M/s, 68.4M / 405M issued at 10.0M/s
0B repaired, 16.91% done, 00:00:04 to go
...
.Ed
diff --git a/man/man8/zpool-split.8 b/man/man8/zpool-split.8
index c3b05c2366bf..6bbe49248529 100644
--- a/man/man8/zpool-split.8
+++ b/man/man8/zpool-split.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -81,7 +81,8 @@ datasets it attempts to mount as it is bringing the new pool online.
Note that if any datasets have
.Sy keylocation Ns = Ns Sy prompt ,
this command will block waiting for the keys to be entered.
-Without this flag, encrypted datasets will be left unavailable until the keys are loaded.
+Without this flag, encrypted datasets will be left unavailable until the keys
+are loaded.
.It Fl n
Do a dry-run
.Pq Qq No-op
diff --git a/man/man8/zpool-status.8 b/man/man8/zpool-status.8
index 8617ab64047b..bbe7a45aa0c6 100644
--- a/man/man8/zpool-status.8
+++ b/man/man8/zpool-status.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -36,7 +36,7 @@
.Sh SYNOPSIS
.Nm zpool
.Cm status
-.Op Fl DigLpPstvx
+.Op Fl DegiLpPstvx
.Op Fl T Sy u Ns | Ns Sy d
.Op Fl c Op Ar SCRIPT1 Ns Oo , Ns Ar SCRIPT2 Oc Ns …
.Oo Ar pool Oc Ns …
@@ -57,6 +57,8 @@ and the estimated time to completion.
Both of these are only approximate, because the amount of data in the pool and
the other workloads on the system can change.
.Bl -tag -width Ds
+.It Fl -power
+Display vdev enclosure slot power status (on or off).
.It Fl c Op Ar SCRIPT1 Ns Oo , Ns Ar SCRIPT2 Oc Ns …
Run a script (or scripts) on each vdev and include the output as a new column
in the
@@ -67,12 +69,20 @@ See the
option of
.Nm zpool Cm iostat
for complete details.
-.It Fl i
-Display vdev initialization status.
+.It Fl D
+Display a histogram of deduplication statistics, showing the allocated
+.Pq physically present on disk
+and referenced
+.Pq logically referenced in the pool
+block counts and sizes by reference count.
+.It Fl e
+Only show unhealthy vdevs (not-ONLINE or with errors).
.It Fl g
Display vdev GUIDs instead of the normal device names
These GUIDs can be used in place of device names for the zpool
detach/offline/remove/replace commands.
+.It Fl i
+Display vdev initialization status.
.It Fl L
Display real paths for vdevs resolving all symbolic links.
This can be used to look up the current block device name regardless of the
@@ -86,19 +96,14 @@ the path.
This can be used in conjunction with the
.Fl L
flag.
-.It Fl D
-Display a histogram of deduplication statistics, showing the allocated
-.Pq physically present on disk
-and referenced
-.Pq logically referenced in the pool
-block counts and sizes by reference count.
.It Fl s
Display the number of leaf vdev slow I/O operations.
This is the number of I/O operations that didn't complete in
.Sy zio_slow_io_ms
milliseconds
.Pq Sy 30000 No by default .
-This does not necessarily mean the I/O operations failed to complete, just took an
+This does not necessarily mean the I/O operations failed to complete, just took
+an
unreasonably long amount of time.
This may indicate a problem with the underlying storage.
.It Fl t
@@ -109,7 +114,7 @@ Specify
.Sy u
for a printed representation of the internal representation of time.
See
-.Xr time 2 .
+.Xr time 1 .
Specify
.Sy d
for standard date format.
@@ -118,6 +123,9 @@ See
.It Fl v
Displays verbose data error information, printing out a complete list of all
data errors since the last complete pool scrub.
+If the head_errlog feature is enabled and files containing errors have been
+removed then the respective filenames will not be reported in subsequent runs
+of this command.
.It Fl x
Only display status for pools that are exhibiting errors or are otherwise
unavailable.
diff --git a/man/man8/zpool-sync.8 b/man/man8/zpool-sync.8
index aa68a5729e9f..33800c5793dc 100644
--- a/man/man8/zpool-sync.8
+++ b/man/man8/zpool-sync.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-trim.8 b/man/man8/zpool-trim.8
index ad0909a3b08d..7eeaf2de3dc4 100644
--- a/man/man8/zpool-trim.8
+++ b/man/man8/zpool-trim.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
diff --git a/man/man8/zpool-upgrade.8 b/man/man8/zpool-upgrade.8
index e66e96cfb31c..1c87630b5e6c 100644
--- a/man/man8/zpool-upgrade.8
+++ b/man/man8/zpool-upgrade.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -92,7 +92,8 @@ for details on compatibility with systems that support feature flags, but do not
support all features enabled on the pool.
.Bl -tag -width Ds
.It Fl a
-Enables all supported features (from specified compatibility sets, if any) on all
+Enables all supported features (from specified compatibility sets, if any) on
+all
pools.
.It Fl V Ar version
Upgrade to the specified legacy version.
diff --git a/man/man8/zpool-wait.8 b/man/man8/zpool-wait.8
index 38f4812ace10..50f947bab603 100644
--- a/man/man8/zpool-wait.8
+++ b/man/man8/zpool-wait.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -20,7 +20,7 @@
.\"
.\"
.\" Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+.\" Copyright (c) 2012, 2021 by Delphix. All rights reserved.
.\" Copyright (c) 2012 Cyril Plisko. All Rights Reserved.
.\" Copyright (c) 2017 Datto Inc.
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
@@ -57,7 +57,7 @@ immediately.
These are the possible values for
.Ar activity ,
along with what each one waits for:
-.Bl -tag -compact -offset Ds -width "initialize"
+.Bl -tag -compact -offset Ds -width "raidz_expand"
.It Sy discard
Checkpoint to be discarded
.It Sy free
@@ -76,6 +76,8 @@ Resilver to cease
Scrub to cease
.It Sy trim
Manual trim to cease
+.It Sy raidz_expand
+Attaching to a RAID-Z vdev to complete
.El
.Pp
If an
@@ -97,7 +99,7 @@ Specify
.Sy u
for a printed representation of the internal representation of time.
See
-.Xr time 2 .
+.Xr time 1 .
Specify
.Sy d
for standard date format.
diff --git a/man/man8/zpool.8 b/man/man8/zpool.8
index 075e31bbeb73..fe44e15cabe1 100644
--- a/man/man8/zpool.8
+++ b/man/man8/zpool.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -110,9 +110,10 @@ Removes ZFS label information from the specified
.It Xo
.Xr zpool-attach 8 Ns / Ns Xr zpool-detach 8
.Xc
-Increases or decreases redundancy by
-.Cm attach Ns ing or
-.Cm detach Ns ing a device on an existing vdev (virtual device).
+Converts a non-redundant disk into a mirror, or increases
+the redundancy level of an existing mirror
+.Cm ( attach Ns ), or performs the inverse operation (
+.Cm detach Ns ).
.It Xo
.Xr zpool-add 8 Ns / Ns Xr zpool-remove 8
.Xc
@@ -121,7 +122,8 @@ or removes the specified device from the pool.
.It Xr zpool-replace 8
Replaces an existing device (which may be faulted) with a new one.
.It Xr zpool-split 8
-Creates a new pool by splitting all mirrors in an existing pool (which decreases its redundancy).
+Creates a new pool by splitting all mirrors in an existing pool (which decreases
+its redundancy).
.El
.
.Ss Properties
@@ -174,7 +176,8 @@ Checkpoints the current state of
which can be later restored by
.Nm zpool Cm import Fl -rewind-to-checkpoint .
.It Xr zpool-trim 8
-Initiates an immediate on-demand TRIM operation for all of the free space in a pool.
+Initiates an immediate on-demand TRIM operation for all of the free space in a
+pool.
This operation informs the underlying storage devices of all blocks
in the pool which are no longer allocated and allows thinly provisioned
devices to reclaim the space.
@@ -201,7 +204,8 @@ pool.
Takes the specified physical device offline or brings it online.
.It Xr zpool-resilver 8
Starts a resilver.
-If an existing resilver is already running it will be restarted from the beginning.
+If an existing resilver is already running it will be restarted from the
+beginning.
.It Xr zpool-reopen 8
Reopen all the vdevs associated with the pool.
.It Xr zpool-clear 8
@@ -230,16 +234,16 @@ Invalid command line options were specified.
.El
.
.Sh EXAMPLES
-.\" Examples 1, 2, 3, 4, 11, 12 are shared with zpool-create.8.
-.\" Examples 5, 13 are shared with zpool-add.8.
-.\" Examples 6, 15 are shared with zpool-list.8.
-.\" Examples 7 are shared with zpool-destroy.8.
-.\" Examples 8 are shared with zpool-export.8.
-.\" Examples 9 are shared with zpool-import.8.
-.\" Examples 10 are shared with zpool-upgrade.8.
-.\" Examples 14 are shared with zpool-remove.8.
-.\" Examples 16 are shared with zpool-status.8.
-.\" Examples 13, 16 are also shared with zpool-iostat.8.
+.\" Examples 1, 2, 3, 4, 12, 13 are shared with zpool-create.8.
+.\" Examples 6, 14 are shared with zpool-add.8.
+.\" Examples 7, 16 are shared with zpool-list.8.
+.\" Examples 8 are shared with zpool-destroy.8.
+.\" Examples 9 are shared with zpool-export.8.
+.\" Examples 10 are shared with zpool-import.8.
+.\" Examples 11 are shared with zpool-upgrade.8.
+.\" Examples 15 are shared with zpool-remove.8.
+.\" Examples 17 are shared with zpool-status.8.
+.\" Examples 14, 17 are also shared with zpool-iostat.8.
.\" Make sure to update them omnidirectionally
.Ss Example 1 : No Creating a RAID-Z Storage Pool
The following command creates a pool with a single raidz root vdev that
@@ -261,14 +265,21 @@ While not recommended, a pool based on files can be useful for experimental
purposes.
.Dl # Nm zpool Cm create Ar tank Pa /path/to/file/a /path/to/file/b
.
-.Ss Example 5 : No Adding a Mirror to a ZFS Storage Pool
+.Ss Example 5 : No Making a non-mirrored ZFS Storage Pool mirrored
+The following command converts an existing single device
+.Ar sda
+into a mirror by attaching a second device to it,
+.Ar sdb .
+.Dl # Nm zpool Cm attach Ar tank Pa sda sdb
+.
+.Ss Example 6 : No Adding a Mirror to a ZFS Storage Pool
The following command adds two mirrored disks to the pool
.Ar tank ,
assuming the pool is already made up of two-way mirrors.
The additional space is immediately available to any datasets within the pool.
.Dl # Nm zpool Cm add Ar tank Sy mirror Pa sda sdb
.
-.Ss Example 6 : No Listing Available ZFS Storage Pools
+.Ss Example 7 : No Listing Available ZFS Storage Pools
The following command lists all available pools on the system.
In this case, the pool
.Ar zion
@@ -282,19 +293,19 @@ tank 61.5G 20.0G 41.5G - 48% 32% 1.00x ONLINE -
zion - - - - - - - FAULTED -
.Ed
.
-.Ss Example 7 : No Destroying a ZFS Storage Pool
+.Ss Example 8 : No Destroying a ZFS Storage Pool
The following command destroys the pool
.Ar tank
and any datasets contained within:
.Dl # Nm zpool Cm destroy Fl f Ar tank
.
-.Ss Example 8 : No Exporting a ZFS Storage Pool
+.Ss Example 9 : No Exporting a ZFS Storage Pool
The following command exports the devices in pool
.Ar tank
so that they can be relocated or later imported:
.Dl # Nm zpool Cm export Ar tank
.
-.Ss Example 9 : No Importing a ZFS Storage Pool
+.Ss Example 10 : No Importing a ZFS Storage Pool
The following command displays available pools, and then imports the pool
.Ar tank
for use on the system.
@@ -315,7 +326,7 @@ config:
.No # Nm zpool Cm import Ar tank
.Ed
.
-.Ss Example 10 : No Upgrading All ZFS Storage Pools to the Current Version
+.Ss Example 11 : No Upgrading All ZFS Storage Pools to the Current Version
The following command upgrades all ZFS Storage pools to the current version of
the software:
.Bd -literal -compact -offset Ds
@@ -323,7 +334,7 @@ the software:
This system is currently running ZFS version 2.
.Ed
.
-.Ss Example 11 : No Managing Hot Spares
+.Ss Example 12 : No Managing Hot Spares
The following command creates a new pool with an available hot spare:
.Dl # Nm zpool Cm create Ar tank Sy mirror Pa sda sdb Sy spare Pa sdc
.Pp
@@ -338,12 +349,12 @@ The hot spare can be permanently removed from the pool using the following
command:
.Dl # Nm zpool Cm remove Ar tank Pa sdc
.
-.Ss Example 12 : No Creating a ZFS Pool with Mirrored Separate Intent Logs
+.Ss Example 13 : No Creating a ZFS Pool with Mirrored Separate Intent Logs
The following command creates a ZFS storage pool consisting of two, two-way
mirrors and mirrored log devices:
.Dl # Nm zpool Cm create Ar pool Sy mirror Pa sda sdb Sy mirror Pa sdc sdd Sy log mirror Pa sde sdf
.
-.Ss Example 13 : No Adding Cache Devices to a ZFS Pool
+.Ss Example 14 : No Adding Cache Devices to a ZFS Pool
The following command adds two disks for use as cache devices to a ZFS storage
pool:
.Dl # Nm zpool Cm add Ar pool Sy cache Pa sdc sdd
@@ -356,7 +367,7 @@ Capacity and reads can be monitored using the
subcommand as follows:
.Dl # Nm zpool Cm iostat Fl v Ar pool 5
.
-.Ss Example 14 : No Removing a Mirrored top-level (Log or Data) Device
+.Ss Example 15 : No Removing a Mirrored top-level (Log or Data) Device
The following commands remove the mirrored log device
.Sy mirror-2
and mirrored top-level data device
@@ -384,14 +395,14 @@ config:
.Ed
.Pp
The command to remove the mirrored log
-.Ar mirror-2 No is:
+.Ar mirror-2 No is :
.Dl # Nm zpool Cm remove Ar tank mirror-2
.Pp
The command to remove the mirrored data
-.Ar mirror-1 No is:
+.Ar mirror-1 No is :
.Dl # Nm zpool Cm remove Ar tank mirror-1
.
-.Ss Example 15 : No Displaying expanded space on a device
+.Ss Example 16 : No Displaying expanded space on a device
The following command displays the detailed information for the pool
.Ar data .
This pool is comprised of a single raidz vdev where one of its devices
@@ -408,7 +419,7 @@ data 23.9G 14.6G 9.30G - 48% 61% 1.00x ONLINE -
sdc - - - - -
.Ed
.
-.Ss Example 16 : No Adding output columns
+.Ss Example 17 : No Adding output columns
Additional columns can be added to the
.Nm zpool Cm status No and Nm zpool Cm iostat No output with Fl c .
.Bd -literal -compact -offset Ds
@@ -433,7 +444,7 @@ rpool 14.6G 54.9G 4 55 250K 2.69M
.Ed
.
.Sh ENVIRONMENT VARIABLES
-.Bl -tag -compact -width "ZPOOL_IMPORT_UDEV_TIMEOUT_MS"
+.Bl -tag -compact -width "ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE"
.It Sy ZFS_ABORT
Cause
.Nm
@@ -442,7 +453,26 @@ to dump core on exit for the purposes of running
.It Sy ZFS_COLOR
Use ANSI color in
.Nm zpool Cm status
+and
+.Nm zpool Cm iostat
output.
+.It Sy ZPOOL_AUTO_POWER_ON_SLOT
+Automatically attempt to turn on the drives enclosure slot power to a drive when
+running the
+.Nm zpool Cm online
+or
+.Nm zpool Cm clear
+commands.
+This has the same effect as passing the
+.Fl -power
+option to those commands.
+.It Sy ZPOOL_POWER_ON_SLOT_TIMEOUT_MS
+The maximum time in milliseconds to wait for a slot power sysfs value
+to return the correct value after writing it.
+For example, after writing "on" to the sysfs enclosure slot power_control file,
+it can take some time for the enclosure to power down the slot and return
+"on" if you read back the 'power_control' value.
+Defaults to 30 seconds (30000ms) if not set.
.It Sy ZPOOL_IMPORT_PATH
The search path for devices or files to use with the pool.
This is a colon-separated list of directories in which
diff --git a/man/man8/zstream.8 b/man/man8/zstream.8
index aac7e3487712..c09a20ad20b6 100644
--- a/man/man8/zstream.8
+++ b/man/man8/zstream.8
@@ -6,7 +6,7 @@
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-.\" or http://www.opensolaris.org/os/licensing.
+.\" or https://opensource.org/licenses/CDDL-1.0.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
@@ -20,7 +20,7 @@
.\"
.\" Copyright (c) 2020 by Delphix. All rights reserved.
.\"
-.Dd March 25, 2022
+.Dd October 4, 2022
.Dt ZSTREAM 8
.Os
.
@@ -43,6 +43,10 @@
.Nm
.Cm token
.Ar resume_token
+.Nm
+.Cm recompress
+.Op Fl l Ar level
+.Ar algorithm
.
.Sh DESCRIPTION
The
@@ -96,6 +100,7 @@ Specify the object number and byte offset of each record that you wish to
decompress.
Optionally specify the compression type.
Valid compression types include
+.Sy off ,
.Sy gzip ,
.Sy lz4 ,
.Sy lzjb ,
@@ -108,6 +113,11 @@ Every record for that object beginning at that offset will be decompressed, if
possible.
It may not be possible, because the record may be corrupted in some but not
all of the stream's snapshots.
+Specifying a compression type of
+.Sy off
+will change the stream's metadata accordingly, without attempting decompression.
+This can be useful if the record is already uncompressed but the metadata
+insists otherwise.
The repaired stream will be written to standard output.
.Bl -tag -width "-v"
.It Fl v
@@ -143,6 +153,27 @@ Therefore, a deduplicated send stream can be received by running:
Verbose.
Print summary of converted records.
.El
+.It Xo
+.Nm
+.Cm recompress
+.Op Fl l Ar level
+.Ar algorithm
+.Xc
+Recompresses a send stream, provided on standard input, using the provided
+algorithm and optional level, and writes the modified stream to standard output.
+All WRITE records in the send stream will be recompressed, unless they fail
+to result in size reduction compared to being left uncompressed.
+The provided algorithm can be any valid value to the
+.Nm compress
+property.
+Note that encrypted send streams cannot be recompressed.
+.Bl -tag -width "-l"
+.It Fl l Ar level
+Specifies compression level.
+Only needed for algorithms where the level is not implied as part of the name
+of the algorithm (e.g. gzip-3 does not require it, while zstd does, if a
+non-default level is desired).
+.El
.El
.
.Sh EXAMPLES
diff --git a/module/.gitignore b/module/.gitignore
index 7a4bd3673e77..0ec6052f1bb0 100644
--- a/module/.gitignore
+++ b/module/.gitignore
@@ -22,5 +22,6 @@
/export_syms
/machine
/x86
+/i386
!Makefile.in
diff --git a/module/Kbuild.in b/module/Kbuild.in
index 4803952cbfed..7e08374fa2b9 100644
--- a/module/Kbuild.in
+++ b/module/Kbuild.in
@@ -34,6 +34,20 @@ ifeq ($(CONFIG_KASAN),y)
ZFS_MODULE_CFLAGS += -Wno-error=frame-larger-than=
endif
+# Generated binary search code is particularly bad with this optimization.
+# Oddly, range_tree.c is not affected when unrolling is not done and dsl_scan.c
+# is not affected when unrolling is done.
+# Disable it until the following upstream issue is resolved:
+# https://github.com/llvm/llvm-project/issues/62790
+ifeq ($(CONFIG_X86),y)
+ifeq ($(CONFIG_CC_IS_CLANG),y)
+CFLAGS_zfs/dsl_scan.o += -mllvm -x86-cmov-converter=false
+CFLAGS_zfs/metaslab.o += -mllvm -x86-cmov-converter=false
+CFLAGS_zfs/range_tree.o += -mllvm -x86-cmov-converter=false
+CFLAGS_zfs/zap_micro.o += -mllvm -x86-cmov-converter=false
+endif
+endif
+
ifneq ($(KBUILD_EXTMOD),)
@CONFIG_QAT_TRUE@ZFS_MODULE_CFLAGS += -I@QAT_SRC@/include
@CONFIG_QAT_TRUE@KBUILD_EXTRA_SYMBOLS += @QAT_SYMBOLS@
@@ -42,6 +56,12 @@ endif
asflags-y := $(ZFS_MODULE_CFLAGS) $(ZFS_MODULE_CPPFLAGS)
ccflags-y := $(ZFS_MODULE_CFLAGS) $(ZFS_MODULE_CPPFLAGS)
+ifeq ($(CONFIG_ARM64),y)
+CFLAGS_REMOVE_zcommon/zfs_fletcher_aarch64_neon.o += -mgeneral-regs-only
+CFLAGS_REMOVE_zfs/vdev_raidz_math_aarch64_neon.o += -mgeneral-regs-only
+CFLAGS_REMOVE_zfs/vdev_raidz_math_aarch64_neonx2.o += -mgeneral-regs-only
+endif
+
# Suppress unused-value warnings in sparc64 architecture headers
ccflags-$(CONFIG_SPARC64) += -Wno-unused-value
@@ -59,6 +79,7 @@ SPL_OBJS := \
spl-kstat.o \
spl-proc.o \
spl-procfs-list.o \
+ spl-shrinker.o \
spl-taskq.o \
spl-thread.o \
spl-trace.o \
@@ -79,7 +100,6 @@ ICP_OBJS := \
algs/blake3/blake3.o \
algs/blake3/blake3_generic.o \
algs/blake3/blake3_impl.o \
- algs/blake3/blake3_x86-64.o \
algs/edonr/edonr.o \
algs/modes/cbc.o \
algs/modes/ccm.o \
@@ -88,7 +108,9 @@ ICP_OBJS := \
algs/modes/gcm.o \
algs/modes/gcm_generic.o \
algs/modes/modes.o \
- algs/sha2/sha2.o \
+ algs/sha2/sha2_generic.o \
+ algs/sha2/sha256_impl.o \
+ algs/sha2/sha512_impl.o \
algs/skein/skein.o \
algs/skein/skein_block.o \
algs/skein/skein_iv.o \
@@ -114,55 +136,57 @@ ICP_OBJS_X86_64 := \
asm-x86_64/blake3/blake3_avx512.o \
asm-x86_64/blake3/blake3_sse2.o \
asm-x86_64/blake3/blake3_sse41.o \
+ asm-x86_64/sha2/sha256-x86_64.o \
+ asm-x86_64/sha2/sha512-x86_64.o \
asm-x86_64/modes/aesni-gcm-x86_64.o \
asm-x86_64/modes/gcm_pclmulqdq.o \
- asm-x86_64/modes/ghash-x86_64.o \
- asm-x86_64/sha2/sha256_impl.o \
- asm-x86_64/sha2/sha512_impl.o
-
+ asm-x86_64/modes/ghash-x86_64.o
ICP_OBJS_X86 := \
algs/aes/aes_impl_aesni.o \
algs/aes/aes_impl_x86-64.o \
algs/modes/gcm_pclmulqdq.o
+ICP_OBJS_ARM := \
+ asm-arm/sha2/sha256-armv7.o \
+ asm-arm/sha2/sha512-armv7.o
ICP_OBJS_ARM64 := \
asm-aarch64/blake3/b3_aarch64_sse2.o \
- asm-aarch64/blake3/b3_aarch64_sse41.o
-
+ asm-aarch64/blake3/b3_aarch64_sse41.o \
+ asm-aarch64/sha2/sha256-armv8.o \
+ asm-aarch64/sha2/sha512-armv8.o
ICP_OBJS_PPC_PPC64 := \
asm-ppc64/blake3/b3_ppc64le_sse2.o \
- asm-ppc64/blake3/b3_ppc64le_sse41.o
+ asm-ppc64/blake3/b3_ppc64le_sse41.o \
+ asm-ppc64/sha2/sha256-p8.o \
+ asm-ppc64/sha2/sha512-p8.o \
+ asm-ppc64/sha2/sha256-ppc.o \
+ asm-ppc64/sha2/sha512-ppc.o
zfs-objs += $(addprefix icp/,$(ICP_OBJS))
zfs-$(CONFIG_X86) += $(addprefix icp/,$(ICP_OBJS_X86))
zfs-$(CONFIG_UML_X86)+= $(addprefix icp/,$(ICP_OBJS_X86))
zfs-$(CONFIG_X86_64) += $(addprefix icp/,$(ICP_OBJS_X86_64))
+zfs-$(CONFIG_ARM) += $(addprefix icp/,$(ICP_OBJS_ARM))
zfs-$(CONFIG_ARM64) += $(addprefix icp/,$(ICP_OBJS_ARM64))
zfs-$(CONFIG_PPC) += $(addprefix icp/,$(ICP_OBJS_PPC_PPC64))
zfs-$(CONFIG_PPC64) += $(addprefix icp/,$(ICP_OBJS_PPC_PPC64))
$(addprefix $(obj)/icp/,$(ICP_OBJS) $(ICP_OBJS_X86) $(ICP_OBJS_X86_64) \
- $(ICP_OBJS_ARM64) $(ICP_OBJS_PPC_PPC64)) : asflags-y += -I$(icp_include)
+ $(ICP_OBJS_ARM64) $(ICP_OBJS_PPC_PPC64)) : asflags-y += -I$(icp_include) -I$(zfs_include)/os/linux/spl -I$(zfs_include)
$(addprefix $(obj)/icp/,$(ICP_OBJS) $(ICP_OBJS_X86) $(ICP_OBJS_X86_64) \
- $(ICP_OBJS_ARM64) $(ICP_OBJS_PPC_PPC64)) : ccflags-y += -I$(icp_include)
+ $(ICP_OBJS_ARM64) $(ICP_OBJS_PPC_PPC64)) : ccflags-y += -I$(icp_include) -I$(zfs_include)/os/linux/spl -I$(zfs_include)
-# 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.
+# Suppress objtool "unsupported stack pointer realignment" warnings.
# See #6950 for the reasoning.
-OBJECT_FILES_NON_STANDARD_sha256_impl.o := y
-OBJECT_FILES_NON_STANDARD_sha512_impl.o := y
-
+OBJECT_FILES_NON_STANDARD_sha256-x86_64.o := y
+OBJECT_FILES_NON_STANDARD_sha512-x86_64.o := y
LUA_OBJS := \
lapi.o \
@@ -296,11 +320,13 @@ ZFS_OBJS := \
bpobj.o \
bptree.o \
bqueue.o \
+ brt.o \
btree.o \
dataset_kstats.o \
dbuf.o \
dbuf_stats.o \
ddt.o \
+ ddt_stats.o \
ddt_zap.o \
dmu.o \
dmu_diff.o \
@@ -342,10 +368,9 @@ ZFS_OBJS := \
refcount.o \
rrwlock.o \
sa.o \
- sha256.o \
+ sha2_zfs.o \
skein_zfs.o \
spa.o \
- spa_boot.o \
spa_checkpoint.o \
spa_config.o \
spa_errlog.o \
@@ -359,7 +384,6 @@ ZFS_OBJS := \
uberblock.o \
unique.o \
vdev.o \
- vdev_cache.o \
vdev_draid.o \
vdev_draid_rand.o \
vdev_indirect.o \
@@ -391,6 +415,7 @@ ZFS_OBJS := \
zfs_chksum.o \
zfs_fm.o \
zfs_fuid.o \
+ zfs_impl.o \
zfs_ioctl.o \
zfs_log.o \
zfs_onexit.o \
@@ -422,6 +447,7 @@ ZFS_OBJS_OS := \
trace.o \
vdev_disk.o \
vdev_file.o \
+ vdev_label_os.o \
zfs_acl.o \
zfs_ctldir.o \
zfs_debug.o \
@@ -438,6 +464,7 @@ ZFS_OBJS_OS := \
zpl_ctldir.o \
zpl_export.o \
zpl_file.o \
+ zpl_file_range.o \
zpl_inode.o \
zpl_super.o \
zpl_xattr.o \
@@ -464,6 +491,10 @@ zfs-$(CONFIG_ARM64) += $(addprefix zfs/,$(ZFS_OBJS_ARM64))
zfs-$(CONFIG_PPC) += $(addprefix zfs/,$(ZFS_OBJS_PPC_PPC64))
zfs-$(CONFIG_PPC64) += $(addprefix zfs/,$(ZFS_OBJS_PPC_PPC64))
+UBSAN_SANITIZE_zap_leaf.o := n
+UBSAN_SANITIZE_zap_micro.o := n
+UBSAN_SANITIZE_sa.o := n
+
# Suppress incorrect warnings from versions of objtool which are not
# aware of x86 EVEX prefix instructions used for AVX512.
OBJECT_FILES_NON_STANDARD_vdev_raidz_math_avx512bw.o := y
diff --git a/module/Makefile.bsd b/module/Makefile.bsd
index 589ca60b29be..d9d31564d090 100644
--- a/module/Makefile.bsd
+++ b/module/Makefile.bsd
@@ -10,13 +10,18 @@ INCDIR=${.CURDIR:H}/include
KMOD= openzfs
.PATH: ${SRCDIR}/avl \
+ ${SRCDIR}/lua \
+ ${SRCDIR}/nvpair \
${SRCDIR}/icp/algs/blake3 \
+ ${SRCDIR}/icp/algs/edonr \
+ ${SRCDIR}/icp/algs/sha2 \
${SRCDIR}/icp/asm-aarch64/blake3 \
+ ${SRCDIR}/icp/asm-aarch64/sha2 \
+ ${SRCDIR}/icp/asm-arm/sha2 \
+ ${SRCDIR}/icp/asm-ppc64/sha2 \
${SRCDIR}/icp/asm-ppc64/blake3 \
${SRCDIR}/icp/asm-x86_64/blake3 \
- ${SRCDIR}/lua \
- ${SRCDIR}/nvpair \
- ${SRCDIR}/icp/algs/edonr \
+ ${SRCDIR}/icp/asm-x86_64/sha2 \
${SRCDIR}/os/freebsd/spl \
${SRCDIR}/os/freebsd/zfs \
${SRCDIR}/unicode \
@@ -27,24 +32,22 @@ KMOD= openzfs
${SRCDIR}/zstd/lib/compress \
${SRCDIR}/zstd/lib/decompress
-
-
-CFLAGS+= -I${.OBJDIR:H}/include
CFLAGS+= -I${INCDIR}
+CFLAGS+= -I${SRCDIR}/icp/include
CFLAGS+= -I${INCDIR}/os/freebsd
CFLAGS+= -I${INCDIR}/os/freebsd/spl
CFLAGS+= -I${INCDIR}/os/freebsd/zfs
CFLAGS+= -I${SRCDIR}/zstd/include
-CFLAGS+= -I${SRCDIR}/icp/include
CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h
+CFLAGS+= -I${.CURDIR}
-CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
- -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \
- -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DSMP -DCOMPAT_FREEBSD11
+CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
+ -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \
+ -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DCOMPAT_FREEBSD11
.if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 -DHAVE_SSE4_2 \
- -DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL
+ -DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW
.endif
.if defined(WITH_DEBUG) && ${WITH_DEBUG} == "true"
@@ -71,7 +74,7 @@ CFLAGS+= -fprofile-arcs -ftest-coverage
DEBUG_FLAGS=-g
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "powerpc" || \
- ${MACHINE_ARCH} == "arm"
+ ${MACHINE_ARCH} == "powerpcspe" || ${MACHINE_ARCH} == "arm"
CFLAGS+= -DBITS_PER_LONG=32
.else
CFLAGS+= -DBITS_PER_LONG=64
@@ -82,14 +85,10 @@ SRCS= vnode_if.h device_if.h bus_if.h
#avl
SRCS+= avl.c
-# icp
-SRCS+= edonr.c
-
#icp/algs/blake3
SRCS+= blake3.c \
blake3_generic.c \
- blake3_impl.c \
- blake3_x86-64.c
+ blake3_impl.c
#icp/asm-aarch64/blake3
SRCS+= b3_aarch64_sse2.S \
@@ -105,6 +104,32 @@ SRCS+= blake3_avx2.S \
blake3_sse2.S \
blake3_sse41.S
+#icp/algs/edonr
+SRCS+= edonr.c
+
+#icp/algs/sha2
+SRCS+= sha256_impl.c \
+ sha2_generic.c \
+ sha512_impl.c
+
+#icp/asm-arm/sha2
+SRCS+= sha256-armv7.S \
+ sha512-armv7.S
+
+#icp/asm-aarch64/sha2
+SRCS+= sha256-armv8.S \
+ sha512-armv8.S
+
+#icp/asm-ppc64/sha2
+SRCS+= sha256-p8.S \
+ sha256-ppc.S \
+ sha512-p8.S \
+ sha512-ppc.S
+
+#icp/asm-x86_64/sha2
+SRCS+= sha256-x86_64.S \
+ sha512-x86_64.S
+
#lua
SRCS+= lapi.c \
lauxlib.c \
@@ -132,17 +157,15 @@ SRCS+= lapi.c \
lzio.c
#nvpair
-SRCS+= nvpair.c \
- fnvpair.c \
- nvpair_alloc_spl.c \
- nvpair_alloc_fixed.c
+SRCS+= fnvpair.c \
+ nvpair.c \
+ nvpair_alloc_fixed.c \
+ nvpair_alloc_spl.c
#os/freebsd/spl
SRCS+= acl_common.c \
callb.c \
list.c \
- sha256c.c \
- sha512c.c \
spl_acl.c \
spl_cmn_err.c \
spl_dtrace.c \
@@ -161,9 +184,8 @@ SRCS+= acl_common.c \
spl_zlib.c \
spl_zone.c
-
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "powerpc" || \
- ${MACHINE_ARCH} == "arm"
+ ${MACHINE_ARCH} == "powerpcspe" || ${MACHINE_ARCH} == "arm"
SRCS+= spl_atomic.c
.endif
@@ -172,6 +194,7 @@ SRCS+= abd_os.c \
arc_os.c \
crypto_os.c \
dmu_os.c \
+ event_os.c \
hkdf.c \
kmod_core.c \
spa_os.c \
@@ -183,6 +206,7 @@ SRCS+= abd_os.c \
zfs_ctldir.c \
zfs_debug.c \
zfs_dir.c \
+ zfs_file_os.c \
zfs_ioctl_compat.c \
zfs_ioctl_os.c \
zfs_racct.c \
@@ -193,19 +217,20 @@ SRCS+= abd_os.c \
zvol_os.c
#unicode
-SRCS+= uconv.c \
- u8_textprep.c
+SRCS+= u8_textprep.c \
+ uconv.c
#zcommon
-SRCS+= zfeature_common.c \
+SRCS+= cityhash.c \
+ zfeature_common.c \
zfs_comutil.c \
zfs_deleg.c \
- zfs_fletcher.c \
zfs_fletcher_avx512.c \
+ zfs_fletcher.c \
zfs_fletcher_intel.c \
zfs_fletcher_sse.c \
- zfs_fletcher_superscalar.c \
zfs_fletcher_superscalar4.c \
+ zfs_fletcher_superscalar.c \
zfs_namecheck.c \
zfs_prop.c \
zpool_prop.c \
@@ -219,14 +244,15 @@ SRCS+= abd.c \
blkptr.c \
bplist.c \
bpobj.c \
- btree.c \
- cityhash.c \
- dbuf.c \
- dbuf_stats.c \
bptree.c \
bqueue.c \
+ brt.c \
+ btree.c \
dataset_kstats.c \
+ dbuf.c \
+ dbuf_stats.c \
ddt.c \
+ ddt_stats.c \
ddt_zap.c \
dmu.c \
dmu_diff.c \
@@ -240,13 +266,13 @@ SRCS+= abd.c \
dmu_zfetch.c \
dnode.c \
dnode_sync.c \
+ dsl_bookmark.c \
+ dsl_crypt.c \
dsl_dataset.c \
dsl_deadlist.c \
dsl_deleg.c \
- dsl_bookmark.c \
- dsl_dir.c \
- dsl_crypt.c \
dsl_destroy.c \
+ dsl_dir.c \
dsl_pool.c \
dsl_prop.c \
dsl_scan.c \
@@ -255,9 +281,9 @@ SRCS+= abd.c \
edonr_zfs.c \
fm.c \
gzip.c \
- lzjb.c \
lz4.c \
lz4_zfs.c \
+ lzjb.c \
metaslab.c \
mmp.c \
multilist.c \
@@ -267,10 +293,11 @@ SRCS+= abd.c \
refcount.c \
rrwlock.c \
sa.c \
- sha256.c \
+ sha2_zfs.c \
skein_zfs.c \
spa.c \
- spa_boot.c \
+ space_map.c \
+ space_reftree.c \
spa_checkpoint.c \
spa_config.c \
spa_errlog.c \
@@ -278,17 +305,14 @@ SRCS+= abd.c \
spa_log_spacemap.c \
spa_misc.c \
spa_stats.c \
- space_map.c \
- space_reftree.c \
txg.c \
uberblock.c \
unique.c \
vdev.c \
- vdev_cache.c \
vdev_draid.c \
vdev_draid_rand.c \
- vdev_indirect.c \
vdev_indirect_births.c \
+ vdev_indirect.c \
vdev_indirect_mapping.c \
vdev_initialize.c \
vdev_label.c \
@@ -296,11 +320,11 @@ SRCS+= abd.c \
vdev_missing.c \
vdev_queue.c \
vdev_raidz.c \
- vdev_raidz_math.c \
- vdev_raidz_math_scalar.c \
vdev_raidz_math_avx2.c \
vdev_raidz_math_avx512bw.c \
vdev_raidz_math_avx512f.c \
+ vdev_raidz_math.c \
+ vdev_raidz_math_scalar.c \
vdev_raidz_math_sse2.c \
vdev_raidz_math_ssse3.c \
vdev_rebuild.c \
@@ -319,9 +343,9 @@ SRCS+= abd.c \
zfeature.c \
zfs_byteswap.c \
zfs_chksum.c \
- zfs_file_os.c \
zfs_fm.c \
zfs_fuid.c \
+ zfs_impl.c \
zfs_ioctl.c \
zfs_log.c \
zfs_onexit.c \
@@ -342,13 +366,18 @@ SRCS+= abd.c \
zvol.c
#zstd
-SRCS+= zfs_zstd.c \
- entropy_common.c \
+SRCS+= zfs_zstd.c
+
+#zstd/common
+SRCS+= entropy_common.c \
error_private.c \
fse_decompress.c \
pool.c \
+ xxhash.c \
zstd_common.c \
- fse_compress.c \
+
+#zstd/compress
+SRCS+= fse_compress.c \
hist.c \
huf_compress.c \
zstd_compress.c \
@@ -359,11 +388,13 @@ SRCS+= zfs_zstd.c \
zstd_fast.c \
zstd_lazy.c \
zstd_ldm.c \
- zstd_opt.c \
- huf_decompress.c \
+ zstd_opt.c
+
+#zstd/decompress
+SRCS+= huf_decompress.c \
zstd_ddict.c \
- zstd_decompress.c \
- zstd_decompress_block.c
+ zstd_decompress_block.c \
+ zstd_decompress.c
beforeinstall:
.if ${MK_DEBUG_FILES} != "no"
@@ -374,74 +405,146 @@ beforeinstall:
.include <bsd.kmod.mk>
+# Generated binary search code is particularly bad with this optimization.
+# Oddly, range_tree.c is not affected when unrolling is not done and dsl_scan.c
+# is not affected when unrolling is done.
+# Disable it until the following upstream issue is resolved:
+# https://github.com/llvm/llvm-project/issues/62790
+.if ${CC} == "clang"
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
+CFLAGS.dsl_scan.c= -mllvm -x86-cmov-converter=false
+CFLAGS.metaslab.c= -mllvm -x86-cmov-converter=false
+CFLAGS.range_tree.c= -mllvm -x86-cmov-converter=false
+CFLAGS.zap_micro.c= -mllvm -x86-cmov-converter=false
+.endif
+.endif
+
+CFLAGS.sysctl_os.c= -include ../zfs_config.h
+CFLAGS.xxhash.c+= -include ${SYSDIR}/sys/_null.h
CFLAGS.gcc+= -Wno-pointer-to-int-cast
-CFLAGS.lapi.c= -Wno-cast-qual
-CFLAGS.lcompat.c= -Wno-cast-qual
-CFLAGS.lobject.c= -Wno-cast-qual
-CFLAGS.ltable.c= -Wno-cast-qual
-CFLAGS.lvm.c= -Wno-cast-qual
-CFLAGS.nvpair.c= -DHAVE_RPC_TYPES -Wno-cast-qual
-CFLAGS.spl_string.c= -Wno-cast-qual
-CFLAGS.spl_vm.c= -Wno-cast-qual
-CFLAGS.spl_zlib.c= -Wno-cast-qual
CFLAGS.abd.c= -Wno-cast-qual
-CFLAGS.zfs_log.c= -Wno-cast-qual
-CFLAGS.zfs_vnops_os.c= -Wno-pointer-arith
-CFLAGS.u8_textprep.c= -Wno-cast-qual
-CFLAGS.zfs_fletcher.c= -Wno-cast-qual -Wno-pointer-arith
-CFLAGS.zfs_fletcher_intel.c= -Wno-cast-qual -Wno-pointer-arith
-CFLAGS.zfs_fletcher_sse.c= -Wno-cast-qual -Wno-pointer-arith
-CFLAGS.zfs_fletcher_avx512.c= -Wno-cast-qual -Wno-pointer-arith
-CFLAGS.zprop_common.c= -Wno-cast-qual
CFLAGS.ddt.c= -Wno-cast-qual
+CFLAGS.ddt_zap.c= -Wno-cast-qual
CFLAGS.dmu.c= -Wno-cast-qual
CFLAGS.dmu_traverse.c= -Wno-cast-qual
-CFLAGS.dsl_dir.c= -Wno-cast-qual
+CFLAGS.dnode.c= ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.dsl_deadlist.c= -Wno-cast-qual
+CFLAGS.dsl_dir.c= -Wno-cast-qual
CFLAGS.dsl_prop.c= -Wno-cast-qual
-CFLAGS.edonr.c=-Wno-cast-qual
+CFLAGS.edonr.c= -Wno-cast-qual
CFLAGS.fm.c= -Wno-cast-qual
+CFLAGS.hist.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.lapi.c= -Wno-cast-qual
+CFLAGS.lcompat.c= -Wno-cast-qual
+CFLAGS.ldo.c= ${NO_WINFINITE_RECURSION}
+CFLAGS.lobject.c= -Wno-cast-qual
+CFLAGS.ltable.c= -Wno-cast-qual
+CFLAGS.lvm.c= -Wno-cast-qual
+CFLAGS.lz4.c= -Wno-cast-qual
CFLAGS.lz4_zfs.c= -Wno-cast-qual
+CFLAGS.nvpair.c= -Wno-cast-qual -DHAVE_RPC_TYPES ${NO_WSTRINGOP_OVERREAD}
+CFLAGS.pool.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.pool.c= -U__BMI__ -fno-tree-vectorize
CFLAGS.spa.c= -Wno-cast-qual
CFLAGS.spa_misc.c= -Wno-cast-qual
-CFLAGS.sysctl_os.c= -include ../zfs_config.h
+CFLAGS.spl_string.c= -Wno-cast-qual
+CFLAGS.spl_vm.c= -Wno-cast-qual
+CFLAGS.spl_zlib.c= -Wno-cast-qual
+CFLAGS.u8_textprep.c= -Wno-cast-qual
CFLAGS.vdev_draid.c= -Wno-cast-qual
CFLAGS.vdev_raidz.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math.c= -Wno-cast-qual
-CFLAGS.vdev_raidz_math_scalar.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math_avx2.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
CFLAGS.vdev_raidz_math_avx512f.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
+CFLAGS.vdev_raidz_math_scalar.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math_sse2.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
CFLAGS.zap_leaf.c= -Wno-cast-qual
CFLAGS.zap_micro.c= -Wno-cast-qual
CFLAGS.zcp.c= -Wno-cast-qual
-CFLAGS.zfs_fm.c= -Wno-cast-qual
+CFLAGS.zfs_fletcher.c= -Wno-cast-qual -Wno-pointer-arith
+CFLAGS.zfs_fletcher_avx512.c= -Wno-cast-qual -Wno-pointer-arith
+CFLAGS.zfs_fletcher_intel.c= -Wno-cast-qual -Wno-pointer-arith
+CFLAGS.zfs_fletcher_sse.c= -Wno-cast-qual -Wno-pointer-arith
+CFLAGS.zfs_fm.c= -Wno-cast-qual ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.zfs_ioctl.c= -Wno-cast-qual
+CFLAGS.zfs_log.c= -Wno-cast-qual
+CFLAGS.zfs_vnops_os.c= -Wno-pointer-arith
+CFLAGS.zfs_zstd.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zil.c= -Wno-cast-qual
CFLAGS.zio.c= -Wno-cast-qual
+CFLAGS.zprop_common.c= -Wno-cast-qual
CFLAGS.zrlock.c= -Wno-cast-qual
-CFLAGS.zfs_zstd.c= -Wno-cast-qual -Wno-pointer-arith
-CFLAGS.entropy_common.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.error_private.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.fse_decompress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.pool.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.xxhash.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_common.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.fse_compress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.hist.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.huf_compress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_compress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_compress_literals.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_compress_sequences.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_compress_superblock.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_double_fast.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_fast.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_lazy.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_ldm.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_opt.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.huf_decompress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_ddict.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_decompress.c= -fno-tree-vectorize -U__BMI__
-CFLAGS.zstd_decompress_block.c= -fno-tree-vectorize -U__BMI__
+
+#zstd
+CFLAGS.entropy_common.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.error_private.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.fse_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL} ${NO_WUNUSED_BUT_SET_VARIABLE}
+CFLAGS.fse_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.huf_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.huf_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.xxhash.c+= -U__BMI__ -fno-tree-vectorize
+CFLAGS.xxhash.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_common.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_compress_literals.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_compress_sequences.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_compress_superblock.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL} ${NO_WUNUSED_BUT_SET_VARIABLE}
+CFLAGS.zstd_ddict.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_decompress_block.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_double_fast.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_fast.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_lazy.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_ldm.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+CFLAGS.zstd_opt.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
+
+.if ${MACHINE_CPUARCH} == "aarch64"
+__ZFS_ZSTD_AARCH64_FLAGS= -include ${SRCDIR}/zstd/include/aarch64_compat.h
+CFLAGS.zstd.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.entropy_common.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.error_private.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.fse_compress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.fse_decompress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.hist.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.huf_compress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.huf_decompress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.pool.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.xxhash.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_common.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_compress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_compress_literals.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_compress_sequences.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_compress_superblock.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_ddict.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_decompress.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_decompress_block.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_double_fast.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_fast.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_lazy.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_ldm.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+CFLAGS.zstd_opt.c+= ${__ZFS_ZSTD_AARCH64_FLAGS}
+
+sha256-armv8.o: sha256-armv8.S
+ ${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
+ -o ${.TARGET}
+ ${CTFCONVERT_CMD}
+
+sha512-armv8.o: sha512-armv8.S
+ ${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
+ -o ${.TARGET}
+ ${CTFCONVERT_CMD}
+
+b3_aarch64_sse2.o: b3_aarch64_sse2.S
+ ${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
+ -o ${.TARGET}
+ ${CTFCONVERT_CMD}
+
+b3_aarch64_sse41.o: b3_aarch64_sse41.S
+ ${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
+ -o ${.TARGET}
+ ${CTFCONVERT_CMD}
+
+.endif
diff --git a/module/Makefile.in b/module/Makefile.in
index 5b71e1abf79e..9b34b3dfaec7 100644
--- a/module/Makefile.in
+++ b/module/Makefile.in
@@ -168,4 +168,4 @@ gen-zstd-symbols:
for obj in $(addprefix zstd/,$(ZSTD_UPSTREAM_OBJS)); do echo; echo "/* $${obj#zstd/}: */"; @OBJDUMP@ -t $$obj | awk '$$2 == "g" && !/ zfs_/ {print "#define\t" $$6 " zfs_" $$6}' | sort; done >> zstd/include/zstd_compat_wrapper.h
check-zstd-symbols:
- @OBJDUMP@ -t $(addprefix zstd/,$(ZSTD_UPSTREAM_OBJS)) | awk '/file format/ {print} $$2 == "g" && !/ zfs_/ {++ret; print} END {exit ret}'
+ @OBJDUMP@ -t $(addprefix zstd/,$(ZSTD_UPSTREAM_OBJS)) | awk '/file format/ {print} $$2 == "g" && (!/ zfs_/ && !/ __pfx_zfs_/) {++ret; print} END {exit ret}'
diff --git a/module/avl/avl.c b/module/avl/avl.c
index c45be4793fa8..9b74531fa9f7 100644
--- a/module/avl/avl.c
+++ b/module/avl/avl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -108,6 +108,10 @@
#include <sys/cmn_err.h>
#include <sys/mod.h>
+#ifndef _KERNEL
+#include <string.h>
+#endif
+
/*
* Walk from one node to the previous valued node (ie. an infix walk
* towards the left). At any given node we do one of 2 things:
@@ -695,7 +699,7 @@ avl_remove(avl_tree_t *tree, void *data)
*/
tmp = *node;
- *node = *delete;
+ memcpy(node, delete, sizeof (*node));
if (node->avl_child[left] == node)
node->avl_child[left] = &tmp;
diff --git a/module/icp/algs/aes/aes_impl.c b/module/icp/algs/aes/aes_impl.c
index 16afc2572dc8..9daa975226fe 100644
--- a/module/icp/algs/aes/aes_impl.c
+++ b/module/icp/algs/aes/aes_impl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -211,7 +211,7 @@ aes_alloc_keysched(size_t *size, int kmflag)
{
aes_key_t *keysched;
- keysched = (aes_key_t *)kmem_alloc(sizeof (aes_key_t), kmflag);
+ keysched = kmem_alloc(sizeof (aes_key_t), kmflag);
if (keysched != NULL) {
*size = sizeof (aes_key_t);
return (keysched);
@@ -424,13 +424,15 @@ icp_aes_impl_get(char *buffer, zfs_kernel_param_t *kp)
/* list mandatory options */
for (i = 0; i < ARRAY_SIZE(aes_impl_opts); i++) {
fmt = (impl == aes_impl_opts[i].sel) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, aes_impl_opts[i].name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ aes_impl_opts[i].name);
}
/* list all supported implementations */
for (i = 0; i < aes_supp_impl_cnt; i++) {
fmt = (i == impl) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, aes_supp_impl[i]->name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ aes_supp_impl[i]->name);
}
return (cnt);
diff --git a/module/icp/algs/aes/aes_impl_aesni.c b/module/icp/algs/aes/aes_impl_aesni.c
index 4b5eefd71b17..61085214c77b 100644
--- a/module/icp/algs/aes/aes_impl_aesni.c
+++ b/module/icp/algs/aes/aes_impl_aesni.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,15 +26,16 @@
#include <sys/simd.h>
#include <sys/types.h>
+#include <sys/asm_linkage.h>
/* These functions are used to execute AES-NI instructions: */
-extern int rijndael_key_setup_enc_intel(uint32_t rk[],
+extern ASMABI int rijndael_key_setup_enc_intel(uint32_t rk[],
const uint32_t cipherKey[], uint64_t keyBits);
-extern int rijndael_key_setup_dec_intel(uint32_t rk[],
+extern ASMABI int rijndael_key_setup_dec_intel(uint32_t rk[],
const uint32_t cipherKey[], uint64_t keyBits);
-extern void aes_encrypt_intel(const uint32_t rk[], int Nr,
+extern ASMABI void aes_encrypt_intel(const uint32_t rk[], int Nr,
const uint32_t pt[4], uint32_t ct[4]);
-extern void aes_decrypt_intel(const uint32_t rk[], int Nr,
+extern ASMABI void aes_decrypt_intel(const uint32_t rk[], int Nr,
const uint32_t ct[4], uint32_t pt[4]);
diff --git a/module/icp/algs/aes/aes_impl_generic.c b/module/icp/algs/aes/aes_impl_generic.c
index 427c096c6ab3..ae13c0b85578 100644
--- a/module/icp/algs/aes/aes_impl_generic.c
+++ b/module/icp/algs/aes/aes_impl_generic.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/aes/aes_impl_x86-64.c b/module/icp/algs/aes/aes_impl_x86-64.c
index 19f8fd5012cf..f4f206a00935 100644
--- a/module/icp/algs/aes/aes_impl_x86-64.c
+++ b/module/icp/algs/aes/aes_impl_x86-64.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/aes/aes_modes.c b/module/icp/algs/aes/aes_modes.c
index 9e4b498fffcb..6a25496d050e 100644
--- a/module/icp/algs/aes/aes_modes.c
+++ b/module/icp/algs/aes/aes_modes.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/blake3/blake3.c b/module/icp/algs/blake3/blake3.c
index 8c9c06eb9d9f..0bab7a3a7593 100644
--- a/module/icp/algs/blake3/blake3.c
+++ b/module/icp/algs/blake3/blake3.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,6 +25,7 @@
* Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
+#include <sys/simd.h>
#include <sys/zfs_context.h>
#include <sys/blake3.h>
@@ -129,7 +130,7 @@ static output_t make_output(const uint32_t input_cv[8],
* bytes. For that reason, chaining values in the CV stack are represented as
* bytes.
*/
-static void output_chaining_value(const blake3_impl_ops_t *ops,
+static void output_chaining_value(const blake3_ops_t *ops,
const output_t *ctx, uint8_t cv[32])
{
uint32_t cv_words[8];
@@ -139,7 +140,7 @@ static void output_chaining_value(const blake3_impl_ops_t *ops,
store_cv_words(cv, cv_words);
}
-static void output_root_bytes(const blake3_impl_ops_t *ops, const output_t *ctx,
+static void output_root_bytes(const blake3_ops_t *ops, const output_t *ctx,
uint64_t seek, uint8_t *out, size_t out_len)
{
uint64_t output_block_counter = seek / 64;
@@ -163,7 +164,7 @@ static void output_root_bytes(const blake3_impl_ops_t *ops, const output_t *ctx,
}
}
-static void chunk_state_update(const blake3_impl_ops_t *ops,
+static void chunk_state_update(const blake3_ops_t *ops,
blake3_chunk_state_t *ctx, const uint8_t *input, size_t input_len)
{
if (ctx->buf_len > 0) {
@@ -189,9 +190,7 @@ static void chunk_state_update(const blake3_impl_ops_t *ops,
input_len -= BLAKE3_BLOCK_LEN;
}
- size_t take = chunk_state_fill_buf(ctx, input, input_len);
- input += take;
- input_len -= take;
+ chunk_state_fill_buf(ctx, input, input_len);
}
static output_t chunk_state_output(const blake3_chunk_state_t *ctx)
@@ -230,7 +229,7 @@ static size_t left_len(size_t content_len)
* number of chunks hashed. These chunks are never the root and never empty;
* those cases use a different codepath.
*/
-static size_t compress_chunks_parallel(const blake3_impl_ops_t *ops,
+static size_t compress_chunks_parallel(const blake3_ops_t *ops,
const uint8_t *input, size_t input_len, const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags, uint8_t *out)
{
@@ -274,11 +273,11 @@ static size_t compress_chunks_parallel(const blake3_impl_ops_t *ops,
* return it as an additional output.) These parents are never the root and
* never empty; those cases use a different codepath.
*/
-static size_t compress_parents_parallel(const blake3_impl_ops_t *ops,
+static size_t compress_parents_parallel(const blake3_ops_t *ops,
const uint8_t *child_chaining_values, size_t num_chaining_values,
const uint32_t key[8], uint8_t flags, uint8_t *out)
{
- const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2];
+ const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2] = {0};
size_t parents_array_len = 0;
while (num_chaining_values - (2 * parents_array_len) >= 2) {
@@ -320,7 +319,7 @@ static size_t compress_parents_parallel(const blake3_impl_ops_t *ops,
* of implementing this special rule? Because we don't want to limit SIMD or
* multi-threading parallelism for that update().
*/
-static size_t blake3_compress_subtree_wide(const blake3_impl_ops_t *ops,
+static size_t blake3_compress_subtree_wide(const blake3_ops_t *ops,
const uint8_t *input, size_t input_len, const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags, uint8_t *out)
{
@@ -406,7 +405,7 @@ static size_t blake3_compress_subtree_wide(const blake3_impl_ops_t *ops,
* As with compress_subtree_wide(), this function is not used on inputs of 1
* chunk or less. That's a different codepath.
*/
-static void compress_subtree_to_parent_node(const blake3_impl_ops_t *ops,
+static void compress_subtree_to_parent_node(const blake3_ops_t *ops,
const uint8_t *input, size_t input_len, const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN])
{
@@ -434,7 +433,7 @@ static void hasher_init_base(BLAKE3_CTX *ctx, const uint32_t key[8],
memcpy(ctx->key, key, BLAKE3_KEY_LEN);
chunk_state_init(&ctx->chunk, key, flags);
ctx->cv_stack_len = 0;
- ctx->ops = blake3_impl_get_ops();
+ ctx->ops = blake3_get_ops();
}
/*
diff --git a/module/icp/algs/blake3/blake3_generic.c b/module/icp/algs/blake3/blake3_generic.c
index 6ff9a845ccdc..fbe184969672 100644
--- a/module/icp/algs/blake3/blake3_generic.c
+++ b/module/icp/algs/blake3/blake3_generic.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,6 +25,7 @@
* Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
+#include <sys/simd.h>
#include <sys/zfs_context.h>
#include "blake3_impl.h"
@@ -187,16 +188,17 @@ static inline void blake3_hash_many_generic(const uint8_t * const *inputs,
}
}
-static inline boolean_t blake3_is_generic_supported(void)
+/* the generic implementation is always okay */
+static boolean_t blake3_is_supported(void)
{
return (B_TRUE);
}
-const blake3_impl_ops_t blake3_generic_impl = {
+const blake3_ops_t blake3_generic_impl = {
.compress_in_place = blake3_compress_in_place_generic,
.compress_xof = blake3_compress_xof_generic,
.hash_many = blake3_hash_many_generic,
- .is_supported = blake3_is_generic_supported,
+ .is_supported = blake3_is_supported,
.degree = 4,
.name = "generic"
};
diff --git a/module/icp/algs/blake3/blake3_impl.c b/module/icp/algs/blake3/blake3_impl.c
index c3809a2827be..f3f48c2dfa1a 100644
--- a/module/icp/algs/blake3/blake3_impl.c
+++ b/module/icp/algs/blake3/blake3_impl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,185 +23,267 @@
* Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
+#include <sys/simd.h>
#include <sys/zfs_context.h>
-#include <sys/zio_checksum.h>
+#include <sys/zfs_impl.h>
+#include <sys/blake3.h>
#include "blake3_impl.h"
-static const blake3_impl_ops_t *const blake3_impls[] = {
- &blake3_generic_impl,
#if defined(__aarch64__) || \
(defined(__x86_64) && defined(HAVE_SSE2)) || \
(defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
- &blake3_sse2_impl,
-#endif
-#if defined(__aarch64__) || \
- (defined(__x86_64) && defined(HAVE_SSE4_1)) || \
- (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
- &blake3_sse41_impl,
-#endif
-#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
- &blake3_avx2_impl,
-#endif
-#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
- &blake3_avx512_impl,
-#endif
-};
-
-/* this pointer holds current ops for implementation */
-static const blake3_impl_ops_t *blake3_selected_impl = &blake3_generic_impl;
-
-/* special implementation selections */
-#define IMPL_FASTEST (UINT32_MAX)
-#define IMPL_CYCLE (UINT32_MAX-1)
-#define IMPL_USER (UINT32_MAX-2)
-#define IMPL_PARAM (UINT32_MAX-3)
-
-#define IMPL_READ(i) (*(volatile uint32_t *) &(i))
-static uint32_t icp_blake3_impl = IMPL_FASTEST;
-#define BLAKE3_IMPL_NAME_MAX 16
-
-/* id of fastest implementation */
-static uint32_t blake3_fastest_id = 0;
+extern void ASMABI zfs_blake3_compress_in_place_sse2(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags);
+
+extern void ASMABI zfs_blake3_compress_xof_sse2(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]);
+
+extern void ASMABI zfs_blake3_hash_many_sse2(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out);
+
+static void blake3_compress_in_place_sse2(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags) {
+ kfpu_begin();
+ zfs_blake3_compress_in_place_sse2(cv, block, block_len, counter,
+ flags);
+ kfpu_end();
+}
-/* currently used id */
-static uint32_t blake3_current_id = 0;
+static void blake3_compress_xof_sse2(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]) {
+ kfpu_begin();
+ zfs_blake3_compress_xof_sse2(cv, block, block_len, counter, flags,
+ out);
+ kfpu_end();
+}
-/* id of module parameter (-1 == unused) */
-static int blake3_param_id = -1;
+static void blake3_hash_many_sse2(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
+ kfpu_begin();
+ zfs_blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter,
+ increment_counter, flags, flags_start, flags_end, out);
+ kfpu_end();
+}
-/* return number of supported implementations */
-int
-blake3_get_impl_count(void)
+static boolean_t blake3_is_sse2_supported(void)
{
- static int impls = 0;
- int i;
+#if defined(__x86_64)
+ return (kfpu_allowed() && zfs_sse2_available());
+#elif defined(__PPC64__)
+ return (kfpu_allowed() && zfs_vsx_available());
+#else
+ return (kfpu_allowed());
+#endif
+}
- if (impls)
- return (impls);
+const blake3_ops_t blake3_sse2_impl = {
+ .compress_in_place = blake3_compress_in_place_sse2,
+ .compress_xof = blake3_compress_xof_sse2,
+ .hash_many = blake3_hash_many_sse2,
+ .is_supported = blake3_is_sse2_supported,
+ .degree = 4,
+ .name = "sse2"
+};
+#endif
- for (i = 0; i < ARRAY_SIZE(blake3_impls); i++) {
- if (!blake3_impls[i]->is_supported()) continue;
- impls++;
- }
+#if defined(__aarch64__) || \
+ (defined(__x86_64) && defined(HAVE_SSE2)) || \
+ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
- return (impls);
+extern void ASMABI zfs_blake3_compress_in_place_sse41(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags);
+
+extern void ASMABI zfs_blake3_compress_xof_sse41(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]);
+
+extern void ASMABI zfs_blake3_hash_many_sse41(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out);
+
+static void blake3_compress_in_place_sse41(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags) {
+ kfpu_begin();
+ zfs_blake3_compress_in_place_sse41(cv, block, block_len, counter,
+ flags);
+ kfpu_end();
}
-/* return id of selected implementation */
-int
-blake3_get_impl_id(void)
-{
- return (blake3_current_id);
+static void blake3_compress_xof_sse41(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]) {
+ kfpu_begin();
+ zfs_blake3_compress_xof_sse41(cv, block, block_len, counter, flags,
+ out);
+ kfpu_end();
}
-/* return name of selected implementation */
-const char *
-blake3_get_impl_name(void)
-{
- return (blake3_selected_impl->name);
+static void blake3_hash_many_sse41(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
+ kfpu_begin();
+ zfs_blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter,
+ increment_counter, flags, flags_start, flags_end, out);
+ kfpu_end();
}
-/* setup id as fastest implementation */
-void
-blake3_set_impl_fastest(uint32_t id)
+static boolean_t blake3_is_sse41_supported(void)
{
- blake3_fastest_id = id;
+#if defined(__x86_64)
+ return (kfpu_allowed() && zfs_sse4_1_available());
+#elif defined(__PPC64__)
+ return (kfpu_allowed() && zfs_vsx_available());
+#else
+ return (kfpu_allowed());
+#endif
}
-/* set implementation by id */
-void
-blake3_set_impl_id(uint32_t id)
-{
- int i, cid;
-
- /* select fastest */
- if (id == IMPL_FASTEST)
- id = blake3_fastest_id;
-
- /* select next or first */
- if (id == IMPL_CYCLE)
- id = (++blake3_current_id) % blake3_get_impl_count();
-
- /* 0..N for the real impl */
- for (i = 0, cid = 0; i < ARRAY_SIZE(blake3_impls); i++) {
- if (!blake3_impls[i]->is_supported()) continue;
- if (cid == id) {
- blake3_current_id = cid;
- blake3_selected_impl = blake3_impls[i];
- return;
- }
- cid++;
- }
+const blake3_ops_t blake3_sse41_impl = {
+ .compress_in_place = blake3_compress_in_place_sse41,
+ .compress_xof = blake3_compress_xof_sse41,
+ .hash_many = blake3_hash_many_sse41,
+ .is_supported = blake3_is_sse41_supported,
+ .degree = 4,
+ .name = "sse41"
+};
+#endif
+
+#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
+extern void ASMABI zfs_blake3_hash_many_avx2(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out);
+
+static void blake3_hash_many_avx2(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
+ kfpu_begin();
+ zfs_blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter,
+ increment_counter, flags, flags_start, flags_end, out);
+ kfpu_end();
}
-/* set implementation by name */
-int
-blake3_set_impl_name(const char *name)
+static boolean_t blake3_is_avx2_supported(void)
{
- int i, cid;
-
- if (strcmp(name, "fastest") == 0) {
- atomic_swap_32(&icp_blake3_impl, IMPL_FASTEST);
- blake3_set_impl_id(IMPL_FASTEST);
- return (0);
- } else if (strcmp(name, "cycle") == 0) {
- atomic_swap_32(&icp_blake3_impl, IMPL_CYCLE);
- blake3_set_impl_id(IMPL_CYCLE);
- return (0);
- }
+ return (kfpu_allowed() && zfs_sse4_1_available() &&
+ zfs_avx2_available());
+}
- for (i = 0, cid = 0; i < ARRAY_SIZE(blake3_impls); i++) {
- if (!blake3_impls[i]->is_supported()) continue;
- if (strcmp(name, blake3_impls[i]->name) == 0) {
- if (icp_blake3_impl == IMPL_PARAM) {
- blake3_param_id = cid;
- return (0);
- }
- blake3_selected_impl = blake3_impls[i];
- blake3_current_id = cid;
- return (0);
- }
- cid++;
- }
+const blake3_ops_t
+blake3_avx2_impl = {
+ .compress_in_place = blake3_compress_in_place_sse41,
+ .compress_xof = blake3_compress_xof_sse41,
+ .hash_many = blake3_hash_many_avx2,
+ .is_supported = blake3_is_avx2_supported,
+ .degree = 8,
+ .name = "avx2"
+};
+#endif
- return (-EINVAL);
+#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
+extern void ASMABI zfs_blake3_compress_in_place_avx512(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags);
+
+extern void ASMABI zfs_blake3_compress_xof_avx512(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]);
+
+extern void ASMABI zfs_blake3_hash_many_avx512(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out);
+
+static void blake3_compress_in_place_avx512(uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags) {
+ kfpu_begin();
+ zfs_blake3_compress_in_place_avx512(cv, block, block_len, counter,
+ flags);
+ kfpu_end();
}
-/* setup implementation */
-void
-blake3_setup_impl(void)
-{
- switch (IMPL_READ(icp_blake3_impl)) {
- case IMPL_PARAM:
- blake3_set_impl_id(blake3_param_id);
- atomic_swap_32(&icp_blake3_impl, IMPL_USER);
- break;
- case IMPL_FASTEST:
- blake3_set_impl_id(IMPL_FASTEST);
- break;
- case IMPL_CYCLE:
- blake3_set_impl_id(IMPL_CYCLE);
- break;
- default:
- blake3_set_impl_id(blake3_current_id);
- break;
- }
+static void blake3_compress_xof_avx512(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
+ uint64_t counter, uint8_t flags, uint8_t out[64]) {
+ kfpu_begin();
+ zfs_blake3_compress_xof_avx512(cv, block, block_len, counter, flags,
+ out);
+ kfpu_end();
}
-/* return selected implementation */
-const blake3_impl_ops_t *
-blake3_impl_get_ops(void)
-{
- /* each call to ops will cycle */
- if (icp_blake3_impl == IMPL_CYCLE)
- blake3_set_impl_id(IMPL_CYCLE);
+static void blake3_hash_many_avx512(const uint8_t * const *inputs,
+ size_t num_inputs, size_t blocks, const uint32_t key[8],
+ uint64_t counter, boolean_t increment_counter, uint8_t flags,
+ uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
+ kfpu_begin();
+ zfs_blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter,
+ increment_counter, flags, flags_start, flags_end, out);
+ kfpu_end();
+}
- return (blake3_selected_impl);
+static boolean_t blake3_is_avx512_supported(void)
+{
+ return (kfpu_allowed() && zfs_avx512f_available() &&
+ zfs_avx512vl_available());
}
-#if defined(_KERNEL)
+const blake3_ops_t blake3_avx512_impl = {
+ .compress_in_place = blake3_compress_in_place_avx512,
+ .compress_xof = blake3_compress_xof_avx512,
+ .hash_many = blake3_hash_many_avx512,
+ .is_supported = blake3_is_avx512_supported,
+ .degree = 16,
+ .name = "avx512"
+};
+#endif
+
+extern const blake3_ops_t blake3_generic_impl;
+
+static const blake3_ops_t *const blake3_impls[] = {
+ &blake3_generic_impl,
+#if defined(__aarch64__) || \
+ (defined(__x86_64) && defined(HAVE_SSE2)) || \
+ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+ &blake3_sse2_impl,
+#endif
+#if defined(__aarch64__) || \
+ (defined(__x86_64) && defined(HAVE_SSE4_1)) || \
+ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+ &blake3_sse41_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
+ &blake3_avx2_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
+ &blake3_avx512_impl,
+#endif
+};
+
+/* use the generic implementation functions */
+#define IMPL_NAME "blake3"
+#define IMPL_OPS_T blake3_ops_t
+#define IMPL_ARRAY blake3_impls
+#define IMPL_GET_OPS blake3_get_ops
+#define ZFS_IMPL_OPS zfs_blake3_ops
+#include <generic_impl.c>
+
+#ifdef _KERNEL
void **blake3_per_cpu_ctx;
void
@@ -227,58 +309,96 @@ blake3_per_cpu_ctx_fini(void)
memset(blake3_per_cpu_ctx, 0, max_ncpus * sizeof (void *));
kmem_free(blake3_per_cpu_ctx, max_ncpus * sizeof (void *));
}
-#endif
-#if defined(_KERNEL) && defined(__linux__)
+#define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")
+
+#if defined(__linux__)
+
static int
-icp_blake3_impl_set(const char *name, zfs_kernel_param_t *kp)
+blake3_param_get(char *buffer, zfs_kernel_param_t *unused)
{
- char req_name[BLAKE3_IMPL_NAME_MAX];
- size_t i;
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ char *fmt;
+ int cnt = 0;
- /* sanitize input */
- i = strnlen(name, BLAKE3_IMPL_NAME_MAX);
- if (i == 0 || i >= BLAKE3_IMPL_NAME_MAX)
- return (-EINVAL);
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, "fastest");
+
+ /* list all supported implementations */
+ generic_impl_init();
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ blake3_impls[i]->name);
+ }
- strlcpy(req_name, name, BLAKE3_IMPL_NAME_MAX);
- while (i > 0 && isspace(req_name[i-1]))
- i--;
- req_name[i] = '\0';
+ return (cnt);
+}
- atomic_swap_32(&icp_blake3_impl, IMPL_PARAM);
- return (blake3_set_impl_name(req_name));
+static int
+blake3_param_set(const char *val, zfs_kernel_param_t *unused)
+{
+ (void) unused;
+ return (generic_impl_setname(val));
}
+#elif defined(__FreeBSD__)
+
+#include <sys/sbuf.h>
+
static int
-icp_blake3_impl_get(char *buffer, zfs_kernel_param_t *kp)
+blake3_param(ZFS_MODULE_PARAM_ARGS)
{
- int i, cid, cnt = 0;
- char *fmt;
+ int err;
- /* cycling */
- fmt = (icp_blake3_impl == IMPL_CYCLE) ? "[cycle] " : "cycle ";
- cnt += sprintf(buffer + cnt, fmt);
-
- /* fastest one */
- fmt = (icp_blake3_impl == IMPL_FASTEST) ? "[fastest] " : "fastest ";
- cnt += sprintf(buffer + cnt, fmt);
-
- /* user selected */
- for (i = 0, cid = 0; i < ARRAY_SIZE(blake3_impls); i++) {
- if (!blake3_impls[i]->is_supported()) continue;
- fmt = (icp_blake3_impl == IMPL_USER &&
- cid == blake3_current_id) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, blake3_impls[i]->name);
- cid++;
+ generic_impl_init();
+ if (req->newptr == NULL) {
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ const int init_buflen = 64;
+ const char *fmt;
+ struct sbuf *s;
+
+ s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);
+
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ (void) sbuf_printf(s, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ (void) sbuf_printf(s, fmt, "fastest");
+
+ /* list all supported implementations */
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ (void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);
+ }
+
+ err = sbuf_finish(s);
+ sbuf_delete(s);
+
+ return (err);
}
- buffer[cnt] = 0;
+ char buf[16];
- return (cnt);
+ err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (err) {
+ return (err);
+ }
+
+ return (-generic_impl_setname(buf));
}
+#endif
+
+#undef IMPL_FMT
-module_param_call(icp_blake3_impl, icp_blake3_impl_set, icp_blake3_impl_get,
- NULL, 0644);
-MODULE_PARM_DESC(icp_blake3_impl, "Select BLAKE3 implementation.");
+ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, blake3_impl,
+ blake3_param_set, blake3_param_get, ZMOD_RW, \
+ "Select BLAKE3 implementation.");
#endif
diff --git a/module/icp/algs/blake3/blake3_impl.h b/module/icp/algs/blake3/blake3_impl.h
index 7b40cc4d3f02..90d508fac08f 100644
--- a/module/icp/algs/blake3/blake3_impl.h
+++ b/module/icp/algs/blake3/blake3_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,16 +25,16 @@
* Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
-#ifndef BLAKE3_IMPL_H
+#ifndef BLAKE3_IMPL_H
#define BLAKE3_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
-#include <sys/types.h>
#include <sys/blake3.h>
#include <sys/simd.h>
+#include <sys/asm_linkage.h>
/*
* Methods used to define BLAKE3 assembler implementations
@@ -55,39 +55,17 @@ typedef void (*blake3_hash_many_f)(const uint8_t * const *inputs,
typedef boolean_t (*blake3_is_supported_f)(void);
-typedef struct blake3_impl_ops {
+typedef struct {
blake3_compress_in_place_f compress_in_place;
blake3_compress_xof_f compress_xof;
blake3_hash_many_f hash_many;
blake3_is_supported_f is_supported;
int degree;
const char *name;
-} blake3_impl_ops_t;
+} blake3_ops_t;
-/* Return selected BLAKE3 implementation ops */
-extern const blake3_impl_ops_t *blake3_impl_get_ops(void);
-
-extern const blake3_impl_ops_t blake3_generic_impl;
-
-#if defined(__aarch64__) || \
- (defined(__x86_64) && defined(HAVE_SSE2)) || \
- (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
-extern const blake3_impl_ops_t blake3_sse2_impl;
-#endif
-
-#if defined(__aarch64__) || \
- (defined(__x86_64) && defined(HAVE_SSE4_1)) || \
- (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
-extern const blake3_impl_ops_t blake3_sse41_impl;
-#endif
-
-#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
-extern const blake3_impl_ops_t blake3_avx2_impl;
-#endif
-
-#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
-extern const blake3_impl_ops_t blake3_avx512_impl;
-#endif
+/* return selected BLAKE3 implementation ops */
+extern const blake3_ops_t *blake3_get_ops(void);
#if defined(__x86_64)
#define MAX_SIMD_DEGREE 16
diff --git a/module/icp/algs/blake3/blake3_x86-64.c b/module/icp/algs/blake3/blake3_x86-64.c
deleted file mode 100644
index 48715e2128d2..000000000000
--- a/module/icp/algs/blake3/blake3_x86-64.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
- */
-
-#include "blake3_impl.h"
-
-#if defined(__aarch64__) || \
- (defined(__x86_64) && defined(HAVE_SSE2)) || \
- (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
-
-extern void zfs_blake3_compress_in_place_sse2(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags);
-
-extern void zfs_blake3_compress_xof_sse2(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]);
-
-extern void zfs_blake3_hash_many_sse2(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out);
-
-static void blake3_compress_in_place_sse2(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags) {
- kfpu_begin();
- zfs_blake3_compress_in_place_sse2(cv, block, block_len, counter,
- flags);
- kfpu_end();
-}
-
-static void blake3_compress_xof_sse2(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]) {
- kfpu_begin();
- zfs_blake3_compress_xof_sse2(cv, block, block_len, counter, flags,
- out);
- kfpu_end();
-}
-
-static void blake3_hash_many_sse2(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
- kfpu_begin();
- zfs_blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter,
- increment_counter, flags, flags_start, flags_end, out);
- kfpu_end();
-}
-
-static boolean_t blake3_is_sse2_supported(void)
-{
-#if defined(__x86_64)
- return (kfpu_allowed() && zfs_sse2_available());
-#elif defined(__PPC64__)
- return (kfpu_allowed() && zfs_vsx_available());
-#else
- return (kfpu_allowed());
-#endif
-}
-
-const blake3_impl_ops_t blake3_sse2_impl = {
- .compress_in_place = blake3_compress_in_place_sse2,
- .compress_xof = blake3_compress_xof_sse2,
- .hash_many = blake3_hash_many_sse2,
- .is_supported = blake3_is_sse2_supported,
- .degree = 4,
- .name = "sse2"
-};
-#endif
-
-#if defined(__aarch64__) || \
- (defined(__x86_64) && defined(HAVE_SSE2)) || \
- (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
-
-extern void zfs_blake3_compress_in_place_sse41(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags);
-
-extern void zfs_blake3_compress_xof_sse41(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]);
-
-extern void zfs_blake3_hash_many_sse41(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out);
-
-static void blake3_compress_in_place_sse41(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags) {
- kfpu_begin();
- zfs_blake3_compress_in_place_sse41(cv, block, block_len, counter,
- flags);
- kfpu_end();
-}
-
-static void blake3_compress_xof_sse41(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]) {
- kfpu_begin();
- zfs_blake3_compress_xof_sse41(cv, block, block_len, counter, flags,
- out);
- kfpu_end();
-}
-
-static void blake3_hash_many_sse41(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
- kfpu_begin();
- zfs_blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter,
- increment_counter, flags, flags_start, flags_end, out);
- kfpu_end();
-}
-
-static boolean_t blake3_is_sse41_supported(void)
-{
-#if defined(__x86_64)
- return (kfpu_allowed() && zfs_sse4_1_available());
-#elif defined(__PPC64__)
- return (kfpu_allowed() && zfs_vsx_available());
-#else
- return (kfpu_allowed());
-#endif
-}
-
-const blake3_impl_ops_t blake3_sse41_impl = {
- .compress_in_place = blake3_compress_in_place_sse41,
- .compress_xof = blake3_compress_xof_sse41,
- .hash_many = blake3_hash_many_sse41,
- .is_supported = blake3_is_sse41_supported,
- .degree = 4,
- .name = "sse41"
-};
-#endif
-
-#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2)
-extern void zfs_blake3_hash_many_avx2(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out);
-
-static void blake3_hash_many_avx2(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
- kfpu_begin();
- zfs_blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter,
- increment_counter, flags, flags_start, flags_end, out);
- kfpu_end();
-}
-
-static boolean_t blake3_is_avx2_supported(void)
-{
- return (kfpu_allowed() && zfs_sse4_1_available() &&
- zfs_avx2_available());
-}
-
-const blake3_impl_ops_t blake3_avx2_impl = {
- .compress_in_place = blake3_compress_in_place_sse41,
- .compress_xof = blake3_compress_xof_sse41,
- .hash_many = blake3_hash_many_avx2,
- .is_supported = blake3_is_avx2_supported,
- .degree = 8,
- .name = "avx2"
-};
-#endif
-
-#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL)
-extern void zfs_blake3_compress_in_place_avx512(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags);
-
-extern void zfs_blake3_compress_xof_avx512(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]);
-
-extern void zfs_blake3_hash_many_avx512(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out);
-
-static void blake3_compress_in_place_avx512(uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags) {
- kfpu_begin();
- zfs_blake3_compress_in_place_avx512(cv, block, block_len, counter,
- flags);
- kfpu_end();
-}
-
-static void blake3_compress_xof_avx512(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len,
- uint64_t counter, uint8_t flags, uint8_t out[64]) {
- kfpu_begin();
- zfs_blake3_compress_xof_avx512(cv, block, block_len, counter, flags,
- out);
- kfpu_end();
-}
-
-static void blake3_hash_many_avx512(const uint8_t * const *inputs,
- size_t num_inputs, size_t blocks, const uint32_t key[8],
- uint64_t counter, boolean_t increment_counter, uint8_t flags,
- uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
- kfpu_begin();
- zfs_blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter,
- increment_counter, flags, flags_start, flags_end, out);
- kfpu_end();
-}
-
-static boolean_t blake3_is_avx512_supported(void)
-{
- return (kfpu_allowed() && zfs_avx512f_available() &&
- zfs_avx512vl_available());
-}
-
-const blake3_impl_ops_t blake3_avx512_impl = {
- .compress_in_place = blake3_compress_in_place_avx512,
- .compress_xof = blake3_compress_xof_avx512,
- .hash_many = blake3_hash_many_avx512,
- .is_supported = blake3_is_avx512_supported,
- .degree = 16,
- .name = "avx512"
-};
-#endif
diff --git a/module/icp/algs/edonr/edonr.c b/module/icp/algs/edonr/edonr.c
index 345133d7433a..d17a40cefcb8 100644
--- a/module/icp/algs/edonr/edonr.c
+++ b/module/icp/algs/edonr/edonr.c
@@ -1,6 +1,4 @@
/*
- * IDI,NTNU
- *
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
@@ -19,75 +17,44 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
- *
- * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no>
- * Tweaked Edon-R implementation for SUPERCOP, based on NIST API.
- *
- * $Id: edonr.c 517 2013-02-17 20:34:39Z joern $
- */
-/*
- * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved
*/
/*
- * Unlike sha2 or skein, we won't expose edonr via the Kernel Cryptographic
- * Framework (KCF), because Edon-R is *NOT* suitable for general-purpose
- * cryptographic use. Users of Edon-R must interface directly to this module.
+ * Based on Edon-R implementation for SUPERCOP, based on NIST API.
+ * Copyright (c) 2009, 2010, Jørn Amundsen <jorn.amundsen@ntnu.no>
+ * Copyright (c) 2013 Saso Kiselkov, All rights reserved
+ * Copyright (c) 2023 Tino Reichardt <milky-zfs@mcmilk.de>
*/
+#include <sys/zfs_context.h>
#include <sys/string.h>
#include <sys/edonr.h>
-#include <sys/debug.h>
-
-/* big endian support, provides no-op's if run on little endian hosts */
-#include "edonr_byteorder.h"
-
-#define hashState224(x) ((x)->pipe->p256)
-#define hashState256(x) ((x)->pipe->p256)
-#define hashState384(x) ((x)->pipe->p512)
-#define hashState512(x) ((x)->pipe->p512)
-
-/* rotate shortcuts */
-#define rotl32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-#define rotr32(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
-#define rotl64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
-#define rotr64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
-
-#if !defined(__C99_RESTRICT)
-#define restrict /* restrict */
+/*
+ * We need 1196 byte stack for Q512() on i386
+ * - we define this pragma to make gcc happy
+ */
+#if defined(__GNUC__) && defined(_ILP32)
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
#endif
-#define EDONR_VALID_HASHBITLEN(x) \
- ((x) == 512 || (x) == 384 || (x) == 256 || (x) == 224)
+/*
+ * Insert compiler memory barriers to reduce stack frame size.
+ */
+#define MEMORY_BARRIER asm volatile("" ::: "memory");
-/* EdonR224 initial double chaining pipe */
-static const uint32_t i224p2[16] = {
- 0x00010203ul, 0x04050607ul, 0x08090a0bul, 0x0c0d0e0ful,
- 0x10111213ul, 0x14151617ul, 0x18191a1bul, 0x1c1d1e1ful,
- 0x20212223ul, 0x24252627ul, 0x28292a2bul, 0x2c2d2e2ful,
- 0x30313233ul, 0x34353637ul, 0x38393a3bul, 0x3c3d3e3ful,
-};
+#if defined(_ZFS_BIG_ENDIAN)
+#define ld_swap64(s, d) (d = __builtin_bswap64(*(s)))
+#define st_swap64(s, d) (*(d) = __builtin_bswap64(s))
+#else
+#define ld_swap64(s, d) (d = *(s))
+#define st_swap64(s, d) (*(d) = s)
+#endif
-/* EdonR256 initial double chaining pipe */
-static const uint32_t i256p2[16] = {
- 0x40414243ul, 0x44454647ul, 0x48494a4bul, 0x4c4d4e4ful,
- 0x50515253ul, 0x54555657ul, 0x58595a5bul, 0x5c5d5e5ful,
- 0x60616263ul, 0x64656667ul, 0x68696a6bul, 0x6c6d6e6ful,
- 0x70717273ul, 0x74757677ul, 0x78797a7bul, 0x7c7d7e7ful,
-};
+#define hashState512(x) ((x)->pipe->p512)
-/* EdonR384 initial double chaining pipe */
-static const uint64_t i384p2[16] = {
- 0x0001020304050607ull, 0x08090a0b0c0d0e0full,
- 0x1011121314151617ull, 0x18191a1b1c1d1e1full,
- 0x2021222324252627ull, 0x28292a2b2c2d2e2full,
- 0x3031323334353637ull, 0x38393a3b3c3d3e3full,
- 0x4041424344454647ull, 0x48494a4b4c4d4e4full,
- 0x5051525354555657ull, 0x58595a5b5c5d5e5full,
- 0x6061626364656667ull, 0x68696a6b6c6d6e6full,
- 0x7071727374757677ull, 0x78797a7b7c7d7e7full
-};
+/* rotate shortcuts */
+#define rotl64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
/* EdonR512 initial double chaining pipe */
static const uint64_t i512p2[16] = {
@@ -101,294 +68,66 @@ static const uint64_t i512p2[16] = {
0xf0f1f2f3f4f5f6f7ull, 0xf8f9fafbfcfdfeffull
};
-/*
- * First Latin Square
- * 0 7 1 3 2 4 6 5
- * 4 1 7 6 3 0 5 2
- * 7 0 4 2 5 3 1 6
- * 1 4 0 5 6 2 7 3
- * 2 3 6 7 1 5 0 4
- * 5 2 3 1 7 6 4 0
- * 3 6 5 0 4 7 2 1
- * 6 5 2 4 0 1 3 7
- */
-#define LS1_256(c, x0, x1, x2, x3, x4, x5, x6, x7) \
-{ \
- uint32_t x04, x17, x23, x56, x07, x26; \
- x04 = x0+x4, x17 = x1+x7, x07 = x04+x17; \
- s0 = c + x07 + x2; \
- s1 = rotl32(x07 + x3, 4); \
- s2 = rotl32(x07 + x6, 8); \
- x23 = x2 + x3; \
- s5 = rotl32(x04 + x23 + x5, 22); \
- x56 = x5 + x6; \
- s6 = rotl32(x17 + x56 + x0, 24); \
- x26 = x23+x56; \
- s3 = rotl32(x26 + x7, 13); \
- s4 = rotl32(x26 + x1, 17); \
- s7 = rotl32(x26 + x4, 29); \
-}
-
-#define LS1_512(c, x0, x1, x2, x3, x4, x5, x6, x7) \
-{ \
- uint64_t x04, x17, x23, x56, x07, x26; \
- x04 = x0+x4, x17 = x1+x7, x07 = x04+x17; \
- s0 = c + x07 + x2; \
- s1 = rotl64(x07 + x3, 5); \
- s2 = rotl64(x07 + x6, 15); \
- x23 = x2 + x3; \
- s5 = rotl64(x04 + x23 + x5, 40); \
- x56 = x5 + x6; \
- s6 = rotl64(x17 + x56 + x0, 50); \
- x26 = x23+x56; \
- s3 = rotl64(x26 + x7, 22); \
- s4 = rotl64(x26 + x1, 31); \
- s7 = rotl64(x26 + x4, 59); \
-}
-
-/*
- * Second Orthogonal Latin Square
- * 0 4 2 3 1 6 5 7
- * 7 6 3 2 5 4 1 0
- * 5 3 1 6 0 2 7 4
- * 1 0 5 4 3 7 2 6
- * 2 1 0 7 4 5 6 3
- * 3 5 7 0 6 1 4 2
- * 4 7 6 1 2 0 3 5
- * 6 2 4 5 7 3 0 1
- */
-#define LS2_256(c, y0, y1, y2, y3, y4, y5, y6, y7) \
-{ \
- uint32_t y01, y25, y34, y67, y04, y05, y27, y37; \
- y01 = y0+y1, y25 = y2+y5, y05 = y01+y25; \
- t0 = ~c + y05 + y7; \
- t2 = rotl32(y05 + y3, 9); \
- y34 = y3+y4, y04 = y01+y34; \
- t1 = rotl32(y04 + y6, 5); \
- t4 = rotl32(y04 + y5, 15); \
- y67 = y6+y7, y37 = y34+y67; \
- t3 = rotl32(y37 + y2, 11); \
- t7 = rotl32(y37 + y0, 27); \
- y27 = y25+y67; \
- t5 = rotl32(y27 + y4, 20); \
- t6 = rotl32(y27 + y1, 25); \
-}
-
-#define LS2_512(c, y0, y1, y2, y3, y4, y5, y6, y7) \
-{ \
- uint64_t y01, y25, y34, y67, y04, y05, y27, y37; \
- y01 = y0+y1, y25 = y2+y5, y05 = y01+y25; \
- t0 = ~c + y05 + y7; \
- t2 = rotl64(y05 + y3, 19); \
- y34 = y3+y4, y04 = y01+y34; \
- t1 = rotl64(y04 + y6, 10); \
- t4 = rotl64(y04 + y5, 36); \
- y67 = y6+y7, y37 = y34+y67; \
- t3 = rotl64(y37 + y2, 29); \
- t7 = rotl64(y37 + y0, 55); \
- y27 = y25+y67; \
- t5 = rotl64(y27 + y4, 44); \
- t6 = rotl64(y27 + y1, 48); \
-}
-
-#define quasi_exform256(r0, r1, r2, r3, r4, r5, r6, r7) \
-{ \
- uint32_t s04, s17, s23, s56, t01, t25, t34, t67; \
- s04 = s0 ^ s4, t01 = t0 ^ t1; \
- r0 = (s04 ^ s1) + (t01 ^ t5); \
- t67 = t6 ^ t7; \
- r1 = (s04 ^ s7) + (t2 ^ t67); \
- s23 = s2 ^ s3; \
- r7 = (s23 ^ s5) + (t4 ^ t67); \
- t34 = t3 ^ t4; \
- r3 = (s23 ^ s4) + (t0 ^ t34); \
- s56 = s5 ^ s6; \
- r5 = (s3 ^ s56) + (t34 ^ t6); \
- t25 = t2 ^ t5; \
- r6 = (s2 ^ s56) + (t25 ^ t7); \
- s17 = s1 ^ s7; \
- r4 = (s0 ^ s17) + (t1 ^ t25); \
- r2 = (s17 ^ s6) + (t01 ^ t3); \
+#define LS1_512(x0, x1, x2, x3, x4, x5, x6, x7) \
+{ \
+ MEMORY_BARRIER \
+ z1 = x0 + x4, z2 = x1 + x7; z5 = z1 + z2; \
+ s0 = 0xaaaaaaaaaaaaaaaaull + z5 + x2; \
+ s1 = rotl64(z5 + x3, 5); \
+ s2 = rotl64(z5 + x6, 15); z3 = x2 + x3; \
+ s5 = rotl64(z1 + z3 + x5, 40); z4 = x5 + x6; \
+ s6 = rotl64(z2 + z4 + x0, 50); z6 = z3 + z4; \
+ s3 = rotl64(z6 + x7, 22); \
+ s4 = rotl64(z6 + x1, 31); \
+ s7 = rotl64(z6 + x4, 59); \
}
-#define quasi_exform512(r0, r1, r2, r3, r4, r5, r6, r7) \
-{ \
- uint64_t s04, s17, s23, s56, t01, t25, t34, t67; \
- s04 = s0 ^ s4, t01 = t0 ^ t1; \
- r0 = (s04 ^ s1) + (t01 ^ t5); \
- t67 = t6 ^ t7; \
- r1 = (s04 ^ s7) + (t2 ^ t67); \
- s23 = s2 ^ s3; \
- r7 = (s23 ^ s5) + (t4 ^ t67); \
- t34 = t3 ^ t4; \
- r3 = (s23 ^ s4) + (t0 ^ t34); \
- s56 = s5 ^ s6; \
- r5 = (s3 ^ s56) + (t34 ^ t6); \
- t25 = t2 ^ t5; \
- r6 = (s2 ^ s56) + (t25 ^ t7); \
- s17 = s1 ^ s7; \
- r4 = (s0 ^ s17) + (t1 ^ t25); \
- r2 = (s17 ^ s6) + (t01 ^ t3); \
+#define LS2_512(y0, y1, y2, y3, y4, y5, y6, y7) \
+{ \
+ z1 = y0 + y1, z2 = y2 + y5; z6 = z1 + z2; \
+ t0 = ~0xaaaaaaaaaaaaaaaaull + z6 + y7; \
+ t2 = rotl64(z6 + y3, 19); \
+ z3 = y3 + y4, z5 = z1 + z3; \
+ t1 = rotl64(z5 + y6, 10); \
+ t4 = rotl64(z5 + y5, 36); \
+ z4 = y6 + y7, z8 = z3 + z4; \
+ t3 = rotl64(z8 + y2, 29); \
+ t7 = rotl64(z8 + y0, 55); z7 = z2 + z4; \
+ t5 = rotl64(z7 + y4, 44); \
+ t6 = rotl64(z7 + y1, 48); \
}
-static size_t
-Q256(size_t bitlen, const uint32_t *data, uint32_t *restrict p)
-{
- size_t bl;
-
- for (bl = bitlen; bl >= EdonR256_BLOCK_BITSIZE;
- bl -= EdonR256_BLOCK_BITSIZE, data += 16) {
- uint32_t s0, s1, s2, s3, s4, s5, s6, s7, t0, t1, t2, t3, t4,
- t5, t6, t7;
- uint32_t p0, p1, p2, p3, p4, p5, p6, p7, q0, q1, q2, q3, q4,
- q5, q6, q7;
- const uint32_t defix = 0xaaaaaaaa;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint32_t swp0, swp1, swp2, swp3, swp4, swp5, swp6, swp7, swp8,
- swp9, swp10, swp11, swp12, swp13, swp14, swp15;
-#define d(j) swp ## j
-#define s32(j) ld_swap32((uint32_t *)data + j, swp ## j)
-#else
-#define d(j) data[j]
-#endif
-
- /* First row of quasigroup e-transformations */
-#if defined(MACHINE_IS_BIG_ENDIAN)
- s32(8);
- s32(9);
- s32(10);
- s32(11);
- s32(12);
- s32(13);
- s32(14);
- s32(15);
-#endif
- LS1_256(defix, d(15), d(14), d(13), d(12), d(11), d(10), d(9),
- d(8));
-#if defined(MACHINE_IS_BIG_ENDIAN)
- s32(0);
- s32(1);
- s32(2);
- s32(3);
- s32(4);
- s32(5);
- s32(6);
- s32(7);
-#undef s32
-#endif
- LS2_256(defix, d(0), d(1), d(2), d(3), d(4), d(5), d(6), d(7));
- quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7);
-
- LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_256(defix, d(8), d(9), d(10), d(11), d(12), d(13), d(14),
- d(15));
- quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7);
-
- /* Second row of quasigroup e-transformations */
- LS1_256(defix, p[8], p[9], p[10], p[11], p[12], p[13], p[14],
- p[15]);
- LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7);
-
- LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_256(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7);
-
- /* Third row of quasigroup e-transformations */
- LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_256(defix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
- quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7);
-
- LS1_256(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7);
-
- /* Fourth row of quasigroup e-transformations */
- LS1_256(defix, d(7), d(6), d(5), d(4), d(3), d(2), d(1), d(0));
- LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7);
-
- LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_256(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7);
-
- /* Edon-R tweak on the original SHA-3 Edon-R submission. */
- p[0] ^= d(8) ^ p0;
- p[1] ^= d(9) ^ p1;
- p[2] ^= d(10) ^ p2;
- p[3] ^= d(11) ^ p3;
- p[4] ^= d(12) ^ p4;
- p[5] ^= d(13) ^ p5;
- p[6] ^= d(14) ^ p6;
- p[7] ^= d(15) ^ p7;
- p[8] ^= d(0) ^ q0;
- p[9] ^= d(1) ^ q1;
- p[10] ^= d(2) ^ q2;
- p[11] ^= d(3) ^ q3;
- p[12] ^= d(4) ^ q4;
- p[13] ^= d(5) ^ q5;
- p[14] ^= d(6) ^ q6;
- p[15] ^= d(7) ^ q7;
- }
-
-#undef d
- return (bitlen - bl);
+#define QEF_512(r0, r1, r2, r3, r4, r5, r6, r7) \
+{ \
+ z1 = s0 ^ s4, z5 = t0 ^ t1; \
+ r0 = (z1 ^ s1) + (z5 ^ t5); z8 = t6 ^ t7; \
+ r1 = (z1 ^ s7) + (t2 ^ z8); z3 = s2 ^ s3; \
+ r7 = (z3 ^ s5) + (t4 ^ z8); z7 = t3 ^ t4; \
+ r3 = (z3 ^ s4) + (t0 ^ z7); z4 = s5 ^ s6; \
+ r5 = (s3 ^ z4) + (z7 ^ t6); z6 = t2 ^ t5; \
+ r6 = (s2 ^ z4) + (z6 ^ t7); z2 = s1 ^ s7; \
+ r4 = (s0 ^ z2) + (t1 ^ z6); \
+ r2 = (z2 ^ s6) + (z5 ^ t3); \
}
-/*
- * Why is this #pragma here?
- *
- * Checksum functions like this one can go over the stack frame size check
- * Linux imposes on 32-bit platforms (-Wframe-larger-than=1024). We can
- * safely ignore the compiler error since we know that in OpenZFS, that
- * the function will be called from a worker thread that won't be using
- * much stack. The only function that goes over the 1k limit is Q512(),
- * which only goes over it by a hair (1248 bytes on ARM32).
- */
-#include <sys/isa_defs.h> /* for _ILP32 */
-#ifdef _ILP32 /* We're 32-bit, assume small stack frames */
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
-#endif
-
-#if defined(__IBMC__) && defined(_AIX) && defined(__64BIT__)
static inline size_t
-#else
-static size_t
-#endif
-Q512(size_t bitlen, const uint64_t *data, uint64_t *restrict p)
+Q512(size_t bitlen, const uint64_t *data, uint64_t *p)
{
size_t bl;
for (bl = bitlen; bl >= EdonR512_BLOCK_BITSIZE;
bl -= EdonR512_BLOCK_BITSIZE, data += 16) {
- uint64_t s0, s1, s2, s3, s4, s5, s6, s7, t0, t1, t2, t3, t4,
- t5, t6, t7;
- uint64_t p0, p1, p2, p3, p4, p5, p6, p7, q0, q1, q2, q3, q4,
- q5, q6, q7;
- const uint64_t defix = 0xaaaaaaaaaaaaaaaaull;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint64_t swp0, swp1, swp2, swp3, swp4, swp5, swp6, swp7, swp8,
- swp9, swp10, swp11, swp12, swp13, swp14, swp15;
+ uint64_t q0, q1, q2, q3, q4, q5, q6, q7;
+ uint64_t p0, p1, p2, p3, p4, p5, p6, p7;
+ uint64_t s0, s1, s2, s3, s4, s5, s6, s7;
+ uint64_t t0, t1, t2, t3, t4, t5, t6, t7;
+ uint64_t z1, z2, z3, z4, z5, z6, z7, z8;
+
+#if defined(_ZFS_BIG_ENDIAN)
+ uint64_t swp0, swp1, swp2, swp3, swp4, swp5, swp6, swp7,
+ swp8, swp9, swp10, swp11, swp12, swp13, swp14, swp15;
#define d(j) swp##j
#define s64(j) ld_swap64((uint64_t *)data+j, swp##j)
-#else
-#define d(j) data[j]
-#endif
-
- /* First row of quasigroup e-transformations */
-#if defined(MACHINE_IS_BIG_ENDIAN)
- s64(8);
- s64(9);
- s64(10);
- s64(11);
- s64(12);
- s64(13);
- s64(14);
- s64(15);
-#endif
- LS1_512(defix, d(15), d(14), d(13), d(12), d(11), d(10), d(9),
- d(8));
-#if defined(MACHINE_IS_BIG_ENDIAN)
s64(0);
s64(1);
s64(2);
@@ -397,43 +136,53 @@ Q512(size_t bitlen, const uint64_t *data, uint64_t *restrict p)
s64(5);
s64(6);
s64(7);
-#undef s64
+ s64(8);
+ s64(9);
+ s64(10);
+ s64(11);
+ s64(12);
+ s64(13);
+ s64(14);
+ s64(15);
+#else
+#define d(j) data[j]
#endif
- LS2_512(defix, d(0), d(1), d(2), d(3), d(4), d(5), d(6), d(7));
- quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7);
- LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_512(defix, d(8), d(9), d(10), d(11), d(12), d(13), d(14),
- d(15));
- quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7);
+ /* First row of quasigroup e-transformations */
+ LS1_512(d(15), d(14), d(13), d(12), d(11), d(10), d(9), d(8));
+ LS2_512(d(0), d(1), d(2), d(3), d(4), d(5), d(6), d(7));
+ QEF_512(p0, p1, p2, p3, p4, p5, p6, p7);
+
+ LS1_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS2_512(d(8), d(9), d(10), d(11), d(12), d(13), d(14), d(15));
+ QEF_512(q0, q1, q2, q3, q4, q5, q6, q7);
/* Second row of quasigroup e-transformations */
- LS1_512(defix, p[8], p[9], p[10], p[11], p[12], p[13], p[14],
- p[15]);
- LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS1_512(p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+ LS2_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ QEF_512(p0, p1, p2, p3, p4, p5, p6, p7);
- LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_512(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7);
+ LS1_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS2_512(q0, q1, q2, q3, q4, q5, q6, q7);
+ QEF_512(q0, q1, q2, q3, q4, q5, q6, q7);
/* Third row of quasigroup e-transformations */
- LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_512(defix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
- quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS1_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS2_512(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ QEF_512(p0, p1, p2, p3, p4, p5, p6, p7);
- LS1_512(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7);
+ LS1_512(q0, q1, q2, q3, q4, q5, q6, q7);
+ LS2_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ QEF_512(q0, q1, q2, q3, q4, q5, q6, q7);
/* Fourth row of quasigroup e-transformations */
- LS1_512(defix, d(7), d(6), d(5), d(4), d(3), d(2), d(1), d(0));
- LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS1_512(d(7), d(6), d(5), d(4), d(3), d(2), d(1), d(0));
+ LS2_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ QEF_512(p0, p1, p2, p3, p4, p5, p6, p7);
- LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7);
- LS2_512(defix, q0, q1, q2, q3, q4, q5, q6, q7);
- quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7);
+ LS1_512(p0, p1, p2, p3, p4, p5, p6, p7);
+ LS2_512(q0, q1, q2, q3, q4, q5, q6, q7);
+ QEF_512(q0, q1, q2, q3, q4, q5, q6, q7);
/* Edon-R tweak on the original SHA-3 Edon-R submission. */
p[0] ^= d(8) ^ p0;
@@ -454,293 +203,115 @@ Q512(size_t bitlen, const uint64_t *data, uint64_t *restrict p)
p[15] ^= d(7) ^ q7;
}
+#undef s64
#undef d
return (bitlen - bl);
}
void
-EdonRInit(EdonRState *state, size_t hashbitlen)
+EdonRInit(EdonRState *state)
{
- ASSERT(EDONR_VALID_HASHBITLEN(hashbitlen));
- switch (hashbitlen) {
- case 224:
- state->hashbitlen = 224;
- state->bits_processed = 0;
- state->unprocessed_bits = 0;
- memcpy(hashState224(state)->DoublePipe, i224p2,
- sizeof (i224p2));
- break;
-
- case 256:
- state->hashbitlen = 256;
- state->bits_processed = 0;
- state->unprocessed_bits = 0;
- memcpy(hashState256(state)->DoublePipe, i256p2,
- sizeof (i256p2));
- break;
-
- case 384:
- state->hashbitlen = 384;
- state->bits_processed = 0;
- state->unprocessed_bits = 0;
- memcpy(hashState384(state)->DoublePipe, i384p2,
- sizeof (i384p2));
- break;
-
- case 512:
- state->hashbitlen = 512;
- state->bits_processed = 0;
- state->unprocessed_bits = 0;
- memcpy(hashState512(state)->DoublePipe, i512p2,
- sizeof (i512p2));
- break;
- }
+ state->bits_processed = 0;
+ state->unprocessed_bits = 0;
+ memcpy(hashState512(state)->DoublePipe, i512p2, sizeof (i512p2));
}
-
void
EdonRUpdate(EdonRState *state, const uint8_t *data, size_t databitlen)
{
- uint32_t *data32;
uint64_t *data64;
-
size_t bits_processed;
- ASSERT(EDONR_VALID_HASHBITLEN(state->hashbitlen));
- switch (state->hashbitlen) {
- case 224:
- case 256:
- if (state->unprocessed_bits > 0) {
- /* LastBytes = databitlen / 8 */
- int LastBytes = (int)databitlen >> 3;
-
- ASSERT(state->unprocessed_bits + databitlen <=
- EdonR256_BLOCK_SIZE * 8);
-
- memcpy(hashState256(state)->LastPart
- + (state->unprocessed_bits >> 3),
- data, LastBytes);
- state->unprocessed_bits += (int)databitlen;
- databitlen = state->unprocessed_bits;
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data32 = (uint32_t *)hashState256(state)->LastPart;
- } else
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data32 = (uint32_t *)data;
-
- bits_processed = Q256(databitlen, data32,
- hashState256(state)->DoublePipe);
- state->bits_processed += bits_processed;
- databitlen -= bits_processed;
- state->unprocessed_bits = (int)databitlen;
- if (databitlen > 0) {
- /* LastBytes = Ceil(databitlen / 8) */
- int LastBytes =
- ((~(((-(int)databitlen) >> 3) & 0x01ff)) +
- 1) & 0x01ff;
-
- data32 += bits_processed >> 5; /* byte size update */
- memmove(hashState256(state)->LastPart,
- data32, LastBytes);
- }
- break;
-
- case 384:
- case 512:
- if (state->unprocessed_bits > 0) {
- /* LastBytes = databitlen / 8 */
- int LastBytes = (int)databitlen >> 3;
-
- ASSERT(state->unprocessed_bits + databitlen <=
- EdonR512_BLOCK_SIZE * 8);
-
- memcpy(hashState512(state)->LastPart
- + (state->unprocessed_bits >> 3),
- data, LastBytes);
- state->unprocessed_bits += (int)databitlen;
- databitlen = state->unprocessed_bits;
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data64 = (uint64_t *)hashState512(state)->LastPart;
- } else
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data64 = (uint64_t *)data;
-
- bits_processed = Q512(databitlen, data64,
- hashState512(state)->DoublePipe);
- state->bits_processed += bits_processed;
- databitlen -= bits_processed;
- state->unprocessed_bits = (int)databitlen;
- if (databitlen > 0) {
- /* LastBytes = Ceil(databitlen / 8) */
- int LastBytes =
- ((~(((-(int)databitlen) >> 3) & 0x03ff)) +
- 1) & 0x03ff;
-
- data64 += bits_processed >> 6; /* byte size update */
- memmove(hashState512(state)->LastPart,
- data64, LastBytes);
- }
- break;
+ if (state->unprocessed_bits > 0) {
+ /* LastBytes = databitlen / 8 */
+ int LastBytes = (int)databitlen >> 3;
+
+ ASSERT(state->unprocessed_bits + databitlen <=
+ EdonR512_BLOCK_SIZE * 8);
+
+ memcpy(hashState512(state)->LastPart
+ + (state->unprocessed_bits >> 3), data, LastBytes);
+ state->unprocessed_bits += (int)databitlen;
+ databitlen = state->unprocessed_bits;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ data64 = (uint64_t *)hashState512(state)->LastPart;
+ } else
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ data64 = (uint64_t *)data;
+
+ bits_processed = Q512(databitlen, data64,
+ hashState512(state)->DoublePipe);
+ state->bits_processed += bits_processed;
+ databitlen -= bits_processed;
+ state->unprocessed_bits = (int)databitlen;
+ if (databitlen > 0) {
+ /* LastBytes = Ceil(databitlen / 8) */
+ int LastBytes = ((~(((-(int)databitlen) >> 3) & 0x03ff)) + 1) \
+ & 0x03ff;
+
+ data64 += bits_processed >> 6; /* byte size update */
+ memmove(hashState512(state)->LastPart, data64, LastBytes);
}
}
void
EdonRFinal(EdonRState *state, uint8_t *hashval)
{
- uint32_t *data32;
uint64_t *data64, num_bits;
-
size_t databitlen;
int LastByte, PadOnePosition;
num_bits = state->bits_processed + state->unprocessed_bits;
- ASSERT(EDONR_VALID_HASHBITLEN(state->hashbitlen));
- switch (state->hashbitlen) {
- case 224:
- case 256:
- LastByte = (int)state->unprocessed_bits >> 3;
- PadOnePosition = 7 - (state->unprocessed_bits & 0x07);
- hashState256(state)->LastPart[LastByte] =
- (hashState256(state)->LastPart[LastByte]
- & (0xff << (PadOnePosition + 1))) ^
- (0x01 << PadOnePosition);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data64 = (uint64_t *)hashState256(state)->LastPart;
-
- if (state->unprocessed_bits < 448) {
- (void) memset((hashState256(state)->LastPart) +
- LastByte + 1, 0x00,
- EdonR256_BLOCK_SIZE - LastByte - 9);
- databitlen = EdonR256_BLOCK_SIZE * 8;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- st_swap64(num_bits, data64 + 7);
+ LastByte = (int)state->unprocessed_bits >> 3;
+ PadOnePosition = 7 - (state->unprocessed_bits & 0x07);
+ hashState512(state)->LastPart[LastByte] =
+ (hashState512(state)->LastPart[LastByte] \
+ & (0xff << (PadOnePosition + 1))) ^ (0x01 << PadOnePosition);
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ data64 = (uint64_t *)hashState512(state)->LastPart;
+
+ if (state->unprocessed_bits < 960) {
+ memset((hashState512(state)->LastPart) +
+ LastByte + 1, 0x00, EdonR512_BLOCK_SIZE - LastByte - 9);
+ databitlen = EdonR512_BLOCK_SIZE * 8;
+#if defined(_ZFS_BIG_ENDIAN)
+ st_swap64(num_bits, data64 + 15);
#else
- data64[7] = num_bits;
+ data64[15] = num_bits;
#endif
- } else {
- (void) memset((hashState256(state)->LastPart) +
- LastByte + 1, 0x00,
- EdonR256_BLOCK_SIZE * 2 - LastByte - 9);
- databitlen = EdonR256_BLOCK_SIZE * 16;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- st_swap64(num_bits, data64 + 15);
+ } else {
+ memset((hashState512(state)->LastPart) + LastByte + 1,
+ 0x00, EdonR512_BLOCK_SIZE * 2 - LastByte - 9);
+ databitlen = EdonR512_BLOCK_SIZE * 16;
+#if defined(_ZFS_BIG_ENDIAN)
+ st_swap64(num_bits, data64 + 31);
#else
- data64[15] = num_bits;
+ data64[31] = num_bits;
#endif
- }
-
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data32 = (uint32_t *)hashState256(state)->LastPart;
- state->bits_processed += Q256(databitlen, data32,
- hashState256(state)->DoublePipe);
- break;
-
- case 384:
- case 512:
- LastByte = (int)state->unprocessed_bits >> 3;
- PadOnePosition = 7 - (state->unprocessed_bits & 0x07);
- hashState512(state)->LastPart[LastByte] =
- (hashState512(state)->LastPart[LastByte]
- & (0xff << (PadOnePosition + 1))) ^
- (0x01 << PadOnePosition);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- data64 = (uint64_t *)hashState512(state)->LastPart;
-
- if (state->unprocessed_bits < 960) {
- (void) memset((hashState512(state)->LastPart) +
- LastByte + 1, 0x00,
- EdonR512_BLOCK_SIZE - LastByte - 9);
- databitlen = EdonR512_BLOCK_SIZE * 8;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- st_swap64(num_bits, data64 + 15);
-#else
- data64[15] = num_bits;
-#endif
- } else {
- (void) memset((hashState512(state)->LastPart) +
- LastByte + 1, 0x00,
- EdonR512_BLOCK_SIZE * 2 - LastByte - 9);
- databitlen = EdonR512_BLOCK_SIZE * 16;
-#if defined(MACHINE_IS_BIG_ENDIAN)
- st_swap64(num_bits, data64 + 31);
-#else
- data64[31] = num_bits;
-#endif
- }
-
- state->bits_processed += Q512(databitlen, data64,
- hashState512(state)->DoublePipe);
- break;
}
- switch (state->hashbitlen) {
- case 224: {
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint32_t *d32 = (uint32_t *)hashval;
- uint32_t *s32 = hashState224(state)->DoublePipe + 9;
- int j;
+ state->bits_processed += Q512(databitlen, data64,
+ hashState512(state)->DoublePipe);
- for (j = 0; j < EdonR224_DIGEST_SIZE >> 2; j++)
- st_swap32(s32[j], d32 + j);
-#else
- memcpy(hashval, hashState256(state)->DoublePipe + 9,
- EdonR224_DIGEST_SIZE);
-#endif
- break;
- }
- case 256: {
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint32_t *d32 = (uint32_t *)hashval;
- uint32_t *s32 = hashState224(state)->DoublePipe + 8;
- int j;
-
- for (j = 0; j < EdonR256_DIGEST_SIZE >> 2; j++)
- st_swap32(s32[j], d32 + j);
-#else
- memcpy(hashval, hashState256(state)->DoublePipe + 8,
- EdonR256_DIGEST_SIZE);
-#endif
- break;
- }
- case 384: {
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint64_t *d64 = (uint64_t *)hashval;
- uint64_t *s64 = hashState384(state)->DoublePipe + 10;
- int j;
-
- for (j = 0; j < EdonR384_DIGEST_SIZE >> 3; j++)
- st_swap64(s64[j], d64 + j);
-#else
- memcpy(hashval, hashState384(state)->DoublePipe + 10,
- EdonR384_DIGEST_SIZE);
-#endif
- break;
- }
- case 512: {
-#if defined(MACHINE_IS_BIG_ENDIAN)
- uint64_t *d64 = (uint64_t *)hashval;
- uint64_t *s64 = hashState512(state)->DoublePipe + 8;
- int j;
-
- for (j = 0; j < EdonR512_DIGEST_SIZE >> 3; j++)
- st_swap64(s64[j], d64 + j);
+#if defined(_ZFS_BIG_ENDIAN)
+ data64 = (uint64_t *)hashval;
+ uint64_t *s64 = hashState512(state)->DoublePipe + 8;
+ int j;
+
+ for (j = 0; j < EdonR512_DIGEST_SIZE >> 3; j++)
+ st_swap64(s64[j], data64 + j);
#else
- memcpy(hashval, hashState512(state)->DoublePipe + 8,
- EdonR512_DIGEST_SIZE);
+ memcpy(hashval, hashState512(state)->DoublePipe + 8,
+ EdonR512_DIGEST_SIZE);
#endif
- break;
- }
- }
}
-
void
-EdonRHash(size_t hashbitlen, const uint8_t *data, size_t databitlen,
- uint8_t *hashval)
+EdonRHash(const uint8_t *data, size_t databitlen, uint8_t *hashval)
{
EdonRState state;
- EdonRInit(&state, hashbitlen);
+ EdonRInit(&state);
EdonRUpdate(&state, data, databitlen);
EdonRFinal(&state, hashval);
}
diff --git a/module/icp/algs/edonr/edonr_byteorder.h b/module/icp/algs/edonr/edonr_byteorder.h
deleted file mode 100644
index cd35e5e4c7c9..000000000000
--- a/module/icp/algs/edonr/edonr_byteorder.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * IDI,NTNU
- *
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://opensource.org/licenses/CDDL-1.0.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no>
- *
- * C header file to determine compile machine byte order. Take care when cross
- * compiling.
- *
- * $Id: byteorder.h 517 2013-02-17 20:34:39Z joern $
- */
-/*
- * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved
- */
-
-#ifndef _CRYPTO_EDONR_BYTEORDER_H
-#define _CRYPTO_EDONR_BYTEORDER_H
-
-#include <sys/sysmacros.h>
-#include <sys/param.h>
-
-#if defined(__BYTE_ORDER)
-#if (__BYTE_ORDER == __BIG_ENDIAN)
-#define MACHINE_IS_BIG_ENDIAN
-#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
-#define MACHINE_IS_LITTLE_ENDIAN
-#endif
-#elif defined(BYTE_ORDER)
-#if (BYTE_ORDER == BIG_ENDIAN)
-#define MACHINE_IS_BIG_ENDIAN
-#elif (BYTE_ORDER == LITTLE_ENDIAN)
-#define MACHINE_IS_LITTLE_ENDIAN
-#endif
-#endif /* __BYTE_ORDER || BYTE_ORDER */
-
-#if !defined(MACHINE_IS_BIG_ENDIAN) && !defined(MACHINE_IS_LITTLE_ENDIAN)
-#if defined(_ZFS_BIG_ENDIAN) || defined(_MIPSEB)
-#define MACHINE_IS_BIG_ENDIAN
-#endif
-#if defined(_ZFS_LITTLE_ENDIAN) || defined(_MIPSEL)
-#define MACHINE_IS_LITTLE_ENDIAN
-#endif
-#endif /* !MACHINE_IS_BIG_ENDIAN && !MACHINE_IS_LITTLE_ENDIAN */
-
-#if !defined(MACHINE_IS_BIG_ENDIAN) && !defined(MACHINE_IS_LITTLE_ENDIAN)
-#error unknown machine byte order
-#endif
-
-#define BYTEORDER_INCLUDED
-
-#if defined(MACHINE_IS_BIG_ENDIAN)
-/*
- * Byte swapping macros for big endian architectures and compilers,
- * add as appropriate for other architectures and/or compilers.
- *
- * ld_swap64(src,dst) : uint64_t dst = *(src)
- * st_swap64(src,dst) : *(dst) = uint64_t src
- */
-
-#if defined(__PPC__) || defined(_ARCH_PPC)
-
-#if defined(__64BIT__)
-#if defined(_ARCH_PWR7)
-#define aix_ld_swap64(s64, d64)\
- __asm__("ldbrx %0,0,%1" : "=r"(d64) : "r"(s64))
-#define aix_st_swap64(s64, d64)\
- __asm__ volatile("stdbrx %1,0,%0" : : "r"(d64), "r"(s64))
-#else
-#define aix_ld_swap64(s64, d64) \
-{ \
- uint64_t *s4 = 0, h; /* initialize to zero for gcc warning */ \
- \
- __asm__("addi %0,%3,4;lwbrx %1,0,%3;lwbrx %2,0,%0;rldimi %1,%2,32,0"\
- : "+r"(s4), "=r"(d64), "=r"(h) : "b"(s64)); \
-}
-
-#define aix_st_swap64(s64, d64) \
-{ \
- uint64_t *s4 = 0, h; /* initialize to zero for gcc warning */ \
- h = (s64) >> 32; \
- __asm__ volatile("addi %0,%3,4;stwbrx %1,0,%3;stwbrx %2,0,%0" \
- : "+r"(s4) : "r"(s64), "r"(h), "b"(d64)); \
-}
-#endif /* 64BIT && PWR7 */
-#else
-#define aix_ld_swap64(s64, d64) \
-{ \
- uint32_t *s4 = 0, h, l; /* initialize to zero for gcc warning */\
- __asm__("addi %0,%3,4;lwbrx %1,0,%3;lwbrx %2,0,%0" \
- : "+r"(s4), "=r"(l), "=r"(h) : "b"(s64)); \
- d64 = ((uint64_t)h<<32) | l; \
-}
-
-#define aix_st_swap64(s64, d64) \
-{ \
- uint32_t *s4 = 0, h, l; /* initialize to zero for gcc warning */\
- l = (s64) & 0xfffffffful, h = (s64) >> 32; \
- __asm__ volatile("addi %0,%3,4;stwbrx %1,0,%3;stwbrx %2,0,%0" \
- : "+r"(s4) : "r"(l), "r"(h), "b"(d64)); \
-}
-#endif /* __64BIT__ */
-#define aix_ld_swap32(s32, d32)\
- __asm__("lwbrx %0,0,%1" : "=r"(d32) : "r"(s32))
-#define aix_st_swap32(s32, d32)\
- __asm__ volatile("stwbrx %1,0,%0" : : "r"(d32), "r"(s32))
-#define ld_swap32(s, d) aix_ld_swap32(s, d)
-#define st_swap32(s, d) aix_st_swap32(s, d)
-#define ld_swap64(s, d) aix_ld_swap64(s, d)
-#define st_swap64(s, d) aix_st_swap64(s, d)
-#endif /* __PPC__ || _ARCH_PPC */
-
-#if defined(__sparc)
-#if !defined(__arch64__) && !defined(__sparcv8) && defined(__sparcv9)
-#define __arch64__
-#endif
-#if defined(__GNUC__) || (defined(__SUNPRO_C) && __SUNPRO_C > 0x590)
-/* need Sun Studio C 5.10 and above for GNU inline assembly */
-#if defined(__arch64__)
-#define sparc_ld_swap64(s64, d64) \
- __asm__("ldxa [%1]0x88,%0" : "=r"(d64) : "r"(s64))
-#define sparc_st_swap64(s64, d64) \
- __asm__ volatile("stxa %0,[%1]0x88" : : "r"(s64), "r"(d64))
-#define st_swap64(s, d) sparc_st_swap64(s, d)
-#else
-#define sparc_ld_swap64(s64, d64) \
-{ \
- uint32_t *s4, h, l; \
- __asm__("add %3,4,%0\n\tlda [%3]0x88,%1\n\tlda [%0]0x88,%2" \
- : "+r"(s4), "=r"(l), "=r"(h) : "r"(s64)); \
- d64 = ((uint64_t)h<<32) | l; \
-}
-#define sparc_st_swap64(s64, d64) \
-{ \
- uint32_t *s4, h, l; \
- l = (s64) & 0xfffffffful, h = (s64) >> 32; \
- __asm__ volatile("add %3,4,%0\n\tsta %1,[%3]0x88\n\tsta %2,[%0]0x88"\
- : "+r"(s4) : "r"(l), "r"(h), "r"(d64)); \
-}
-#endif /* sparc64 */
-#define sparc_ld_swap32(s32, d32)\
- __asm__("lda [%1]0x88,%0" : "=r"(d32) : "r"(s32))
-#define sparc_st_swap32(s32, d32)\
- __asm__ volatile("sta %0,[%1]0x88" : : "r"(s32), "r"(d32))
-#define ld_swap32(s, d) sparc_ld_swap32(s, d)
-#define st_swap32(s, d) sparc_st_swap32(s, d)
-#define ld_swap64(s, d) sparc_ld_swap64(s, d)
-#define st_swap64(s, d) sparc_st_swap64(s, d)
-#endif /* GCC || Sun Studio C > 5.9 */
-#endif /* sparc */
-
-/* GCC fallback */
-#if ((__GNUC__ >= 4) || defined(__PGIC__)) && !defined(ld_swap32)
-#define ld_swap32(s, d) (d = __builtin_bswap32(*(s)))
-#define st_swap32(s, d) (*(d) = __builtin_bswap32(s))
-#endif /* GCC4/PGIC && !swap32 */
-#if ((__GNUC__ >= 4) || defined(__PGIC__)) && !defined(ld_swap64)
-#define ld_swap64(s, d) (d = __builtin_bswap64(*(s)))
-#define st_swap64(s, d) (*(d) = __builtin_bswap64(s))
-#endif /* GCC4/PGIC && !swap64 */
-
-/* generic fallback */
-#if !defined(ld_swap32)
-#define ld_swap32(s, d) \
- (d = (*(s) >> 24) | (*(s) >> 8 & 0xff00) | \
- (*(s) << 8 & 0xff0000) | (*(s) << 24))
-#define st_swap32(s, d) \
- (*(d) = ((s) >> 24) | ((s) >> 8 & 0xff00) | \
- ((s) << 8 & 0xff0000) | ((s) << 24))
-#endif
-#if !defined(ld_swap64)
-#define ld_swap64(s, d) \
- (d = (*(s) >> 56) | (*(s) >> 40 & 0xff00) | \
- (*(s) >> 24 & 0xff0000) | (*(s) >> 8 & 0xff000000) | \
- (*(s) & 0xff000000) << 8 | (*(s) & 0xff0000) << 24 | \
- (*(s) & 0xff00) << 40 | *(s) << 56)
-#define st_swap64(s, d) \
- (*(d) = ((s) >> 56) | ((s) >> 40 & 0xff00) | \
- ((s) >> 24 & 0xff0000) | ((s) >> 8 & 0xff000000) | \
- ((s) & 0xff000000) << 8 | ((s) & 0xff0000) << 24 | \
- ((s) & 0xff00) << 40 | (s) << 56)
-#endif
-
-#endif /* MACHINE_IS_BIG_ENDIAN */
-
-
-#if defined(MACHINE_IS_LITTLE_ENDIAN)
-/* replace swaps with simple assignments on little endian systems */
-#undef ld_swap32
-#undef st_swap32
-#define ld_swap32(s, d) (d = *(s))
-#define st_swap32(s, d) (*(d) = s)
-#undef ld_swap64
-#undef st_swap64
-#define ld_swap64(s, d) (d = *(s))
-#define st_swap64(s, d) (*(d) = s)
-#endif /* MACHINE_IS_LITTLE_ENDIAN */
-
-#endif /* _CRYPTO_EDONR_BYTEORDER_H */
diff --git a/module/icp/algs/modes/cbc.c b/module/icp/algs/modes/cbc.c
index da3ff4e3595b..d0219fb24c49 100644
--- a/module/icp/algs/modes/cbc.c
+++ b/module/icp/algs/modes/cbc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/modes/ccm.c b/module/icp/algs/modes/ccm.c
index 9fde2684a7c4..1371676d6e68 100644
--- a/module/icp/algs/modes/ccm.c
+++ b/module/icp/algs/modes/ccm.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -67,7 +67,6 @@ ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
return (CRYPTO_SUCCESS);
}
- lastp = (uint8_t *)ctx->ccm_cb;
crypto_init_ptrs(out, &iov_or_mp, &offset);
mac_buf = (uint8_t *)ctx->ccm_mac_buf;
@@ -658,7 +657,7 @@ ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
memset(&(b0[1+nonceSize]), 0, q);
payloadSize = aes_ctx->ccm_data_len;
- limit = 8 < q ? 8 : q;
+ limit = MIN(8, q);
for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) {
b0[k] = (uint8_t)((payloadSize >> j) & 0xFF);
diff --git a/module/icp/algs/modes/ctr.c b/module/icp/algs/modes/ctr.c
index c31c6251624b..db6b1c71d5cd 100644
--- a/module/icp/algs/modes/ctr.c
+++ b/module/icp/algs/modes/ctr.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -60,7 +60,6 @@ ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
return (CRYPTO_SUCCESS);
}
- lastp = (uint8_t *)ctx->ctr_cb;
crypto_init_ptrs(out, &iov_or_mp, &offset);
do {
diff --git a/module/icp/algs/modes/ecb.c b/module/icp/algs/modes/ecb.c
index e0b8ab15cdcf..e2d8e71c161c 100644
--- a/module/icp/algs/modes/ecb.c
+++ b/module/icp/algs/modes/ecb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/modes/gcm.c b/module/icp/algs/modes/gcm.c
index e6a631c1a78e..dd8db6f97460 100644
--- a/module/icp/algs/modes/gcm.c
+++ b/module/icp/algs/modes/gcm.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,6 +23,7 @@
*/
#include <sys/zfs_context.h>
+#include <sys/cmn_err.h>
#include <modes/modes.h>
#include <sys/crypto/common.h>
#include <sys/crypto/icp.h>
@@ -49,6 +50,11 @@
static uint32_t icp_gcm_impl = IMPL_FASTEST;
static uint32_t user_sel_impl = IMPL_FASTEST;
+static inline int gcm_init_ctx_impl(boolean_t, gcm_ctx_t *, char *, size_t,
+ int (*)(const void *, const uint8_t *, uint8_t *),
+ void (*)(uint8_t *, uint8_t *),
+ void (*)(uint8_t *, uint8_t *));
+
#ifdef CAN_USE_GCM_ASM
/* Does the architecture we run on support the MOVBE instruction? */
boolean_t gcm_avx_can_use_movbe = B_FALSE;
@@ -59,7 +65,7 @@ boolean_t gcm_avx_can_use_movbe = B_FALSE;
static boolean_t gcm_use_avx = B_FALSE;
#define GCM_IMPL_USE_AVX (*(volatile boolean_t *)&gcm_use_avx)
-extern boolean_t atomic_toggle_boolean_nv(volatile boolean_t *);
+extern boolean_t ASMABI atomic_toggle_boolean_nv(volatile boolean_t *);
static inline boolean_t gcm_avx_will_work(void);
static inline void gcm_set_avx(boolean_t);
@@ -71,7 +77,7 @@ static int gcm_mode_encrypt_contiguous_blocks_avx(gcm_ctx_t *, char *, size_t,
static int gcm_encrypt_final_avx(gcm_ctx_t *, crypto_data_t *, size_t);
static int gcm_decrypt_final_avx(gcm_ctx_t *, crypto_data_t *, size_t);
-static int gcm_init_avx(gcm_ctx_t *, unsigned char *, size_t, unsigned char *,
+static int gcm_init_avx(gcm_ctx_t *, const uint8_t *, size_t, const uint8_t *,
size_t, size_t);
#endif /* ifdef CAN_USE_GCM_ASM */
@@ -118,7 +124,6 @@ gcm_mode_encrypt_contiguous_blocks(gcm_ctx_t *ctx, char *data, size_t length,
return (CRYPTO_SUCCESS);
}
- lastp = (uint8_t *)ctx->gcm_cb;
crypto_init_ptrs(out, &iov_or_mp, &offset);
gops = gcm_impl_get_ops();
@@ -479,7 +484,7 @@ gcm_validate_args(CK_AES_GCM_PARAMS *gcm_param)
}
static void
-gcm_format_initial_blocks(uchar_t *iv, ulong_t iv_len,
+gcm_format_initial_blocks(const uint8_t *iv, ulong_t iv_len,
gcm_ctx_t *ctx, size_t block_size,
void (*copy_block)(uint8_t *, uint8_t *),
void (*xor_block)(uint8_t *, uint8_t *))
@@ -528,8 +533,8 @@ gcm_format_initial_blocks(uchar_t *iv, ulong_t iv_len,
}
static int
-gcm_init(gcm_ctx_t *ctx, unsigned char *iv, size_t iv_len,
- unsigned char *auth_data, size_t auth_data_len, size_t block_size,
+gcm_init(gcm_ctx_t *ctx, const uint8_t *iv, size_t iv_len,
+ const uint8_t *auth_data, size_t auth_data_len, size_t block_size,
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
void (*copy_block)(uint8_t *, uint8_t *),
void (*xor_block)(uint8_t *, uint8_t *))
@@ -588,8 +593,6 @@ gcm_init(gcm_ctx_t *ctx, unsigned char *iv, size_t iv_len,
/*
* The following function is called at encrypt or decrypt init time
* for AES GCM mode.
- *
- * Init the GCM context struct. Handle the cycle and avx implementations here.
*/
int
gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
@@ -597,31 +600,75 @@ gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
void (*copy_block)(uint8_t *, uint8_t *),
void (*xor_block)(uint8_t *, uint8_t *))
{
- int rv;
+ return (gcm_init_ctx_impl(B_FALSE, gcm_ctx, param, block_size,
+ encrypt_block, copy_block, xor_block));
+}
+
+/*
+ * The following function is called at encrypt or decrypt init time
+ * for AES GMAC mode.
+ */
+int
+gmac_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
+ int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
+ void (*copy_block)(uint8_t *, uint8_t *),
+ void (*xor_block)(uint8_t *, uint8_t *))
+{
+ return (gcm_init_ctx_impl(B_TRUE, gcm_ctx, param, block_size,
+ encrypt_block, copy_block, xor_block));
+}
+
+/*
+ * Init the GCM context struct. Handle the cycle and avx implementations here.
+ * Initialization of a GMAC context differs slightly from a GCM context.
+ */
+static inline int
+gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
+ size_t block_size, int (*encrypt_block)(const void *, const uint8_t *,
+ uint8_t *), void (*copy_block)(uint8_t *, uint8_t *),
+ void (*xor_block)(uint8_t *, uint8_t *))
+{
CK_AES_GCM_PARAMS *gcm_param;
+ int rv = CRYPTO_SUCCESS;
+ size_t tag_len, iv_len;
if (param != NULL) {
gcm_param = (CK_AES_GCM_PARAMS *)(void *)param;
- if ((rv = gcm_validate_args(gcm_param)) != 0) {
- return (rv);
- }
+ if (gmac_mode == B_FALSE) {
+ /* GCM mode. */
+ if ((rv = gcm_validate_args(gcm_param)) != 0) {
+ return (rv);
+ }
+ gcm_ctx->gcm_flags |= GCM_MODE;
- gcm_ctx->gcm_tag_len = gcm_param->ulTagBits;
- gcm_ctx->gcm_tag_len >>= 3;
+ size_t tbits = gcm_param->ulTagBits;
+ tag_len = CRYPTO_BITS2BYTES(tbits);
+ iv_len = gcm_param->ulIvLen;
+ } else {
+ /* GMAC mode. */
+ gcm_ctx->gcm_flags |= GMAC_MODE;
+ tag_len = CRYPTO_BITS2BYTES(AES_GMAC_TAG_BITS);
+ iv_len = AES_GMAC_IV_LEN;
+ }
+ gcm_ctx->gcm_tag_len = tag_len;
gcm_ctx->gcm_processed_data_len = 0;
/* these values are in bits */
gcm_ctx->gcm_len_a_len_c[0]
= htonll(CRYPTO_BYTES2BITS(gcm_param->ulAADLen));
-
- rv = CRYPTO_SUCCESS;
- gcm_ctx->gcm_flags |= GCM_MODE;
} else {
return (CRYPTO_MECHANISM_PARAM_INVALID);
}
+ const uint8_t *iv = (const uint8_t *)gcm_param->pIv;
+ const uint8_t *aad = (const uint8_t *)gcm_param->pAAD;
+ size_t aad_len = gcm_param->ulAADLen;
+
#ifdef CAN_USE_GCM_ASM
+ boolean_t needs_bswap =
+ ((aes_key_t *)gcm_ctx->gcm_keysched)->ops->needs_byteswap;
+
if (GCM_IMPL_READ(icp_gcm_impl) != IMPL_CYCLE) {
gcm_ctx->gcm_use_avx = GCM_IMPL_USE_AVX;
} else {
@@ -630,96 +677,41 @@ gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
* non-avx contexts alternately.
*/
gcm_ctx->gcm_use_avx = gcm_toggle_avx();
- /*
- * We don't handle byte swapped key schedules in the avx
- * code path.
- */
- aes_key_t *ks = (aes_key_t *)gcm_ctx->gcm_keysched;
- if (ks->ops->needs_byteswap == B_TRUE) {
+
+ /* The avx impl. doesn't handle byte swapped key schedules. */
+ if (gcm_ctx->gcm_use_avx == B_TRUE && needs_bswap == B_TRUE) {
gcm_ctx->gcm_use_avx = B_FALSE;
}
- /* Use the MOVBE and the BSWAP variants alternately. */
- if (gcm_ctx->gcm_use_avx == B_TRUE &&
+ /*
+ * If this is a GCM context, use the MOVBE and the BSWAP
+ * variants alternately. GMAC contexts code paths do not
+ * use the MOVBE instruction.
+ */
+ if (gcm_ctx->gcm_use_avx == B_TRUE && gmac_mode == B_FALSE &&
zfs_movbe_available() == B_TRUE) {
(void) atomic_toggle_boolean_nv(
(volatile boolean_t *)&gcm_avx_can_use_movbe);
}
}
- /* Allocate Htab memory as needed. */
- if (gcm_ctx->gcm_use_avx == B_TRUE) {
- size_t htab_len = gcm_simd_get_htab_size(gcm_ctx->gcm_use_avx);
-
- if (htab_len == 0) {
- return (CRYPTO_MECHANISM_PARAM_INVALID);
- }
- gcm_ctx->gcm_htab_len = htab_len;
- gcm_ctx->gcm_Htable =
- (uint64_t *)kmem_alloc(htab_len, KM_SLEEP);
-
- if (gcm_ctx->gcm_Htable == NULL) {
- return (CRYPTO_HOST_MEMORY);
- }
- }
- /* Avx and non avx context initialization differs from here on. */
- if (gcm_ctx->gcm_use_avx == B_FALSE) {
-#endif /* ifdef CAN_USE_GCM_ASM */
- if (gcm_init(gcm_ctx, gcm_param->pIv, gcm_param->ulIvLen,
- gcm_param->pAAD, gcm_param->ulAADLen, block_size,
- encrypt_block, copy_block, xor_block) != 0) {
- rv = CRYPTO_MECHANISM_PARAM_INVALID;
- }
-#ifdef CAN_USE_GCM_ASM
- } else {
- if (gcm_init_avx(gcm_ctx, gcm_param->pIv, gcm_param->ulIvLen,
- gcm_param->pAAD, gcm_param->ulAADLen, block_size) != 0) {
- rv = CRYPTO_MECHANISM_PARAM_INVALID;
- }
- }
-#endif /* ifdef CAN_USE_GCM_ASM */
-
- return (rv);
-}
-
-int
-gmac_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
- int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
- void (*copy_block)(uint8_t *, uint8_t *),
- void (*xor_block)(uint8_t *, uint8_t *))
-{
- int rv;
- CK_AES_GMAC_PARAMS *gmac_param;
-
- if (param != NULL) {
- gmac_param = (CK_AES_GMAC_PARAMS *)(void *)param;
-
- gcm_ctx->gcm_tag_len = CRYPTO_BITS2BYTES(AES_GMAC_TAG_BITS);
- gcm_ctx->gcm_processed_data_len = 0;
-
- /* these values are in bits */
- gcm_ctx->gcm_len_a_len_c[0]
- = htonll(CRYPTO_BYTES2BITS(gmac_param->ulAADLen));
-
- rv = CRYPTO_SUCCESS;
- gcm_ctx->gcm_flags |= GMAC_MODE;
- } else {
- return (CRYPTO_MECHANISM_PARAM_INVALID);
- }
-
-#ifdef CAN_USE_GCM_ASM
/*
- * Handle the "cycle" implementation by creating avx and non avx
- * contexts alternately.
+ * We don't handle byte swapped key schedules in the avx code path,
+ * still they could be created by the aes generic implementation.
+ * Make sure not to use them since we'll corrupt data if we do.
*/
- if (GCM_IMPL_READ(icp_gcm_impl) != IMPL_CYCLE) {
- gcm_ctx->gcm_use_avx = GCM_IMPL_USE_AVX;
- } else {
- gcm_ctx->gcm_use_avx = gcm_toggle_avx();
- }
- /* We don't handle byte swapped key schedules in the avx code path. */
- aes_key_t *ks = (aes_key_t *)gcm_ctx->gcm_keysched;
- if (ks->ops->needs_byteswap == B_TRUE) {
+ if (gcm_ctx->gcm_use_avx == B_TRUE && needs_bswap == B_TRUE) {
gcm_ctx->gcm_use_avx = B_FALSE;
+
+ cmn_err_once(CE_WARN,
+ "ICP: Can't use the aes generic or cycle implementations "
+ "in combination with the gcm avx implementation!");
+ cmn_err_once(CE_WARN,
+ "ICP: Falling back to a compatible implementation, "
+ "aes-gcm performance will likely be degraded.");
+ cmn_err_once(CE_WARN,
+ "ICP: Choose at least the x86_64 aes implementation to "
+ "restore performance.");
}
+
/* Allocate Htab memory as needed. */
if (gcm_ctx->gcm_use_avx == B_TRUE) {
size_t htab_len = gcm_simd_get_htab_size(gcm_ctx->gcm_use_avx);
@@ -729,25 +721,23 @@ gmac_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
}
gcm_ctx->gcm_htab_len = htab_len;
gcm_ctx->gcm_Htable =
- (uint64_t *)kmem_alloc(htab_len, KM_SLEEP);
+ kmem_alloc(htab_len, KM_SLEEP);
if (gcm_ctx->gcm_Htable == NULL) {
return (CRYPTO_HOST_MEMORY);
}
}
-
/* Avx and non avx context initialization differs from here on. */
if (gcm_ctx->gcm_use_avx == B_FALSE) {
-#endif /* ifdef CAN_USE_GCM_ASM */
- if (gcm_init(gcm_ctx, gmac_param->pIv, AES_GMAC_IV_LEN,
- gmac_param->pAAD, gmac_param->ulAADLen, block_size,
- encrypt_block, copy_block, xor_block) != 0) {
+#endif /* ifdef CAN_USE_GCM_ASM */
+ if (gcm_init(gcm_ctx, iv, iv_len, aad, aad_len, block_size,
+ encrypt_block, copy_block, xor_block) != CRYPTO_SUCCESS) {
rv = CRYPTO_MECHANISM_PARAM_INVALID;
}
#ifdef CAN_USE_GCM_ASM
} else {
- if (gcm_init_avx(gcm_ctx, gmac_param->pIv, AES_GMAC_IV_LEN,
- gmac_param->pAAD, gmac_param->ulAADLen, block_size) != 0) {
+ if (gcm_init_avx(gcm_ctx, iv, iv_len, aad, aad_len,
+ block_size) != CRYPTO_SUCCESS) {
rv = CRYPTO_MECHANISM_PARAM_INVALID;
}
}
@@ -1021,13 +1011,15 @@ icp_gcm_impl_get(char *buffer, zfs_kernel_param_t *kp)
}
#endif
fmt = (impl == gcm_impl_opts[i].sel) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, gcm_impl_opts[i].name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ gcm_impl_opts[i].name);
}
/* list all supported implementations */
for (i = 0; i < gcm_supp_impl_cnt; i++) {
fmt = (i == impl) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, gcm_supp_impl[i]->name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ gcm_supp_impl[i]->name);
}
return (cnt);
@@ -1072,19 +1064,19 @@ MODULE_PARM_DESC(icp_gcm_impl, "Select gcm implementation.");
static uint32_t gcm_avx_chunk_size =
((32 * 1024) / GCM_AVX_MIN_DECRYPT_BYTES) * GCM_AVX_MIN_DECRYPT_BYTES;
-extern void clear_fpu_regs_avx(void);
-extern void gcm_xor_avx(const uint8_t *src, uint8_t *dst);
-extern void aes_encrypt_intel(const uint32_t rk[], int nr,
+extern void ASMABI clear_fpu_regs_avx(void);
+extern void ASMABI gcm_xor_avx(const uint8_t *src, uint8_t *dst);
+extern void ASMABI aes_encrypt_intel(const uint32_t rk[], int nr,
const uint32_t pt[4], uint32_t ct[4]);
-extern void gcm_init_htab_avx(uint64_t *Htable, const uint64_t H[2]);
-extern void gcm_ghash_avx(uint64_t ghash[2], const uint64_t *Htable,
+extern void ASMABI gcm_init_htab_avx(uint64_t *Htable, const uint64_t H[2]);
+extern void ASMABI gcm_ghash_avx(uint64_t ghash[2], const uint64_t *Htable,
const uint8_t *in, size_t len);
-extern size_t aesni_gcm_encrypt(const uint8_t *, uint8_t *, size_t,
+extern size_t ASMABI aesni_gcm_encrypt(const uint8_t *, uint8_t *, size_t,
const void *, uint64_t *, uint64_t *);
-extern size_t aesni_gcm_decrypt(const uint8_t *, uint8_t *, size_t,
+extern size_t ASMABI aesni_gcm_decrypt(const uint8_t *, uint8_t *, size_t,
const void *, uint64_t *, uint64_t *);
static inline boolean_t
@@ -1126,24 +1118,6 @@ gcm_simd_get_htab_size(boolean_t simd_mode)
}
}
-/*
- * Clear sensitive data in the context.
- *
- * ctx->gcm_remainder may contain a plaintext remainder. ctx->gcm_H and
- * ctx->gcm_Htable contain the hash sub key which protects authentication.
- *
- * Although extremely unlikely, ctx->gcm_J0 and ctx->gcm_tmp could be used for
- * a known plaintext attack, they consists of the IV and the first and last
- * counter respectively. If they should be cleared is debatable.
- */
-static inline void
-gcm_clear_ctx(gcm_ctx_t *ctx)
-{
- memset(ctx->gcm_remainder, 0, sizeof (ctx->gcm_remainder));
- memset(ctx->gcm_H, 0, sizeof (ctx->gcm_H));
- memset(ctx->gcm_J0, 0, sizeof (ctx->gcm_J0));
- memset(ctx->gcm_tmp, 0, sizeof (ctx->gcm_tmp));
-}
/* Increment the GCM counter block by n. */
static inline void
@@ -1179,6 +1153,8 @@ gcm_mode_encrypt_contiguous_blocks_avx(gcm_ctx_t *ctx, char *data,
int rv = CRYPTO_SUCCESS;
ASSERT(block_size == GCM_BLOCK_LEN);
+ ASSERT3S(((aes_key_t *)ctx->gcm_keysched)->ops->needs_byteswap, ==,
+ B_FALSE);
/*
* If the last call left an incomplete block, try to fill
* it first.
@@ -1323,6 +1299,8 @@ gcm_encrypt_final_avx(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size)
int rv;
ASSERT(block_size == GCM_BLOCK_LEN);
+ ASSERT3S(((aes_key_t *)ctx->gcm_keysched)->ops->needs_byteswap, ==,
+ B_FALSE);
if (out->cd_length < (rem_len + ctx->gcm_tag_len)) {
return (CRYPTO_DATA_LEN_RANGE);
@@ -1366,8 +1344,6 @@ gcm_encrypt_final_avx(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size)
return (rv);
out->cd_offset += ctx->gcm_tag_len;
- /* Clear sensitive data in the context before returning. */
- gcm_clear_ctx(ctx);
return (CRYPTO_SUCCESS);
}
@@ -1380,6 +1356,8 @@ gcm_decrypt_final_avx(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size)
{
ASSERT3U(ctx->gcm_processed_data_len, ==, ctx->gcm_pt_buf_len);
ASSERT3U(block_size, ==, 16);
+ ASSERT3S(((aes_key_t *)ctx->gcm_keysched)->ops->needs_byteswap, ==,
+ B_FALSE);
size_t chunk_size = (size_t)GCM_CHUNK_SIZE_READ;
size_t pt_len = ctx->gcm_processed_data_len - ctx->gcm_tag_len;
@@ -1477,7 +1455,6 @@ gcm_decrypt_final_avx(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size)
return (rv);
}
out->cd_offset += pt_len;
- gcm_clear_ctx(ctx);
return (CRYPTO_SUCCESS);
}
@@ -1486,18 +1463,20 @@ gcm_decrypt_final_avx(gcm_ctx_t *ctx, crypto_data_t *out, size_t block_size)
* initial counter block.
*/
static int
-gcm_init_avx(gcm_ctx_t *ctx, unsigned char *iv, size_t iv_len,
- unsigned char *auth_data, size_t auth_data_len, size_t block_size)
+gcm_init_avx(gcm_ctx_t *ctx, const uint8_t *iv, size_t iv_len,
+ const uint8_t *auth_data, size_t auth_data_len, size_t block_size)
{
uint8_t *cb = (uint8_t *)ctx->gcm_cb;
uint64_t *H = ctx->gcm_H;
const void *keysched = ((aes_key_t *)ctx->gcm_keysched)->encr_ks.ks32;
int aes_rounds = ((aes_key_t *)ctx->gcm_keysched)->nr;
- uint8_t *datap = auth_data;
+ const uint8_t *datap = auth_data;
size_t chunk_size = (size_t)GCM_CHUNK_SIZE_READ;
size_t bleft;
ASSERT(block_size == GCM_BLOCK_LEN);
+ ASSERT3S(((aes_key_t *)ctx->gcm_keysched)->ops->needs_byteswap, ==,
+ B_FALSE);
/* Init H (encrypt zero block) and create the initial counter block. */
memset(ctx->gcm_ghash, 0, sizeof (ctx->gcm_ghash));
diff --git a/module/icp/algs/modes/gcm_generic.c b/module/icp/algs/modes/gcm_generic.c
index 16b57998a92f..84e26d09cdcf 100644
--- a/module/icp/algs/modes/gcm_generic.c
+++ b/module/icp/algs/modes/gcm_generic.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/algs/modes/gcm_pclmulqdq.c b/module/icp/algs/modes/gcm_pclmulqdq.c
index 05920115ce86..737d2e47ecb7 100644
--- a/module/icp/algs/modes/gcm_pclmulqdq.c
+++ b/module/icp/algs/modes/gcm_pclmulqdq.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,9 +26,10 @@
#include <sys/types.h>
#include <sys/simd.h>
+#include <sys/asm_linkage.h>
/* These functions are used to execute pclmulqdq based assembly methods */
-extern void gcm_mul_pclmulqdq(uint64_t *, uint64_t *, uint64_t *);
+extern void ASMABI gcm_mul_pclmulqdq(uint64_t *, uint64_t *, uint64_t *);
#include <modes/gcm_impl.h>
diff --git a/module/icp/algs/modes/modes.c b/module/icp/algs/modes/modes.c
index d505de40ee2a..6f6649b3b58b 100644
--- a/module/icp/algs/modes/modes.c
+++ b/module/icp/algs/modes/modes.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -106,8 +106,10 @@ crypto_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset,
} else {
/* one block spans two iovecs */
*out_data_1_len = iov_len - offset;
- if (vec_idx == zfs_uio_iovcnt(uio))
+ if (vec_idx == zfs_uio_iovcnt(uio)) {
+ *out_data_2 = NULL;
return;
+ }
vec_idx++;
zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len);
*out_data_2 = (uint8_t *)iov_base;
@@ -148,18 +150,47 @@ crypto_free_mode_ctx(void *ctx)
case GCM_MODE:
case GMAC_MODE:
- if (((gcm_ctx_t *)ctx)->gcm_pt_buf != NULL)
- vmem_free(((gcm_ctx_t *)ctx)->gcm_pt_buf,
- ((gcm_ctx_t *)ctx)->gcm_pt_buf_len);
-
-#ifdef CAN_USE_GCM_ASM
- if (((gcm_ctx_t *)ctx)->gcm_Htable != NULL) {
- gcm_ctx_t *gcm_ctx = (gcm_ctx_t *)ctx;
- memset(gcm_ctx->gcm_Htable, 0, gcm_ctx->gcm_htab_len);
- kmem_free(gcm_ctx->gcm_Htable, gcm_ctx->gcm_htab_len);
- }
-#endif
-
+ gcm_clear_ctx((gcm_ctx_t *)ctx);
kmem_free(ctx, sizeof (gcm_ctx_t));
}
}
+
+static void *
+explicit_memset(void *s, int c, size_t n)
+{
+ memset(s, c, n);
+ __asm__ __volatile__("" :: "r"(s) : "memory");
+ return (s);
+}
+
+/*
+ * Clear sensitive data in the context and free allocated memory.
+ *
+ * ctx->gcm_remainder may contain a plaintext remainder. ctx->gcm_H and
+ * ctx->gcm_Htable contain the hash sub key which protects authentication.
+ * ctx->gcm_pt_buf contains the plaintext result of decryption.
+ *
+ * Although extremely unlikely, ctx->gcm_J0 and ctx->gcm_tmp could be used for
+ * a known plaintext attack, they consist of the IV and the first and last
+ * counter respectively. If they should be cleared is debatable.
+ */
+void
+gcm_clear_ctx(gcm_ctx_t *ctx)
+{
+ explicit_memset(ctx->gcm_remainder, 0, sizeof (ctx->gcm_remainder));
+ explicit_memset(ctx->gcm_H, 0, sizeof (ctx->gcm_H));
+#if defined(CAN_USE_GCM_ASM)
+ if (ctx->gcm_use_avx == B_TRUE) {
+ ASSERT3P(ctx->gcm_Htable, !=, NULL);
+ memset(ctx->gcm_Htable, 0, ctx->gcm_htab_len);
+ kmem_free(ctx->gcm_Htable, ctx->gcm_htab_len);
+ }
+#endif
+ if (ctx->gcm_pt_buf != NULL) {
+ memset(ctx->gcm_pt_buf, 0, ctx->gcm_pt_buf_len);
+ vmem_free(ctx->gcm_pt_buf, ctx->gcm_pt_buf_len);
+ }
+ /* Optional */
+ explicit_memset(ctx->gcm_J0, 0, sizeof (ctx->gcm_J0));
+ explicit_memset(ctx->gcm_tmp, 0, sizeof (ctx->gcm_tmp));
+}
diff --git a/module/icp/algs/sha2/sha2.c b/module/icp/algs/sha2/sha2.c
deleted file mode 100644
index 151432f1a5df..000000000000
--- a/module/icp/algs/sha2/sha2.c
+++ /dev/null
@@ -1,956 +0,0 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright 2013 Saso Kiselkov. All rights reserved.
- */
-
-/*
- * The basic framework for this code came from the reference
- * implementation for MD5. That implementation is Copyright (C)
- * 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
- *
- * License to copy and use this software is granted provided that it
- * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
- * Algorithm" in all material mentioning or referencing this software
- * or this function.
- *
- * License is also granted to make and use derivative works provided
- * that such works are identified as "derived from the RSA Data
- * Security, Inc. MD5 Message-Digest Algorithm" in all material
- * mentioning or referencing the derived work.
- *
- * RSA Data Security, Inc. makes no representations concerning either
- * the merchantability of this software or the suitability of this
- * software for any particular purpose. It is provided "as is"
- * without express or implied warranty of any kind.
- *
- * These notices must be retained in any copies of any part of this
- * documentation and/or software.
- *
- * NOTE: Cleaned-up and optimized, version of SHA2, based on the FIPS 180-2
- * standard, available at
- * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
- * Not as fast as one would like -- further optimizations are encouraged
- * and appreciated.
- */
-
-#include <sys/zfs_context.h>
-#define _SHA2_IMPL
-#include <sys/sha2.h>
-#include <sha2/sha2_consts.h>
-
-#define _RESTRICT_KYWD
-
-#ifdef _ZFS_LITTLE_ENDIAN
-#include <sys/byteorder.h>
-#define HAVE_HTONL
-#endif
-#include <sys/isa_defs.h> /* for _ILP32 */
-
-static void Encode(uint8_t *, uint32_t *, size_t);
-static void Encode64(uint8_t *, uint64_t *, size_t);
-
-/* userspace only supports the generic version */
-#if defined(__amd64) && defined(_KERNEL)
-#define SHA512Transform(ctx, in) SHA512TransformBlocks((ctx), (in), 1)
-#define SHA256Transform(ctx, in) SHA256TransformBlocks((ctx), (in), 1)
-
-void SHA512TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num);
-void SHA256TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num);
-
-#else
-static void SHA256Transform(SHA2_CTX *, const uint8_t *);
-static void SHA512Transform(SHA2_CTX *, const uint8_t *);
-#endif /* __amd64 && _KERNEL */
-
-static const uint8_t PADDING[128] = { 0x80, /* all zeros */ };
-
-/*
- * The low-level checksum routines use a lot of stack space. On systems where
- * small stacks are enforced (like 32-bit kernel builds), insert compiler memory
- * barriers to reduce stack frame size. This can reduce the SHA512Transform()
- * stack frame usage from 3k to <1k on ARM32, for example.
- */
-#if defined(_ILP32) || defined(__powerpc) /* small stack */
-#define SMALL_STACK_MEMORY_BARRIER asm volatile("": : :"memory");
-#else
-#define SMALL_STACK_MEMORY_BARRIER
-#endif
-
-/* Ch and Maj are the basic SHA2 functions. */
-#define Ch(b, c, d) (((b) & (c)) ^ ((~b) & (d)))
-#define Maj(b, c, d) (((b) & (c)) ^ ((b) & (d)) ^ ((c) & (d)))
-
-/* Rotates x right n bits. */
-#define ROTR(x, n) \
- (((x) >> (n)) | ((x) << ((sizeof (x) * NBBY)-(n))))
-
-/* Shift x right n bits */
-#define SHR(x, n) ((x) >> (n))
-
-/* SHA256 Functions */
-#define BIGSIGMA0_256(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22))
-#define BIGSIGMA1_256(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25))
-#define SIGMA0_256(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ SHR((x), 3))
-#define SIGMA1_256(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ SHR((x), 10))
-
-#define SHA256ROUND(a, b, c, d, e, f, g, h, i, w) \
- T1 = h + BIGSIGMA1_256(e) + Ch(e, f, g) + SHA256_CONST(i) + w; \
- d += T1; \
- T2 = BIGSIGMA0_256(a) + Maj(a, b, c); \
- h = T1 + T2
-
-/* SHA384/512 Functions */
-#define BIGSIGMA0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39))
-#define BIGSIGMA1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41))
-#define SIGMA0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ SHR((x), 7))
-#define SIGMA1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ SHR((x), 6))
-#define SHA512ROUND(a, b, c, d, e, f, g, h, i, w) \
- T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + SHA512_CONST(i) + w; \
- d += T1; \
- T2 = BIGSIGMA0(a) + Maj(a, b, c); \
- h = T1 + T2; \
- SMALL_STACK_MEMORY_BARRIER;
-
-/*
- * sparc optimization:
- *
- * on the sparc, we can load big endian 32-bit data easily. note that
- * special care must be taken to ensure the address is 32-bit aligned.
- * in the interest of speed, we don't check to make sure, since
- * careful programming can guarantee this for us.
- */
-
-#if defined(_ZFS_BIG_ENDIAN)
-#define LOAD_BIG_32(addr) (*(uint32_t *)(addr))
-#define LOAD_BIG_64(addr) (*(uint64_t *)(addr))
-
-#elif defined(HAVE_HTONL)
-#define LOAD_BIG_32(addr) htonl(*((uint32_t *)(addr)))
-#define LOAD_BIG_64(addr) htonll(*((uint64_t *)(addr)))
-
-#else
-/* little endian -- will work on big endian, but slowly */
-#define LOAD_BIG_32(addr) \
- (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3])
-#define LOAD_BIG_64(addr) \
- (((uint64_t)(addr)[0] << 56) | ((uint64_t)(addr)[1] << 48) | \
- ((uint64_t)(addr)[2] << 40) | ((uint64_t)(addr)[3] << 32) | \
- ((uint64_t)(addr)[4] << 24) | ((uint64_t)(addr)[5] << 16) | \
- ((uint64_t)(addr)[6] << 8) | (uint64_t)(addr)[7])
-#endif /* _BIG_ENDIAN */
-
-
-#if !defined(__amd64) || !defined(_KERNEL)
-/* SHA256 Transform */
-
-static void
-SHA256Transform(SHA2_CTX *ctx, const uint8_t *blk)
-{
- uint32_t a = ctx->state.s32[0];
- uint32_t b = ctx->state.s32[1];
- uint32_t c = ctx->state.s32[2];
- uint32_t d = ctx->state.s32[3];
- uint32_t e = ctx->state.s32[4];
- uint32_t f = ctx->state.s32[5];
- uint32_t g = ctx->state.s32[6];
- uint32_t h = ctx->state.s32[7];
-
- uint32_t w0, w1, w2, w3, w4, w5, w6, w7;
- uint32_t w8, w9, w10, w11, w12, w13, w14, w15;
- uint32_t T1, T2;
-
-#if defined(__sparc)
- static const uint32_t sha256_consts[] = {
- SHA256_CONST_0, SHA256_CONST_1, SHA256_CONST_2,
- SHA256_CONST_3, SHA256_CONST_4, SHA256_CONST_5,
- SHA256_CONST_6, SHA256_CONST_7, SHA256_CONST_8,
- SHA256_CONST_9, SHA256_CONST_10, SHA256_CONST_11,
- SHA256_CONST_12, SHA256_CONST_13, SHA256_CONST_14,
- SHA256_CONST_15, SHA256_CONST_16, SHA256_CONST_17,
- SHA256_CONST_18, SHA256_CONST_19, SHA256_CONST_20,
- SHA256_CONST_21, SHA256_CONST_22, SHA256_CONST_23,
- SHA256_CONST_24, SHA256_CONST_25, SHA256_CONST_26,
- SHA256_CONST_27, SHA256_CONST_28, SHA256_CONST_29,
- SHA256_CONST_30, SHA256_CONST_31, SHA256_CONST_32,
- SHA256_CONST_33, SHA256_CONST_34, SHA256_CONST_35,
- SHA256_CONST_36, SHA256_CONST_37, SHA256_CONST_38,
- SHA256_CONST_39, SHA256_CONST_40, SHA256_CONST_41,
- SHA256_CONST_42, SHA256_CONST_43, SHA256_CONST_44,
- SHA256_CONST_45, SHA256_CONST_46, SHA256_CONST_47,
- SHA256_CONST_48, SHA256_CONST_49, SHA256_CONST_50,
- SHA256_CONST_51, SHA256_CONST_52, SHA256_CONST_53,
- SHA256_CONST_54, SHA256_CONST_55, SHA256_CONST_56,
- SHA256_CONST_57, SHA256_CONST_58, SHA256_CONST_59,
- SHA256_CONST_60, SHA256_CONST_61, SHA256_CONST_62,
- SHA256_CONST_63
- };
-#endif /* __sparc */
-
- if ((uintptr_t)blk & 0x3) { /* not 4-byte aligned? */
- memcpy(ctx->buf_un.buf32, blk, sizeof (ctx->buf_un.buf32));
- blk = (uint8_t *)ctx->buf_un.buf32;
- }
-
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w0 = LOAD_BIG_32(blk + 4 * 0);
- SHA256ROUND(a, b, c, d, e, f, g, h, 0, w0);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w1 = LOAD_BIG_32(blk + 4 * 1);
- SHA256ROUND(h, a, b, c, d, e, f, g, 1, w1);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w2 = LOAD_BIG_32(blk + 4 * 2);
- SHA256ROUND(g, h, a, b, c, d, e, f, 2, w2);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w3 = LOAD_BIG_32(blk + 4 * 3);
- SHA256ROUND(f, g, h, a, b, c, d, e, 3, w3);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w4 = LOAD_BIG_32(blk + 4 * 4);
- SHA256ROUND(e, f, g, h, a, b, c, d, 4, w4);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w5 = LOAD_BIG_32(blk + 4 * 5);
- SHA256ROUND(d, e, f, g, h, a, b, c, 5, w5);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w6 = LOAD_BIG_32(blk + 4 * 6);
- SHA256ROUND(c, d, e, f, g, h, a, b, 6, w6);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w7 = LOAD_BIG_32(blk + 4 * 7);
- SHA256ROUND(b, c, d, e, f, g, h, a, 7, w7);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w8 = LOAD_BIG_32(blk + 4 * 8);
- SHA256ROUND(a, b, c, d, e, f, g, h, 8, w8);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w9 = LOAD_BIG_32(blk + 4 * 9);
- SHA256ROUND(h, a, b, c, d, e, f, g, 9, w9);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w10 = LOAD_BIG_32(blk + 4 * 10);
- SHA256ROUND(g, h, a, b, c, d, e, f, 10, w10);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w11 = LOAD_BIG_32(blk + 4 * 11);
- SHA256ROUND(f, g, h, a, b, c, d, e, 11, w11);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w12 = LOAD_BIG_32(blk + 4 * 12);
- SHA256ROUND(e, f, g, h, a, b, c, d, 12, w12);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w13 = LOAD_BIG_32(blk + 4 * 13);
- SHA256ROUND(d, e, f, g, h, a, b, c, 13, w13);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w14 = LOAD_BIG_32(blk + 4 * 14);
- SHA256ROUND(c, d, e, f, g, h, a, b, 14, w14);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w15 = LOAD_BIG_32(blk + 4 * 15);
- SHA256ROUND(b, c, d, e, f, g, h, a, 15, w15);
-
- w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0;
- SHA256ROUND(a, b, c, d, e, f, g, h, 16, w0);
- w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1;
- SHA256ROUND(h, a, b, c, d, e, f, g, 17, w1);
- w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2;
- SHA256ROUND(g, h, a, b, c, d, e, f, 18, w2);
- w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3;
- SHA256ROUND(f, g, h, a, b, c, d, e, 19, w3);
- w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4;
- SHA256ROUND(e, f, g, h, a, b, c, d, 20, w4);
- w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5;
- SHA256ROUND(d, e, f, g, h, a, b, c, 21, w5);
- w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6;
- SHA256ROUND(c, d, e, f, g, h, a, b, 22, w6);
- w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7;
- SHA256ROUND(b, c, d, e, f, g, h, a, 23, w7);
- w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8;
- SHA256ROUND(a, b, c, d, e, f, g, h, 24, w8);
- w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9;
- SHA256ROUND(h, a, b, c, d, e, f, g, 25, w9);
- w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10;
- SHA256ROUND(g, h, a, b, c, d, e, f, 26, w10);
- w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11;
- SHA256ROUND(f, g, h, a, b, c, d, e, 27, w11);
- w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12;
- SHA256ROUND(e, f, g, h, a, b, c, d, 28, w12);
- w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13;
- SHA256ROUND(d, e, f, g, h, a, b, c, 29, w13);
- w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14;
- SHA256ROUND(c, d, e, f, g, h, a, b, 30, w14);
- w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15;
- SHA256ROUND(b, c, d, e, f, g, h, a, 31, w15);
-
- w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0;
- SHA256ROUND(a, b, c, d, e, f, g, h, 32, w0);
- w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1;
- SHA256ROUND(h, a, b, c, d, e, f, g, 33, w1);
- w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2;
- SHA256ROUND(g, h, a, b, c, d, e, f, 34, w2);
- w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3;
- SHA256ROUND(f, g, h, a, b, c, d, e, 35, w3);
- w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4;
- SHA256ROUND(e, f, g, h, a, b, c, d, 36, w4);
- w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5;
- SHA256ROUND(d, e, f, g, h, a, b, c, 37, w5);
- w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6;
- SHA256ROUND(c, d, e, f, g, h, a, b, 38, w6);
- w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7;
- SHA256ROUND(b, c, d, e, f, g, h, a, 39, w7);
- w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8;
- SHA256ROUND(a, b, c, d, e, f, g, h, 40, w8);
- w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9;
- SHA256ROUND(h, a, b, c, d, e, f, g, 41, w9);
- w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10;
- SHA256ROUND(g, h, a, b, c, d, e, f, 42, w10);
- w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11;
- SHA256ROUND(f, g, h, a, b, c, d, e, 43, w11);
- w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12;
- SHA256ROUND(e, f, g, h, a, b, c, d, 44, w12);
- w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13;
- SHA256ROUND(d, e, f, g, h, a, b, c, 45, w13);
- w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14;
- SHA256ROUND(c, d, e, f, g, h, a, b, 46, w14);
- w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15;
- SHA256ROUND(b, c, d, e, f, g, h, a, 47, w15);
-
- w0 = SIGMA1_256(w14) + w9 + SIGMA0_256(w1) + w0;
- SHA256ROUND(a, b, c, d, e, f, g, h, 48, w0);
- w1 = SIGMA1_256(w15) + w10 + SIGMA0_256(w2) + w1;
- SHA256ROUND(h, a, b, c, d, e, f, g, 49, w1);
- w2 = SIGMA1_256(w0) + w11 + SIGMA0_256(w3) + w2;
- SHA256ROUND(g, h, a, b, c, d, e, f, 50, w2);
- w3 = SIGMA1_256(w1) + w12 + SIGMA0_256(w4) + w3;
- SHA256ROUND(f, g, h, a, b, c, d, e, 51, w3);
- w4 = SIGMA1_256(w2) + w13 + SIGMA0_256(w5) + w4;
- SHA256ROUND(e, f, g, h, a, b, c, d, 52, w4);
- w5 = SIGMA1_256(w3) + w14 + SIGMA0_256(w6) + w5;
- SHA256ROUND(d, e, f, g, h, a, b, c, 53, w5);
- w6 = SIGMA1_256(w4) + w15 + SIGMA0_256(w7) + w6;
- SHA256ROUND(c, d, e, f, g, h, a, b, 54, w6);
- w7 = SIGMA1_256(w5) + w0 + SIGMA0_256(w8) + w7;
- SHA256ROUND(b, c, d, e, f, g, h, a, 55, w7);
- w8 = SIGMA1_256(w6) + w1 + SIGMA0_256(w9) + w8;
- SHA256ROUND(a, b, c, d, e, f, g, h, 56, w8);
- w9 = SIGMA1_256(w7) + w2 + SIGMA0_256(w10) + w9;
- SHA256ROUND(h, a, b, c, d, e, f, g, 57, w9);
- w10 = SIGMA1_256(w8) + w3 + SIGMA0_256(w11) + w10;
- SHA256ROUND(g, h, a, b, c, d, e, f, 58, w10);
- w11 = SIGMA1_256(w9) + w4 + SIGMA0_256(w12) + w11;
- SHA256ROUND(f, g, h, a, b, c, d, e, 59, w11);
- w12 = SIGMA1_256(w10) + w5 + SIGMA0_256(w13) + w12;
- SHA256ROUND(e, f, g, h, a, b, c, d, 60, w12);
- w13 = SIGMA1_256(w11) + w6 + SIGMA0_256(w14) + w13;
- SHA256ROUND(d, e, f, g, h, a, b, c, 61, w13);
- w14 = SIGMA1_256(w12) + w7 + SIGMA0_256(w15) + w14;
- SHA256ROUND(c, d, e, f, g, h, a, b, 62, w14);
- w15 = SIGMA1_256(w13) + w8 + SIGMA0_256(w0) + w15;
- SHA256ROUND(b, c, d, e, f, g, h, a, 63, w15);
-
- ctx->state.s32[0] += a;
- ctx->state.s32[1] += b;
- ctx->state.s32[2] += c;
- ctx->state.s32[3] += d;
- ctx->state.s32[4] += e;
- ctx->state.s32[5] += f;
- ctx->state.s32[6] += g;
- ctx->state.s32[7] += h;
-}
-
-
-/* SHA384 and SHA512 Transform */
-
-static void
-SHA512Transform(SHA2_CTX *ctx, const uint8_t *blk)
-{
-
- uint64_t a = ctx->state.s64[0];
- uint64_t b = ctx->state.s64[1];
- uint64_t c = ctx->state.s64[2];
- uint64_t d = ctx->state.s64[3];
- uint64_t e = ctx->state.s64[4];
- uint64_t f = ctx->state.s64[5];
- uint64_t g = ctx->state.s64[6];
- uint64_t h = ctx->state.s64[7];
-
- uint64_t w0, w1, w2, w3, w4, w5, w6, w7;
- uint64_t w8, w9, w10, w11, w12, w13, w14, w15;
- uint64_t T1, T2;
-
-#if defined(__sparc)
- static const uint64_t sha512_consts[] = {
- SHA512_CONST_0, SHA512_CONST_1, SHA512_CONST_2,
- SHA512_CONST_3, SHA512_CONST_4, SHA512_CONST_5,
- SHA512_CONST_6, SHA512_CONST_7, SHA512_CONST_8,
- SHA512_CONST_9, SHA512_CONST_10, SHA512_CONST_11,
- SHA512_CONST_12, SHA512_CONST_13, SHA512_CONST_14,
- SHA512_CONST_15, SHA512_CONST_16, SHA512_CONST_17,
- SHA512_CONST_18, SHA512_CONST_19, SHA512_CONST_20,
- SHA512_CONST_21, SHA512_CONST_22, SHA512_CONST_23,
- SHA512_CONST_24, SHA512_CONST_25, SHA512_CONST_26,
- SHA512_CONST_27, SHA512_CONST_28, SHA512_CONST_29,
- SHA512_CONST_30, SHA512_CONST_31, SHA512_CONST_32,
- SHA512_CONST_33, SHA512_CONST_34, SHA512_CONST_35,
- SHA512_CONST_36, SHA512_CONST_37, SHA512_CONST_38,
- SHA512_CONST_39, SHA512_CONST_40, SHA512_CONST_41,
- SHA512_CONST_42, SHA512_CONST_43, SHA512_CONST_44,
- SHA512_CONST_45, SHA512_CONST_46, SHA512_CONST_47,
- SHA512_CONST_48, SHA512_CONST_49, SHA512_CONST_50,
- SHA512_CONST_51, SHA512_CONST_52, SHA512_CONST_53,
- SHA512_CONST_54, SHA512_CONST_55, SHA512_CONST_56,
- SHA512_CONST_57, SHA512_CONST_58, SHA512_CONST_59,
- SHA512_CONST_60, SHA512_CONST_61, SHA512_CONST_62,
- SHA512_CONST_63, SHA512_CONST_64, SHA512_CONST_65,
- SHA512_CONST_66, SHA512_CONST_67, SHA512_CONST_68,
- SHA512_CONST_69, SHA512_CONST_70, SHA512_CONST_71,
- SHA512_CONST_72, SHA512_CONST_73, SHA512_CONST_74,
- SHA512_CONST_75, SHA512_CONST_76, SHA512_CONST_77,
- SHA512_CONST_78, SHA512_CONST_79
- };
-#endif /* __sparc */
-
-
- if ((uintptr_t)blk & 0x7) { /* not 8-byte aligned? */
- memcpy(ctx->buf_un.buf64, blk, sizeof (ctx->buf_un.buf64));
- blk = (uint8_t *)ctx->buf_un.buf64;
- }
-
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w0 = LOAD_BIG_64(blk + 8 * 0);
- SHA512ROUND(a, b, c, d, e, f, g, h, 0, w0);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w1 = LOAD_BIG_64(blk + 8 * 1);
- SHA512ROUND(h, a, b, c, d, e, f, g, 1, w1);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w2 = LOAD_BIG_64(blk + 8 * 2);
- SHA512ROUND(g, h, a, b, c, d, e, f, 2, w2);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w3 = LOAD_BIG_64(blk + 8 * 3);
- SHA512ROUND(f, g, h, a, b, c, d, e, 3, w3);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w4 = LOAD_BIG_64(blk + 8 * 4);
- SHA512ROUND(e, f, g, h, a, b, c, d, 4, w4);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w5 = LOAD_BIG_64(blk + 8 * 5);
- SHA512ROUND(d, e, f, g, h, a, b, c, 5, w5);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w6 = LOAD_BIG_64(blk + 8 * 6);
- SHA512ROUND(c, d, e, f, g, h, a, b, 6, w6);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w7 = LOAD_BIG_64(blk + 8 * 7);
- SHA512ROUND(b, c, d, e, f, g, h, a, 7, w7);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w8 = LOAD_BIG_64(blk + 8 * 8);
- SHA512ROUND(a, b, c, d, e, f, g, h, 8, w8);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w9 = LOAD_BIG_64(blk + 8 * 9);
- SHA512ROUND(h, a, b, c, d, e, f, g, 9, w9);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w10 = LOAD_BIG_64(blk + 8 * 10);
- SHA512ROUND(g, h, a, b, c, d, e, f, 10, w10);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w11 = LOAD_BIG_64(blk + 8 * 11);
- SHA512ROUND(f, g, h, a, b, c, d, e, 11, w11);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w12 = LOAD_BIG_64(blk + 8 * 12);
- SHA512ROUND(e, f, g, h, a, b, c, d, 12, w12);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w13 = LOAD_BIG_64(blk + 8 * 13);
- SHA512ROUND(d, e, f, g, h, a, b, c, 13, w13);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w14 = LOAD_BIG_64(blk + 8 * 14);
- SHA512ROUND(c, d, e, f, g, h, a, b, 14, w14);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- w15 = LOAD_BIG_64(blk + 8 * 15);
- SHA512ROUND(b, c, d, e, f, g, h, a, 15, w15);
-
- w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0;
- SHA512ROUND(a, b, c, d, e, f, g, h, 16, w0);
- w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1;
- SHA512ROUND(h, a, b, c, d, e, f, g, 17, w1);
- w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2;
- SHA512ROUND(g, h, a, b, c, d, e, f, 18, w2);
- w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3;
- SHA512ROUND(f, g, h, a, b, c, d, e, 19, w3);
- w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4;
- SHA512ROUND(e, f, g, h, a, b, c, d, 20, w4);
- w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5;
- SHA512ROUND(d, e, f, g, h, a, b, c, 21, w5);
- w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6;
- SHA512ROUND(c, d, e, f, g, h, a, b, 22, w6);
- w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7;
- SHA512ROUND(b, c, d, e, f, g, h, a, 23, w7);
- w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8;
- SHA512ROUND(a, b, c, d, e, f, g, h, 24, w8);
- w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9;
- SHA512ROUND(h, a, b, c, d, e, f, g, 25, w9);
- w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10;
- SHA512ROUND(g, h, a, b, c, d, e, f, 26, w10);
- w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11;
- SHA512ROUND(f, g, h, a, b, c, d, e, 27, w11);
- w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12;
- SHA512ROUND(e, f, g, h, a, b, c, d, 28, w12);
- w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13;
- SHA512ROUND(d, e, f, g, h, a, b, c, 29, w13);
- w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14;
- SHA512ROUND(c, d, e, f, g, h, a, b, 30, w14);
- w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15;
- SHA512ROUND(b, c, d, e, f, g, h, a, 31, w15);
-
- w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0;
- SHA512ROUND(a, b, c, d, e, f, g, h, 32, w0);
- w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1;
- SHA512ROUND(h, a, b, c, d, e, f, g, 33, w1);
- w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2;
- SHA512ROUND(g, h, a, b, c, d, e, f, 34, w2);
- w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3;
- SHA512ROUND(f, g, h, a, b, c, d, e, 35, w3);
- w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4;
- SHA512ROUND(e, f, g, h, a, b, c, d, 36, w4);
- w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5;
- SHA512ROUND(d, e, f, g, h, a, b, c, 37, w5);
- w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6;
- SHA512ROUND(c, d, e, f, g, h, a, b, 38, w6);
- w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7;
- SHA512ROUND(b, c, d, e, f, g, h, a, 39, w7);
- w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8;
- SHA512ROUND(a, b, c, d, e, f, g, h, 40, w8);
- w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9;
- SHA512ROUND(h, a, b, c, d, e, f, g, 41, w9);
- w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10;
- SHA512ROUND(g, h, a, b, c, d, e, f, 42, w10);
- w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11;
- SHA512ROUND(f, g, h, a, b, c, d, e, 43, w11);
- w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12;
- SHA512ROUND(e, f, g, h, a, b, c, d, 44, w12);
- w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13;
- SHA512ROUND(d, e, f, g, h, a, b, c, 45, w13);
- w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14;
- SHA512ROUND(c, d, e, f, g, h, a, b, 46, w14);
- w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15;
- SHA512ROUND(b, c, d, e, f, g, h, a, 47, w15);
-
- w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0;
- SHA512ROUND(a, b, c, d, e, f, g, h, 48, w0);
- w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1;
- SHA512ROUND(h, a, b, c, d, e, f, g, 49, w1);
- w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2;
- SHA512ROUND(g, h, a, b, c, d, e, f, 50, w2);
- w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3;
- SHA512ROUND(f, g, h, a, b, c, d, e, 51, w3);
- w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4;
- SHA512ROUND(e, f, g, h, a, b, c, d, 52, w4);
- w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5;
- SHA512ROUND(d, e, f, g, h, a, b, c, 53, w5);
- w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6;
- SHA512ROUND(c, d, e, f, g, h, a, b, 54, w6);
- w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7;
- SHA512ROUND(b, c, d, e, f, g, h, a, 55, w7);
- w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8;
- SHA512ROUND(a, b, c, d, e, f, g, h, 56, w8);
- w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9;
- SHA512ROUND(h, a, b, c, d, e, f, g, 57, w9);
- w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10;
- SHA512ROUND(g, h, a, b, c, d, e, f, 58, w10);
- w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11;
- SHA512ROUND(f, g, h, a, b, c, d, e, 59, w11);
- w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12;
- SHA512ROUND(e, f, g, h, a, b, c, d, 60, w12);
- w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13;
- SHA512ROUND(d, e, f, g, h, a, b, c, 61, w13);
- w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14;
- SHA512ROUND(c, d, e, f, g, h, a, b, 62, w14);
- w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15;
- SHA512ROUND(b, c, d, e, f, g, h, a, 63, w15);
-
- w0 = SIGMA1(w14) + w9 + SIGMA0(w1) + w0;
- SHA512ROUND(a, b, c, d, e, f, g, h, 64, w0);
- w1 = SIGMA1(w15) + w10 + SIGMA0(w2) + w1;
- SHA512ROUND(h, a, b, c, d, e, f, g, 65, w1);
- w2 = SIGMA1(w0) + w11 + SIGMA0(w3) + w2;
- SHA512ROUND(g, h, a, b, c, d, e, f, 66, w2);
- w3 = SIGMA1(w1) + w12 + SIGMA0(w4) + w3;
- SHA512ROUND(f, g, h, a, b, c, d, e, 67, w3);
- w4 = SIGMA1(w2) + w13 + SIGMA0(w5) + w4;
- SHA512ROUND(e, f, g, h, a, b, c, d, 68, w4);
- w5 = SIGMA1(w3) + w14 + SIGMA0(w6) + w5;
- SHA512ROUND(d, e, f, g, h, a, b, c, 69, w5);
- w6 = SIGMA1(w4) + w15 + SIGMA0(w7) + w6;
- SHA512ROUND(c, d, e, f, g, h, a, b, 70, w6);
- w7 = SIGMA1(w5) + w0 + SIGMA0(w8) + w7;
- SHA512ROUND(b, c, d, e, f, g, h, a, 71, w7);
- w8 = SIGMA1(w6) + w1 + SIGMA0(w9) + w8;
- SHA512ROUND(a, b, c, d, e, f, g, h, 72, w8);
- w9 = SIGMA1(w7) + w2 + SIGMA0(w10) + w9;
- SHA512ROUND(h, a, b, c, d, e, f, g, 73, w9);
- w10 = SIGMA1(w8) + w3 + SIGMA0(w11) + w10;
- SHA512ROUND(g, h, a, b, c, d, e, f, 74, w10);
- w11 = SIGMA1(w9) + w4 + SIGMA0(w12) + w11;
- SHA512ROUND(f, g, h, a, b, c, d, e, 75, w11);
- w12 = SIGMA1(w10) + w5 + SIGMA0(w13) + w12;
- SHA512ROUND(e, f, g, h, a, b, c, d, 76, w12);
- w13 = SIGMA1(w11) + w6 + SIGMA0(w14) + w13;
- SHA512ROUND(d, e, f, g, h, a, b, c, 77, w13);
- w14 = SIGMA1(w12) + w7 + SIGMA0(w15) + w14;
- SHA512ROUND(c, d, e, f, g, h, a, b, 78, w14);
- w15 = SIGMA1(w13) + w8 + SIGMA0(w0) + w15;
- SHA512ROUND(b, c, d, e, f, g, h, a, 79, w15);
-
- ctx->state.s64[0] += a;
- ctx->state.s64[1] += b;
- ctx->state.s64[2] += c;
- ctx->state.s64[3] += d;
- ctx->state.s64[4] += e;
- ctx->state.s64[5] += f;
- ctx->state.s64[6] += g;
- ctx->state.s64[7] += h;
-
-}
-#endif /* !__amd64 || !_KERNEL */
-
-
-/*
- * Encode()
- *
- * purpose: to convert a list of numbers from little endian to big endian
- * input: uint8_t * : place to store the converted big endian numbers
- * uint32_t * : place to get numbers to convert from
- * size_t : the length of the input in bytes
- * output: void
- */
-
-static void
-Encode(uint8_t *_RESTRICT_KYWD output, uint32_t *_RESTRICT_KYWD input,
- size_t len)
-{
- size_t i, j;
-
-#if defined(__sparc)
- if (IS_P2ALIGNED(output, sizeof (uint32_t))) {
- for (i = 0, j = 0; j < len; i++, j += 4) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- *((uint32_t *)(output + j)) = input[i];
- }
- } else {
-#endif /* little endian -- will work on big endian, but slowly */
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (input[i] >> 24) & 0xff;
- output[j + 1] = (input[i] >> 16) & 0xff;
- output[j + 2] = (input[i] >> 8) & 0xff;
- output[j + 3] = input[i] & 0xff;
- }
-#if defined(__sparc)
- }
-#endif
-}
-
-static void
-Encode64(uint8_t *_RESTRICT_KYWD output, uint64_t *_RESTRICT_KYWD input,
- size_t len)
-{
- size_t i, j;
-
-#if defined(__sparc)
- if (IS_P2ALIGNED(output, sizeof (uint64_t))) {
- for (i = 0, j = 0; j < len; i++, j += 8) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- *((uint64_t *)(output + j)) = input[i];
- }
- } else {
-#endif /* little endian -- will work on big endian, but slowly */
- for (i = 0, j = 0; j < len; i++, j += 8) {
-
- output[j] = (input[i] >> 56) & 0xff;
- output[j + 1] = (input[i] >> 48) & 0xff;
- output[j + 2] = (input[i] >> 40) & 0xff;
- output[j + 3] = (input[i] >> 32) & 0xff;
- output[j + 4] = (input[i] >> 24) & 0xff;
- output[j + 5] = (input[i] >> 16) & 0xff;
- output[j + 6] = (input[i] >> 8) & 0xff;
- output[j + 7] = input[i] & 0xff;
- }
-#if defined(__sparc)
- }
-#endif
-}
-
-
-void
-SHA2Init(uint64_t mech, SHA2_CTX *ctx)
-{
-
- switch (mech) {
- case SHA256_MECH_INFO_TYPE:
- case SHA256_HMAC_MECH_INFO_TYPE:
- case SHA256_HMAC_GEN_MECH_INFO_TYPE:
- ctx->state.s32[0] = 0x6a09e667U;
- ctx->state.s32[1] = 0xbb67ae85U;
- ctx->state.s32[2] = 0x3c6ef372U;
- ctx->state.s32[3] = 0xa54ff53aU;
- ctx->state.s32[4] = 0x510e527fU;
- ctx->state.s32[5] = 0x9b05688cU;
- ctx->state.s32[6] = 0x1f83d9abU;
- ctx->state.s32[7] = 0x5be0cd19U;
- break;
- case SHA384_MECH_INFO_TYPE:
- case SHA384_HMAC_MECH_INFO_TYPE:
- case SHA384_HMAC_GEN_MECH_INFO_TYPE:
- ctx->state.s64[0] = 0xcbbb9d5dc1059ed8ULL;
- ctx->state.s64[1] = 0x629a292a367cd507ULL;
- ctx->state.s64[2] = 0x9159015a3070dd17ULL;
- ctx->state.s64[3] = 0x152fecd8f70e5939ULL;
- ctx->state.s64[4] = 0x67332667ffc00b31ULL;
- ctx->state.s64[5] = 0x8eb44a8768581511ULL;
- ctx->state.s64[6] = 0xdb0c2e0d64f98fa7ULL;
- ctx->state.s64[7] = 0x47b5481dbefa4fa4ULL;
- break;
- case SHA512_MECH_INFO_TYPE:
- case SHA512_HMAC_MECH_INFO_TYPE:
- case SHA512_HMAC_GEN_MECH_INFO_TYPE:
- ctx->state.s64[0] = 0x6a09e667f3bcc908ULL;
- ctx->state.s64[1] = 0xbb67ae8584caa73bULL;
- ctx->state.s64[2] = 0x3c6ef372fe94f82bULL;
- ctx->state.s64[3] = 0xa54ff53a5f1d36f1ULL;
- ctx->state.s64[4] = 0x510e527fade682d1ULL;
- ctx->state.s64[5] = 0x9b05688c2b3e6c1fULL;
- ctx->state.s64[6] = 0x1f83d9abfb41bd6bULL;
- ctx->state.s64[7] = 0x5be0cd19137e2179ULL;
- break;
- case SHA512_224_MECH_INFO_TYPE:
- ctx->state.s64[0] = 0x8C3D37C819544DA2ULL;
- ctx->state.s64[1] = 0x73E1996689DCD4D6ULL;
- ctx->state.s64[2] = 0x1DFAB7AE32FF9C82ULL;
- ctx->state.s64[3] = 0x679DD514582F9FCFULL;
- ctx->state.s64[4] = 0x0F6D2B697BD44DA8ULL;
- ctx->state.s64[5] = 0x77E36F7304C48942ULL;
- ctx->state.s64[6] = 0x3F9D85A86A1D36C8ULL;
- ctx->state.s64[7] = 0x1112E6AD91D692A1ULL;
- break;
- case SHA512_256_MECH_INFO_TYPE:
- ctx->state.s64[0] = 0x22312194FC2BF72CULL;
- ctx->state.s64[1] = 0x9F555FA3C84C64C2ULL;
- ctx->state.s64[2] = 0x2393B86B6F53B151ULL;
- ctx->state.s64[3] = 0x963877195940EABDULL;
- ctx->state.s64[4] = 0x96283EE2A88EFFE3ULL;
- ctx->state.s64[5] = 0xBE5E1E2553863992ULL;
- ctx->state.s64[6] = 0x2B0199FC2C85B8AAULL;
- ctx->state.s64[7] = 0x0EB72DDC81C52CA2ULL;
- break;
-#ifdef _KERNEL
- default:
- cmn_err(CE_PANIC,
- "sha2_init: failed to find a supported algorithm: 0x%x",
- (uint32_t)mech);
-
-#endif /* _KERNEL */
- }
-
- ctx->algotype = (uint32_t)mech;
- ctx->count.c64[0] = ctx->count.c64[1] = 0;
-}
-
-#ifndef _KERNEL
-
-// #pragma inline(SHA256Init, SHA384Init, SHA512Init)
-void
-SHA256Init(SHA256_CTX *ctx)
-{
- SHA2Init(SHA256, ctx);
-}
-
-void
-SHA384Init(SHA384_CTX *ctx)
-{
- SHA2Init(SHA384, ctx);
-}
-
-void
-SHA512Init(SHA512_CTX *ctx)
-{
- SHA2Init(SHA512, ctx);
-}
-
-#endif /* _KERNEL */
-
-/*
- * SHA2Update()
- *
- * purpose: continues an sha2 digest operation, using the message block
- * to update the context.
- * input: SHA2_CTX * : the context to update
- * void * : the message block
- * size_t : the length of the message block, in bytes
- * output: void
- */
-
-void
-SHA2Update(SHA2_CTX *ctx, const void *inptr, size_t input_len)
-{
- uint32_t i, buf_index, buf_len, buf_limit;
- const uint8_t *input = inptr;
- uint32_t algotype = ctx->algotype;
-
- /* check for noop */
- if (input_len == 0)
- return;
-
- if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
- buf_limit = 64;
-
- /* compute number of bytes mod 64 */
- buf_index = (ctx->count.c32[1] >> 3) & 0x3F;
-
- /* update number of bits */
- if ((ctx->count.c32[1] += (input_len << 3)) < (input_len << 3))
- ctx->count.c32[0]++;
-
- ctx->count.c32[0] += (input_len >> 29);
-
- } else {
- buf_limit = 128;
-
- /* compute number of bytes mod 128 */
- buf_index = (ctx->count.c64[1] >> 3) & 0x7F;
-
- /* update number of bits */
- if ((ctx->count.c64[1] += (input_len << 3)) < (input_len << 3))
- ctx->count.c64[0]++;
-
- ctx->count.c64[0] += (input_len >> 29);
- }
-
- buf_len = buf_limit - buf_index;
-
- /* transform as many times as possible */
- i = 0;
- if (input_len >= buf_len) {
-
- /*
- * general optimization:
- *
- * only do initial memcpy() and SHA2Transform() if
- * buf_index != 0. if buf_index == 0, we're just
- * wasting our time doing the memcpy() since there
- * wasn't any data left over from a previous call to
- * SHA2Update().
- */
- if (buf_index) {
- memcpy(&ctx->buf_un.buf8[buf_index], input, buf_len);
- if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE)
- SHA256Transform(ctx, ctx->buf_un.buf8);
- else
- SHA512Transform(ctx, ctx->buf_un.buf8);
-
- i = buf_len;
- }
-
-#if !defined(__amd64) || !defined(_KERNEL)
- if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
- for (; i + buf_limit - 1 < input_len; i += buf_limit) {
- SHA256Transform(ctx, &input[i]);
- }
- } else {
- for (; i + buf_limit - 1 < input_len; i += buf_limit) {
- SHA512Transform(ctx, &input[i]);
- }
- }
-
-#else
- uint32_t block_count;
- if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
- block_count = (input_len - i) >> 6;
- if (block_count > 0) {
- SHA256TransformBlocks(ctx, &input[i],
- block_count);
- i += block_count << 6;
- }
- } else {
- block_count = (input_len - i) >> 7;
- if (block_count > 0) {
- SHA512TransformBlocks(ctx, &input[i],
- block_count);
- i += block_count << 7;
- }
- }
-#endif /* !__amd64 || !_KERNEL */
-
- /*
- * general optimization:
- *
- * if i and input_len are the same, return now instead
- * of calling memcpy(), since the memcpy() in this case
- * will be an expensive noop.
- */
-
- if (input_len == i)
- return;
-
- buf_index = 0;
- }
-
- /* buffer remaining input */
- memcpy(&ctx->buf_un.buf8[buf_index], &input[i], input_len - i);
-}
-
-
-/*
- * SHA2Final()
- *
- * purpose: ends an sha2 digest operation, finalizing the message digest and
- * zeroing the context.
- * input: uchar_t * : a buffer to store the digest
- * : The function actually uses void* because many
- * : callers pass things other than uchar_t here.
- * SHA2_CTX * : the context to finalize, save, and zero
- * output: void
- */
-
-void
-SHA2Final(void *digest, SHA2_CTX *ctx)
-{
- uint8_t bitcount_be[sizeof (ctx->count.c32)];
- uint8_t bitcount_be64[sizeof (ctx->count.c64)];
- uint32_t index;
- uint32_t algotype = ctx->algotype;
-
- if (algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
- index = (ctx->count.c32[1] >> 3) & 0x3f;
- Encode(bitcount_be, ctx->count.c32, sizeof (bitcount_be));
- SHA2Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index);
- SHA2Update(ctx, bitcount_be, sizeof (bitcount_be));
- Encode(digest, ctx->state.s32, sizeof (ctx->state.s32));
- } else {
- index = (ctx->count.c64[1] >> 3) & 0x7f;
- Encode64(bitcount_be64, ctx->count.c64,
- sizeof (bitcount_be64));
- SHA2Update(ctx, PADDING, ((index < 112) ? 112 : 240) - index);
- SHA2Update(ctx, bitcount_be64, sizeof (bitcount_be64));
- if (algotype <= SHA384_HMAC_GEN_MECH_INFO_TYPE) {
- ctx->state.s64[6] = ctx->state.s64[7] = 0;
- Encode64(digest, ctx->state.s64,
- sizeof (uint64_t) * 6);
- } else if (algotype == SHA512_224_MECH_INFO_TYPE) {
- uint8_t last[sizeof (uint64_t)];
- /*
- * Since SHA-512/224 doesn't align well to 64-bit
- * boundaries, we must do the encoding in three steps:
- * 1) encode the three 64-bit words that fit neatly
- * 2) encode the last 64-bit word to a temp buffer
- * 3) chop out the lower 32-bits from the temp buffer
- * and append them to the digest
- */
- Encode64(digest, ctx->state.s64, sizeof (uint64_t) * 3);
- Encode64(last, &ctx->state.s64[3], sizeof (uint64_t));
- memcpy((uint8_t *)digest + 24, last, 4);
- } else if (algotype == SHA512_256_MECH_INFO_TYPE) {
- Encode64(digest, ctx->state.s64, sizeof (uint64_t) * 4);
- } else {
- Encode64(digest, ctx->state.s64,
- sizeof (ctx->state.s64));
- }
- }
-
- /* zeroize sensitive information */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-#ifdef _KERNEL
-EXPORT_SYMBOL(SHA2Init);
-EXPORT_SYMBOL(SHA2Update);
-EXPORT_SYMBOL(SHA2Final);
-#endif
diff --git a/module/icp/algs/sha2/sha256_impl.c b/module/icp/algs/sha2/sha256_impl.c
new file mode 100644
index 000000000000..0f24319511d7
--- /dev/null
+++ b/module/icp/algs/sha2/sha256_impl.c
@@ -0,0 +1,313 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#include <sys/simd.h>
+#include <sys/zfs_context.h>
+#include <sys/zfs_impl.h>
+#include <sys/sha2.h>
+
+#include <sha2/sha2_impl.h>
+#include <sys/asm_linkage.h>
+
+#define TF(E, N) \
+ extern void ASMABI E(uint32_t s[8], const void *, size_t); \
+ static inline void N(uint32_t s[8], const void *d, size_t b) { \
+ kfpu_begin(); E(s, d, b); kfpu_end(); \
+}
+
+/* some implementation is always okay */
+static inline boolean_t sha2_is_supported(void)
+{
+ return (B_TRUE);
+}
+
+#if defined(__x86_64)
+
+/* Users of ASMABI requires all calls to be from wrappers */
+extern void ASMABI
+zfs_sha256_transform_x64(uint32_t s[8], const void *, size_t);
+
+static inline void
+tf_sha256_transform_x64(uint32_t s[8], const void *d, size_t b)
+{
+ zfs_sha256_transform_x64(s, d, b);
+}
+
+const sha256_ops_t sha256_x64_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = tf_sha256_transform_x64,
+ .name = "x64"
+};
+
+#if defined(HAVE_SSSE3)
+static boolean_t sha2_have_ssse3(void)
+{
+ return (kfpu_allowed() && zfs_ssse3_available());
+}
+
+TF(zfs_sha256_transform_ssse3, tf_sha256_ssse3);
+const sha256_ops_t sha256_ssse3_impl = {
+ .is_supported = sha2_have_ssse3,
+ .transform = tf_sha256_ssse3,
+ .name = "ssse3"
+};
+#endif
+
+#if defined(HAVE_AVX)
+static boolean_t sha2_have_avx(void)
+{
+ return (kfpu_allowed() && zfs_avx_available());
+}
+
+TF(zfs_sha256_transform_avx, tf_sha256_avx);
+const sha256_ops_t sha256_avx_impl = {
+ .is_supported = sha2_have_avx,
+ .transform = tf_sha256_avx,
+ .name = "avx"
+};
+#endif
+
+#if defined(HAVE_AVX2)
+static boolean_t sha2_have_avx2(void)
+{
+ return (kfpu_allowed() && zfs_avx2_available());
+}
+
+TF(zfs_sha256_transform_avx2, tf_sha256_avx2);
+const sha256_ops_t sha256_avx2_impl = {
+ .is_supported = sha2_have_avx2,
+ .transform = tf_sha256_avx2,
+ .name = "avx2"
+};
+#endif
+
+#if defined(HAVE_SSE4_1)
+static boolean_t sha2_have_shani(void)
+{
+ return (kfpu_allowed() && zfs_sse4_1_available() && \
+ zfs_shani_available());
+}
+
+TF(zfs_sha256_transform_shani, tf_sha256_shani);
+const sha256_ops_t sha256_shani_impl = {
+ .is_supported = sha2_have_shani,
+ .transform = tf_sha256_shani,
+ .name = "shani"
+};
+#endif
+
+#elif defined(__aarch64__) || defined(__arm__)
+extern void zfs_sha256_block_armv7(uint32_t s[8], const void *, size_t);
+const sha256_ops_t sha256_armv7_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = zfs_sha256_block_armv7,
+ .name = "armv7"
+};
+
+#if __ARM_ARCH > 6
+static boolean_t sha256_have_neon(void)
+{
+ return (kfpu_allowed() && zfs_neon_available());
+}
+
+static boolean_t sha256_have_armv8ce(void)
+{
+ return (kfpu_allowed() && zfs_sha256_available());
+}
+
+TF(zfs_sha256_block_neon, tf_sha256_neon);
+const sha256_ops_t sha256_neon_impl = {
+ .is_supported = sha256_have_neon,
+ .transform = tf_sha256_neon,
+ .name = "neon"
+};
+
+TF(zfs_sha256_block_armv8, tf_sha256_armv8ce);
+const sha256_ops_t sha256_armv8_impl = {
+ .is_supported = sha256_have_armv8ce,
+ .transform = tf_sha256_armv8ce,
+ .name = "armv8-ce"
+};
+#endif
+
+#elif defined(__PPC64__)
+static boolean_t sha256_have_isa207(void)
+{
+ return (kfpu_allowed() && zfs_isa207_available());
+}
+
+TF(zfs_sha256_ppc, tf_sha256_ppc);
+const sha256_ops_t sha256_ppc_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = tf_sha256_ppc,
+ .name = "ppc"
+};
+
+TF(zfs_sha256_power8, tf_sha256_power8);
+const sha256_ops_t sha256_power8_impl = {
+ .is_supported = sha256_have_isa207,
+ .transform = tf_sha256_power8,
+ .name = "power8"
+};
+#endif /* __PPC64__ */
+
+/* the two generic ones */
+extern const sha256_ops_t sha256_generic_impl;
+
+/* array with all sha256 implementations */
+static const sha256_ops_t *const sha256_impls[] = {
+ &sha256_generic_impl,
+#if defined(__x86_64)
+ &sha256_x64_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_SSSE3)
+ &sha256_ssse3_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_AVX)
+ &sha256_avx_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_AVX2)
+ &sha256_avx2_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_SSE4_1)
+ &sha256_shani_impl,
+#endif
+#if defined(__aarch64__) || defined(__arm__)
+ &sha256_armv7_impl,
+#if __ARM_ARCH > 6
+ &sha256_neon_impl,
+ &sha256_armv8_impl,
+#endif
+#endif
+#if defined(__PPC64__)
+ &sha256_ppc_impl,
+ &sha256_power8_impl,
+#endif /* __PPC64__ */
+};
+
+/* use the generic implementation functions */
+#define IMPL_NAME "sha256"
+#define IMPL_OPS_T sha256_ops_t
+#define IMPL_ARRAY sha256_impls
+#define IMPL_GET_OPS sha256_get_ops
+#define ZFS_IMPL_OPS zfs_sha256_ops
+#include <generic_impl.c>
+
+#ifdef _KERNEL
+
+#define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")
+
+#if defined(__linux__)
+
+static int
+sha256_param_get(char *buffer, zfs_kernel_param_t *unused)
+{
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ char *fmt;
+ int cnt = 0;
+
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ cnt += sprintf(buffer + cnt, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ cnt += sprintf(buffer + cnt, fmt, "fastest");
+
+ /* list all supported implementations */
+ generic_impl_init();
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ cnt += sprintf(buffer + cnt, fmt,
+ generic_supp_impls[i]->name);
+ }
+
+ return (cnt);
+}
+
+static int
+sha256_param_set(const char *val, zfs_kernel_param_t *unused)
+{
+ (void) unused;
+ return (generic_impl_setname(val));
+}
+
+#elif defined(__FreeBSD__)
+
+#include <sys/sbuf.h>
+
+static int
+sha256_param(ZFS_MODULE_PARAM_ARGS)
+{
+ int err;
+
+ generic_impl_init();
+ if (req->newptr == NULL) {
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ const int init_buflen = 64;
+ const char *fmt;
+ struct sbuf *s;
+
+ s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);
+
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ (void) sbuf_printf(s, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ (void) sbuf_printf(s, fmt, "fastest");
+
+ /* list all supported implementations */
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ (void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);
+ }
+
+ err = sbuf_finish(s);
+ sbuf_delete(s);
+
+ return (err);
+ }
+
+ char buf[16];
+
+ err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (err) {
+ return (err);
+ }
+
+ return (-generic_impl_setname(buf));
+}
+#endif
+
+#undef IMPL_FMT
+
+ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, sha256_impl,
+ sha256_param_set, sha256_param_get, ZMOD_RW, \
+ "Select SHA256 implementation.");
+#endif
+
+#undef TF
diff --git a/module/icp/algs/sha2/sha2_generic.c b/module/icp/algs/sha2/sha2_generic.c
new file mode 100644
index 000000000000..60d7ad9a1dfa
--- /dev/null
+++ b/module/icp/algs/sha2/sha2_generic.c
@@ -0,0 +1,562 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Based on public domain code in cppcrypto 0.10.
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#include <sys/zfs_context.h>
+#include <sys/zfs_impl.h>
+#include <sys/sha2.h>
+
+#include <sha2/sha2_impl.h>
+
+/*
+ * On i386, gcc brings this for sha512_generic():
+ * error: the frame size of 1040 bytes is larger than 1024
+ */
+#if defined(__GNUC__) && defined(_ILP32)
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+#endif
+
+/* SHA256 */
+static const uint32_t SHA256_K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define Maj(x, y, z) (((y) & (z)) | (((y) | (z)) & (x)))
+
+#define rotr32(x, n) (((x) >> n) | ((x) << (32 - n)))
+#define sum0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
+#define sum1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
+#define sigma0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
+#define sigma1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
+
+#define WU(j) (W[j & 15] += sigma1(W[(j + 14) & 15]) \
+ + W[(j + 9) & 15] + sigma0(W[(j + 1) & 15]))
+
+#define COMPRESS(i, j, K) \
+ T1 = h + sum1(e) + Ch(e, f, g) + K[i + j] + (i? WU(j): W[j]); \
+ T2 = sum0(a) + Maj(a, b, c); \
+ h = g, g = f, f = e, e = d + T1; \
+ d = c, c = b, b = a, a = T1 + T2;
+
+static void sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
+{
+ uint64_t blk;
+
+ for (blk = 0; blk < num_blks; blk++) {
+ uint32_t W[16];
+ uint32_t a, b, c, d, e, f, g, h;
+ uint32_t T1, T2;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ W[i] = BE_32( \
+ (((const uint32_t *)(data))[blk * 16 + i]));
+ }
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ f = state[5];
+ g = state[6];
+ h = state[7];
+
+ for (i = 0; i <= 63; i += 16) {
+ COMPRESS(i, 0, SHA256_K);
+ COMPRESS(i, 1, SHA256_K);
+ COMPRESS(i, 2, SHA256_K);
+ COMPRESS(i, 3, SHA256_K);
+ COMPRESS(i, 4, SHA256_K);
+ COMPRESS(i, 5, SHA256_K);
+ COMPRESS(i, 6, SHA256_K);
+ COMPRESS(i, 7, SHA256_K);
+ COMPRESS(i, 8, SHA256_K);
+ COMPRESS(i, 9, SHA256_K);
+ COMPRESS(i, 10, SHA256_K);
+ COMPRESS(i, 11, SHA256_K);
+ COMPRESS(i, 12, SHA256_K);
+ COMPRESS(i, 13, SHA256_K);
+ COMPRESS(i, 14, SHA256_K);
+ COMPRESS(i, 15, SHA256_K);
+ }
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ state[5] += f;
+ state[6] += g;
+ state[7] += h;
+ }
+}
+
+#undef sum0
+#undef sum1
+#undef sigma0
+#undef sigma1
+
+#define rotr64(x, n) (((x) >> n) | ((x) << (64 - n)))
+#define sum0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
+#define sum1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
+#define sigma0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
+#define sigma1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
+
+/* SHA512 */
+static const uint64_t SHA512_K[80] = {
+ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
+ 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
+ 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
+ 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
+ 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
+ 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+ 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
+ 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
+ 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
+ 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
+ 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
+ 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
+ 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
+ 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
+ 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+};
+
+static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
+{
+ uint64_t blk;
+
+ for (blk = 0; blk < num_blks; blk++) {
+ uint64_t W[16];
+ uint64_t a, b, c, d, e, f, g, h;
+ uint64_t T1, T2;
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ W[i] = BE_64( \
+ (((const uint64_t *)(data))[blk * 16 + i]));
+ }
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ f = state[5];
+ g = state[6];
+ h = state[7];
+
+ for (i = 0; i <= 79; i += 16) {
+ COMPRESS(i, 0, SHA512_K);
+ COMPRESS(i, 1, SHA512_K);
+ COMPRESS(i, 2, SHA512_K);
+ COMPRESS(i, 3, SHA512_K);
+ COMPRESS(i, 4, SHA512_K);
+ COMPRESS(i, 5, SHA512_K);
+ COMPRESS(i, 6, SHA512_K);
+ COMPRESS(i, 7, SHA512_K);
+ COMPRESS(i, 8, SHA512_K);
+ COMPRESS(i, 9, SHA512_K);
+ COMPRESS(i, 10, SHA512_K);
+ COMPRESS(i, 11, SHA512_K);
+ COMPRESS(i, 12, SHA512_K);
+ COMPRESS(i, 13, SHA512_K);
+ COMPRESS(i, 14, SHA512_K);
+ COMPRESS(i, 15, SHA512_K);
+ }
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ state[5] += f;
+ state[6] += g;
+ state[7] += h;
+ }
+}
+
+static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
+{
+ uint64_t pos = ctx->count[0];
+ uint64_t total = ctx->count[1];
+ uint8_t *m = ctx->wbuf;
+ const sha256_ops_t *ops = ctx->ops;
+
+ if (pos && pos + len >= 64) {
+ memcpy(m + pos, data, 64 - pos);
+ ops->transform(ctx->state, m, 1);
+ len -= 64 - pos;
+ total += (64 - pos) * 8;
+ data += 64 - pos;
+ pos = 0;
+ }
+
+ if (len >= 64) {
+ uint32_t blocks = len / 64;
+ uint32_t bytes = blocks * 64;
+ ops->transform(ctx->state, data, blocks);
+ len -= bytes;
+ total += (bytes) * 8;
+ data += bytes;
+ }
+ memcpy(m + pos, data, len);
+
+ pos += len;
+ total += len * 8;
+ ctx->count[0] = pos;
+ ctx->count[1] = total;
+}
+
+static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
+{
+ uint64_t pos = ctx->count[0];
+ uint64_t total = ctx->count[1];
+ uint8_t *m = ctx->wbuf;
+ const sha512_ops_t *ops = ctx->ops;
+
+ if (pos && pos + len >= 128) {
+ memcpy(m + pos, data, 128 - pos);
+ ops->transform(ctx->state, m, 1);
+ len -= 128 - pos;
+ total += (128 - pos) * 8;
+ data += 128 - pos;
+ pos = 0;
+ }
+
+ if (len >= 128) {
+ uint64_t blocks = len / 128;
+ uint64_t bytes = blocks * 128;
+ ops->transform(ctx->state, data, blocks);
+ len -= bytes;
+ total += (bytes) * 8;
+ data += bytes;
+ }
+ memcpy(m + pos, data, len);
+
+ pos += len;
+ total += len * 8;
+ ctx->count[0] = pos;
+ ctx->count[1] = total;
+}
+
+static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
+{
+ uint64_t mlen, pos = ctx->count[0];
+ uint8_t *m = ctx->wbuf;
+ uint32_t *R = (uint32_t *)result;
+ const sha256_ops_t *ops = ctx->ops;
+
+ m[pos++] = 0x80;
+ if (pos > 56) {
+ memset(m + pos, 0, 64 - pos);
+ ops->transform(ctx->state, m, 1);
+ pos = 0;
+ }
+
+ memset(m + pos, 0, 64 - pos);
+ mlen = BE_64(ctx->count[1]);
+ memcpy(m + (64 - 8), &mlen, 64 / 8);
+ ops->transform(ctx->state, m, 1);
+
+ switch (bits) {
+ case 224: /* 28 - unused currently /TR */
+ R[0] = BE_32(ctx->state[0]);
+ R[1] = BE_32(ctx->state[1]);
+ R[2] = BE_32(ctx->state[2]);
+ R[3] = BE_32(ctx->state[3]);
+ R[4] = BE_32(ctx->state[4]);
+ R[5] = BE_32(ctx->state[5]);
+ R[6] = BE_32(ctx->state[6]);
+ break;
+ case 256: /* 32 */
+ R[0] = BE_32(ctx->state[0]);
+ R[1] = BE_32(ctx->state[1]);
+ R[2] = BE_32(ctx->state[2]);
+ R[3] = BE_32(ctx->state[3]);
+ R[4] = BE_32(ctx->state[4]);
+ R[5] = BE_32(ctx->state[5]);
+ R[6] = BE_32(ctx->state[6]);
+ R[7] = BE_32(ctx->state[7]);
+ break;
+ }
+
+ memset(ctx, 0, sizeof (*ctx));
+}
+
+static void sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
+{
+ uint64_t mlen, pos = ctx->count[0];
+ uint8_t *m = ctx->wbuf, *r;
+ uint64_t *R = (uint64_t *)result;
+ const sha512_ops_t *ops = ctx->ops;
+
+ m[pos++] = 0x80;
+ if (pos > 112) {
+ memset(m + pos, 0, 128 - pos);
+ ops->transform(ctx->state, m, 1);
+ pos = 0;
+ }
+
+ memset(m + pos, 0, 128 - pos);
+ mlen = BE_64(ctx->count[1]);
+ memcpy(m + (128 - 8), &mlen, 64 / 8);
+ ops->transform(ctx->state, m, 1);
+
+ switch (bits) {
+ case 224: /* 28 => 3,5 x 8 */
+ r = result + 24;
+ R[0] = BE_64(ctx->state[0]);
+ R[1] = BE_64(ctx->state[1]);
+ R[2] = BE_64(ctx->state[2]);
+ /* last 4 bytes are special here */
+ *r++ = (uint8_t)(ctx->state[3] >> 56);
+ *r++ = (uint8_t)(ctx->state[3] >> 48);
+ *r++ = (uint8_t)(ctx->state[3] >> 40);
+ *r++ = (uint8_t)(ctx->state[3] >> 32);
+ break;
+ case 256: /* 32 */
+ R[0] = BE_64(ctx->state[0]);
+ R[1] = BE_64(ctx->state[1]);
+ R[2] = BE_64(ctx->state[2]);
+ R[3] = BE_64(ctx->state[3]);
+ break;
+ case 384: /* 48 */
+ R[0] = BE_64(ctx->state[0]);
+ R[1] = BE_64(ctx->state[1]);
+ R[2] = BE_64(ctx->state[2]);
+ R[3] = BE_64(ctx->state[3]);
+ R[4] = BE_64(ctx->state[4]);
+ R[5] = BE_64(ctx->state[5]);
+ break;
+ case 512: /* 64 */
+ R[0] = BE_64(ctx->state[0]);
+ R[1] = BE_64(ctx->state[1]);
+ R[2] = BE_64(ctx->state[2]);
+ R[3] = BE_64(ctx->state[3]);
+ R[4] = BE_64(ctx->state[4]);
+ R[5] = BE_64(ctx->state[5]);
+ R[6] = BE_64(ctx->state[6]);
+ R[7] = BE_64(ctx->state[7]);
+ break;
+ }
+
+ memset(ctx, 0, sizeof (*ctx));
+}
+
+/* SHA2 Init function */
+void
+SHA2Init(int algotype, SHA2_CTX *ctx)
+{
+ sha256_ctx *ctx256 = &ctx->sha256;
+ sha512_ctx *ctx512 = &ctx->sha512;
+
+ ASSERT3S(algotype, >=, SHA256_MECH_INFO_TYPE);
+ ASSERT3S(algotype, <=, SHA512_256_MECH_INFO_TYPE);
+
+ memset(ctx, 0, sizeof (*ctx));
+ ctx->algotype = algotype;
+ switch (ctx->algotype) {
+ case SHA256_MECH_INFO_TYPE:
+ case SHA256_HMAC_MECH_INFO_TYPE:
+ case SHA256_HMAC_GEN_MECH_INFO_TYPE:
+ ctx256->state[0] = 0x6a09e667;
+ ctx256->state[1] = 0xbb67ae85;
+ ctx256->state[2] = 0x3c6ef372;
+ ctx256->state[3] = 0xa54ff53a;
+ ctx256->state[4] = 0x510e527f;
+ ctx256->state[5] = 0x9b05688c;
+ ctx256->state[6] = 0x1f83d9ab;
+ ctx256->state[7] = 0x5be0cd19;
+ ctx256->count[0] = 0;
+ ctx256->ops = sha256_get_ops();
+ break;
+ case SHA384_MECH_INFO_TYPE:
+ case SHA384_HMAC_MECH_INFO_TYPE:
+ case SHA384_HMAC_GEN_MECH_INFO_TYPE:
+ ctx512->state[0] = 0xcbbb9d5dc1059ed8ULL;
+ ctx512->state[1] = 0x629a292a367cd507ULL;
+ ctx512->state[2] = 0x9159015a3070dd17ULL;
+ ctx512->state[3] = 0x152fecd8f70e5939ULL;
+ ctx512->state[4] = 0x67332667ffc00b31ULL;
+ ctx512->state[5] = 0x8eb44a8768581511ULL;
+ ctx512->state[6] = 0xdb0c2e0d64f98fa7ULL;
+ ctx512->state[7] = 0x47b5481dbefa4fa4ULL;
+ ctx512->count[0] = 0;
+ ctx512->count[1] = 0;
+ ctx512->ops = sha512_get_ops();
+ break;
+ case SHA512_MECH_INFO_TYPE:
+ case SHA512_HMAC_MECH_INFO_TYPE:
+ case SHA512_HMAC_GEN_MECH_INFO_TYPE:
+ ctx512->state[0] = 0x6a09e667f3bcc908ULL;
+ ctx512->state[1] = 0xbb67ae8584caa73bULL;
+ ctx512->state[2] = 0x3c6ef372fe94f82bULL;
+ ctx512->state[3] = 0xa54ff53a5f1d36f1ULL;
+ ctx512->state[4] = 0x510e527fade682d1ULL;
+ ctx512->state[5] = 0x9b05688c2b3e6c1fULL;
+ ctx512->state[6] = 0x1f83d9abfb41bd6bULL;
+ ctx512->state[7] = 0x5be0cd19137e2179ULL;
+ ctx512->count[0] = 0;
+ ctx512->count[1] = 0;
+ ctx512->ops = sha512_get_ops();
+ break;
+ case SHA512_224_MECH_INFO_TYPE:
+ ctx512->state[0] = 0x8c3d37c819544da2ULL;
+ ctx512->state[1] = 0x73e1996689dcd4d6ULL;
+ ctx512->state[2] = 0x1dfab7ae32ff9c82ULL;
+ ctx512->state[3] = 0x679dd514582f9fcfULL;
+ ctx512->state[4] = 0x0f6d2b697bd44da8ULL;
+ ctx512->state[5] = 0x77e36f7304c48942ULL;
+ ctx512->state[6] = 0x3f9d85a86a1d36c8ULL;
+ ctx512->state[7] = 0x1112e6ad91d692a1ULL;
+ ctx512->count[0] = 0;
+ ctx512->count[1] = 0;
+ ctx512->ops = sha512_get_ops();
+ break;
+ case SHA512_256_MECH_INFO_TYPE:
+ ctx512->state[0] = 0x22312194fc2bf72cULL;
+ ctx512->state[1] = 0x9f555fa3c84c64c2ULL;
+ ctx512->state[2] = 0x2393b86b6f53b151ULL;
+ ctx512->state[3] = 0x963877195940eabdULL;
+ ctx512->state[4] = 0x96283ee2a88effe3ULL;
+ ctx512->state[5] = 0xbe5e1e2553863992ULL;
+ ctx512->state[6] = 0x2b0199fc2c85b8aaULL;
+ ctx512->state[7] = 0x0eb72ddc81c52ca2ULL;
+ ctx512->count[0] = 0;
+ ctx512->count[1] = 0;
+ ctx512->ops = sha512_get_ops();
+ break;
+ }
+}
+
+/* SHA2 Update function */
+void
+SHA2Update(SHA2_CTX *ctx, const void *data, size_t len)
+{
+ /* check for zero input length */
+ if (len == 0)
+ return;
+
+ ASSERT3P(data, !=, NULL);
+
+ switch (ctx->algotype) {
+ case SHA256_MECH_INFO_TYPE:
+ case SHA256_HMAC_MECH_INFO_TYPE:
+ case SHA256_HMAC_GEN_MECH_INFO_TYPE:
+ sha256_update(&ctx->sha256, data, len);
+ break;
+ case SHA384_MECH_INFO_TYPE:
+ case SHA384_HMAC_MECH_INFO_TYPE:
+ case SHA384_HMAC_GEN_MECH_INFO_TYPE:
+ sha512_update(&ctx->sha512, data, len);
+ break;
+ case SHA512_MECH_INFO_TYPE:
+ case SHA512_HMAC_MECH_INFO_TYPE:
+ case SHA512_HMAC_GEN_MECH_INFO_TYPE:
+ sha512_update(&ctx->sha512, data, len);
+ break;
+ case SHA512_224_MECH_INFO_TYPE:
+ sha512_update(&ctx->sha512, data, len);
+ break;
+ case SHA512_256_MECH_INFO_TYPE:
+ sha512_update(&ctx->sha512, data, len);
+ break;
+ }
+}
+
+/* SHA2Final function */
+void
+SHA2Final(void *digest, SHA2_CTX *ctx)
+{
+ switch (ctx->algotype) {
+ case SHA256_MECH_INFO_TYPE:
+ case SHA256_HMAC_MECH_INFO_TYPE:
+ case SHA256_HMAC_GEN_MECH_INFO_TYPE:
+ sha256_final(&ctx->sha256, digest, 256);
+ break;
+ case SHA384_MECH_INFO_TYPE:
+ case SHA384_HMAC_MECH_INFO_TYPE:
+ case SHA384_HMAC_GEN_MECH_INFO_TYPE:
+ sha512_final(&ctx->sha512, digest, 384);
+ break;
+ case SHA512_MECH_INFO_TYPE:
+ case SHA512_HMAC_MECH_INFO_TYPE:
+ case SHA512_HMAC_GEN_MECH_INFO_TYPE:
+ sha512_final(&ctx->sha512, digest, 512);
+ break;
+ case SHA512_224_MECH_INFO_TYPE:
+ sha512_final(&ctx->sha512, digest, 224);
+ break;
+ case SHA512_256_MECH_INFO_TYPE:
+ sha512_final(&ctx->sha512, digest, 256);
+ break;
+ }
+}
+
+/* the generic implementation is always okay */
+static boolean_t sha2_is_supported(void)
+{
+ return (B_TRUE);
+}
+
+const sha256_ops_t sha256_generic_impl = {
+ .name = "generic",
+ .transform = sha256_generic,
+ .is_supported = sha2_is_supported
+};
+
+const sha512_ops_t sha512_generic_impl = {
+ .name = "generic",
+ .transform = sha512_generic,
+ .is_supported = sha2_is_supported
+};
diff --git a/module/icp/algs/sha2/sha512_impl.c b/module/icp/algs/sha2/sha512_impl.c
new file mode 100644
index 000000000000..6291fbd77e36
--- /dev/null
+++ b/module/icp/algs/sha2/sha512_impl.c
@@ -0,0 +1,282 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#include <sys/simd.h>
+#include <sys/zfs_context.h>
+#include <sys/zfs_impl.h>
+#include <sys/sha2.h>
+
+#include <sha2/sha2_impl.h>
+#include <sys/asm_linkage.h>
+
+#define TF(E, N) \
+ extern void ASMABI E(uint64_t s[8], const void *, size_t); \
+ static inline void N(uint64_t s[8], const void *d, size_t b) { \
+ kfpu_begin(); E(s, d, b); kfpu_end(); \
+}
+
+/* some implementation is always okay */
+static inline boolean_t sha2_is_supported(void)
+{
+ return (B_TRUE);
+}
+
+#if defined(__x86_64)
+
+/* Users of ASMABI requires all calls to be from wrappers */
+extern void ASMABI
+zfs_sha512_transform_x64(uint64_t s[8], const void *, size_t);
+
+static inline void
+tf_sha512_transform_x64(uint64_t s[8], const void *d, size_t b)
+{
+ zfs_sha512_transform_x64(s, d, b);
+}
+const sha512_ops_t sha512_x64_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = tf_sha512_transform_x64,
+ .name = "x64"
+};
+
+#if defined(HAVE_AVX)
+static boolean_t sha2_have_avx(void)
+{
+ return (kfpu_allowed() && zfs_avx_available());
+}
+
+TF(zfs_sha512_transform_avx, tf_sha512_avx);
+const sha512_ops_t sha512_avx_impl = {
+ .is_supported = sha2_have_avx,
+ .transform = tf_sha512_avx,
+ .name = "avx"
+};
+#endif
+
+#if defined(HAVE_AVX2)
+static boolean_t sha2_have_avx2(void)
+{
+ return (kfpu_allowed() && zfs_avx2_available());
+}
+
+TF(zfs_sha512_transform_avx2, tf_sha512_avx2);
+const sha512_ops_t sha512_avx2_impl = {
+ .is_supported = sha2_have_avx2,
+ .transform = tf_sha512_avx2,
+ .name = "avx2"
+};
+#endif
+
+#elif defined(__aarch64__) || defined(__arm__)
+extern void zfs_sha512_block_armv7(uint64_t s[8], const void *, size_t);
+const sha512_ops_t sha512_armv7_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = zfs_sha512_block_armv7,
+ .name = "armv7"
+};
+
+#if defined(__aarch64__)
+static boolean_t sha512_have_armv8ce(void)
+{
+ return (kfpu_allowed() && zfs_sha512_available());
+}
+
+TF(zfs_sha512_block_armv8, tf_sha512_armv8ce);
+const sha512_ops_t sha512_armv8_impl = {
+ .is_supported = sha512_have_armv8ce,
+ .transform = tf_sha512_armv8ce,
+ .name = "armv8-ce"
+};
+#endif
+
+#if defined(__arm__) && __ARM_ARCH > 6
+static boolean_t sha512_have_neon(void)
+{
+ return (kfpu_allowed() && zfs_neon_available());
+}
+
+TF(zfs_sha512_block_neon, tf_sha512_neon);
+const sha512_ops_t sha512_neon_impl = {
+ .is_supported = sha512_have_neon,
+ .transform = tf_sha512_neon,
+ .name = "neon"
+};
+#endif
+
+#elif defined(__PPC64__)
+TF(zfs_sha512_ppc, tf_sha512_ppc);
+const sha512_ops_t sha512_ppc_impl = {
+ .is_supported = sha2_is_supported,
+ .transform = tf_sha512_ppc,
+ .name = "ppc"
+};
+
+static boolean_t sha512_have_isa207(void)
+{
+ return (kfpu_allowed() && zfs_isa207_available());
+}
+
+TF(zfs_sha512_power8, tf_sha512_power8);
+const sha512_ops_t sha512_power8_impl = {
+ .is_supported = sha512_have_isa207,
+ .transform = tf_sha512_power8,
+ .name = "power8"
+};
+#endif /* __PPC64__ */
+
+/* the two generic ones */
+extern const sha512_ops_t sha512_generic_impl;
+
+/* array with all sha512 implementations */
+static const sha512_ops_t *const sha512_impls[] = {
+ &sha512_generic_impl,
+#if defined(__x86_64)
+ &sha512_x64_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_AVX)
+ &sha512_avx_impl,
+#endif
+#if defined(__x86_64) && defined(HAVE_AVX2)
+ &sha512_avx2_impl,
+#endif
+#if defined(__aarch64__) || defined(__arm__)
+ &sha512_armv7_impl,
+#if defined(__aarch64__)
+ &sha512_armv8_impl,
+#endif
+#if defined(__arm__) && __ARM_ARCH > 6
+ &sha512_neon_impl,
+#endif
+#endif
+#if defined(__PPC64__)
+ &sha512_ppc_impl,
+ &sha512_power8_impl,
+#endif /* __PPC64__ */
+};
+
+/* use the generic implementation functions */
+#define IMPL_NAME "sha512"
+#define IMPL_OPS_T sha512_ops_t
+#define IMPL_ARRAY sha512_impls
+#define IMPL_GET_OPS sha512_get_ops
+#define ZFS_IMPL_OPS zfs_sha512_ops
+#include <generic_impl.c>
+
+#ifdef _KERNEL
+
+#define IMPL_FMT(impl, i) (((impl) == (i)) ? "[%s] " : "%s ")
+
+#if defined(__linux__)
+
+static int
+sha512_param_get(char *buffer, zfs_kernel_param_t *unused)
+{
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ char *fmt;
+ int cnt = 0;
+
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ cnt += sprintf(buffer + cnt, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ cnt += sprintf(buffer + cnt, fmt, "fastest");
+
+ /* list all supported implementations */
+ generic_impl_init();
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ cnt += sprintf(buffer + cnt, fmt,
+ generic_supp_impls[i]->name);
+ }
+
+ return (cnt);
+}
+
+static int
+sha512_param_set(const char *val, zfs_kernel_param_t *unused)
+{
+ (void) unused;
+ return (generic_impl_setname(val));
+}
+
+#elif defined(__FreeBSD__)
+
+#include <sys/sbuf.h>
+
+static int
+sha512_param(ZFS_MODULE_PARAM_ARGS)
+{
+ int err;
+
+ generic_impl_init();
+ if (req->newptr == NULL) {
+ const uint32_t impl = IMPL_READ(generic_impl_chosen);
+ const int init_buflen = 64;
+ const char *fmt;
+ struct sbuf *s;
+
+ s = sbuf_new_for_sysctl(NULL, NULL, init_buflen, req);
+
+ /* cycling */
+ fmt = IMPL_FMT(impl, IMPL_CYCLE);
+ (void) sbuf_printf(s, fmt, "cycle");
+
+ /* list fastest */
+ fmt = IMPL_FMT(impl, IMPL_FASTEST);
+ (void) sbuf_printf(s, fmt, "fastest");
+
+ /* list all supported implementations */
+ for (uint32_t i = 0; i < generic_supp_impls_cnt; ++i) {
+ fmt = IMPL_FMT(impl, i);
+ (void) sbuf_printf(s, fmt, generic_supp_impls[i]->name);
+ }
+
+ err = sbuf_finish(s);
+ sbuf_delete(s);
+
+ return (err);
+ }
+
+ /* we got module parameter */
+ char buf[16];
+
+ err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (err) {
+ return (err);
+ }
+
+ return (-generic_impl_setname(buf));
+}
+#endif
+
+#undef IMPL_FMT
+
+ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs, zfs_, sha512_impl,
+ sha512_param_set, sha512_param_get, ZMOD_RW, \
+ "Select SHA512 implementation.");
+#endif
+
+#undef TF
diff --git a/module/icp/algs/skein/skein_block.c b/module/icp/algs/skein/skein_block.c
index 7ba165a48511..3ad52da5f6a3 100644
--- a/module/icp/algs/skein/skein_block.c
+++ b/module/icp/algs/skein/skein_block.c
@@ -30,7 +30,9 @@
* the #pragma here to ignore the warning.
*/
#if defined(_ILP32) || defined(__powerpc) /* Assume small stack */
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wframe-larger-than="
+#endif
/*
* We're running on 32-bit, don't unroll loops to save stack frame space
*
diff --git a/module/icp/api/kcf_cipher.c b/module/icp/api/kcf_cipher.c
index 81c3b96b1509..4bea46807197 100644
--- a/module/icp/api/kcf_cipher.c
+++ b/module/icp/api/kcf_cipher.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/api/kcf_ctxops.c b/module/icp/api/kcf_ctxops.c
index 25ed94fe8bdf..b8cd67ea7f67 100644
--- a/module/icp/api/kcf_ctxops.c
+++ b/module/icp/api/kcf_ctxops.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -88,7 +88,7 @@ crypto_create_ctx_template(crypto_mechanism_t *mech, crypto_key_t *key,
if (error != CRYPTO_SUCCESS)
return (error);
- if ((ctx_tmpl = (kcf_ctx_template_t *)kmem_alloc(
+ if ((ctx_tmpl = kmem_alloc(
sizeof (kcf_ctx_template_t), KM_SLEEP)) == NULL) {
KCF_PROV_REFRELE(pd);
return (CRYPTO_HOST_MEMORY);
diff --git a/module/icp/api/kcf_mac.c b/module/icp/api/kcf_mac.c
index 6a72811ea480..287467e68350 100644
--- a/module/icp/api/kcf_mac.c
+++ b/module/icp/api/kcf_mac.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S b/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
index 59a4d9afd437..fefebf08116e 100644
--- a/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
+++ b/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,480 +22,69 @@
/*
* Based on BLAKE3 v1.3.1, https://github.com/BLAKE3-team/BLAKE3
* Copyright (c) 2019-2022 Samuel Neves and Matthew Krupcale
- * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * Copyright (c) 2022-2023 Tino Reichardt <milky-zfs@mcmilk.de>
*
* This is converted assembly: SSE2 -> ARMv8-A
* Used tools: SIMDe https://github.com/simd-everywhere/simde
+ *
+ * Should work on FreeBSD, Linux and macOS
+ * see: https://github.com/mcmilk/BLAKE3-tests/blob/master/contrib/simde.sh
*/
#if defined(__aarch64__)
+
+/* make gcc <= 9 happy */
+#if !defined(LD_VERSION) || LD_VERSION >= 233010000
+#define CFI_NEGATE_RA_STATE .cfi_negate_ra_state
+#else
+#define CFI_NEGATE_RA_STATE
+#endif
+
.text
- .section .rodata.cst16,"aM",@progbits,16
- .p2align 4
-.LCPI0_0:
- .word 1779033703
- .word 3144134277
- .word 1013904242
- .word 2773480762
-.LCPI0_1:
- .xword 0
- .xword -4294967296
-.LCPI0_2:
- .xword -1
- .xword 4294967295
+ .section .note.gnu.property,"a",@note
+ .p2align 3
+ .word 4
+ .word 16
+ .word 5
+ .asciz "GNU"
+ .word 3221225472
+ .word 4
+ .word 3
+ .word 0
+.Lsec_end0:
.text
.globl zfs_blake3_compress_in_place_sse2
.p2align 2
.type zfs_blake3_compress_in_place_sse2,@function
zfs_blake3_compress_in_place_sse2:
.cfi_startproc
- ldp q3, q2, [x0]
- ldp q5, q6, [x1]
- add x10, x1, #32
- lsr x11, x3, #32
- fmov s4, w3
- ld2 { v17.4s, v18.4s }, [x10]
- adrp x10, .LCPI0_2
- and w8, w2, #0xff
- mov v4.s[1], w11
- ldr q1, [x10, :lo12:.LCPI0_2]
- and w9, w4, #0xff
- adrp x12, .LCPI0_0
- mov v4.s[2], w8
- uzp1 v19.4s, v5.4s, v6.4s
- add v3.4s, v2.4s, v3.4s
- ldr q7, [x12, :lo12:.LCPI0_0]
- mov v4.s[3], w9
- add v3.4s, v3.4s, v19.4s
- uzp2 v5.4s, v5.4s, v6.4s
- ext v21.16b, v18.16b, v18.16b, #12
- uzp1 v6.4s, v19.4s, v19.4s
- ext v22.16b, v19.16b, v19.16b, #12
- eor v4.16b, v3.16b, v4.16b
- ext v20.16b, v17.16b, v17.16b, #12
- ext v6.16b, v6.16b, v19.16b, #8
- ext v19.16b, v19.16b, v22.16b, #12
- zip1 v22.2d, v21.2d, v5.2d
- rev32 v24.8h, v4.8h
- mov v4.16b, v1.16b
- zip2 v23.4s, v5.4s, v21.4s
- uzp2 v6.4s, v6.4s, v5.4s
- bsl v4.16b, v22.16b, v20.16b
- add v3.4s, v3.4s, v5.4s
- zip1 v5.4s, v23.4s, v20.4s
- zip1 v22.4s, v20.4s, v23.4s
- add v23.4s, v24.4s, v7.4s
- ext v7.16b, v6.16b, v6.16b, #4
- ext v25.16b, v4.16b, v4.16b, #12
- ext v5.16b, v22.16b, v5.16b, #8
- eor v2.16b, v23.16b, v2.16b
- uzp1 v4.4s, v4.4s, v25.4s
- uzp1 v22.4s, v7.4s, v7.4s
- ext v25.16b, v7.16b, v7.16b, #12
- ext v22.16b, v22.16b, v7.16b, #8
- ext v7.16b, v7.16b, v25.16b, #12
- ushr v25.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- orr v2.16b, v2.16b, v25.16b
- add v3.4s, v3.4s, v2.4s
- eor v24.16b, v3.16b, v24.16b
- add v3.4s, v3.4s, v17.4s
- ushr v17.4s, v24.4s, #8
- shl v18.4s, v24.4s, #24
- orr v17.16b, v18.16b, v17.16b
- add v18.4s, v17.4s, v23.4s
- eor v2.16b, v18.16b, v2.16b
- ushr v23.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- ext v3.16b, v3.16b, v3.16b, #12
- orr v2.16b, v2.16b, v23.16b
- ext v17.16b, v17.16b, v17.16b, #8
- add v3.4s, v2.4s, v3.4s
- adrp x11, .LCPI0_1
- eor v17.16b, v3.16b, v17.16b
- ldr q16, [x11, :lo12:.LCPI0_1]
- ext v18.16b, v18.16b, v18.16b, #4
- rev32 v24.8h, v17.8h
- movi v0.2d, #0xffffffff00000000
- add v23.4s, v3.4s, v21.4s
- mov v21.s[1], v20.s[2]
- add v20.4s, v18.4s, v24.4s
- bit v19.16b, v21.16b, v0.16b
- eor v3.16b, v20.16b, v2.16b
- uzp2 v2.4s, v22.4s, v19.4s
- zip1 v17.2d, v5.2d, v19.2d
- zip2 v18.4s, v19.4s, v5.4s
- ushr v21.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- ext v22.16b, v2.16b, v2.16b, #4
- bsl v16.16b, v4.16b, v17.16b
- zip1 v17.4s, v18.4s, v4.4s
- zip1 v18.4s, v4.4s, v18.4s
- orr v21.16b, v3.16b, v21.16b
- ext v25.16b, v16.16b, v16.16b, #12
- ext v3.16b, v18.16b, v17.16b, #8
- uzp1 v18.4s, v22.4s, v22.4s
- ext v26.16b, v22.16b, v22.16b, #12
- add v23.4s, v23.4s, v21.4s
- uzp1 v17.4s, v16.4s, v25.4s
- ext v16.16b, v18.16b, v22.16b, #8
- ext v18.16b, v22.16b, v26.16b, #12
- eor v22.16b, v23.16b, v24.16b
- add v6.4s, v23.4s, v6.4s
- ushr v23.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- orr v22.16b, v22.16b, v23.16b
- add v20.4s, v22.4s, v20.4s
- eor v21.16b, v20.16b, v21.16b
- ushr v23.4s, v21.4s, #7
- shl v21.4s, v21.4s, #25
- ext v6.16b, v6.16b, v6.16b, #4
- orr v21.16b, v21.16b, v23.16b
- ext v22.16b, v22.16b, v22.16b, #8
- add v6.4s, v21.4s, v6.4s
- eor v22.16b, v6.16b, v22.16b
- ext v20.16b, v20.16b, v20.16b, #12
- add v6.4s, v6.4s, v19.4s
- rev32 v19.8h, v22.8h
- add v20.4s, v20.4s, v19.4s
- eor v21.16b, v20.16b, v21.16b
- ushr v22.4s, v21.4s, #12
- shl v21.4s, v21.4s, #20
- orr v21.16b, v21.16b, v22.16b
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- ushr v22.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v19.16b, v19.16b, v22.16b
- add v20.4s, v19.4s, v20.4s
- eor v21.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #12
- ushr v22.4s, v21.4s, #7
- shl v21.4s, v21.4s, #25
- add v6.4s, v6.4s, v4.4s
- orr v21.16b, v21.16b, v22.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- ext v20.16b, v20.16b, v20.16b, #4
- rev32 v19.8h, v19.8h
- add v20.4s, v20.4s, v19.4s
- add v6.4s, v6.4s, v5.4s
- mov v5.s[1], v4.s[2]
- eor v4.16b, v20.16b, v21.16b
- ushr v21.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- orr v21.16b, v4.16b, v21.16b
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- add v2.4s, v6.4s, v2.4s
- ushr v6.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v6.16b, v19.16b, v6.16b
- add v19.4s, v6.4s, v20.4s
- eor v20.16b, v19.16b, v21.16b
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- ext v2.16b, v2.16b, v2.16b, #4
- orr v20.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v2.4s, v20.4s, v2.4s
- eor v6.16b, v2.16b, v6.16b
- ext v19.16b, v19.16b, v19.16b, #12
- rev32 v6.8h, v6.8h
- add v19.4s, v19.4s, v6.4s
- mov v22.16b, v0.16b
- eor v20.16b, v19.16b, v20.16b
- bsl v22.16b, v5.16b, v7.16b
- ushr v21.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- add v2.4s, v2.4s, v22.4s
- orr v20.16b, v20.16b, v21.16b
- add v2.4s, v2.4s, v20.4s
- eor v6.16b, v2.16b, v6.16b
- ushr v21.4s, v6.4s, #8
- shl v6.4s, v6.4s, #24
- orr v6.16b, v6.16b, v21.16b
- add v19.4s, v6.4s, v19.4s
- eor v20.16b, v19.16b, v20.16b
- ext v2.16b, v2.16b, v2.16b, #12
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- add v2.4s, v2.4s, v17.4s
- orr v20.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v2.4s, v2.4s, v20.4s
- eor v6.16b, v2.16b, v6.16b
- uzp2 v5.4s, v16.4s, v22.4s
- zip1 v7.2d, v3.2d, v22.2d
- zip2 v16.4s, v22.4s, v3.4s
- ext v19.16b, v19.16b, v19.16b, #4
- rev32 v22.8h, v6.8h
- ext v23.16b, v5.16b, v5.16b, #4
- bif v7.16b, v17.16b, v1.16b
- zip1 v24.4s, v16.4s, v17.4s
- zip1 v16.4s, v17.4s, v16.4s
- add v21.4s, v2.4s, v3.4s
- mov v3.s[1], v17.s[2]
- add v17.4s, v19.4s, v22.4s
- mov v19.16b, v0.16b
- ext v25.16b, v7.16b, v7.16b, #12
- ext v4.16b, v16.16b, v24.16b, #8
- uzp1 v16.4s, v23.4s, v23.4s
- bsl v19.16b, v3.16b, v18.16b
- eor v2.16b, v17.16b, v20.16b
- uzp1 v7.4s, v7.4s, v25.4s
- ext v25.16b, v16.16b, v23.16b, #8
- zip1 v3.2d, v4.2d, v19.2d
- ushr v20.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- ext v24.16b, v23.16b, v23.16b, #12
- uzp2 v6.4s, v25.4s, v19.4s
- zip2 v18.4s, v19.4s, v4.4s
- bif v3.16b, v7.16b, v1.16b
- orr v20.16b, v2.16b, v20.16b
- ext v16.16b, v23.16b, v24.16b, #12
- ext v23.16b, v6.16b, v6.16b, #4
- zip1 v24.4s, v18.4s, v7.4s
- zip1 v18.4s, v7.4s, v18.4s
- ext v25.16b, v3.16b, v3.16b, #12
- add v21.4s, v21.4s, v20.4s
- ext v2.16b, v18.16b, v24.16b, #8
- uzp1 v18.4s, v23.4s, v23.4s
- ext v24.16b, v23.16b, v23.16b, #12
- uzp1 v3.4s, v3.4s, v25.4s
- eor v22.16b, v21.16b, v22.16b
- ext v25.16b, v18.16b, v23.16b, #8
- dup v18.4s, v2.s[3]
- ext v23.16b, v23.16b, v24.16b, #12
- add v5.4s, v21.4s, v5.4s
- trn1 v21.4s, v3.4s, v3.4s
- ushr v24.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- ext v18.16b, v21.16b, v18.16b, #8
- orr v21.16b, v22.16b, v24.16b
- add v17.4s, v21.4s, v17.4s
- eor v20.16b, v17.16b, v20.16b
- ushr v22.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- ext v5.16b, v5.16b, v5.16b, #4
- orr v20.16b, v20.16b, v22.16b
- ext v21.16b, v21.16b, v21.16b, #8
- add v5.4s, v20.4s, v5.4s
- eor v21.16b, v5.16b, v21.16b
- ext v17.16b, v17.16b, v17.16b, #12
- add v5.4s, v5.4s, v19.4s
- rev32 v19.8h, v21.8h
- add v17.4s, v17.4s, v19.4s
- eor v20.16b, v17.16b, v20.16b
- ushr v21.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- orr v20.16b, v20.16b, v21.16b
- add v5.4s, v5.4s, v20.4s
- eor v19.16b, v5.16b, v19.16b
- ushr v21.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v19.16b, v19.16b, v21.16b
- add v17.4s, v19.4s, v17.4s
- eor v20.16b, v17.16b, v20.16b
- ext v5.16b, v5.16b, v5.16b, #12
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- add v5.4s, v5.4s, v7.4s
- orr v20.16b, v20.16b, v21.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v5.4s, v5.4s, v20.4s
- eor v19.16b, v5.16b, v19.16b
- ext v17.16b, v17.16b, v17.16b, #4
- rev32 v22.8h, v19.8h
- add v21.4s, v5.4s, v4.4s
- mov v4.s[1], v7.s[2]
- add v19.4s, v17.4s, v22.4s
- bit v16.16b, v4.16b, v0.16b
- eor v5.16b, v19.16b, v20.16b
- uzp2 v4.4s, v25.4s, v16.4s
- zip1 v7.2d, v2.2d, v16.2d
- zip2 v17.4s, v16.4s, v2.4s
- ushr v20.4s, v5.4s, #12
- shl v5.4s, v5.4s, #20
- ext v24.16b, v4.16b, v4.16b, #4
- bif v7.16b, v3.16b, v1.16b
- zip1 v25.4s, v17.4s, v3.4s
- zip1 v17.4s, v3.4s, v17.4s
- orr v20.16b, v5.16b, v20.16b
- ext v26.16b, v7.16b, v7.16b, #12
- ext v5.16b, v17.16b, v25.16b, #8
- uzp1 v17.4s, v24.4s, v24.4s
- ext v25.16b, v24.16b, v24.16b, #12
- bit v23.16b, v18.16b, v0.16b
- add v21.4s, v21.4s, v20.4s
- uzp1 v7.4s, v7.4s, v26.4s
- ext v26.16b, v17.16b, v24.16b, #8
- ext v17.16b, v24.16b, v25.16b, #12
- eor v22.16b, v21.16b, v22.16b
- add v6.4s, v21.4s, v6.4s
- zip1 v21.2d, v5.2d, v23.2d
- zip2 v24.4s, v23.4s, v5.4s
- bif v21.16b, v7.16b, v1.16b
- zip1 v1.4s, v24.4s, v7.4s
- zip1 v24.4s, v7.4s, v24.4s
- ext v1.16b, v24.16b, v1.16b, #8
- ushr v24.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- orr v22.16b, v22.16b, v24.16b
- add v19.4s, v22.4s, v19.4s
- ext v24.16b, v21.16b, v21.16b, #12
- eor v20.16b, v19.16b, v20.16b
- uzp1 v21.4s, v21.4s, v24.4s
- ushr v24.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- orr v20.16b, v20.16b, v24.16b
- ext v6.16b, v6.16b, v6.16b, #4
- ext v22.16b, v22.16b, v22.16b, #8
- add v6.4s, v20.4s, v6.4s
- eor v22.16b, v6.16b, v22.16b
- ext v19.16b, v19.16b, v19.16b, #12
- add v6.4s, v6.4s, v16.4s
- rev32 v16.8h, v22.8h
- add v19.4s, v19.4s, v16.4s
- eor v20.16b, v19.16b, v20.16b
- ushr v22.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- orr v20.16b, v20.16b, v22.16b
- add v6.4s, v6.4s, v20.4s
- eor v16.16b, v6.16b, v16.16b
- ext v6.16b, v6.16b, v6.16b, #12
- add v3.4s, v6.4s, v3.4s
- ushr v6.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- orr v6.16b, v16.16b, v6.16b
- add v16.4s, v6.4s, v19.4s
- eor v19.16b, v16.16b, v20.16b
- ushr v20.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v19.16b, v19.16b, v20.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v3.4s, v3.4s, v19.4s
- eor v6.16b, v3.16b, v6.16b
- ext v16.16b, v16.16b, v16.16b, #4
- add v2.4s, v3.4s, v2.4s
- rev32 v3.8h, v6.8h
- add v6.4s, v16.4s, v3.4s
- eor v16.16b, v6.16b, v19.16b
- ushr v19.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- orr v16.16b, v16.16b, v19.16b
- add v2.4s, v2.4s, v16.4s
- eor v3.16b, v2.16b, v3.16b
- add v2.4s, v2.4s, v4.4s
- ushr v4.4s, v3.4s, #8
- shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v4.16b
- add v4.4s, v3.4s, v6.4s
- eor v6.16b, v4.16b, v16.16b
- ushr v16.4s, v6.4s, #7
- shl v6.4s, v6.4s, #25
- ext v2.16b, v2.16b, v2.16b, #4
- orr v6.16b, v6.16b, v16.16b
- ext v3.16b, v3.16b, v3.16b, #8
- add v2.4s, v6.4s, v2.4s
- eor v3.16b, v2.16b, v3.16b
- ext v4.16b, v4.16b, v4.16b, #12
- rev32 v3.8h, v3.8h
- add v4.4s, v4.4s, v3.4s
- eor v6.16b, v4.16b, v6.16b
- ushr v16.4s, v6.4s, #12
- shl v6.4s, v6.4s, #20
- add v2.4s, v2.4s, v23.4s
- orr v6.16b, v6.16b, v16.16b
- add v2.4s, v2.4s, v6.4s
- eor v3.16b, v2.16b, v3.16b
- ushr v16.4s, v3.4s, #8
- shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v16.16b
- add v4.4s, v3.4s, v4.4s
- eor v6.16b, v4.16b, v6.16b
- ext v2.16b, v2.16b, v2.16b, #12
- ushr v16.4s, v6.4s, #7
- shl v6.4s, v6.4s, #25
- add v2.4s, v2.4s, v7.4s
- orr v6.16b, v6.16b, v16.16b
- ext v3.16b, v3.16b, v3.16b, #8
- add v2.4s, v2.4s, v6.4s
- eor v3.16b, v2.16b, v3.16b
- ext v4.16b, v4.16b, v4.16b, #4
- rev32 v3.8h, v3.8h
- add v2.4s, v2.4s, v5.4s
- mov v5.s[1], v7.s[2]
- add v4.4s, v4.4s, v3.4s
- bsl v0.16b, v5.16b, v17.16b
- eor v5.16b, v4.16b, v6.16b
- ushr v6.4s, v5.4s, #12
- shl v5.4s, v5.4s, #20
- orr v5.16b, v5.16b, v6.16b
- add v2.4s, v2.4s, v5.4s
- eor v3.16b, v2.16b, v3.16b
- ushr v6.4s, v3.4s, #8
- shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v6.16b
- add v4.4s, v3.4s, v4.4s
- uzp2 v18.4s, v26.4s, v18.4s
- eor v5.16b, v4.16b, v5.16b
- add v2.4s, v2.4s, v18.4s
- ushr v6.4s, v5.4s, #7
- shl v5.4s, v5.4s, #25
- ext v2.16b, v2.16b, v2.16b, #4
- orr v5.16b, v5.16b, v6.16b
- ext v3.16b, v3.16b, v3.16b, #8
- add v2.4s, v5.4s, v2.4s
- eor v3.16b, v2.16b, v3.16b
- ext v4.16b, v4.16b, v4.16b, #12
- add v0.4s, v2.4s, v0.4s
- rev32 v2.8h, v3.8h
- add v3.4s, v4.4s, v2.4s
- eor v4.16b, v3.16b, v5.16b
- ushr v5.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- orr v4.16b, v4.16b, v5.16b
- add v0.4s, v0.4s, v4.4s
- eor v2.16b, v0.16b, v2.16b
- ushr v5.4s, v2.4s, #8
- shl v2.4s, v2.4s, #24
- orr v2.16b, v2.16b, v5.16b
- add v3.4s, v2.4s, v3.4s
- eor v4.16b, v3.16b, v4.16b
- ext v0.16b, v0.16b, v0.16b, #12
- ushr v5.4s, v4.4s, #7
- shl v4.4s, v4.4s, #25
- add v0.4s, v0.4s, v21.4s
- orr v4.16b, v4.16b, v5.16b
- ext v2.16b, v2.16b, v2.16b, #8
- add v0.4s, v0.4s, v4.4s
- eor v2.16b, v0.16b, v2.16b
- ext v3.16b, v3.16b, v3.16b, #4
- add v0.4s, v0.4s, v1.4s
- rev32 v1.8h, v2.8h
- add v2.4s, v3.4s, v1.4s
- eor v3.16b, v2.16b, v4.16b
- ushr v4.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- orr v3.16b, v3.16b, v4.16b
- add v0.4s, v0.4s, v3.4s
- eor v1.16b, v0.16b, v1.16b
- ushr v4.4s, v1.4s, #8
- shl v1.4s, v1.4s, #24
- orr v1.16b, v1.16b, v4.16b
- add v2.4s, v1.4s, v2.4s
- eor v3.16b, v2.16b, v3.16b
- ext v0.16b, v0.16b, v0.16b, #4
- ext v2.16b, v2.16b, v2.16b, #12
- ushr v4.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- ext v1.16b, v1.16b, v1.16b, #8
+ hint #25
+ CFI_NEGATE_RA_STATE
+ sub sp, sp, #96
+ stp x29, x30, [sp, #64]
+ add x29, sp, #64
+ str x19, [sp, #80]
+ .cfi_def_cfa w29, 32
+ .cfi_offset w19, -16
+ .cfi_offset w30, -24
+ .cfi_offset w29, -32
+ mov x19, x0
+ mov w5, w4
+ mov x4, x3
+ mov w3, w2
+ mov x2, x1
+ mov x0, sp
+ mov x1, x19
+ bl compress_pre
+ ldp q0, q1, [sp]
+ ldp q2, q3, [sp, #32]
eor v0.16b, v2.16b, v0.16b
- orr v2.16b, v3.16b, v4.16b
- eor v1.16b, v2.16b, v1.16b
- stp q0, q1, [x0]
+ eor v1.16b, v3.16b, v1.16b
+ ldp x29, x30, [sp, #64]
+ stp q0, q1, [x19]
+ ldr x19, [sp, #80]
+ add sp, sp, #96
+ hint #29
ret
.Lfunc_end0:
.size zfs_blake3_compress_in_place_sse2, .Lfunc_end0-zfs_blake3_compress_in_place_sse2
@@ -504,483 +93,518 @@ zfs_blake3_compress_in_place_sse2:
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
.LCPI1_0:
- .word 1779033703
- .word 3144134277
- .word 1013904242
- .word 2773480762
-.LCPI1_1:
- .xword 0
- .xword -4294967296
-.LCPI1_2:
- .xword -1
- .xword 4294967295
+ .xword -4942790177982912921
+ .xword -6534734903820487822
.text
- .globl zfs_blake3_compress_xof_sse2
.p2align 2
- .type zfs_blake3_compress_xof_sse2,@function
-zfs_blake3_compress_xof_sse2:
+ .type compress_pre,@function
+compress_pre:
.cfi_startproc
- ldp q3, q2, [x0]
- ldp q5, q6, [x1]
- add x10, x1, #32
- lsr x11, x3, #32
- fmov s4, w3
- ld2 { v17.4s, v18.4s }, [x10]
- adrp x10, .LCPI1_2
- and w8, w2, #0xff
- mov v4.s[1], w11
- ldr q1, [x10, :lo12:.LCPI1_2]
- and w9, w4, #0xff
- adrp x12, .LCPI1_0
- mov v4.s[2], w8
- uzp1 v19.4s, v5.4s, v6.4s
- add v3.4s, v2.4s, v3.4s
- ldr q7, [x12, :lo12:.LCPI1_0]
- mov v4.s[3], w9
- add v3.4s, v3.4s, v19.4s
- uzp2 v5.4s, v5.4s, v6.4s
- ext v21.16b, v18.16b, v18.16b, #12
- uzp1 v6.4s, v19.4s, v19.4s
- ext v22.16b, v19.16b, v19.16b, #12
- eor v4.16b, v3.16b, v4.16b
- ext v20.16b, v17.16b, v17.16b, #12
- ext v6.16b, v6.16b, v19.16b, #8
- ext v19.16b, v19.16b, v22.16b, #12
- zip1 v22.2d, v21.2d, v5.2d
- rev32 v24.8h, v4.8h
- mov v4.16b, v1.16b
- zip2 v23.4s, v5.4s, v21.4s
- uzp2 v6.4s, v6.4s, v5.4s
- bsl v4.16b, v22.16b, v20.16b
- add v3.4s, v3.4s, v5.4s
- zip1 v5.4s, v23.4s, v20.4s
- zip1 v22.4s, v20.4s, v23.4s
- add v23.4s, v24.4s, v7.4s
- ext v7.16b, v6.16b, v6.16b, #4
- ext v25.16b, v4.16b, v4.16b, #12
- ext v5.16b, v22.16b, v5.16b, #8
- eor v2.16b, v23.16b, v2.16b
- uzp1 v4.4s, v4.4s, v25.4s
- uzp1 v22.4s, v7.4s, v7.4s
- ext v25.16b, v7.16b, v7.16b, #12
- ext v22.16b, v22.16b, v7.16b, #8
- ext v7.16b, v7.16b, v25.16b, #12
- ushr v25.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- orr v2.16b, v2.16b, v25.16b
- add v3.4s, v3.4s, v2.4s
- eor v24.16b, v3.16b, v24.16b
- add v3.4s, v3.4s, v17.4s
- ushr v17.4s, v24.4s, #8
- shl v18.4s, v24.4s, #24
- orr v17.16b, v18.16b, v17.16b
- add v18.4s, v17.4s, v23.4s
- eor v2.16b, v18.16b, v2.16b
- ushr v23.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- ext v3.16b, v3.16b, v3.16b, #12
- orr v2.16b, v2.16b, v23.16b
- ext v17.16b, v17.16b, v17.16b, #8
- add v3.4s, v2.4s, v3.4s
- adrp x11, .LCPI1_1
- eor v17.16b, v3.16b, v17.16b
- ldr q16, [x11, :lo12:.LCPI1_1]
- ext v18.16b, v18.16b, v18.16b, #4
- rev32 v24.8h, v17.8h
- movi v0.2d, #0xffffffff00000000
- add v23.4s, v3.4s, v21.4s
- mov v21.s[1], v20.s[2]
- add v20.4s, v18.4s, v24.4s
- bit v19.16b, v21.16b, v0.16b
- eor v3.16b, v20.16b, v2.16b
- uzp2 v2.4s, v22.4s, v19.4s
- zip1 v17.2d, v5.2d, v19.2d
- zip2 v18.4s, v19.4s, v5.4s
- ushr v21.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- ext v22.16b, v2.16b, v2.16b, #4
- bsl v16.16b, v4.16b, v17.16b
- zip1 v17.4s, v18.4s, v4.4s
- zip1 v18.4s, v4.4s, v18.4s
- orr v21.16b, v3.16b, v21.16b
- ext v25.16b, v16.16b, v16.16b, #12
- ext v3.16b, v18.16b, v17.16b, #8
- uzp1 v18.4s, v22.4s, v22.4s
- ext v26.16b, v22.16b, v22.16b, #12
- add v23.4s, v23.4s, v21.4s
- uzp1 v17.4s, v16.4s, v25.4s
- ext v16.16b, v18.16b, v22.16b, #8
- ext v18.16b, v22.16b, v26.16b, #12
- eor v22.16b, v23.16b, v24.16b
- add v6.4s, v23.4s, v6.4s
- ushr v23.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- orr v22.16b, v22.16b, v23.16b
- add v20.4s, v22.4s, v20.4s
- eor v21.16b, v20.16b, v21.16b
- ushr v23.4s, v21.4s, #7
- shl v21.4s, v21.4s, #25
- ext v6.16b, v6.16b, v6.16b, #4
- orr v21.16b, v21.16b, v23.16b
- ext v22.16b, v22.16b, v22.16b, #8
- add v6.4s, v21.4s, v6.4s
- eor v22.16b, v6.16b, v22.16b
- ext v20.16b, v20.16b, v20.16b, #12
- add v6.4s, v6.4s, v19.4s
- rev32 v19.8h, v22.8h
- add v20.4s, v20.4s, v19.4s
- eor v21.16b, v20.16b, v21.16b
- ushr v22.4s, v21.4s, #12
- shl v21.4s, v21.4s, #20
- orr v21.16b, v21.16b, v22.16b
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- ushr v22.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v19.16b, v19.16b, v22.16b
- add v20.4s, v19.4s, v20.4s
- eor v21.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #12
- ushr v22.4s, v21.4s, #7
- shl v21.4s, v21.4s, #25
- add v6.4s, v6.4s, v4.4s
- orr v21.16b, v21.16b, v22.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- ext v20.16b, v20.16b, v20.16b, #4
- rev32 v19.8h, v19.8h
- add v20.4s, v20.4s, v19.4s
- add v6.4s, v6.4s, v5.4s
- mov v5.s[1], v4.s[2]
- eor v4.16b, v20.16b, v21.16b
- ushr v21.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- orr v21.16b, v4.16b, v21.16b
- add v6.4s, v6.4s, v21.4s
- eor v19.16b, v6.16b, v19.16b
- add v2.4s, v6.4s, v2.4s
- ushr v6.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v6.16b, v19.16b, v6.16b
- add v19.4s, v6.4s, v20.4s
- eor v20.16b, v19.16b, v21.16b
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- ext v2.16b, v2.16b, v2.16b, #4
- orr v20.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v2.4s, v20.4s, v2.4s
- eor v6.16b, v2.16b, v6.16b
- ext v19.16b, v19.16b, v19.16b, #12
- rev32 v6.8h, v6.8h
- add v19.4s, v19.4s, v6.4s
- mov v22.16b, v0.16b
- eor v20.16b, v19.16b, v20.16b
- bsl v22.16b, v5.16b, v7.16b
- ushr v21.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- add v2.4s, v2.4s, v22.4s
- orr v20.16b, v20.16b, v21.16b
- add v2.4s, v2.4s, v20.4s
- eor v6.16b, v2.16b, v6.16b
- ushr v21.4s, v6.4s, #8
- shl v6.4s, v6.4s, #24
- orr v6.16b, v6.16b, v21.16b
- add v19.4s, v6.4s, v19.4s
- eor v20.16b, v19.16b, v20.16b
- ext v2.16b, v2.16b, v2.16b, #12
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- add v2.4s, v2.4s, v17.4s
- orr v20.16b, v20.16b, v21.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v2.4s, v2.4s, v20.4s
- eor v6.16b, v2.16b, v6.16b
- uzp2 v5.4s, v16.4s, v22.4s
- zip1 v7.2d, v3.2d, v22.2d
- zip2 v16.4s, v22.4s, v3.4s
- ext v19.16b, v19.16b, v19.16b, #4
- rev32 v22.8h, v6.8h
- ext v23.16b, v5.16b, v5.16b, #4
- bif v7.16b, v17.16b, v1.16b
- zip1 v24.4s, v16.4s, v17.4s
- zip1 v16.4s, v17.4s, v16.4s
- add v21.4s, v2.4s, v3.4s
- mov v3.s[1], v17.s[2]
- add v17.4s, v19.4s, v22.4s
- mov v19.16b, v0.16b
- ext v25.16b, v7.16b, v7.16b, #12
- ext v4.16b, v16.16b, v24.16b, #8
- uzp1 v16.4s, v23.4s, v23.4s
- bsl v19.16b, v3.16b, v18.16b
- eor v2.16b, v17.16b, v20.16b
- uzp1 v7.4s, v7.4s, v25.4s
- ext v25.16b, v16.16b, v23.16b, #8
- zip1 v3.2d, v4.2d, v19.2d
- ushr v20.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- ext v24.16b, v23.16b, v23.16b, #12
- uzp2 v6.4s, v25.4s, v19.4s
- zip2 v18.4s, v19.4s, v4.4s
- bif v3.16b, v7.16b, v1.16b
- orr v20.16b, v2.16b, v20.16b
- ext v16.16b, v23.16b, v24.16b, #12
- ext v23.16b, v6.16b, v6.16b, #4
- zip1 v24.4s, v18.4s, v7.4s
- zip1 v18.4s, v7.4s, v18.4s
- ext v25.16b, v3.16b, v3.16b, #12
- add v21.4s, v21.4s, v20.4s
- ext v2.16b, v18.16b, v24.16b, #8
- uzp1 v18.4s, v23.4s, v23.4s
- ext v24.16b, v23.16b, v23.16b, #12
- uzp1 v3.4s, v3.4s, v25.4s
- eor v22.16b, v21.16b, v22.16b
- ext v25.16b, v18.16b, v23.16b, #8
- dup v18.4s, v2.s[3]
- ext v23.16b, v23.16b, v24.16b, #12
- add v5.4s, v21.4s, v5.4s
- trn1 v21.4s, v3.4s, v3.4s
- ushr v24.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- ext v18.16b, v21.16b, v18.16b, #8
- orr v21.16b, v22.16b, v24.16b
- add v17.4s, v21.4s, v17.4s
- eor v20.16b, v17.16b, v20.16b
- ushr v22.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- ext v5.16b, v5.16b, v5.16b, #4
- orr v20.16b, v20.16b, v22.16b
- ext v21.16b, v21.16b, v21.16b, #8
- add v5.4s, v20.4s, v5.4s
- eor v21.16b, v5.16b, v21.16b
- ext v17.16b, v17.16b, v17.16b, #12
- add v5.4s, v5.4s, v19.4s
- rev32 v19.8h, v21.8h
- add v17.4s, v17.4s, v19.4s
- eor v20.16b, v17.16b, v20.16b
- ushr v21.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- orr v20.16b, v20.16b, v21.16b
- add v5.4s, v5.4s, v20.4s
- eor v19.16b, v5.16b, v19.16b
- ushr v21.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v19.16b, v19.16b, v21.16b
- add v17.4s, v19.4s, v17.4s
- eor v20.16b, v17.16b, v20.16b
- ext v5.16b, v5.16b, v5.16b, #12
- ushr v21.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- add v5.4s, v5.4s, v7.4s
- orr v20.16b, v20.16b, v21.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v5.4s, v5.4s, v20.4s
- eor v19.16b, v5.16b, v19.16b
- ext v17.16b, v17.16b, v17.16b, #4
- rev32 v22.8h, v19.8h
- add v21.4s, v5.4s, v4.4s
- mov v4.s[1], v7.s[2]
- add v19.4s, v17.4s, v22.4s
- bit v16.16b, v4.16b, v0.16b
- eor v5.16b, v19.16b, v20.16b
- uzp2 v4.4s, v25.4s, v16.4s
- zip1 v7.2d, v2.2d, v16.2d
- zip2 v17.4s, v16.4s, v2.4s
- ushr v20.4s, v5.4s, #12
- shl v5.4s, v5.4s, #20
- ext v24.16b, v4.16b, v4.16b, #4
- bif v7.16b, v3.16b, v1.16b
- zip1 v25.4s, v17.4s, v3.4s
- zip1 v17.4s, v3.4s, v17.4s
- orr v20.16b, v5.16b, v20.16b
- ext v26.16b, v7.16b, v7.16b, #12
- ext v5.16b, v17.16b, v25.16b, #8
- uzp1 v17.4s, v24.4s, v24.4s
- ext v25.16b, v24.16b, v24.16b, #12
- bit v23.16b, v18.16b, v0.16b
- add v21.4s, v21.4s, v20.4s
- uzp1 v7.4s, v7.4s, v26.4s
- ext v26.16b, v17.16b, v24.16b, #8
- ext v17.16b, v24.16b, v25.16b, #12
- eor v22.16b, v21.16b, v22.16b
- add v6.4s, v21.4s, v6.4s
- zip1 v21.2d, v5.2d, v23.2d
- zip2 v24.4s, v23.4s, v5.4s
- bif v21.16b, v7.16b, v1.16b
- zip1 v1.4s, v24.4s, v7.4s
- zip1 v24.4s, v7.4s, v24.4s
- ext v1.16b, v24.16b, v1.16b, #8
- ushr v24.4s, v22.4s, #8
- shl v22.4s, v22.4s, #24
- orr v22.16b, v22.16b, v24.16b
- add v19.4s, v22.4s, v19.4s
- ext v24.16b, v21.16b, v21.16b, #12
- eor v20.16b, v19.16b, v20.16b
- uzp1 v21.4s, v21.4s, v24.4s
- ushr v24.4s, v20.4s, #7
- shl v20.4s, v20.4s, #25
- orr v20.16b, v20.16b, v24.16b
- ext v6.16b, v6.16b, v6.16b, #4
- ext v22.16b, v22.16b, v22.16b, #8
- add v6.4s, v20.4s, v6.4s
- eor v22.16b, v6.16b, v22.16b
- ext v19.16b, v19.16b, v19.16b, #12
- add v6.4s, v6.4s, v16.4s
- rev32 v16.8h, v22.8h
- add v19.4s, v19.4s, v16.4s
- eor v20.16b, v19.16b, v20.16b
- ushr v22.4s, v20.4s, #12
- shl v20.4s, v20.4s, #20
- orr v20.16b, v20.16b, v22.16b
- add v6.4s, v6.4s, v20.4s
- eor v16.16b, v6.16b, v16.16b
- ext v6.16b, v6.16b, v6.16b, #12
- add v3.4s, v6.4s, v3.4s
- ushr v6.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- orr v6.16b, v16.16b, v6.16b
- add v16.4s, v6.4s, v19.4s
- eor v19.16b, v16.16b, v20.16b
- ushr v20.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v19.16b, v19.16b, v20.16b
- ext v6.16b, v6.16b, v6.16b, #8
- add v3.4s, v3.4s, v19.4s
- eor v6.16b, v3.16b, v6.16b
- ext v16.16b, v16.16b, v16.16b, #4
- add v2.4s, v3.4s, v2.4s
- rev32 v3.8h, v6.8h
- add v6.4s, v16.4s, v3.4s
- eor v16.16b, v6.16b, v19.16b
- ushr v19.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- orr v16.16b, v16.16b, v19.16b
- add v2.4s, v2.4s, v16.4s
- eor v3.16b, v2.16b, v3.16b
- add v2.4s, v2.4s, v4.4s
- ushr v4.4s, v3.4s, #8
- shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v4.16b
- add v4.4s, v3.4s, v6.4s
- eor v6.16b, v4.16b, v16.16b
- ushr v16.4s, v6.4s, #7
- shl v6.4s, v6.4s, #25
- ext v2.16b, v2.16b, v2.16b, #4
- orr v6.16b, v6.16b, v16.16b
- ext v3.16b, v3.16b, v3.16b, #8
- add v2.4s, v6.4s, v2.4s
+ hint #34
+ fmov s1, w3
+ movi d0, #0x0000ff000000ff
+ ldr q2, [x1]
+ fmov d3, x4
+ adrp x8, .LCPI1_0
+ mov v1.s[1], w5
+ str q2, [x0]
+ ldr q4, [x8, :lo12:.LCPI1_0]
+ add x8, x2, #32
+ ldr q5, [x1, #16]
+ and v0.8b, v1.8b, v0.8b
+ stp q5, q4, [x0, #16]
+ mov v3.d[1], v0.d[0]
+ str q3, [x0, #48]
+ ldp q0, q6, [x2]
+ uzp1 v1.4s, v0.4s, v6.4s
+ uzp2 v0.4s, v0.4s, v6.4s
+ add v2.4s, v2.4s, v1.4s
+ uzp1 v18.4s, v1.4s, v1.4s
+ add v2.4s, v2.4s, v5.4s
eor v3.16b, v2.16b, v3.16b
- ext v4.16b, v4.16b, v4.16b, #12
+ add v2.4s, v2.4s, v0.4s
rev32 v3.8h, v3.8h
- add v4.4s, v4.4s, v3.4s
- eor v6.16b, v4.16b, v6.16b
- ushr v16.4s, v6.4s, #12
- shl v6.4s, v6.4s, #20
- add v2.4s, v2.4s, v23.4s
- orr v6.16b, v6.16b, v16.16b
- add v2.4s, v2.4s, v6.4s
+ add v4.4s, v3.4s, v4.4s
+ eor v5.16b, v4.16b, v5.16b
+ ushr v6.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v6.16b
+ add v2.4s, v2.4s, v5.4s
eor v3.16b, v2.16b, v3.16b
- ushr v16.4s, v3.4s, #8
+ ushr v6.4s, v3.4s, #8
shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v16.16b
+ orr v3.16b, v3.16b, v6.16b
+ ld2 { v6.4s, v7.4s }, [x8]
add v4.4s, v3.4s, v4.4s
- eor v6.16b, v4.16b, v6.16b
- ext v2.16b, v2.16b, v2.16b, #12
- ushr v16.4s, v6.4s, #7
- shl v6.4s, v6.4s, #25
- add v2.4s, v2.4s, v7.4s
- orr v6.16b, v6.16b, v16.16b
ext v3.16b, v3.16b, v3.16b, #8
add v2.4s, v2.4s, v6.4s
- eor v3.16b, v2.16b, v3.16b
+ eor v5.16b, v4.16b, v5.16b
ext v4.16b, v4.16b, v4.16b, #4
- rev32 v3.8h, v3.8h
+ ext v6.16b, v6.16b, v6.16b, #12
+ ext v2.16b, v2.16b, v2.16b, #12
+ ushr v16.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v16.16b
+ ext v16.16b, v7.16b, v7.16b, #12
add v2.4s, v2.4s, v5.4s
- mov v5.s[1], v7.s[2]
+ mov v7.16b, v16.16b
+ eor v3.16b, v3.16b, v2.16b
+ add v2.4s, v2.4s, v16.4s
+ mov v7.s[1], v6.s[2]
+ rev32 v3.8h, v3.8h
add v4.4s, v4.4s, v3.4s
- bsl v0.16b, v5.16b, v17.16b
- eor v5.16b, v4.16b, v6.16b
- ushr v6.4s, v5.4s, #12
+ eor v5.16b, v4.16b, v5.16b
+ ushr v17.4s, v5.4s, #12
shl v5.4s, v5.4s, #20
- orr v5.16b, v5.16b, v6.16b
+ orr v5.16b, v5.16b, v17.16b
add v2.4s, v2.4s, v5.4s
eor v3.16b, v2.16b, v3.16b
- ushr v6.4s, v3.4s, #8
+ ushr v17.4s, v3.4s, #8
shl v3.4s, v3.4s, #24
- orr v3.16b, v3.16b, v6.16b
+ orr v3.16b, v3.16b, v17.16b
+ ext v17.16b, v18.16b, v1.16b, #8
add v4.4s, v3.4s, v4.4s
- uzp2 v18.4s, v26.4s, v18.4s
+ uzp2 v17.4s, v17.4s, v0.4s
+ ext v3.16b, v3.16b, v3.16b, #8
eor v5.16b, v4.16b, v5.16b
- add v2.4s, v2.4s, v18.4s
- ushr v6.4s, v5.4s, #7
+ add v2.4s, v2.4s, v17.4s
+ ext v4.16b, v4.16b, v4.16b, #12
+ ushr v18.4s, v5.4s, #7
shl v5.4s, v5.4s, #25
ext v2.16b, v2.16b, v2.16b, #4
- orr v5.16b, v5.16b, v6.16b
+ orr v5.16b, v5.16b, v18.16b
+ ext v18.16b, v1.16b, v1.16b, #12
+ add v2.4s, v2.4s, v5.4s
+ ext v1.16b, v1.16b, v18.16b, #12
+ zip1 v18.2d, v16.2d, v0.2d
+ zip2 v0.4s, v0.4s, v16.4s
+ eor v3.16b, v3.16b, v2.16b
+ rev64 v1.4s, v1.4s
+ mov v18.s[3], v6.s[3]
+ zip1 v16.4s, v0.4s, v6.4s
+ rev32 v3.8h, v3.8h
+ trn2 v1.4s, v1.4s, v7.4s
+ zip1 v0.4s, v6.4s, v0.4s
+ add v4.4s, v4.4s, v3.4s
+ add v2.4s, v2.4s, v1.4s
+ ext v6.16b, v0.16b, v16.16b, #8
+ eor v5.16b, v4.16b, v5.16b
+ ushr v7.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v7.16b
+ add v7.4s, v2.4s, v5.4s
+ eor v2.16b, v7.16b, v3.16b
+ ext v7.16b, v7.16b, v7.16b, #12
+ ushr v3.4s, v2.4s, #8
+ shl v2.4s, v2.4s, #24
+ orr v3.16b, v2.16b, v3.16b
+ ext v2.16b, v18.16b, v18.16b, #12
+ add v4.4s, v3.4s, v4.4s
+ uzp1 v2.4s, v18.4s, v2.4s
ext v3.16b, v3.16b, v3.16b, #8
- add v2.4s, v5.4s, v2.4s
- eor v3.16b, v2.16b, v3.16b
+ eor v5.16b, v4.16b, v5.16b
+ add v7.4s, v7.4s, v2.4s
+ ext v4.16b, v4.16b, v4.16b, #4
+ ushr v18.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v18.16b
+ add v7.4s, v7.4s, v5.4s
+ eor v3.16b, v3.16b, v7.16b
+ add v7.4s, v7.4s, v6.4s
+ rev32 v3.8h, v3.8h
+ add v4.4s, v4.4s, v3.4s
+ eor v5.16b, v4.16b, v5.16b
+ ushr v0.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v0.16b, v5.16b, v0.16b
+ add v5.4s, v7.4s, v0.4s
+ ext v7.16b, v17.16b, v17.16b, #4
+ eor v3.16b, v5.16b, v3.16b
+ uzp1 v17.4s, v7.4s, v7.4s
+ ushr v16.4s, v3.4s, #8
+ shl v3.4s, v3.4s, #24
+ orr v3.16b, v3.16b, v16.16b
+ ext v16.16b, v17.16b, v7.16b, #8
+ add v4.4s, v3.4s, v4.4s
+ uzp2 v16.4s, v16.4s, v1.4s
+ ext v3.16b, v3.16b, v3.16b, #8
+ eor v0.16b, v4.16b, v0.16b
+ add v5.4s, v5.4s, v16.4s
ext v4.16b, v4.16b, v4.16b, #12
- add v0.4s, v2.4s, v0.4s
- rev32 v2.8h, v3.8h
- add v3.4s, v4.4s, v2.4s
- eor v4.16b, v3.16b, v5.16b
- ushr v5.4s, v4.4s, #12
+ ushr v17.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ext v5.16b, v5.16b, v5.16b, #4
+ orr v0.16b, v0.16b, v17.16b
+ ext v17.16b, v7.16b, v7.16b, #12
+ add v5.4s, v5.4s, v0.4s
+ ext v7.16b, v7.16b, v17.16b, #12
+ mov v17.16b, v6.16b
+ eor v3.16b, v3.16b, v5.16b
+ rev64 v7.4s, v7.4s
+ mov v17.s[1], v2.s[2]
+ rev32 v3.8h, v3.8h
+ add v4.4s, v4.4s, v3.4s
+ eor v18.16b, v4.16b, v0.16b
+ trn2 v0.4s, v7.4s, v17.4s
+ ushr v7.4s, v18.4s, #12
+ shl v17.4s, v18.4s, #20
+ add v5.4s, v5.4s, v0.4s
+ zip1 v18.2d, v6.2d, v1.2d
+ zip2 v1.4s, v1.4s, v6.4s
+ orr v7.16b, v17.16b, v7.16b
+ mov v18.s[3], v2.s[3]
+ zip1 v6.4s, v1.4s, v2.4s
+ add v5.4s, v5.4s, v7.4s
+ zip1 v1.4s, v2.4s, v1.4s
+ eor v3.16b, v5.16b, v3.16b
+ ext v5.16b, v5.16b, v5.16b, #12
+ ext v6.16b, v1.16b, v6.16b, #8
+ ushr v17.4s, v3.4s, #8
+ shl v3.4s, v3.4s, #24
+ orr v17.16b, v3.16b, v17.16b
+ ext v3.16b, v18.16b, v18.16b, #12
+ add v4.4s, v17.4s, v4.4s
+ uzp1 v3.4s, v18.4s, v3.4s
+ ext v17.16b, v17.16b, v17.16b, #8
+ eor v7.16b, v4.16b, v7.16b
+ add v5.4s, v5.4s, v3.4s
+ ext v4.16b, v4.16b, v4.16b, #4
+ ushr v18.4s, v7.4s, #7
+ shl v7.4s, v7.4s, #25
+ orr v7.16b, v7.16b, v18.16b
+ add v5.4s, v5.4s, v7.4s
+ eor v17.16b, v17.16b, v5.16b
+ add v5.4s, v5.4s, v6.4s
+ rev32 v17.8h, v17.8h
+ add v4.4s, v4.4s, v17.4s
+ eor v2.16b, v4.16b, v7.16b
+ ext v7.16b, v16.16b, v16.16b, #4
+ ushr v1.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v2.16b, v1.16b
+ add v2.4s, v5.4s, v1.4s
+ eor v5.16b, v2.16b, v17.16b
+ uzp1 v17.4s, v7.4s, v7.4s
+ ushr v16.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ orr v5.16b, v5.16b, v16.16b
+ ext v16.16b, v17.16b, v7.16b, #8
+ add v4.4s, v5.4s, v4.4s
+ uzp2 v16.4s, v16.4s, v0.4s
+ ext v5.16b, v5.16b, v5.16b, #8
+ eor v1.16b, v4.16b, v1.16b
+ add v2.4s, v2.4s, v16.4s
+ ext v4.16b, v4.16b, v4.16b, #12
+ ushr v17.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ext v2.16b, v2.16b, v2.16b, #4
+ orr v1.16b, v1.16b, v17.16b
+ ext v17.16b, v7.16b, v7.16b, #12
+ add v2.4s, v2.4s, v1.4s
+ ext v7.16b, v7.16b, v17.16b, #12
+ mov v17.16b, v6.16b
+ eor v5.16b, v5.16b, v2.16b
+ rev64 v7.4s, v7.4s
+ mov v17.s[1], v3.s[2]
+ rev32 v5.8h, v5.8h
+ add v4.4s, v4.4s, v5.4s
+ eor v18.16b, v4.16b, v1.16b
+ trn2 v1.4s, v7.4s, v17.4s
+ ushr v7.4s, v18.4s, #12
+ shl v17.4s, v18.4s, #20
+ add v2.4s, v2.4s, v1.4s
+ zip1 v18.2d, v6.2d, v0.2d
+ zip2 v0.4s, v0.4s, v6.4s
+ orr v7.16b, v17.16b, v7.16b
+ mov v18.s[3], v3.s[3]
+ add v2.4s, v2.4s, v7.4s
+ eor v5.16b, v2.16b, v5.16b
+ ext v2.16b, v2.16b, v2.16b, #12
+ ushr v17.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ orr v5.16b, v5.16b, v17.16b
+ add v17.4s, v5.4s, v4.4s
+ ext v4.16b, v18.16b, v18.16b, #12
+ ext v5.16b, v5.16b, v5.16b, #8
+ eor v7.16b, v17.16b, v7.16b
+ uzp1 v4.4s, v18.4s, v4.4s
+ ext v17.16b, v17.16b, v17.16b, #4
+ ushr v18.4s, v7.4s, #7
+ shl v7.4s, v7.4s, #25
+ add v2.4s, v2.4s, v4.4s
+ orr v7.16b, v7.16b, v18.16b
+ add v2.4s, v2.4s, v7.4s
+ eor v5.16b, v5.16b, v2.16b
+ rev32 v5.8h, v5.8h
+ add v6.4s, v17.4s, v5.4s
+ zip1 v17.4s, v0.4s, v3.4s
+ zip1 v0.4s, v3.4s, v0.4s
+ eor v3.16b, v6.16b, v7.16b
+ ext v0.16b, v0.16b, v17.16b, #8
+ ushr v7.4s, v3.4s, #12
+ shl v3.4s, v3.4s, #20
+ add v2.4s, v2.4s, v0.4s
+ orr v3.16b, v3.16b, v7.16b
+ ext v7.16b, v16.16b, v16.16b, #4
+ add v2.4s, v2.4s, v3.4s
+ uzp1 v17.4s, v7.4s, v7.4s
+ eor v5.16b, v2.16b, v5.16b
+ ushr v16.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ orr v5.16b, v5.16b, v16.16b
+ ext v16.16b, v17.16b, v7.16b, #8
+ add v6.4s, v5.4s, v6.4s
+ uzp2 v16.4s, v16.4s, v1.4s
+ ext v5.16b, v5.16b, v5.16b, #8
+ eor v3.16b, v6.16b, v3.16b
+ add v2.4s, v2.4s, v16.4s
+ ext v6.16b, v6.16b, v6.16b, #12
+ ushr v17.4s, v3.4s, #7
+ shl v3.4s, v3.4s, #25
+ ext v2.16b, v2.16b, v2.16b, #4
+ orr v3.16b, v3.16b, v17.16b
+ add v17.4s, v2.4s, v3.4s
+ eor v2.16b, v5.16b, v17.16b
+ ext v5.16b, v7.16b, v7.16b, #12
+ rev32 v18.8h, v2.8h
+ ext v2.16b, v7.16b, v5.16b, #12
+ mov v5.16b, v0.16b
+ add v6.4s, v6.4s, v18.4s
+ rev64 v2.4s, v2.4s
+ mov v5.s[1], v4.s[2]
+ eor v3.16b, v6.16b, v3.16b
+ trn2 v2.4s, v2.4s, v5.4s
+ ushr v5.4s, v3.4s, #12
+ shl v3.4s, v3.4s, #20
+ add v7.4s, v17.4s, v2.4s
+ orr v3.16b, v3.16b, v5.16b
+ add v5.4s, v7.4s, v3.4s
+ eor v7.16b, v5.16b, v18.16b
+ zip1 v18.2d, v0.2d, v1.2d
+ ext v5.16b, v5.16b, v5.16b, #12
+ zip2 v0.4s, v1.4s, v0.4s
+ ushr v17.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ mov v18.s[3], v4.s[3]
+ orr v7.16b, v7.16b, v17.16b
+ ext v17.16b, v18.16b, v18.16b, #12
+ add v6.4s, v7.4s, v6.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v19.16b, v6.16b, v3.16b
+ uzp1 v3.4s, v18.4s, v17.4s
+ ext v6.16b, v6.16b, v6.16b, #4
+ ushr v17.4s, v19.4s, #7
+ shl v18.4s, v19.4s, #25
+ add v5.4s, v5.4s, v3.4s
+ orr v17.16b, v18.16b, v17.16b
+ add v5.4s, v5.4s, v17.4s
+ eor v7.16b, v7.16b, v5.16b
+ rev32 v7.8h, v7.8h
+ add v1.4s, v6.4s, v7.4s
+ zip1 v6.4s, v0.4s, v4.4s
+ zip1 v0.4s, v4.4s, v0.4s
+ eor v4.16b, v1.16b, v17.16b
+ ext v6.16b, v0.16b, v6.16b, #8
+ ushr v0.4s, v4.4s, #12
shl v4.4s, v4.4s, #20
- orr v4.16b, v4.16b, v5.16b
- add v0.4s, v0.4s, v4.4s
- eor v2.16b, v0.16b, v2.16b
- ushr v5.4s, v2.4s, #8
- shl v2.4s, v2.4s, #24
- orr v2.16b, v2.16b, v5.16b
- add v3.4s, v2.4s, v3.4s
- eor v4.16b, v3.16b, v4.16b
- ext v0.16b, v0.16b, v0.16b, #12
- ushr v5.4s, v4.4s, #7
- shl v4.4s, v4.4s, #25
- add v0.4s, v0.4s, v21.4s
- orr v4.16b, v4.16b, v5.16b
- ext v2.16b, v2.16b, v2.16b, #8
- add v0.4s, v0.4s, v4.4s
- eor v2.16b, v0.16b, v2.16b
- ext v3.16b, v3.16b, v3.16b, #4
- add v0.4s, v0.4s, v1.4s
- rev32 v1.8h, v2.8h
- add v2.4s, v3.4s, v1.4s
- eor v3.16b, v2.16b, v4.16b
- ushr v4.4s, v3.4s, #12
+ add v5.4s, v5.4s, v6.4s
+ zip1 v20.2d, v6.2d, v2.2d
+ orr v0.16b, v4.16b, v0.16b
+ mov v20.s[3], v3.s[3]
+ add v4.4s, v5.4s, v0.4s
+ eor v5.16b, v4.16b, v7.16b
+ ext v7.16b, v16.16b, v16.16b, #4
+ ushr v16.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ uzp1 v17.4s, v7.4s, v7.4s
+ orr v5.16b, v5.16b, v16.16b
+ ext v16.16b, v17.16b, v7.16b, #8
+ add v1.4s, v5.4s, v1.4s
+ uzp2 v16.4s, v16.4s, v2.4s
+ zip2 v2.4s, v2.4s, v6.4s
+ eor v0.16b, v1.16b, v0.16b
+ add v4.4s, v4.4s, v16.4s
+ ext v1.16b, v1.16b, v1.16b, #12
+ ext v16.16b, v16.16b, v16.16b, #4
+ ushr v17.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ext v4.16b, v4.16b, v4.16b, #4
+ orr v17.16b, v0.16b, v17.16b
+ ext v0.16b, v5.16b, v5.16b, #8
+ ext v5.16b, v7.16b, v7.16b, #12
+ add v4.4s, v4.4s, v17.4s
+ eor v0.16b, v0.16b, v4.16b
+ rev32 v18.8h, v0.8h
+ ext v0.16b, v7.16b, v5.16b, #12
+ mov v5.16b, v6.16b
+ add v7.4s, v1.4s, v18.4s
+ rev64 v1.4s, v0.4s
+ mov v5.s[1], v3.s[2]
+ eor v17.16b, v7.16b, v17.16b
+ trn2 v1.4s, v1.4s, v5.4s
+ ushr v19.4s, v17.4s, #12
+ shl v17.4s, v17.4s, #20
+ add v4.4s, v4.4s, v1.4s
+ orr v17.16b, v17.16b, v19.16b
+ add v19.4s, v4.4s, v17.4s
+ eor v4.16b, v19.16b, v18.16b
+ ext v19.16b, v19.16b, v19.16b, #12
+ ushr v18.4s, v4.4s, #8
+ shl v4.4s, v4.4s, #24
+ orr v18.16b, v4.16b, v18.16b
+ ext v4.16b, v20.16b, v20.16b, #12
+ add v7.4s, v18.4s, v7.4s
+ uzp1 v4.4s, v20.4s, v4.4s
+ ext v18.16b, v18.16b, v18.16b, #8
+ eor v17.16b, v7.16b, v17.16b
+ add v19.4s, v19.4s, v4.4s
+ ext v7.16b, v7.16b, v7.16b, #4
+ ushr v20.4s, v17.4s, #7
+ shl v17.4s, v17.4s, #25
+ orr v17.16b, v17.16b, v20.16b
+ add v19.4s, v19.4s, v17.4s
+ eor v18.16b, v18.16b, v19.16b
+ rev32 v18.8h, v18.8h
+ add v6.4s, v7.4s, v18.4s
+ zip1 v7.4s, v2.4s, v3.4s
+ zip1 v2.4s, v3.4s, v2.4s
+ eor v3.16b, v6.16b, v17.16b
+ ext v2.16b, v2.16b, v7.16b, #8
+ ushr v7.4s, v3.4s, #12
shl v3.4s, v3.4s, #20
- orr v3.16b, v3.16b, v4.16b
- add v0.4s, v0.4s, v3.4s
- eor v1.16b, v0.16b, v1.16b
- ushr v4.4s, v1.4s, #8
- shl v1.4s, v1.4s, #24
- orr v1.16b, v1.16b, v4.16b
- add v2.4s, v1.4s, v2.4s
- eor v3.16b, v2.16b, v3.16b
- ushr v4.4s, v3.4s, #7
+ add v17.4s, v19.4s, v2.4s
+ zip1 v1.2d, v2.2d, v1.2d
+ zip2 v0.4s, v0.4s, v2.4s
+ orr v3.16b, v3.16b, v7.16b
+ mov v1.s[3], v4.s[3]
+ add v7.4s, v17.4s, v3.4s
+ eor v17.16b, v7.16b, v18.16b
+ ext v7.16b, v7.16b, v7.16b, #4
+ ushr v18.4s, v17.4s, #8
+ shl v17.4s, v17.4s, #24
+ orr v17.16b, v17.16b, v18.16b
+ ext v18.16b, v16.16b, v16.16b, #8
+ add v6.4s, v17.4s, v6.4s
+ uzp2 v5.4s, v18.4s, v5.4s
+ eor v3.16b, v6.16b, v3.16b
+ ext v5.16b, v5.16b, v18.16b, #4
+ ext v6.16b, v6.16b, v6.16b, #12
+ ushr v18.4s, v3.4s, #7
+ shl v3.4s, v3.4s, #25
+ add v5.4s, v7.4s, v5.4s
+ ext v7.16b, v17.16b, v17.16b, #8
+ ext v17.16b, v16.16b, v16.16b, #12
+ orr v3.16b, v3.16b, v18.16b
+ ext v16.16b, v16.16b, v17.16b, #12
+ add v5.4s, v3.4s, v5.4s
+ mov v17.16b, v2.16b
+ rev64 v16.4s, v16.4s
+ eor v7.16b, v7.16b, v5.16b
+ mov v17.s[1], v4.s[2]
+ rev32 v7.8h, v7.8h
+ trn2 v16.4s, v16.4s, v17.4s
+ add v6.4s, v6.4s, v7.4s
+ add v5.4s, v5.4s, v16.4s
+ eor v3.16b, v6.16b, v3.16b
+ ushr v17.4s, v3.4s, #12
+ shl v3.4s, v3.4s, #20
+ orr v3.16b, v3.16b, v17.16b
+ add v5.4s, v5.4s, v3.4s
+ eor v7.16b, v5.16b, v7.16b
+ ext v5.16b, v5.16b, v5.16b, #12
+ ushr v16.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ orr v7.16b, v7.16b, v16.16b
+ ext v16.16b, v1.16b, v1.16b, #12
+ add v6.4s, v7.4s, v6.4s
+ uzp1 v1.4s, v1.4s, v16.4s
+ eor v3.16b, v6.16b, v3.16b
+ add v1.4s, v5.4s, v1.4s
+ ext v5.16b, v7.16b, v7.16b, #8
+ ext v6.16b, v6.16b, v6.16b, #4
+ ushr v16.4s, v3.4s, #7
shl v3.4s, v3.4s, #25
+ orr v3.16b, v3.16b, v16.16b
+ add v1.4s, v1.4s, v3.4s
+ eor v5.16b, v5.16b, v1.16b
+ rev32 v5.8h, v5.8h
+ add v2.4s, v6.4s, v5.4s
+ zip1 v6.4s, v0.4s, v4.4s
+ zip1 v0.4s, v4.4s, v0.4s
+ eor v3.16b, v2.16b, v3.16b
+ ext v0.16b, v0.16b, v6.16b, #8
+ ushr v4.4s, v3.4s, #12
+ shl v3.4s, v3.4s, #20
+ add v0.4s, v1.4s, v0.4s
+ orr v1.16b, v3.16b, v4.16b
+ add v0.4s, v0.4s, v1.4s
+ eor v3.16b, v0.16b, v5.16b
ext v0.16b, v0.16b, v0.16b, #4
- ext v1.16b, v1.16b, v1.16b, #8
- ext v2.16b, v2.16b, v2.16b, #12
+ ushr v4.4s, v3.4s, #8
+ shl v3.4s, v3.4s, #24
orr v3.16b, v3.16b, v4.16b
+ add v2.4s, v3.4s, v2.4s
+ ext v3.16b, v3.16b, v3.16b, #8
+ eor v1.16b, v2.16b, v1.16b
+ ext v2.16b, v2.16b, v2.16b, #12
+ ushr v4.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ stp q2, q3, [x0, #32]
+ orr v1.16b, v1.16b, v4.16b
+ stp q0, q1, [x0]
+ ret
+.Lfunc_end1:
+ .size compress_pre, .Lfunc_end1-compress_pre
+ .cfi_endproc
+
+ .globl zfs_blake3_compress_xof_sse2
+ .p2align 2
+ .type zfs_blake3_compress_xof_sse2,@function
+zfs_blake3_compress_xof_sse2:
+ .cfi_startproc
+ hint #25
+ CFI_NEGATE_RA_STATE
+ sub sp, sp, #96
+ stp x29, x30, [sp, #64]
+ add x29, sp, #64
+ stp x20, x19, [sp, #80]
+ .cfi_def_cfa w29, 32
+ .cfi_offset w19, -8
+ .cfi_offset w20, -16
+ .cfi_offset w30, -24
+ .cfi_offset w29, -32
+ mov x20, x0
+ mov x19, x5
+ mov w5, w4
+ mov x4, x3
+ mov w3, w2
+ mov x2, x1
+ mov x0, sp
+ mov x1, x20
+ bl compress_pre
+ ldp q0, q1, [sp]
+ ldp q2, q3, [sp, #32]
eor v0.16b, v2.16b, v0.16b
- eor v3.16b, v3.16b, v1.16b
- stp q0, q3, [x5]
- ldr q0, [x0]
+ eor v1.16b, v3.16b, v1.16b
+ ldp x29, x30, [sp, #64]
+ stp q0, q1, [x19]
+ ldr q0, [x20]
eor v0.16b, v0.16b, v2.16b
- str q0, [x5, #32]
- ldr q0, [x0, #16]
- eor v0.16b, v0.16b, v1.16b
- str q0, [x5, #48]
+ str q0, [x19, #32]
+ ldr q0, [x20, #16]
+ eor v0.16b, v0.16b, v3.16b
+ str q0, [x19, #48]
+ ldp x20, x19, [sp, #80]
+ add sp, sp, #96
+ hint #29
ret
-.Lfunc_end1:
- .size zfs_blake3_compress_xof_sse2, .Lfunc_end1-zfs_blake3_compress_xof_sse2
+.Lfunc_end2:
+ .size zfs_blake3_compress_xof_sse2, .Lfunc_end2-zfs_blake3_compress_xof_sse2
.cfi_endproc
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
-.LCPI2_0:
+.LCPI3_0:
.word 0
.word 1
.word 2
@@ -991,19 +615,21 @@ zfs_blake3_compress_xof_sse2:
.type zfs_blake3_hash_many_sse2,@function
zfs_blake3_hash_many_sse2:
.cfi_startproc
+ hint #25
+ CFI_NEGATE_RA_STATE
stp d15, d14, [sp, #-160]!
stp d13, d12, [sp, #16]
stp d11, d10, [sp, #32]
stp d9, d8, [sp, #48]
stp x29, x30, [sp, #64]
+ add x29, sp, #64
stp x28, x27, [sp, #80]
stp x26, x25, [sp, #96]
stp x24, x23, [sp, #112]
stp x22, x21, [sp, #128]
stp x20, x19, [sp, #144]
- mov x29, sp
- sub sp, sp, #384
- .cfi_def_cfa w29, 160
+ sub sp, sp, #464
+ .cfi_def_cfa w29, 96
.cfi_offset w19, -8
.cfi_offset w20, -16
.cfi_offset w21, -24
@@ -1024,1414 +650,1406 @@ zfs_blake3_hash_many_sse2:
.cfi_offset b13, -144
.cfi_offset b14, -152
.cfi_offset b15, -160
- ldr x26, [x29, #168]
- ldrb w27, [x29, #160]
mov w19, w6
mov x20, x4
- mov x22, x2
- mov x28, x1
+ mov x24, x1
+ ldr x26, [x29, #104]
+ ldrb w27, [x29, #96]
cmp x1, #4
- mov x24, x0
str x3, [sp, #40]
- b.lo .LBB2_8
- adrp x9, .LCPI2_0
- ldr q0, [x9, :lo12:.LCPI2_0]
- sbfx w11, w5, #0, #1
- dup v1.4s, w11
- mov w9, #58983
+ b.lo .LBB3_6
+ adrp x8, .LCPI3_0
+ sbfx w9, w5, #0, #1
mov w10, #44677
- and v0.16b, v1.16b, v0.16b
mov w11, #62322
- mov w12, #62778
- orr w8, w7, w19
- movk w9, #27145, lsl #16
movk w10, #47975, lsl #16
movk w11, #15470, lsl #16
+ ldr q0, [x8, :lo12:.LCPI3_0]
+ dup v1.4s, w9
+ mov w9, #58983
+ orr w8, w7, w19
+ movk w9, #27145, lsl #16
+ and v0.16b, v1.16b, v0.16b
+ dup v1.4s, w11
+ movi v24.4s, #64
+ dup v2.4s, w9
+ mov w9, #62778
+ movk w9, #42319, lsl #16
str q0, [sp, #16]
orr v0.4s, #128, lsl #24
- movk w12, #42319, lsl #16
+ stp q2, q1, [sp, #48]
str q0, [sp]
-.LBB2_2:
- ldr x0, [sp, #40]
- mov x13, x0
- ld1r { v20.4s }, [x13], #4
- add x14, x0, #8
- add x15, x0, #12
- add x16, x0, #16
- add x17, x0, #20
- add x18, x0, #24
- add x0, x0, #28
- ld1r { v17.4s }, [x14]
- ld1r { v6.4s }, [x15]
- ld1r { v8.4s }, [x16]
- ld1r { v9.4s }, [x17]
- ld1r { v31.4s }, [x18]
- ld1r { v26.4s }, [x13]
- ld1r { v15.4s }, [x0]
- cbz x22, .LBB2_7
+ dup v0.4s, w10
+ str q0, [sp, #80]
+ b .LBB3_3
+.LBB3_2:
+ zip1 v0.4s, v12.4s, v31.4s
+ add x10, x20, #4
+ zip1 v1.4s, v29.4s, v30.4s
+ tst w5, #0x1
+ zip1 v2.4s, v28.4s, v23.4s
+ csel x20, x10, x20, ne
+ zip1 v3.4s, v13.4s, v25.4s
+ add x0, x0, #32
+ zip2 v6.4s, v12.4s, v31.4s
+ sub x24, x24, #4
+ zip1 v4.2d, v0.2d, v1.2d
+ cmp x24, #3
+ zip2 v7.4s, v29.4s, v30.4s
+ zip1 v5.2d, v2.2d, v3.2d
+ zip2 v0.2d, v0.2d, v1.2d
+ zip2 v1.2d, v2.2d, v3.2d
+ zip2 v2.4s, v28.4s, v23.4s
+ zip2 v3.4s, v13.4s, v25.4s
+ stp q4, q5, [x26]
+ zip2 v4.2d, v6.2d, v7.2d
+ stp q0, q1, [x26, #32]
+ zip1 v0.2d, v6.2d, v7.2d
+ zip1 v1.2d, v2.2d, v3.2d
+ zip2 v2.2d, v2.2d, v3.2d
+ stp q0, q1, [x26, #64]
+ stp q4, q2, [x26, #96]
+ add x26, x26, #128
+ b.ls .LBB3_6
+.LBB3_3:
+ ldr x14, [sp, #40]
+ mov x10, x14
+ add x11, x14, #8
+ add x12, x14, #12
+ add x13, x14, #16
+ ld1r { v12.4s }, [x10], #4
+ ld1r { v29.4s }, [x11]
+ add x11, x14, #20
+ ld1r { v30.4s }, [x12]
+ add x12, x14, #24
+ ld1r { v28.4s }, [x13]
+ ld1r { v23.4s }, [x11]
+ add x11, x14, #28
+ ld1r { v13.4s }, [x12]
+ ld1r { v31.4s }, [x10]
+ ld1r { v25.4s }, [x11]
+ cbz x2, .LBB3_2
ldr q1, [sp, #16]
dup v0.4s, w20
- ldp x13, x14, [x24]
- ldp x15, x16, [x24, #16]
+ lsr x12, x20, #32
+ mov x10, xzr
+ ldp x13, x14, [x0, #16]
add v1.4s, v0.4s, v1.4s
+ mov x15, x2
movi v0.4s, #128, lsl #24
- str q1, [sp, #64]
+ mov w4, w8
+ str q1, [sp, #112]
eor v0.16b, v1.16b, v0.16b
ldr q1, [sp]
- lsr x18, x20, #32
- mov x17, xzr
cmgt v0.4s, v1.4s, v0.4s
- dup v1.4s, w18
+ dup v1.4s, w12
+ ldp x11, x12, [x0]
sub v0.4s, v1.4s, v0.4s
- mov w18, w8
- str q0, [sp, #48]
-.LBB2_4:
- mov w2, #16
- bfi x2, x17, #6, #58
- ldr q1, [x13, x2]
- ldr q3, [x14, x2]
- ldr q2, [x15, x2]
- ldr q4, [x16, x2]
- mov w2, #32
- bfi x2, x17, #6, #58
- ldr q5, [x13, x2]
- ldr q18, [x14, x2]
- ldr q19, [x15, x2]
- ldr q23, [x16, x2]
- mov w2, #48
- lsl x3, x17, #6
- bfi x2, x17, #6, #58
- add x17, x17, #1
- ldr q0, [x13, x3]
- ldr q21, [x14, x3]
- ldr q7, [x15, x3]
- ldr q16, [x16, x3]
- cmp x17, x22
- ldr q13, [x13, x2]
- ldr q14, [x14, x2]
- ldr q29, [x15, x2]
- ldr q10, [x16, x2]
- csel w2, w27, wzr, eq
- orr w18, w2, w18
- mov x0, xzr
- and w18, w18, #0xff
- add x3, x3, #256
-.LBB2_5:
- ldr x2, [x24, x0]
- add x0, x0, #8
- cmp x0, #32
- add x2, x2, x3
- prfm pldl1keep, [x2]
- b.ne .LBB2_5
- dup v22.4s, w18
- str q22, [sp, #192]
- zip1 v27.4s, v0.4s, v21.4s
- zip2 v21.4s, v0.4s, v21.4s
- zip1 v0.4s, v7.4s, v16.4s
- zip2 v22.4s, v7.4s, v16.4s
- zip1 v7.4s, v1.4s, v3.4s
- zip1 v25.4s, v2.4s, v4.4s
- zip2 v16.4s, v2.4s, v4.4s
- zip1 v11.4s, v19.4s, v23.4s
- zip2 v12.4s, v19.4s, v23.4s
- zip1 v19.4s, v13.4s, v14.4s
- zip2 v23.4s, v13.4s, v14.4s
- zip1 v13.4s, v29.4s, v10.4s
- zip2 v14.4s, v29.4s, v10.4s
- add v10.4s, v20.4s, v8.4s
- add v2.4s, v26.4s, v9.4s
- ext v20.16b, v22.16b, v21.16b, #8
- ext v26.16b, v25.16b, v7.16b, #8
- zip2 v24.4s, v1.4s, v3.4s
- add v1.4s, v6.4s, v15.4s
- ext v6.16b, v0.16b, v27.16b, #8
- ext v20.16b, v21.16b, v20.16b, #8
- mov v21.d[1], v22.d[0]
- ext v22.16b, v7.16b, v26.16b, #8
- mov v7.d[1], v25.d[0]
- add v3.4s, v17.4s, v31.4s
- str q1, [sp, #144]
- ext v1.16b, v27.16b, v6.16b, #8
- mov v6.16b, v7.16b
- zip1 v28.4s, v5.4s, v18.4s
- stur q1, [x29, #-80]
- mov v1.16b, v27.16b
- mov v27.16b, v24.16b
- add v3.4s, v3.4s, v6.4s
- ldr q6, [sp, #64]
- ext v29.16b, v16.16b, v24.16b, #8
- mov v1.d[1], v0.d[0]
- ext v0.16b, v11.16b, v28.16b, #8
- mov v27.d[1], v16.d[0]
- ext v16.16b, v14.16b, v23.16b, #8
- stur q7, [x29, #-144]
- ext v7.16b, v24.16b, v29.16b, #8
- ext v29.16b, v28.16b, v0.16b, #8
- ext v0.16b, v23.16b, v16.16b, #8
- mov v23.d[1], v14.d[0]
- stp q0, q23, [sp, #80]
- add v0.4s, v10.4s, v1.4s
- eor v16.16b, v0.16b, v6.16b
- ldr q6, [sp, #48]
- add v2.4s, v2.4s, v21.4s
- mov v28.d[1], v11.d[0]
- zip2 v18.4s, v5.4s, v18.4s
- eor v10.16b, v2.16b, v6.16b
- movi v6.4s, #64
- eor v11.16b, v3.16b, v6.16b
- ldr q6, [sp, #144]
- dup v17.4s, w9
- ext v30.16b, v12.16b, v18.16b, #8
- rev32 v16.8h, v16.8h
- dup v5.4s, w10
- ext v25.16b, v18.16b, v30.16b, #8
- mov v30.16b, v23.16b
- mov v23.16b, v1.16b
- str q1, [sp, #160]
- rev32 v10.8h, v10.8h
- add v1.4s, v16.4s, v17.4s
- add v17.4s, v6.4s, v27.4s
- ldr q6, [sp, #192]
- dup v4.4s, w11
- rev32 v11.8h, v11.8h
- add v5.4s, v10.4s, v5.4s
- eor v8.16b, v1.16b, v8.16b
- stur q21, [x29, #-128]
- mov v18.d[1], v12.d[0]
- add v4.4s, v11.4s, v4.4s
- eor v9.16b, v5.16b, v9.16b
- ushr v12.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- ldur q21, [x29, #-80]
- ext v26.16b, v13.16b, v19.16b, #8
- eor v31.16b, v4.16b, v31.16b
- orr v8.16b, v8.16b, v12.16b
- ushr v12.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- ext v26.16b, v19.16b, v26.16b, #8
- mov v19.d[1], v13.d[0]
- orr v9.16b, v9.16b, v12.16b
- ushr v12.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v17.16b, v6.16b
- orr v31.16b, v31.16b, v12.16b
- dup v12.4s, w12
- rev32 v13.8h, v13.8h
- add v12.4s, v13.4s, v12.4s
- add v0.4s, v0.4s, v21.4s
- eor v14.16b, v12.16b, v15.16b
- add v0.4s, v0.4s, v8.4s
- add v2.4s, v2.4s, v20.4s
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v16.16b, v0.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v22.4s
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v7.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v14.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v13.16b, v17.16b, v13.16b
- add v1.4s, v16.4s, v1.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v13.4s, #8
- shl v13.4s, v13.4s, #24
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v10.4s, v5.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v13.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v14.16b, v12.16b, v14.16b
- add v0.4s, v0.4s, v28.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #7
- shl v14.4s, v14.4s, #25
- add v0.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v18.4s
- orr v14.16b, v14.16b, v15.16b
- eor v13.16b, v0.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v19.4s
- rev32 v13.8h, v13.8h
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v30.4s
- add v4.4s, v4.4s, v13.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v12.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v17.16b, v11.16b
- mov v24.16b, v7.16b
- stur q7, [x29, #-112]
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v1.4s, v10.4s
- rev32 v11.8h, v11.8h
- mov v7.16b, v26.16b
- add v3.4s, v3.4s, v26.4s
- ldr q26, [sp, #80]
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v14.16b, v1.16b, v14.16b
- add v5.4s, v5.4s, v11.4s
- add v0.4s, v0.4s, v29.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v8.16b, v5.16b, v8.16b
- add v0.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v25.4s
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v13.16b, v0.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v13.4s, #8
- shl v13.4s, v13.4s, #24
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v26.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v17.16b, v11.16b
- add v4.4s, v13.4s, v4.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v16.4s, v12.4s
- str q22, [sp, #128]
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v10.4s, v1.4s
- ldur q22, [x29, #-128]
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v14.16b, v1.16b, v14.16b
- add v5.4s, v11.4s, v5.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #7
- shl v14.4s, v14.4s, #25
- eor v8.16b, v5.16b, v8.16b
- mov v6.16b, v18.16b
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- ldur q18, [x29, #-144]
- orr v8.16b, v8.16b, v15.16b
- add v0.4s, v0.4s, v22.4s
- add v0.4s, v0.4s, v8.4s
- add v2.4s, v2.4s, v20.4s
- eor v16.16b, v0.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v24.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v18.4s
- add v1.4s, v1.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v14.4s
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v5.4s, v10.4s
- rev32 v11.8h, v11.8h
- eor v13.16b, v17.16b, v13.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v4.4s, v11.4s
- rev32 v13.8h, v13.8h
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v12.4s, v13.4s
- add v0.4s, v0.4s, v27.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v14.16b, v12.16b, v14.16b
- add v0.4s, v0.4s, v8.4s
- add v2.4s, v2.4s, v6.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v16.16b, v0.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v23.4s
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v7.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v14.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v13.16b, v17.16b, v13.16b
- add v1.4s, v16.4s, v1.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v13.4s, #8
- shl v13.4s, v13.4s, #24
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v10.4s, v5.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v13.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v14.16b, v12.16b, v14.16b
- add v0.4s, v0.4s, v21.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #7
- shl v14.4s, v14.4s, #25
- add v0.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v19.4s
- orr v14.16b, v14.16b, v15.16b
- eor v13.16b, v0.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v29.4s
- str q28, [sp, #112]
- rev32 v13.8h, v13.8h
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v26.4s
- add v4.4s, v4.4s, v13.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- ldp q28, q23, [sp, #112]
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v12.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v17.16b, v11.16b
- ldr q21, [sp, #96]
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v1.4s, v10.4s
- rev32 v11.8h, v11.8h
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v14.16b, v1.16b, v14.16b
- add v5.4s, v5.4s, v11.4s
- add v0.4s, v0.4s, v25.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v8.16b, v5.16b, v8.16b
- add v0.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v23.4s
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v13.16b, v0.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v21.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v13.4s, #8
- shl v13.4s, v13.4s, #24
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v28.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v17.16b, v11.16b
- add v4.4s, v13.4s, v4.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v16.4s, v12.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v10.4s, v1.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v14.16b, v1.16b, v14.16b
- add v5.4s, v11.4s, v5.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #7
- shl v14.4s, v14.4s, #25
- eor v8.16b, v5.16b, v8.16b
- mov v30.16b, v29.16b
- mov v29.16b, v25.16b
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- ldur q25, [x29, #-112]
- orr v8.16b, v8.16b, v15.16b
- add v0.4s, v0.4s, v20.4s
- add v0.4s, v0.4s, v8.4s
- add v2.4s, v2.4s, v6.4s
- eor v16.16b, v0.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v7.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v25.4s
- add v1.4s, v1.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v14.4s
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v5.4s, v10.4s
- rev32 v11.8h, v11.8h
- eor v13.16b, v17.16b, v13.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v4.4s, v11.4s
- rev32 v13.8h, v13.8h
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v12.4s, v13.4s
- add v0.4s, v0.4s, v18.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v14.16b, v12.16b, v14.16b
- add v0.4s, v0.4s, v8.4s
- add v2.4s, v2.4s, v19.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v16.16b, v0.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v22.4s
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v21.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v14.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v13.16b, v17.16b, v13.16b
- add v1.4s, v16.4s, v1.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v13.4s, #8
- shl v13.4s, v13.4s, #24
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v10.4s, v5.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v13.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v14.16b, v12.16b, v14.16b
+ str q0, [sp, #96]
+.LBB3_5:
+ add x17, x11, x10
+ add x21, x12, x10
+ add x16, x13, x10
+ add x6, x14, x10
+ subs x15, x15, #1
+ add x10, x10, #64
+ ldp q0, q1, [x17]
+ csel w3, w27, wzr, eq
+ orr w3, w3, w4
+ mov w4, w19
+ and w3, w3, #0xff
+ ldp q3, q6, [x21]
+ dup v2.4s, w3
+ zip1 v21.4s, v0.4s, v3.4s
+ zip2 v19.4s, v0.4s, v3.4s
+ ldp q5, q7, [x16]
+ zip1 v17.4s, v1.4s, v6.4s
+ zip2 v22.4s, v1.4s, v6.4s
+ ldp q16, q18, [x6]
+ zip1 v4.4s, v5.4s, v16.4s
+ zip2 v0.4s, v5.4s, v16.4s
+ ldp q26, q27, [x17, #32]
+ zip1 v1.4s, v7.4s, v18.4s
+ zip2 v3.4s, v7.4s, v18.4s
+ zip2 v20.2d, v19.2d, v0.2d
+ mov v19.d[1], v0.d[0]
+ dup v18.4s, w9
+ ldp q8, q9, [x21, #32]
+ stur q19, [x29, #-208]
+ zip2 v7.4s, v26.4s, v8.4s
+ zip1 v10.4s, v26.4s, v8.4s
+ ldp q11, q5, [x16, #32]
+ zip2 v26.2d, v17.2d, v1.2d
+ stp q7, q26, [sp, #192]
+ mov v17.d[1], v1.d[0]
+ add v1.4s, v23.4s, v31.4s
+ ldp q16, q6, [x6, #32]
+ stur q17, [x29, #-256]
+ add v1.4s, v1.4s, v19.4s
+ zip1 v8.4s, v11.4s, v16.4s
+ zip2 v7.4s, v11.4s, v16.4s
+ zip1 v11.4s, v27.4s, v9.4s
+ zip2 v9.4s, v27.4s, v9.4s
+ zip2 v27.2d, v21.2d, v4.2d
+ mov v21.d[1], v4.d[0]
+ str q7, [sp, #224]
+ add v4.4s, v28.4s, v12.4s
+ zip1 v15.4s, v5.4s, v6.4s
+ zip2 v14.4s, v5.4s, v6.4s
+ stur q27, [x29, #-192]
+ zip2 v16.2d, v22.2d, v3.2d
+ stp q20, q21, [x29, #-240]
+ add v0.4s, v4.4s, v21.4s
+ ldp q6, q4, [sp, #96]
+ mov v22.d[1], v3.d[0]
+ add v5.4s, v25.4s, v30.4s
+ add v3.4s, v13.4s, v29.4s
+ eor v6.16b, v1.16b, v6.16b
+ add v1.4s, v1.4s, v20.4s
+ str q22, [sp, #256]
+ eor v4.16b, v0.16b, v4.16b
+ add v5.4s, v5.4s, v22.4s
+ add v3.4s, v3.4s, v17.4s
+ ldr q17, [sp, #48]
+ rev32 v6.8h, v6.8h
+ rev32 v4.8h, v4.8h
+ eor v2.16b, v5.16b, v2.16b
+ eor v7.16b, v3.16b, v24.16b
add v0.4s, v0.4s, v27.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #7
- shl v14.4s, v14.4s, #25
- add v0.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v30.4s
- orr v14.16b, v14.16b, v15.16b
- eor v13.16b, v0.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v29.4s
- rev32 v13.8h, v13.8h
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v28.4s
- add v4.4s, v4.4s, v13.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v12.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v17.16b, v11.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v1.4s, v10.4s
- rev32 v11.8h, v11.8h
- ldr q24, [sp, #160]
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v14.16b, v1.16b, v14.16b
- add v5.4s, v5.4s, v11.4s
- stur q7, [x29, #-64]
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v14.4s, #12
- shl v14.4s, v14.4s, #20
- eor v8.16b, v5.16b, v8.16b
- mov v7.16b, v26.16b
- add v3.4s, v3.4s, v26.4s
- ldur q26, [x29, #-80]
- orr v14.16b, v14.16b, v15.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- add v0.4s, v0.4s, v23.4s
- orr v8.16b, v8.16b, v15.16b
- add v15.4s, v0.4s, v9.4s
- add v2.4s, v2.4s, v24.4s
- eor v0.16b, v15.16b, v13.16b
- add v2.4s, v2.4s, v31.4s
- ushr v13.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v14.4s
- add v17.4s, v17.4s, v26.4s
- orr v0.16b, v0.16b, v13.16b
- ushr v13.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- orr v16.16b, v16.16b, v13.16b
- ushr v13.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v17.16b, v11.16b
- add v4.4s, v0.4s, v4.4s
- orr v10.16b, v10.16b, v13.16b
- ushr v13.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v16.4s, v12.4s
- orr v11.16b, v11.16b, v13.16b
- ushr v13.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v12.16b, v31.16b
- orr v9.16b, v9.16b, v13.16b
- ushr v13.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- add v1.4s, v10.4s, v1.4s
- orr v31.16b, v31.16b, v13.16b
- eor v13.16b, v1.16b, v14.16b
- add v5.4s, v11.4s, v5.4s
- ushr v14.4s, v13.4s, #7
- shl v13.4s, v13.4s, #25
- eor v8.16b, v5.16b, v8.16b
- orr v13.16b, v13.16b, v14.16b
- ushr v14.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- stur q6, [x29, #-96]
- orr v8.16b, v8.16b, v14.16b
- add v14.4s, v15.4s, v6.4s
- ldur q6, [x29, #-64]
- mov v18.16b, v19.16b
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v18.4s
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v21.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v6.4s
- add v1.4s, v1.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v13.4s
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v5.4s, v10.4s
- rev32 v11.8h, v11.8h
- eor v0.16b, v17.16b, v0.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v4.4s, v11.4s
- rev32 v0.8h, v0.8h
+ add v21.4s, v4.4s, v17.4s
+ rev32 v31.8h, v2.8h
+ ldr q2, [sp, #80]
+ rev32 v7.8h, v7.8h
+ mov v27.16b, v16.16b
+ eor v17.16b, v21.16b, v28.16b
+ add v29.4s, v6.4s, v2.4s
+ ldr q2, [sp, #64]
+ add v24.4s, v31.4s, v18.4s
str q27, [sp, #176]
- mov v27.16b, v30.16b
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v12.4s, v0.4s
- add v14.4s, v14.4s, v25.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v12.16b, v13.16b
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v27.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #12
- shl v13.4s, v13.4s, #20
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v20.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v7.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v13.4s
- mov v30.16b, v23.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v0.16b, v17.16b, v0.16b
- add v1.4s, v16.4s, v1.4s
- ldur q23, [x29, #-144]
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v10.4s, v5.4s
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v0.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v13.16b, v12.16b, v13.16b
- add v14.4s, v14.4s, v23.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #7
- shl v13.4s, v13.4s, #25
- add v14.4s, v14.4s, v9.4s
- add v2.4s, v2.4s, v29.4s
- orr v13.16b, v13.16b, v15.16b
- eor v0.16b, v14.16b, v0.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v30.4s
- rev32 v0.8h, v0.8h
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v13.4s
- add v17.4s, v17.4s, v26.4s
- add v4.4s, v4.4s, v0.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- ldur q22, [x29, #-128]
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v12.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v17.16b, v11.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v1.4s, v10.4s
- rev32 v11.8h, v11.8h
- ldr q26, [sp, #176]
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v1.16b, v13.16b
- add v5.4s, v5.4s, v11.4s
- add v14.4s, v14.4s, v24.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #12
- shl v13.4s, v13.4s, #20
- eor v8.16b, v5.16b, v8.16b
- add v14.4s, v14.4s, v9.4s
- add v2.4s, v2.4s, v22.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v0.16b, v14.16b, v0.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v28.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v13.4s
+ ushr v19.4s, v17.4s, #12
+ shl v17.4s, v17.4s, #20
+ add v30.4s, v7.4s, v2.4s
+ eor v18.16b, v29.16b, v23.16b
+ orr v12.16b, v17.16b, v19.16b
+ eor v17.16b, v30.16b, v13.16b
+ eor v19.16b, v24.16b, v25.16b
+ ushr v23.4s, v18.4s, #12
+ shl v18.4s, v18.4s, #20
+ ushr v25.4s, v17.4s, #12
+ shl v17.4s, v17.4s, #20
+ ushr v28.4s, v19.4s, #12
+ shl v19.4s, v19.4s, #20
+ orr v13.16b, v18.16b, v23.16b
+ orr v25.16b, v17.16b, v25.16b
+ orr v2.16b, v19.16b, v28.16b
+ add v28.4s, v0.4s, v12.4s
+ add v0.4s, v3.4s, v26.4s
+ add v18.4s, v1.4s, v13.4s
+ add v3.4s, v5.4s, v16.4s
+ eor v1.16b, v28.16b, v4.16b
+ add v17.4s, v0.4s, v25.4s
+ eor v0.16b, v18.16b, v6.16b
+ add v19.4s, v3.4s, v2.4s
+ ushr v16.4s, v1.4s, #8
+ shl v3.4s, v1.4s, #24
+ eor v4.16b, v17.16b, v7.16b
+ ushr v6.4s, v0.4s, #8
+ shl v1.4s, v0.4s, #24
+ eor v5.16b, v19.16b, v31.16b
+ ushr v23.4s, v4.4s, #8
+ shl v4.4s, v4.4s, #24
+ orr v7.16b, v3.16b, v16.16b
+ orr v6.16b, v1.16b, v6.16b
+ ushr v31.4s, v5.4s, #8
+ shl v0.4s, v5.4s, #24
+ orr v5.16b, v4.16b, v23.16b
+ add v4.4s, v7.4s, v21.4s
+ ldr q21, [sp, #192]
+ add v3.4s, v6.4s, v29.4s
+ orr v31.16b, v0.16b, v31.16b
+ add v23.4s, v5.4s, v30.4s
+ eor v0.16b, v4.16b, v12.16b
+ eor v1.16b, v3.16b, v13.16b
+ add v16.4s, v31.4s, v24.4s
+ eor v20.16b, v23.16b, v25.16b
+ ushr v24.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v29.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ushr v30.4s, v20.4s, #7
+ shl v20.4s, v20.4s, #25
+ orr v25.16b, v0.16b, v24.16b
+ orr v0.16b, v1.16b, v29.16b
+ mov v29.16b, v10.16b
+ orr v1.16b, v20.16b, v30.16b
+ mov v20.16b, v10.16b
+ mov v24.16b, v21.16b
+ ldr q20, [sp, #224]
+ mov v29.d[1], v8.d[0]
+ mov v13.16b, v9.16b
+ zip2 v30.2d, v10.2d, v8.2d
+ zip2 v8.2d, v21.2d, v20.2d
+ mov v26.16b, v11.16b
+ mov v24.d[1], v20.d[0]
+ add v20.4s, v28.4s, v29.4s
+ mov v13.d[1], v14.d[0]
+ str q8, [sp, #128]
+ eor v2.16b, v16.16b, v2.16b
+ mov v26.d[1], v15.d[0]
+ str q24, [sp, #192]
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v13.4s
+ ushr v12.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ zip2 v10.2d, v9.2d, v14.2d
+ add v18.4s, v18.4s, v24.4s
add v17.4s, v17.4s, v26.4s
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v17.16b, v11.16b
- add v4.4s, v0.4s, v4.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v16.4s, v12.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v10.4s, v1.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v13.16b, v1.16b, v13.16b
- add v5.4s, v11.4s, v5.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #7
- shl v13.4s, v13.4s, #25
- eor v8.16b, v5.16b, v8.16b
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- orr v8.16b, v8.16b, v15.16b
- add v14.4s, v14.4s, v18.4s
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v27.4s
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v7.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
+ mov v14.16b, v26.16b
+ eor v26.16b, v20.16b, v31.16b
+ stp q10, q30, [sp, #224]
+ add v19.4s, v19.4s, v25.4s
+ orr v2.16b, v2.16b, v12.16b
+ add v18.4s, v18.4s, v1.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ eor v6.16b, v17.16b, v6.16b
+ rev32 v7.8h, v7.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ rev32 v6.8h, v6.8h
+ add v16.4s, v16.4s, v7.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v4.4s, v6.4s
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ add v20.4s, v20.4s, v30.4s
+ zip2 v21.2d, v11.2d, v15.2d
+ ushr v11.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v10.4s
+ add v20.4s, v20.4s, v0.4s
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v18.4s, v18.4s, v8.4s
+ add v19.4s, v19.4s, v25.4s
+ eor v26.16b, v20.16b, v26.16b
+ orr v2.16b, v2.16b, v11.16b
add v17.4s, v17.4s, v21.4s
- add v1.4s, v1.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v3.16b, v11.16b
- add v17.4s, v17.4s, v13.4s
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v5.4s, v10.4s
- rev32 v11.8h, v11.8h
- eor v0.16b, v17.16b, v0.16b
- add v14.4s, v14.4s, v6.4s
- ldur q6, [x29, #-96]
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v4.4s, v11.4s
- rev32 v0.8h, v0.8h
- stur q20, [x29, #-160]
- mov v20.16b, v29.16b
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v12.4s, v0.4s
- mov v19.16b, v29.16b
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v12.16b, v13.16b
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v20.4s
- mov v19.16b, v28.16b
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #12
- shl v13.4s, v13.4s, #20
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ ushr v31.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v17.4s, v17.4s, v2.4s
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ orr v26.16b, v26.16b, v31.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ eor v0.16b, v23.16b, v0.16b
+ ldp q28, q12, [x29, #-256]
+ orr v6.16b, v6.16b, v11.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v4.4s, v6.4s, v4.4s
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ add v18.4s, v18.4s, v12.4s
+ mov v15.16b, v29.16b
+ ldur q29, [x29, #-208]
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ str q15, [sp, #160]
+ add v20.4s, v20.4s, v29.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v27.4s
+ eor v6.16b, v6.16b, v18.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v28.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ rev32 v6.8h, v6.8h
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
add v3.4s, v3.4s, v6.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v19.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v3.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ eor v0.16b, v3.16b, v0.16b
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ ushr v11.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ add v16.4s, v16.4s, v26.4s
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v18.4s, v18.4s, v24.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v20.4s, v20.4s, v22.4s
+ add v18.4s, v18.4s, v0.4s
+ mov v9.16b, v30.16b
+ mov v30.16b, v21.16b
+ ldur q21, [x29, #-224]
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ str q30, [sp, #144]
+ add v17.4s, v17.4s, v21.4s
+ ldur q21, [x29, #-192]
+ eor v6.16b, v18.16b, v6.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v30.4s
+ eor v7.16b, v20.16b, v7.16b
+ add v17.4s, v17.4s, v1.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v19.4s, v19.4s, v2.4s
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ orr v6.16b, v6.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ orr v7.16b, v7.16b, v31.16b
+ ushr v31.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ add v3.4s, v6.4s, v3.4s
+ ushr v11.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v4.4s, v7.4s, v4.4s
+ orr v5.16b, v5.16b, v31.16b
+ eor v0.16b, v3.16b, v0.16b
+ orr v26.16b, v26.16b, v11.16b
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v5.4s, v23.4s
+ ushr v11.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v16.4s, v26.4s, v16.4s
+ ushr v31.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v20.4s, v20.4s, v21.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v10.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v18.4s, v18.4s, v14.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v19.4s, v19.4s, v25.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v9.4s
+ ldr q9, [sp, #208]
+ add v18.4s, v18.4s, v1.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ eor v6.16b, v17.16b, v6.16b
+ rev32 v7.8h, v7.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ rev32 v6.8h, v6.8h
+ add v16.4s, v16.4s, v7.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v4.4s, v6.4s
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ add v20.4s, v20.4s, v8.4s
+ ushr v11.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v15.4s
+ add v20.4s, v20.4s, v0.4s
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v18.4s, v18.4s, v9.4s
+ add v19.4s, v19.4s, v25.4s
+ eor v26.16b, v20.16b, v26.16b
+ orr v2.16b, v2.16b, v11.16b
add v17.4s, v17.4s, v13.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v0.16b, v17.16b, v0.16b
- add v1.4s, v16.4s, v1.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v10.4s, v5.4s
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v0.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v13.16b, v12.16b, v13.16b
- add v14.4s, v14.4s, v25.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #7
- shl v13.4s, v13.4s, #25
- add v14.4s, v14.4s, v9.4s
- add v2.4s, v2.4s, v30.4s
- orr v13.16b, v13.16b, v15.16b
- eor v0.16b, v14.16b, v0.16b
- add v2.4s, v2.4s, v31.4s
- add v3.4s, v3.4s, v24.4s
- rev32 v0.8h, v0.8h
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v13.4s
- add v17.4s, v17.4s, v26.4s
- mov v29.16b, v27.16b
- add v4.4s, v4.4s, v0.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- ldur q27, [x29, #-160]
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v12.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v17.16b, v11.16b
- ldur q6, [x29, #-80]
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v1.4s, v10.4s
- rev32 v11.8h, v11.8h
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v1.16b, v13.16b
- add v5.4s, v5.4s, v11.4s
- add v14.4s, v14.4s, v22.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #12
- shl v13.4s, v13.4s, #20
- eor v8.16b, v5.16b, v8.16b
- add v14.4s, v14.4s, v9.4s
- add v2.4s, v2.4s, v27.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v0.16b, v14.16b, v0.16b
- add v2.4s, v2.4s, v31.4s
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ ushr v31.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v17.4s, v17.4s, v2.4s
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ orr v26.16b, v26.16b, v31.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ eor v0.16b, v23.16b, v0.16b
+ orr v6.16b, v6.16b, v11.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v4.4s, v6.4s, v4.4s
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ add v18.4s, v18.4s, v24.4s
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v12.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v30.4s
+ eor v6.16b, v6.16b, v18.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v27.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ rev32 v6.8h, v6.8h
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
add v3.4s, v3.4s, v6.4s
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- eor v16.16b, v2.16b, v16.16b
- add v3.4s, v3.4s, v13.4s
- add v17.4s, v17.4s, v23.4s
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v3.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- eor v11.16b, v17.16b, v11.16b
- add v4.4s, v0.4s, v4.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v11.4s, #8
- shl v11.4s, v11.4s, #24
- eor v9.16b, v4.16b, v9.16b
- add v12.4s, v16.4s, v12.4s
- orr v11.16b, v11.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v31.16b, v12.16b, v31.16b
- add v1.4s, v10.4s, v1.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- eor v13.16b, v1.16b, v13.16b
- add v5.4s, v11.4s, v5.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #7
- shl v13.4s, v13.4s, #25
- eor v8.16b, v5.16b, v8.16b
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- orr v8.16b, v8.16b, v15.16b
- add v14.4s, v14.4s, v29.4s
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v20.4s
- mov v28.16b, v7.16b
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- add v3.4s, v3.4s, v19.4s
- rev32 v16.8h, v16.8h
- eor v10.16b, v2.16b, v10.16b
- add v3.4s, v3.4s, v31.4s
- add v17.4s, v17.4s, v28.4s
- add v1.4s, v1.4s, v16.4s
- rev32 v10.8h, v10.8h
- eor v11.16b, v3.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ eor v0.16b, v3.16b, v0.16b
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ ushr v11.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ add v16.4s, v16.4s, v26.4s
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v18.4s, v18.4s, v14.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v20.4s, v20.4s, v28.4s
+ add v18.4s, v18.4s, v0.4s
+ mov v10.16b, v13.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v29.4s
+ eor v6.16b, v18.16b, v6.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v10.4s
+ eor v7.16b, v20.16b, v7.16b
+ add v17.4s, v17.4s, v1.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v19.4s, v19.4s, v2.4s
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ orr v6.16b, v6.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ orr v7.16b, v7.16b, v31.16b
+ ushr v31.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ add v3.4s, v6.4s, v3.4s
+ ushr v11.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v4.4s, v7.4s, v4.4s
+ orr v5.16b, v5.16b, v31.16b
+ eor v0.16b, v3.16b, v0.16b
+ mov v22.16b, v8.16b
+ ldp q8, q28, [sp, #240]
+ orr v26.16b, v26.16b, v11.16b
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v5.4s, v23.4s
+ ushr v11.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v16.4s, v26.4s, v16.4s
+ ushr v31.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v20.4s, v20.4s, v28.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v15.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v18.4s, v18.4s, v8.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v19.4s, v19.4s, v25.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v22.4s
+ ldur q22, [x29, #-256]
+ add v18.4s, v18.4s, v1.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ eor v6.16b, v17.16b, v6.16b
+ rev32 v7.8h, v7.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ rev32 v6.8h, v6.8h
+ add v16.4s, v16.4s, v7.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v4.4s, v6.4s
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ add v20.4s, v20.4s, v9.4s
+ mov v13.16b, v12.16b
+ mov v12.16b, v27.16b
+ mov v27.16b, v9.16b
+ ldur q9, [x29, #-192]
+ mov v21.16b, v15.16b
+ ldr q15, [sp, #224]
+ ushr v11.4s, v1.4s, #12
+ ldur q21, [x29, #-224]
+ shl v1.4s, v1.4s, #20
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v9.4s
+ add v20.4s, v20.4s, v0.4s
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v18.4s, v18.4s, v21.4s
+ add v19.4s, v19.4s, v25.4s
+ eor v26.16b, v20.16b, v26.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v15.4s
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ ushr v31.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v17.4s, v17.4s, v2.4s
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ orr v26.16b, v26.16b, v31.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ eor v0.16b, v23.16b, v0.16b
+ orr v6.16b, v6.16b, v11.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v4.4s, v6.4s, v4.4s
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ add v18.4s, v18.4s, v14.4s
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v24.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v10.4s
+ eor v6.16b, v6.16b, v18.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v30.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ rev32 v6.8h, v6.8h
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
+ add v3.4s, v3.4s, v6.4s
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ eor v0.16b, v3.16b, v0.16b
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ ushr v11.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ add v16.4s, v16.4s, v26.4s
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v18.4s, v18.4s, v8.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v20.4s, v20.4s, v12.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
add v17.4s, v17.4s, v13.4s
- eor v8.16b, v1.16b, v8.16b
- add v5.4s, v5.4s, v10.4s
- rev32 v11.8h, v11.8h
- eor v0.16b, v17.16b, v0.16b
- ushr v15.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- eor v9.16b, v5.16b, v9.16b
- add v4.4s, v4.4s, v11.4s
- rev32 v0.8h, v0.8h
- orr v8.16b, v8.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v31.16b, v4.16b, v31.16b
- add v12.4s, v12.4s, v0.4s
- add v14.4s, v14.4s, v21.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- eor v13.16b, v12.16b, v13.16b
- add v14.4s, v14.4s, v8.4s
- add v2.4s, v2.4s, v30.4s
- orr v31.16b, v31.16b, v15.16b
- ushr v15.4s, v13.4s, #12
- shl v13.4s, v13.4s, #20
- eor v16.16b, v14.16b, v16.16b
- add v2.4s, v2.4s, v9.4s
- orr v13.16b, v13.16b, v15.16b
- ushr v15.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v10.16b, v2.16b, v10.16b
- orr v16.16b, v16.16b, v15.16b
- ushr v15.4s, v10.4s, #8
- shl v10.4s, v10.4s, #24
- add v3.4s, v3.4s, v18.4s
- orr v10.16b, v10.16b, v15.16b
- add v15.4s, v3.4s, v31.4s
- eor v3.16b, v15.16b, v11.16b
- ushr v11.4s, v3.4s, #8
- shl v3.4s, v3.4s, #24
- orr v11.16b, v3.16b, v11.16b
- add v3.4s, v17.4s, v6.4s
- add v17.4s, v3.4s, v13.4s
- eor v0.16b, v17.16b, v0.16b
- ushr v3.4s, v0.4s, #8
- shl v0.4s, v0.4s, #24
- add v1.4s, v16.4s, v1.4s
- orr v0.16b, v0.16b, v3.16b
- eor v3.16b, v1.16b, v8.16b
- ushr v8.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- add v5.4s, v10.4s, v5.4s
- orr v8.16b, v3.16b, v8.16b
- eor v3.16b, v5.16b, v9.16b
- add v4.4s, v11.4s, v4.4s
- ushr v9.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- eor v31.16b, v4.16b, v31.16b
- mov v7.16b, v23.16b
- mov v23.16b, v28.16b
- mov v28.16b, v6.16b
- orr v3.16b, v3.16b, v9.16b
- ushr v9.4s, v31.4s, #7
- shl v31.4s, v31.4s, #25
- ldur q6, [x29, #-64]
- orr v31.16b, v31.16b, v9.16b
- add v9.4s, v0.4s, v12.4s
- eor v12.16b, v9.16b, v13.16b
- ushr v13.4s, v12.4s, #7
- shl v12.4s, v12.4s, #25
- orr v12.16b, v12.16b, v13.16b
- add v13.4s, v14.4s, v6.4s
- add v13.4s, v13.4s, v3.4s
- eor v0.16b, v13.16b, v0.16b
- add v2.4s, v2.4s, v24.4s
- rev32 v14.8h, v0.8h
- add v0.4s, v2.4s, v31.4s
- add v6.4s, v4.4s, v14.4s
- eor v2.16b, v0.16b, v16.16b
- eor v3.16b, v6.16b, v3.16b
- rev32 v16.8h, v2.8h
- ushr v4.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- add v2.4s, v9.4s, v16.4s
- orr v4.16b, v3.16b, v4.16b
- eor v3.16b, v2.16b, v31.16b
- ushr v31.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- orr v3.16b, v3.16b, v31.16b
- add v31.4s, v15.4s, v22.4s
- add v31.4s, v31.4s, v12.4s
- add v17.4s, v17.4s, v7.4s
- eor v9.16b, v31.16b, v10.16b
- add v17.4s, v17.4s, v8.4s
- rev32 v9.8h, v9.8h
- eor v11.16b, v17.16b, v11.16b
- add v1.4s, v1.4s, v9.4s
- rev32 v11.8h, v11.8h
- eor v10.16b, v1.16b, v12.16b
- add v5.4s, v5.4s, v11.4s
- ushr v12.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v8.16b, v5.16b, v8.16b
- orr v10.16b, v10.16b, v12.16b
- ushr v12.4s, v8.4s, #12
- shl v8.4s, v8.4s, #20
- orr v8.16b, v8.16b, v12.16b
- add v12.4s, v13.4s, v27.4s
- add v12.4s, v12.4s, v4.4s
- eor v13.16b, v12.16b, v14.16b
- ldur q14, [x29, #-96]
- mov v25.16b, v29.16b
- add v29.4s, v12.4s, v20.4s
- add v20.4s, v31.4s, v26.4s
- add v0.4s, v0.4s, v14.4s
- add v0.4s, v0.4s, v3.4s
- eor v16.16b, v0.16b, v16.16b
- add v0.4s, v0.4s, v30.4s
- ldur q30, [x29, #-112]
+ ldr q13, [sp, #160]
+ eor v6.16b, v18.16b, v6.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v15.4s
+ eor v7.16b, v20.16b, v7.16b
+ add v17.4s, v17.4s, v1.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v19.4s, v19.4s, v2.4s
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ orr v6.16b, v6.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ orr v7.16b, v7.16b, v31.16b
+ ushr v31.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ add v3.4s, v6.4s, v3.4s
+ ushr v11.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v4.4s, v7.4s, v4.4s
+ orr v5.16b, v5.16b, v31.16b
+ eor v0.16b, v3.16b, v0.16b
+ orr v26.16b, v26.16b, v11.16b
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v5.4s, v23.4s
+ ushr v11.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v16.4s, v26.4s, v16.4s
+ ushr v31.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v20.4s, v20.4s, v22.4s
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v9.4s
+ mov v29.16b, v14.16b
+ ldr q14, [sp, #128]
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v18.4s, v18.4s, v14.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v19.4s, v19.4s, v25.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v27.4s
+ add v18.4s, v18.4s, v1.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ eor v6.16b, v17.16b, v6.16b
+ rev32 v7.8h, v7.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ rev32 v6.8h, v6.8h
+ add v16.4s, v16.4s, v7.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v4.4s, v6.4s
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ add v20.4s, v20.4s, v21.4s
+ ushr v11.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v28.4s
+ add v20.4s, v20.4s, v0.4s
+ mov v12.16b, v27.16b
+ ldur q27, [x29, #-208]
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v18.4s, v18.4s, v27.4s
+ add v19.4s, v19.4s, v25.4s
+ eor v26.16b, v20.16b, v26.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v13.4s
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ ushr v31.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v17.4s, v17.4s, v2.4s
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ orr v26.16b, v26.16b, v31.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ eor v0.16b, v23.16b, v0.16b
+ orr v6.16b, v6.16b, v11.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ add v4.4s, v6.4s, v4.4s
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ add v18.4s, v18.4s, v8.4s
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v29.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v15.4s
+ eor v6.16b, v6.16b, v18.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v10.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ rev32 v6.8h, v6.8h
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
+ add v3.4s, v3.4s, v6.4s
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ eor v0.16b, v3.16b, v0.16b
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ ushr v11.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ add v16.4s, v16.4s, v26.4s
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
+ add v18.4s, v18.4s, v14.4s
+ mov v30.16b, v29.16b
+ mov v29.16b, v15.16b
+ ldr q15, [sp, #144]
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v20.4s, v20.4s, v15.4s
+ add v18.4s, v18.4s, v0.4s
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v24.4s
+ eor v6.16b, v18.16b, v6.16b
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v13.4s
+ eor v7.16b, v20.16b, v7.16b
+ add v17.4s, v17.4s, v1.4s
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v19.4s, v19.4s, v2.4s
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ orr v6.16b, v6.16b, v11.16b
+ eor v26.16b, v19.16b, v26.16b
+ orr v7.16b, v7.16b, v31.16b
+ ushr v31.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ add v3.4s, v6.4s, v3.4s
+ ushr v11.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v4.4s, v7.4s, v4.4s
+ orr v5.16b, v5.16b, v31.16b
+ eor v0.16b, v3.16b, v0.16b
+ orr v26.16b, v26.16b, v11.16b
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v5.4s, v23.4s
+ ushr v11.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ mov v9.16b, v28.16b
+ mov v28.16b, v10.16b
+ ldr q10, [sp, #176]
+ add v16.4s, v26.4s, v16.4s
+ ushr v31.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v23.16b, v1.16b
+ orr v0.16b, v0.16b, v11.16b
add v20.4s, v20.4s, v10.4s
- eor v31.16b, v20.16b, v9.16b
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v9.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v18.4s, v18.4s, v12.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v19.4s, v19.4s, v25.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v17.4s, v17.4s, v21.4s
+ add v18.4s, v18.4s, v1.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ eor v6.16b, v17.16b, v6.16b
+ rev32 v7.8h, v7.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ rev32 v6.8h, v6.8h
+ add v16.4s, v16.4s, v7.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v4.4s, v6.4s
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ ushr v11.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ eor v2.16b, v4.16b, v2.16b
+ add v20.4s, v20.4s, v27.4s
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v22.4s
+ mov v9.16b, v22.16b
+ ldur q22, [x29, #-240]
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v20.4s, v20.4s, v0.4s
+ add v18.4s, v18.4s, v22.4s
+ add v19.4s, v19.4s, v25.4s
+ mov v24.16b, v21.16b
+ ldur q21, [x29, #-192]
+ orr v2.16b, v2.16b, v11.16b
+ eor v26.16b, v20.16b, v26.16b
+ add v17.4s, v17.4s, v21.4s
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ ushr v31.4s, v26.4s, #8
+ add v17.4s, v17.4s, v2.4s
+ shl v26.4s, v26.4s, #24
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ orr v26.16b, v26.16b, v31.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ orr v6.16b, v6.16b, v11.16b
+ eor v0.16b, v23.16b, v0.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v6.4s, v4.4s
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ orr v0.16b, v0.16b, v31.16b
+ eor v2.16b, v4.16b, v2.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v8.4s
+ add v18.4s, v18.4s, v14.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
+ add v17.4s, v17.4s, v13.4s
+ add v18.4s, v18.4s, v0.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v29.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ eor v6.16b, v6.16b, v18.16b
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
+ rev32 v6.8h, v6.8h
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ add v3.4s, v3.4s, v6.4s
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ eor v0.16b, v3.16b, v0.16b
+ add v16.4s, v16.4s, v26.4s
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ ushr v11.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ orr v0.16b, v0.16b, v11.16b
+ ushr v31.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
add v20.4s, v20.4s, v28.4s
+ add v18.4s, v18.4s, v12.4s
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ orr v1.16b, v1.16b, v31.16b
+ add v20.4s, v20.4s, v25.4s
add v17.4s, v17.4s, v30.4s
- add v17.4s, v17.4s, v8.4s
- eor v9.16b, v17.16b, v11.16b
- ushr v28.4s, v13.4s, #8
- shl v11.4s, v13.4s, #24
- orr v28.16b, v11.16b, v28.16b
- ushr v11.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- orr v16.16b, v16.16b, v11.16b
- ushr v11.4s, v31.4s, #8
- shl v31.4s, v31.4s, #24
- add v6.4s, v28.4s, v6.4s
- orr v31.16b, v31.16b, v11.16b
- ushr v11.4s, v9.4s, #8
- shl v9.4s, v9.4s, #24
- add v2.4s, v16.4s, v2.4s
- eor v4.16b, v6.16b, v4.16b
- orr v9.16b, v9.16b, v11.16b
- add v1.4s, v31.4s, v1.4s
- eor v3.16b, v2.16b, v3.16b
- ushr v11.4s, v4.4s, #7
- shl v4.4s, v4.4s, #25
- add v5.4s, v9.4s, v5.4s
- eor v10.16b, v1.16b, v10.16b
- orr v4.16b, v4.16b, v11.16b
- ushr v11.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- eor v8.16b, v5.16b, v8.16b
- orr v3.16b, v3.16b, v11.16b
- ushr v11.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- orr v10.16b, v10.16b, v11.16b
- ushr v11.4s, v8.4s, #7
- shl v8.4s, v8.4s, #25
- orr v8.16b, v8.16b, v11.16b
- add v29.4s, v29.4s, v8.4s
- eor v16.16b, v29.16b, v16.16b
- add v0.4s, v0.4s, v4.4s
- mov v12.16b, v26.16b
- add v17.4s, v17.4s, v19.4s
- add v26.4s, v29.4s, v23.4s
- eor v29.16b, v0.16b, v31.16b
- add v20.4s, v20.4s, v3.4s
- rev32 v16.8h, v16.8h
- stur q18, [x29, #-176]
- mov v18.16b, v27.16b
- add v0.4s, v0.4s, v24.4s
- eor v27.16b, v20.16b, v9.16b
- add v17.4s, v17.4s, v10.4s
- rev32 v24.8h, v29.8h
- add v1.4s, v1.4s, v16.4s
+ add v18.4s, v18.4s, v0.4s
+ orr v2.16b, v2.16b, v11.16b
+ add v19.4s, v19.4s, v21.4s
+ eor v7.16b, v20.16b, v7.16b
+ add v17.4s, v17.4s, v1.4s
+ eor v6.16b, v18.16b, v6.16b
+ add v19.4s, v19.4s, v2.4s
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ orr v7.16b, v7.16b, v31.16b
+ eor v26.16b, v19.16b, v26.16b
+ orr v6.16b, v6.16b, v11.16b
+ ushr v31.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ ushr v11.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ add v4.4s, v7.4s, v4.4s
+ orr v5.16b, v5.16b, v31.16b
+ add v3.4s, v6.4s, v3.4s
+ orr v26.16b, v26.16b, v11.16b
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v5.4s, v23.4s
+ eor v0.16b, v3.16b, v0.16b
+ add v16.4s, v26.4s, v16.4s
+ ushr v31.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ ushr v11.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ eor v1.16b, v23.16b, v1.16b
+ orr v25.16b, v25.16b, v31.16b
+ eor v2.16b, v16.16b, v2.16b
+ orr v0.16b, v0.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v20.4s, v20.4s, v15.4s
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v1.16b, v1.16b, v31.16b
+ add v18.4s, v18.4s, v24.4s
+ add v20.4s, v20.4s, v0.4s
+ add v19.4s, v19.4s, v9.4s
+ mov v8.16b, v13.16b
+ ldur q13, [x29, #-208]
+ orr v2.16b, v2.16b, v11.16b
+ add v18.4s, v18.4s, v1.4s
+ add v17.4s, v17.4s, v13.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v19.4s, v19.4s, v25.4s
+ eor v7.16b, v18.16b, v7.16b
+ add v17.4s, v17.4s, v2.4s
+ rev32 v26.8h, v26.8h
+ eor v5.16b, v19.16b, v5.16b
+ rev32 v7.8h, v7.8h
+ eor v6.16b, v17.16b, v6.16b
+ add v23.4s, v23.4s, v26.4s
+ rev32 v5.8h, v5.8h
+ add v16.4s, v16.4s, v7.4s
+ rev32 v6.8h, v6.8h
+ eor v0.16b, v23.16b, v0.16b
+ add v3.4s, v3.4s, v5.4s
+ eor v1.16b, v16.16b, v1.16b
+ add v4.4s, v4.4s, v6.4s
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v25.16b, v3.16b, v25.16b
+ ushr v11.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ orr v0.16b, v0.16b, v31.16b
+ eor v2.16b, v4.16b, v2.16b
+ ushr v31.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ orr v1.16b, v1.16b, v11.16b
+ ushr v11.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v20.4s, v20.4s, v22.4s
+ orr v25.16b, v25.16b, v31.16b
+ add v19.4s, v19.4s, v10.4s
+ mov v27.16b, v12.16b
+ mov v12.16b, v30.16b
+ mov v29.16b, v21.16b
+ mov v21.16b, v24.16b
+ ldr q24, [sp, #192]
+ mov v30.16b, v22.16b
+ ldr q22, [sp, #256]
+ orr v2.16b, v2.16b, v11.16b
+ add v20.4s, v20.4s, v0.4s
+ add v18.4s, v18.4s, v24.4s
+ add v19.4s, v19.4s, v25.4s
+ add v17.4s, v17.4s, v22.4s
+ eor v26.16b, v20.16b, v26.16b
+ add v18.4s, v18.4s, v1.4s
+ eor v5.16b, v19.16b, v5.16b
+ add v17.4s, v17.4s, v2.4s
+ ushr v31.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ ushr v11.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ eor v7.16b, v18.16b, v7.16b
+ eor v6.16b, v17.16b, v6.16b
+ orr v26.16b, v26.16b, v31.16b
+ orr v5.16b, v5.16b, v11.16b
+ ushr v31.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ ushr v11.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ add v23.4s, v26.4s, v23.4s
+ orr v7.16b, v7.16b, v31.16b
+ add v3.4s, v5.4s, v3.4s
+ orr v6.16b, v6.16b, v11.16b
+ eor v0.16b, v23.16b, v0.16b
+ add v16.4s, v7.4s, v16.4s
+ eor v25.16b, v3.16b, v25.16b
+ add v4.4s, v6.4s, v4.4s
+ ushr v31.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v11.4s, v25.4s, #7
+ shl v25.4s, v25.4s, #25
+ eor v1.16b, v16.16b, v1.16b
+ eor v2.16b, v4.16b, v2.16b
+ orr v0.16b, v0.16b, v31.16b
+ orr v25.16b, v25.16b, v11.16b
+ ushr v31.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ushr v11.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ add v20.4s, v20.4s, v14.4s
+ add v18.4s, v18.4s, v27.4s
+ ldr q27, [sp, #224]
+ orr v1.16b, v1.16b, v31.16b
+ orr v2.16b, v2.16b, v11.16b
add v20.4s, v20.4s, v25.4s
- eor v25.16b, v17.16b, v28.16b
- rev32 v27.8h, v27.8h
- add v5.4s, v5.4s, v24.4s
- eor v28.16b, v1.16b, v8.16b
- rev32 v25.8h, v25.8h
- add v6.4s, v6.4s, v27.4s
- eor v4.16b, v5.16b, v4.16b
- ushr v31.4s, v28.4s, #12
- shl v28.4s, v28.4s, #20
- add v2.4s, v2.4s, v25.4s
- eor v3.16b, v6.16b, v3.16b
- orr v28.16b, v28.16b, v31.16b
- ushr v31.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- eor v29.16b, v2.16b, v10.16b
- orr v4.16b, v4.16b, v31.16b
- ushr v31.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- add v26.4s, v26.4s, v28.4s
- orr v3.16b, v3.16b, v31.16b
- ushr v31.4s, v29.4s, #12
- shl v29.4s, v29.4s, #20
- eor v16.16b, v26.16b, v16.16b
- add v0.4s, v0.4s, v4.4s
- add v17.4s, v17.4s, v12.4s
- orr v29.16b, v29.16b, v31.16b
- eor v24.16b, v0.16b, v24.16b
- add v0.4s, v0.4s, v22.4s
- add v20.4s, v20.4s, v3.4s
- ushr v22.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- add v23.4s, v26.4s, v21.4s
- eor v21.16b, v20.16b, v27.16b
add v17.4s, v17.4s, v29.4s
- orr v16.16b, v16.16b, v22.16b
- ushr v22.4s, v24.4s, #8
- shl v24.4s, v24.4s, #24
- eor v25.16b, v17.16b, v25.16b
- orr v22.16b, v24.16b, v22.16b
+ add v18.4s, v18.4s, v0.4s
+ add v19.4s, v19.4s, v8.4s
+ eor v7.16b, v7.16b, v20.16b
+ add v17.4s, v17.4s, v1.4s
+ eor v6.16b, v6.16b, v18.16b
+ add v19.4s, v19.4s, v2.4s
+ rev32 v7.8h, v7.8h
+ eor v5.16b, v17.16b, v5.16b
+ rev32 v6.8h, v6.8h
+ eor v26.16b, v19.16b, v26.16b
+ add v4.4s, v4.4s, v7.4s
+ rev32 v5.8h, v5.8h
+ add v3.4s, v3.4s, v6.4s
+ rev32 v26.8h, v26.8h
+ eor v25.16b, v4.16b, v25.16b
+ add v23.4s, v23.4s, v5.4s
+ eor v0.16b, v3.16b, v0.16b
+ add v16.4s, v16.4s, v26.4s
+ ushr v29.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ ushr v31.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v1.16b, v23.16b, v1.16b
+ eor v2.16b, v16.16b, v2.16b
+ orr v25.16b, v25.16b, v29.16b
+ orr v0.16b, v0.16b, v31.16b
+ ushr v29.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ ushr v31.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ add v18.4s, v18.4s, v21.4s
+ ldr q21, [sp, #240]
+ add v20.4s, v20.4s, v27.4s
+ prfm pldl1keep, [x17, #256]
+ orr v1.16b, v1.16b, v29.16b
+ prfm pldl1keep, [x21, #256]
+ orr v2.16b, v2.16b, v31.16b
+ prfm pldl1keep, [x16, #256]
+ add v18.4s, v18.4s, v0.4s
+ prfm pldl1keep, [x6, #256]
+ add v17.4s, v17.4s, v21.4s
+ add v19.4s, v19.4s, v22.4s
+ add v20.4s, v20.4s, v25.4s
+ eor v6.16b, v18.16b, v6.16b
+ add v17.4s, v17.4s, v1.4s
+ add v19.4s, v19.4s, v2.4s
+ eor v7.16b, v20.16b, v7.16b
+ ushr v22.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ eor v5.16b, v17.16b, v5.16b
+ eor v26.16b, v19.16b, v26.16b
+ ushr v21.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ orr v6.16b, v6.16b, v22.16b
+ ushr v22.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
+ ushr v29.4s, v26.4s, #8
+ shl v26.4s, v26.4s, #24
+ orr v7.16b, v7.16b, v21.16b
+ orr v5.16b, v5.16b, v22.16b
+ add v3.4s, v6.4s, v3.4s
+ orr v21.16b, v26.16b, v29.16b
+ add v4.4s, v7.4s, v4.4s
+ add v22.4s, v5.4s, v23.4s
+ eor v0.16b, v3.16b, v0.16b
+ add v16.4s, v21.4s, v16.4s
+ eor v23.16b, v4.16b, v25.16b
+ eor v1.16b, v22.16b, v1.16b
+ ushr v25.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ eor v2.16b, v16.16b, v2.16b
+ ushr v26.4s, v23.4s, #7
+ shl v23.4s, v23.4s, #25
+ orr v0.16b, v0.16b, v25.16b
+ ushr v25.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ushr v29.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ add v20.4s, v20.4s, v28.4s
+ orr v23.16b, v23.16b, v26.16b
+ orr v1.16b, v1.16b, v25.16b
+ orr v2.16b, v2.16b, v29.16b
+ add v20.4s, v20.4s, v0.4s
+ add v18.4s, v18.4s, v13.4s
+ add v17.4s, v17.4s, v30.4s
+ add v19.4s, v19.4s, v10.4s
+ eor v21.16b, v20.16b, v21.16b
+ add v18.4s, v18.4s, v1.4s
+ add v17.4s, v17.4s, v2.4s
+ add v19.4s, v19.4s, v23.4s
+ rev32 v21.8h, v21.8h
+ eor v7.16b, v18.16b, v7.16b
+ eor v6.16b, v17.16b, v6.16b
+ eor v5.16b, v19.16b, v5.16b
+ add v22.4s, v22.4s, v21.4s
+ rev32 v7.8h, v7.8h
+ rev32 v6.8h, v6.8h
+ rev32 v5.8h, v5.8h
+ eor v0.16b, v22.16b, v0.16b
+ add v16.4s, v16.4s, v7.4s
+ add v4.4s, v4.4s, v6.4s
+ add v3.4s, v3.4s, v5.4s
+ ushr v25.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v1.16b, v16.16b, v1.16b
+ eor v2.16b, v4.16b, v2.16b
+ eor v23.16b, v3.16b, v23.16b
+ orr v0.16b, v0.16b, v25.16b
+ ushr v25.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ ushr v26.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ ushr v27.4s, v23.4s, #12
+ shl v23.4s, v23.4s, #20
+ orr v1.16b, v1.16b, v25.16b
+ add v20.4s, v20.4s, v24.4s
+ orr v2.16b, v2.16b, v26.16b
+ orr v23.16b, v23.16b, v27.16b
+ add v18.4s, v18.4s, v12.4s
+ add v17.4s, v17.4s, v9.4s
+ add v19.4s, v19.4s, v15.4s
+ add v20.4s, v20.4s, v0.4s
+ add v18.4s, v18.4s, v1.4s
+ add v17.4s, v17.4s, v2.4s
+ add v19.4s, v19.4s, v23.4s
+ eor v21.16b, v20.16b, v21.16b
+ eor v7.16b, v18.16b, v7.16b
+ eor v6.16b, v17.16b, v6.16b
+ eor v5.16b, v19.16b, v5.16b
ushr v24.4s, v21.4s, #8
shl v21.4s, v21.4s, #24
+ ushr v25.4s, v7.4s, #8
+ shl v7.4s, v7.4s, #24
+ ushr v26.4s, v6.4s, #8
+ shl v6.4s, v6.4s, #24
+ ushr v27.4s, v5.4s, #8
+ shl v5.4s, v5.4s, #24
orr v21.16b, v21.16b, v24.16b
- ushr v24.4s, v25.4s, #8
- shl v25.4s, v25.4s, #24
- add v1.4s, v16.4s, v1.4s
- orr v24.16b, v25.16b, v24.16b
- add v5.4s, v22.4s, v5.4s
- eor v25.16b, v1.16b, v28.16b
- add v6.4s, v21.4s, v6.4s
- eor v4.16b, v5.16b, v4.16b
- ushr v27.4s, v25.4s, #7
- shl v25.4s, v25.4s, #25
- add v2.4s, v24.4s, v2.4s
- eor v3.16b, v6.16b, v3.16b
- orr v25.16b, v25.16b, v27.16b
- ushr v27.4s, v4.4s, #7
- shl v4.4s, v4.4s, #25
- ldur q19, [x29, #-176]
- eor v26.16b, v2.16b, v29.16b
- orr v4.16b, v4.16b, v27.16b
- ushr v27.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- orr v3.16b, v3.16b, v27.16b
- ushr v27.4s, v26.4s, #7
- shl v26.4s, v26.4s, #25
- add v20.4s, v20.4s, v18.4s
- add v17.4s, v17.4s, v30.4s
- orr v26.16b, v26.16b, v27.16b
- add v0.4s, v0.4s, v3.4s
- eor v16.16b, v0.16b, v16.16b
- add v0.4s, v0.4s, v19.4s
- add v19.4s, v20.4s, v26.4s
- add v17.4s, v17.4s, v25.4s
- eor v20.16b, v19.16b, v22.16b
- add v7.4s, v19.4s, v7.4s
- eor v19.16b, v17.16b, v21.16b
- ldur q21, [x29, #-64]
- add v23.4s, v23.4s, v4.4s
- eor v24.16b, v23.16b, v24.16b
- rev32 v16.8h, v16.8h
- add v17.4s, v17.4s, v21.4s
- rev32 v21.8h, v24.8h
- add v6.4s, v6.4s, v21.4s
- rev32 v20.8h, v20.8h
- add v2.4s, v2.4s, v16.4s
- eor v4.16b, v6.16b, v4.16b
- rev32 v19.8h, v19.8h
- add v1.4s, v1.4s, v20.4s
- eor v3.16b, v2.16b, v3.16b
- ushr v24.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- add v5.4s, v5.4s, v19.4s
- eor v22.16b, v1.16b, v26.16b
- orr v4.16b, v4.16b, v24.16b
- ushr v24.4s, v3.4s, #12
- shl v3.4s, v3.4s, #20
- add v18.4s, v23.4s, v14.4s
- eor v23.16b, v5.16b, v25.16b
- orr v3.16b, v3.16b, v24.16b
- ushr v24.4s, v22.4s, #12
- shl v22.4s, v22.4s, #20
- orr v22.16b, v22.16b, v24.16b
- ushr v24.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- orr v23.16b, v23.16b, v24.16b
- add v18.4s, v18.4s, v4.4s
- add v0.4s, v0.4s, v3.4s
- add v24.4s, v17.4s, v23.4s
- eor v17.16b, v18.16b, v21.16b
- add v7.4s, v7.4s, v22.4s
- eor v16.16b, v0.16b, v16.16b
- ushr v21.4s, v17.4s, #8
- shl v17.4s, v17.4s, #24
- eor v20.16b, v7.16b, v20.16b
- orr v21.16b, v17.16b, v21.16b
- ushr v17.4s, v16.4s, #8
- shl v16.4s, v16.4s, #24
- eor v19.16b, v24.16b, v19.16b
- orr v16.16b, v16.16b, v17.16b
- ushr v17.4s, v20.4s, #8
- shl v20.4s, v20.4s, #24
- orr v25.16b, v20.16b, v17.16b
- ushr v17.4s, v19.4s, #8
- shl v19.4s, v19.4s, #24
- orr v19.16b, v19.16b, v17.16b
- add v1.4s, v25.4s, v1.4s
- eor v22.16b, v1.16b, v22.16b
- eor v20.16b, v1.16b, v18.16b
- add v1.4s, v19.4s, v5.4s
- eor v26.16b, v1.16b, v0.16b
- add v0.4s, v21.4s, v6.4s
- eor v5.16b, v1.16b, v23.16b
- eor v1.16b, v0.16b, v4.16b
- eor v17.16b, v0.16b, v7.16b
- add v0.4s, v16.4s, v2.4s
- eor v2.16b, v0.16b, v3.16b
- eor v6.16b, v0.16b, v24.16b
- ushr v0.4s, v1.4s, #7
+ orr v7.16b, v7.16b, v25.16b
+ orr v6.16b, v6.16b, v26.16b
+ orr v5.16b, v5.16b, v27.16b
+ add v22.4s, v21.4s, v22.4s
+ add v16.4s, v7.4s, v16.4s
+ add v4.4s, v6.4s, v4.4s
+ add v3.4s, v5.4s, v3.4s
+ eor v0.16b, v22.16b, v0.16b
+ eor v1.16b, v16.16b, v1.16b
+ eor v2.16b, v4.16b, v2.16b
+ eor v23.16b, v3.16b, v23.16b
+ ushr v24.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v25.4s, v1.4s, #7
shl v1.4s, v1.4s, #25
- orr v0.16b, v1.16b, v0.16b
- ushr v1.4s, v2.4s, #7
+ ushr v26.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- orr v1.16b, v2.16b, v1.16b
- ushr v2.4s, v22.4s, #7
- shl v3.4s, v22.4s, #25
- orr v2.16b, v3.16b, v2.16b
- ushr v3.4s, v5.4s, #7
- shl v4.4s, v5.4s, #25
- orr v3.16b, v4.16b, v3.16b
- eor v8.16b, v16.16b, v3.16b
- eor v9.16b, v25.16b, v0.16b
- eor v31.16b, v1.16b, v19.16b
- cmp x17, x22
- eor v15.16b, v2.16b, v21.16b
- mov w18, w19
- b.ne .LBB2_4
-.LBB2_7:
- zip1 v0.4s, v20.4s, v26.4s
- zip2 v1.4s, v20.4s, v26.4s
- zip1 v2.4s, v17.4s, v6.4s
- zip2 v3.4s, v17.4s, v6.4s
- zip1 v4.4s, v8.4s, v9.4s
- zip2 v5.4s, v8.4s, v9.4s
- zip1 v6.4s, v31.4s, v15.4s
- zip2 v7.4s, v31.4s, v15.4s
- add x13, x20, #4
- tst w5, #0x1
- sub x28, x28, #4
- zip1 v16.2d, v0.2d, v2.2d
- zip2 v0.2d, v0.2d, v2.2d
- zip1 v2.2d, v1.2d, v3.2d
- zip2 v1.2d, v1.2d, v3.2d
- zip1 v3.2d, v4.2d, v6.2d
- zip2 v4.2d, v4.2d, v6.2d
- zip1 v6.2d, v5.2d, v7.2d
- zip2 v5.2d, v5.2d, v7.2d
- add x24, x24, #32
- csel x20, x13, x20, ne
- cmp x28, #3
- stp q16, q3, [x26]
- stp q0, q4, [x26, #32]
- stp q2, q6, [x26, #64]
- stp q1, q5, [x26, #96]
- add x26, x26, #128
- b.hi .LBB2_2
-.LBB2_8:
- cbz x28, .LBB2_16
+ ushr v27.4s, v23.4s, #7
+ shl v23.4s, v23.4s, #25
+ orr v0.16b, v0.16b, v24.16b
+ orr v1.16b, v1.16b, v25.16b
+ orr v2.16b, v2.16b, v26.16b
+ orr v23.16b, v23.16b, v27.16b
+ movi v24.4s, #64
+ eor v12.16b, v4.16b, v20.16b
+ eor v31.16b, v18.16b, v3.16b
+ eor v29.16b, v17.16b, v22.16b
+ eor v30.16b, v16.16b, v19.16b
+ eor v28.16b, v7.16b, v23.16b
+ eor v23.16b, v6.16b, v0.16b
+ eor v13.16b, v1.16b, v5.16b
+ eor v25.16b, v2.16b, v21.16b
+ cbnz x15, .LBB3_5
+ b .LBB3_2
+.LBB3_6:
+ cbz x24, .LBB3_14
orr w8, w7, w19
- and x21, x5, #0x1
- stur w8, [x29, #-64]
-.LBB2_10:
+ and x22, x5, #0x1
+ stur w8, [x29, #-192]
+.LBB3_8:
ldr x8, [sp, #40]
- ldr x25, [x24]
- ldur w4, [x29, #-64]
- ldp q1, q0, [x8]
- mov x8, x22
- stp q1, q0, [x29, #-48]
-.LBB2_11:
- subs x23, x8, #1
- b.eq .LBB2_13
- cbnz x8, .LBB2_14
- b .LBB2_15
-.LBB2_13:
- orr w4, w4, w27
-.LBB2_14:
- sub x0, x29, #48
- mov w2, #64
- mov x1, x25
- mov x3, x20
- bl zfs_blake3_compress_in_place_sse2
+ mov x28, x0
+ ldr x25, [x0]
+ mov x23, x2
+ ldur w5, [x29, #-192]
+ ldp q0, q1, [x8]
+ mov x8, x2
+ b .LBB3_11
+.LBB3_9:
+ orr w5, w5, w27
+.LBB3_10:
+ sub x0, x29, #144
+ sub x1, x29, #176
+ mov x2, x25
+ mov w3, #64
+ mov x4, x20
+ bl compress_pre
+ ldp q0, q1, [x29, #-144]
add x25, x25, #64
- mov x8, x23
- mov w4, w19
- b .LBB2_11
-.LBB2_15:
- ldp q0, q1, [x29, #-48]
- add x20, x20, x21
- add x24, x24, #8
- subs x28, x28, #1
- stp q0, q1, [x26], #32
- b.ne .LBB2_10
-.LBB2_16:
- add sp, sp, #384
+ mov x8, x21
+ mov w5, w19
+ ldp q2, q3, [x29, #-112]
+ eor v0.16b, v2.16b, v0.16b
+ eor v1.16b, v3.16b, v1.16b
+.LBB3_11:
+ subs x21, x8, #1
+ stp q0, q1, [x29, #-176]
+ b.eq .LBB3_9
+ cbnz x8, .LBB3_10
+ ldp q1, q0, [x29, #-176]
+ mov x0, x28
+ add x20, x20, x22
+ add x0, x28, #8
+ subs x24, x24, #1
+ mov x2, x23
+ stp q1, q0, [x26], #32
+ b.ne .LBB3_8
+.LBB3_14:
+ add sp, sp, #464
ldp x20, x19, [sp, #144]
ldp x22, x21, [sp, #128]
ldp x24, x23, [sp, #112]
@@ -2442,9 +2060,10 @@ zfs_blake3_hash_many_sse2:
ldp d11, d10, [sp, #32]
ldp d13, d12, [sp, #16]
ldp d15, d14, [sp], #160
+ hint #29
ret
-.Lfunc_end2:
- .size zfs_blake3_hash_many_sse2, .Lfunc_end2-zfs_blake3_hash_many_sse2
+.Lfunc_end3:
+ .size zfs_blake3_hash_many_sse2, .Lfunc_end3-zfs_blake3_hash_many_sse2
.cfi_endproc
.section ".note.GNU-stack","",@progbits
-#endif
+#endif \ No newline at end of file
diff --git a/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S b/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
index eb6946400b8a..1ad6cefc6d06 100644
--- a/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
+++ b/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,518 +22,69 @@
/*
* Based on BLAKE3 v1.3.1, https://github.com/BLAKE3-team/BLAKE3
* Copyright (c) 2019-2022 Samuel Neves
- * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * Copyright (c) 2022-2023 Tino Reichardt <milky-zfs@mcmilk.de>
*
* This is converted assembly: SSE4.1 -> ARMv8-A
* Used tools: SIMDe https://github.com/simd-everywhere/simde
+ *
+ * Should work on FreeBSD, Linux and macOS
+ * see: https://github.com/mcmilk/BLAKE3-tests/blob/master/contrib/simde.sh
*/
#if defined(__aarch64__)
+
+/* make gcc <= 9 happy */
+#if !defined(LD_VERSION) || LD_VERSION >= 233010000
+#define CFI_NEGATE_RA_STATE .cfi_negate_ra_state
+#else
+#define CFI_NEGATE_RA_STATE
+#endif
+
.text
- .section .rodata.cst16,"aM",@progbits,16
- .p2align 4
-.LCPI0_0:
- .byte 2
- .byte 3
- .byte 0
- .byte 1
- .byte 6
- .byte 7
- .byte 4
- .byte 5
- .byte 10
- .byte 11
- .byte 8
- .byte 9
- .byte 14
- .byte 15
- .byte 12
- .byte 13
-.LCPI0_1:
- .word 1779033703
- .word 3144134277
- .word 1013904242
- .word 2773480762
-.LCPI0_2:
- .byte 1
- .byte 2
- .byte 3
- .byte 0
- .byte 5
- .byte 6
- .byte 7
- .byte 4
- .byte 9
- .byte 10
- .byte 11
- .byte 8
- .byte 13
- .byte 14
- .byte 15
- .byte 12
-.LCPI0_3:
- .byte 0
- .byte 1
- .byte 2
- .byte 3
- .byte 20
- .byte 21
- .byte 22
- .byte 23
- .byte 8
- .byte 9
- .byte 10
- .byte 11
- .byte 28
- .byte 29
- .byte 30
- .byte 31
-.LCPI0_4:
- .byte 0
- .byte 1
- .byte 2
- .byte 3
- .byte 4
- .byte 5
- .byte 6
- .byte 7
- .byte 8
- .byte 9
- .byte 10
- .byte 11
- .byte 28
- .byte 29
- .byte 30
- .byte 31
+ .section .note.gnu.property,"a",@note
+ .p2align 3
+ .word 4
+ .word 16
+ .word 5
+ .asciz "GNU"
+ .word 3221225472
+ .word 4
+ .word 3
+ .word 0
+.Lsec_end0:
.text
.globl zfs_blake3_compress_in_place_sse41
.p2align 2
.type zfs_blake3_compress_in_place_sse41,@function
zfs_blake3_compress_in_place_sse41:
.cfi_startproc
- ldp q7, q6, [x0]
- ldp q17, q18, [x1]
- add x12, x1, #32
- ld2 { v4.4s, v5.4s }, [x12]
- lsr x10, x3, #32
- fmov s16, w3
- adrp x13, .LCPI0_0
- adrp x11, .LCPI0_1
- and w8, w2, #0xff
- mov v16.s[1], w10
- ldr q0, [x13, :lo12:.LCPI0_0]
- ldr q20, [x11, :lo12:.LCPI0_1]
- adrp x11, .LCPI0_4
- and w9, w4, #0xff
- ldr q2, [x11, :lo12:.LCPI0_4]
- mov v16.s[2], w8
- uzp1 v21.4s, v17.4s, v18.4s
- add v7.4s, v6.4s, v7.4s
- adrp x12, .LCPI0_3
- mov v16.s[3], w9
- uzp2 v18.4s, v17.4s, v18.4s
- add v7.4s, v7.4s, v21.4s
- ext v17.16b, v5.16b, v5.16b, #12
- ldr q3, [x12, :lo12:.LCPI0_3]
- ext v24.16b, v4.16b, v4.16b, #12
- eor v16.16b, v7.16b, v16.16b
- mov v27.16b, v17.16b
- uzp1 v19.4s, v21.4s, v21.4s
- ext v25.16b, v21.16b, v21.16b, #12
- zip2 v28.4s, v18.4s, v17.4s
- tbl v29.16b, { v16.16b }, v0.16b
- mov v27.s[1], v24.s[2]
- zip1 v23.2d, v17.2d, v18.2d
- ext v19.16b, v19.16b, v21.16b, #8
- add v22.4s, v29.4s, v20.4s
- ext v26.16b, v21.16b, v25.16b, #12
- tbl v20.16b, { v23.16b, v24.16b }, v2.16b
- zip1 v21.4s, v28.4s, v24.4s
- zip1 v23.4s, v24.4s, v28.4s
- uzp2 v19.4s, v19.4s, v18.4s
- eor v24.16b, v22.16b, v6.16b
- ext v25.16b, v20.16b, v20.16b, #12
- ext v6.16b, v23.16b, v21.16b, #8
- add v7.4s, v7.4s, v18.4s
- ext v18.16b, v19.16b, v19.16b, #4
- tbl v16.16b, { v26.16b, v27.16b }, v3.16b
- uzp1 v21.4s, v20.4s, v25.4s
- mov v26.16b, v6.16b
- ext v23.16b, v18.16b, v18.16b, #12
- mov v26.s[1], v21.s[2]
- adrp x10, .LCPI0_2
- ext v25.16b, v18.16b, v23.16b, #12
- uzp1 v23.4s, v18.4s, v18.4s
- ldr q1, [x10, :lo12:.LCPI0_2]
- ext v18.16b, v23.16b, v18.16b, #8
- ushr v23.4s, v24.4s, #12
- shl v24.4s, v24.4s, #20
- orr v23.16b, v24.16b, v23.16b
- add v7.4s, v7.4s, v23.4s
- eor v27.16b, v29.16b, v7.16b
- add v4.4s, v7.4s, v4.4s
- tbl v7.16b, { v25.16b, v26.16b }, v3.16b
- tbl v26.16b, { v27.16b }, v1.16b
- add v22.4s, v22.4s, v26.4s
- uzp2 v18.4s, v18.4s, v16.4s
- eor v23.16b, v23.16b, v22.16b
- ext v5.16b, v18.16b, v18.16b, #4
- ushr v27.4s, v23.4s, #7
- shl v23.4s, v23.4s, #25
- uzp1 v25.4s, v5.4s, v5.4s
- orr v23.16b, v23.16b, v27.16b
- ext v28.16b, v4.16b, v4.16b, #12
- ext v4.16b, v25.16b, v5.16b, #8
- ext v25.16b, v26.16b, v26.16b, #8
- add v26.4s, v28.4s, v23.4s
- eor v25.16b, v26.16b, v25.16b
- ext v22.16b, v22.16b, v22.16b, #4
- tbl v25.16b, { v25.16b }, v0.16b
- add v22.4s, v22.4s, v25.4s
- eor v23.16b, v23.16b, v22.16b
- add v17.4s, v26.4s, v17.4s
- ushr v26.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- orr v23.16b, v23.16b, v26.16b
- add v17.4s, v17.4s, v23.4s
- eor v25.16b, v25.16b, v17.16b
- add v17.4s, v17.4s, v19.4s
- tbl v19.16b, { v25.16b }, v1.16b
- add v22.4s, v22.4s, v19.4s
- eor v23.16b, v23.16b, v22.16b
- ushr v25.4s, v23.4s, #7
- shl v23.4s, v23.4s, #25
- ext v17.16b, v17.16b, v17.16b, #4
- orr v23.16b, v23.16b, v25.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v17.4s, v17.4s, v23.4s
- eor v19.16b, v17.16b, v19.16b
- ext v22.16b, v22.16b, v22.16b, #12
- tbl v19.16b, { v19.16b }, v0.16b
- add v22.4s, v22.4s, v19.4s
- eor v23.16b, v23.16b, v22.16b
- ushr v25.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- add v17.4s, v17.4s, v16.4s
- orr v23.16b, v23.16b, v25.16b
- add v17.4s, v17.4s, v23.4s
- ext v25.16b, v17.16b, v17.16b, #12
- eor v17.16b, v19.16b, v17.16b
- tbl v17.16b, { v17.16b }, v1.16b
- add v19.4s, v22.4s, v17.4s
- eor v22.16b, v23.16b, v19.16b
- add v25.4s, v25.4s, v21.4s
- zip1 v20.2d, v6.2d, v16.2d
- ushr v23.4s, v22.4s, #7
- shl v22.4s, v22.4s, #25
- zip2 v24.4s, v16.4s, v6.4s
- tbl v26.16b, { v20.16b, v21.16b }, v2.16b
- orr v22.16b, v22.16b, v23.16b
- zip1 v16.4s, v24.4s, v21.4s
- zip1 v20.4s, v21.4s, v24.4s
- ext v21.16b, v26.16b, v26.16b, #12
- ext v17.16b, v17.16b, v17.16b, #8
- add v25.4s, v25.4s, v22.4s
- ext v16.16b, v20.16b, v16.16b, #8
- uzp1 v21.4s, v26.4s, v21.4s
- eor v26.16b, v25.16b, v17.16b
- ext v19.16b, v19.16b, v19.16b, #4
- tbl v26.16b, { v26.16b }, v0.16b
- mov v29.16b, v16.16b
- add v19.4s, v19.4s, v26.4s
- ext v27.16b, v5.16b, v5.16b, #12
- mov v29.s[1], v21.s[2]
- eor v22.16b, v22.16b, v19.16b
- ext v28.16b, v5.16b, v27.16b, #12
- ushr v27.4s, v22.4s, #12
- shl v22.4s, v22.4s, #20
- add v6.4s, v25.4s, v6.4s
- orr v22.16b, v22.16b, v27.16b
- add v6.4s, v6.4s, v22.4s
- eor v26.16b, v26.16b, v6.16b
- add v6.4s, v6.4s, v18.4s
- tbl v18.16b, { v26.16b }, v1.16b
- add v19.4s, v19.4s, v18.4s
- eor v22.16b, v22.16b, v19.16b
- ushr v26.4s, v22.4s, #7
- shl v22.4s, v22.4s, #25
- ext v6.16b, v6.16b, v6.16b, #4
- orr v22.16b, v22.16b, v26.16b
- ext v18.16b, v18.16b, v18.16b, #8
- add v6.4s, v6.4s, v22.4s
- eor v18.16b, v6.16b, v18.16b
- ext v19.16b, v19.16b, v19.16b, #12
- tbl v18.16b, { v18.16b }, v0.16b
- add v19.4s, v19.4s, v18.4s
- eor v22.16b, v22.16b, v19.16b
- ushr v26.4s, v22.4s, #12
- shl v22.4s, v22.4s, #20
- add v6.4s, v6.4s, v7.4s
- orr v22.16b, v22.16b, v26.16b
- add v6.4s, v6.4s, v22.4s
- ext v26.16b, v6.16b, v6.16b, #12
- eor v6.16b, v18.16b, v6.16b
- uzp2 v4.4s, v4.4s, v7.4s
- zip2 v25.4s, v7.4s, v16.4s
- add v26.4s, v26.4s, v21.4s
- zip1 v20.2d, v16.2d, v7.2d
- tbl v6.16b, { v6.16b }, v1.16b
- ext v24.16b, v4.16b, v4.16b, #4
- tbl v27.16b, { v20.16b, v21.16b }, v2.16b
- zip1 v7.4s, v25.4s, v21.4s
- zip1 v20.4s, v21.4s, v25.4s
- add v18.4s, v19.4s, v6.4s
- uzp1 v5.4s, v24.4s, v24.4s
- ext v21.16b, v27.16b, v27.16b, #12
- ext v7.16b, v20.16b, v7.16b, #8
- eor v19.16b, v22.16b, v18.16b
- ext v5.16b, v5.16b, v24.16b, #8
- tbl v17.16b, { v28.16b, v29.16b }, v3.16b
- uzp1 v21.4s, v27.4s, v21.4s
- mov v28.16b, v7.16b
- ushr v22.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v23.16b, v24.16b, v24.16b, #12
- uzp2 v5.4s, v5.4s, v17.4s
- mov v28.s[1], v21.s[2]
- orr v19.16b, v19.16b, v22.16b
- ext v27.16b, v24.16b, v23.16b, #12
- ext v23.16b, v5.16b, v5.16b, #4
- ext v6.16b, v6.16b, v6.16b, #8
- ext v25.16b, v18.16b, v18.16b, #4
- add v18.4s, v26.4s, v19.4s
- uzp1 v24.4s, v23.4s, v23.4s
- eor v6.16b, v18.16b, v6.16b
- ext v24.16b, v24.16b, v23.16b, #8
- add v16.4s, v18.4s, v16.4s
- tbl v18.16b, { v27.16b, v28.16b }, v3.16b
- tbl v27.16b, { v6.16b }, v0.16b
- uzp2 v6.4s, v24.4s, v18.4s
- add v24.4s, v25.4s, v27.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v19.16b, v19.16b, v25.16b
- add v16.4s, v16.4s, v19.4s
- eor v25.16b, v27.16b, v16.16b
- add v4.4s, v16.4s, v4.4s
- tbl v16.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v16.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v4.16b, v4.16b, v4.16b, #4
- orr v19.16b, v19.16b, v25.16b
- ext v16.16b, v16.16b, v16.16b, #8
- add v4.4s, v4.4s, v19.4s
- eor v16.16b, v4.16b, v16.16b
- ext v24.16b, v24.16b, v24.16b, #12
- tbl v25.16b, { v16.16b }, v0.16b
- add v24.4s, v24.4s, v25.4s
- eor v16.16b, v19.16b, v24.16b
- ushr v19.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- add v4.4s, v4.4s, v17.4s
- orr v19.16b, v16.16b, v19.16b
- add v27.4s, v4.4s, v19.4s
- eor v25.16b, v25.16b, v27.16b
- tbl v25.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v25.4s
- zip2 v26.4s, v17.4s, v7.4s
- ext v4.16b, v27.16b, v27.16b, #12
- eor v19.16b, v19.16b, v24.16b
- add v28.4s, v4.4s, v21.4s
- zip1 v20.2d, v7.2d, v17.2d
- zip1 v4.4s, v26.4s, v21.4s
- zip1 v17.4s, v21.4s, v26.4s
- ushr v26.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v19.16b, v19.16b, v26.16b
- ext v25.16b, v25.16b, v25.16b, #8
- add v27.4s, v28.4s, v19.4s
- eor v25.16b, v27.16b, v25.16b
- ext v24.16b, v24.16b, v24.16b, #4
- tbl v25.16b, { v25.16b }, v0.16b
- add v24.4s, v24.4s, v25.4s
- eor v19.16b, v19.16b, v24.16b
- add v7.4s, v27.4s, v7.4s
- ushr v27.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v19.16b, v19.16b, v27.16b
- add v7.4s, v7.4s, v19.4s
- eor v25.16b, v25.16b, v7.16b
- add v5.4s, v7.4s, v5.4s
- tbl v7.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v7.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v5.16b, v5.16b, v5.16b, #4
- orr v19.16b, v19.16b, v25.16b
- ext v7.16b, v7.16b, v7.16b, #8
- add v5.4s, v5.4s, v19.4s
- eor v7.16b, v5.16b, v7.16b
- ext v24.16b, v24.16b, v24.16b, #12
- tbl v7.16b, { v7.16b }, v0.16b
- add v24.4s, v24.4s, v7.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- tbl v16.16b, { v20.16b, v21.16b }, v2.16b
- add v5.4s, v5.4s, v18.4s
- orr v19.16b, v19.16b, v25.16b
- ext v20.16b, v16.16b, v16.16b, #12
- ext v4.16b, v17.16b, v4.16b, #8
- add v5.4s, v5.4s, v19.4s
- uzp1 v21.4s, v16.4s, v20.4s
- mov v17.16b, v4.16b
- ext v25.16b, v5.16b, v5.16b, #12
- mov v17.s[1], v21.s[2]
- add v25.4s, v25.4s, v21.4s
- zip1 v20.2d, v4.2d, v18.2d
- ext v22.16b, v23.16b, v23.16b, #12
- zip2 v26.4s, v18.4s, v4.4s
- tbl v18.16b, { v20.16b, v21.16b }, v2.16b
- eor v5.16b, v7.16b, v5.16b
- ext v16.16b, v23.16b, v22.16b, #12
- ext v22.16b, v6.16b, v6.16b, #4
- zip1 v27.4s, v26.4s, v21.4s
- zip1 v20.4s, v21.4s, v26.4s
- ext v21.16b, v18.16b, v18.16b, #12
- tbl v5.16b, { v5.16b }, v1.16b
- ext v20.16b, v20.16b, v27.16b, #8
- uzp1 v27.4s, v18.4s, v21.4s
- uzp1 v18.4s, v22.4s, v22.4s
- add v21.4s, v24.4s, v5.4s
- ext v18.16b, v18.16b, v22.16b, #8
- eor v19.16b, v19.16b, v21.16b
- tbl v7.16b, { v16.16b, v17.16b }, v3.16b
- uzp2 v18.4s, v18.4s, v17.4s
- zip2 v16.4s, v16.4s, v20.4s
- ushr v17.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v17.16b, v19.16b, v17.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v19.4s, v25.4s, v17.4s
- eor v5.16b, v19.16b, v5.16b
- ext v21.16b, v21.16b, v21.16b, #4
- tbl v5.16b, { v5.16b }, v0.16b
- add v4.4s, v19.4s, v4.4s
- add v19.4s, v21.4s, v5.4s
- eor v17.16b, v17.16b, v19.16b
- ushr v21.4s, v17.4s, #12
- shl v17.4s, v17.4s, #20
- orr v17.16b, v17.16b, v21.16b
- add v4.4s, v4.4s, v17.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
- add v4.4s, v4.4s, v6.4s
- add v6.4s, v19.4s, v5.4s
- eor v17.16b, v17.16b, v6.16b
- ushr v19.4s, v17.4s, #7
- shl v17.4s, v17.4s, #25
- ext v4.16b, v4.16b, v4.16b, #4
- orr v17.16b, v17.16b, v19.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v4.4s, v17.4s
- eor v5.16b, v4.16b, v5.16b
- ext v6.16b, v6.16b, v6.16b, #12
- tbl v5.16b, { v5.16b }, v0.16b
- add v6.4s, v6.4s, v5.4s
- eor v17.16b, v17.16b, v6.16b
- ushr v19.4s, v17.4s, #12
- shl v17.4s, v17.4s, #20
- add v4.4s, v4.4s, v7.4s
- orr v17.16b, v17.16b, v19.16b
- add v4.4s, v4.4s, v17.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
- mov v29.16b, v20.16b
- ext v4.16b, v4.16b, v4.16b, #12
- add v6.4s, v6.4s, v5.4s
- mov v29.s[1], v27.s[2]
- add v4.4s, v4.4s, v27.4s
- zip1 v26.2d, v20.2d, v7.2d
- zip1 v7.4s, v16.4s, v27.4s
- zip1 v16.4s, v27.4s, v16.4s
- eor v17.16b, v17.16b, v6.16b
- ext v7.16b, v16.16b, v7.16b, #8
- ushr v16.4s, v17.4s, #7
- shl v17.4s, v17.4s, #25
- orr v16.16b, v17.16b, v16.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v4.4s, v16.4s
- eor v5.16b, v4.16b, v5.16b
- ext v6.16b, v6.16b, v6.16b, #4
- tbl v5.16b, { v5.16b }, v0.16b
- add v6.4s, v6.4s, v5.4s
- eor v16.16b, v16.16b, v6.16b
- ushr v17.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- add v4.4s, v4.4s, v20.4s
- orr v16.16b, v16.16b, v17.16b
- add v4.4s, v4.4s, v16.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
- add v6.4s, v6.4s, v5.4s
- eor v16.16b, v16.16b, v6.16b
- add v4.4s, v4.4s, v18.4s
- ushr v17.4s, v16.4s, #7
- shl v16.4s, v16.4s, #25
- ext v23.16b, v22.16b, v22.16b, #12
- ext v4.16b, v4.16b, v4.16b, #4
- orr v16.16b, v16.16b, v17.16b
- ext v28.16b, v22.16b, v23.16b, #12
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v16.4s, v4.4s
- tbl v3.16b, { v28.16b, v29.16b }, v3.16b
- eor v5.16b, v4.16b, v5.16b
- ext v6.16b, v6.16b, v6.16b, #12
- add v3.4s, v4.4s, v3.4s
- tbl v4.16b, { v5.16b }, v0.16b
- add v5.4s, v6.4s, v4.4s
- eor v6.16b, v16.16b, v5.16b
- ushr v16.4s, v6.4s, #12
- shl v6.4s, v6.4s, #20
- orr v6.16b, v6.16b, v16.16b
- tbl v2.16b, { v26.16b, v27.16b }, v2.16b
- add v3.4s, v3.4s, v6.4s
- ext v19.16b, v2.16b, v2.16b, #12
- eor v4.16b, v4.16b, v3.16b
- uzp1 v2.4s, v2.4s, v19.4s
- ext v3.16b, v3.16b, v3.16b, #12
- tbl v4.16b, { v4.16b }, v1.16b
- add v2.4s, v3.4s, v2.4s
- add v3.4s, v5.4s, v4.4s
- eor v5.16b, v6.16b, v3.16b
- ushr v6.4s, v5.4s, #7
- shl v5.4s, v5.4s, #25
- orr v5.16b, v5.16b, v6.16b
- ext v4.16b, v4.16b, v4.16b, #8
- add v2.4s, v2.4s, v5.4s
- eor v4.16b, v2.16b, v4.16b
- ext v3.16b, v3.16b, v3.16b, #4
- tbl v0.16b, { v4.16b }, v0.16b
- add v3.4s, v3.4s, v0.4s
- eor v4.16b, v5.16b, v3.16b
- ushr v5.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- add v2.4s, v2.4s, v7.4s
- orr v4.16b, v4.16b, v5.16b
- add v2.4s, v2.4s, v4.4s
- eor v0.16b, v0.16b, v2.16b
- tbl v0.16b, { v0.16b }, v1.16b
- add v1.4s, v3.4s, v0.4s
- eor v3.16b, v4.16b, v1.16b
- ext v2.16b, v2.16b, v2.16b, #4
- ext v1.16b, v1.16b, v1.16b, #12
- ushr v4.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
- ext v0.16b, v0.16b, v0.16b, #8
- eor v1.16b, v2.16b, v1.16b
- orr v2.16b, v3.16b, v4.16b
+ hint #25
+ CFI_NEGATE_RA_STATE
+ sub sp, sp, #96
+ stp x29, x30, [sp, #64]
+ add x29, sp, #64
+ str x19, [sp, #80]
+ .cfi_def_cfa w29, 32
+ .cfi_offset w19, -16
+ .cfi_offset w30, -24
+ .cfi_offset w29, -32
+ mov x19, x0
+ mov w5, w4
+ mov x4, x3
+ mov w3, w2
+ mov x2, x1
+ mov x0, sp
+ mov x1, x19
+ bl compress_pre
+ ldp q0, q1, [sp]
+ ldp q2, q3, [sp, #32]
eor v0.16b, v2.16b, v0.16b
- stp q1, q0, [x0]
+ eor v1.16b, v3.16b, v1.16b
+ ldp x29, x30, [sp, #64]
+ stp q0, q1, [x19]
+ ldr x19, [sp, #80]
+ add sp, sp, #96
+ hint #29
ret
.Lfunc_end0:
.size zfs_blake3_compress_in_place_sse41, .Lfunc_end0-zfs_blake3_compress_in_place_sse41
@@ -542,6 +93,9 @@ zfs_blake3_compress_in_place_sse41:
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
.LCPI1_0:
+ .xword -4942790177982912921
+ .xword -6534734903820487822
+.LCPI1_1:
.byte 2
.byte 3
.byte 0
@@ -558,11 +112,6 @@ zfs_blake3_compress_in_place_sse41:
.byte 15
.byte 12
.byte 13
-.LCPI1_1:
- .word 1779033703
- .word 3144134277
- .word 1013904242
- .word 2773480762
.LCPI1_2:
.byte 1
.byte 2
@@ -580,488 +129,497 @@ zfs_blake3_compress_in_place_sse41:
.byte 14
.byte 15
.byte 12
-.LCPI1_3:
- .byte 0
- .byte 1
- .byte 2
- .byte 3
- .byte 20
- .byte 21
- .byte 22
- .byte 23
- .byte 8
- .byte 9
- .byte 10
- .byte 11
- .byte 28
- .byte 29
- .byte 30
- .byte 31
-.LCPI1_4:
- .byte 0
- .byte 1
- .byte 2
- .byte 3
- .byte 4
- .byte 5
- .byte 6
- .byte 7
- .byte 8
- .byte 9
- .byte 10
- .byte 11
- .byte 28
- .byte 29
- .byte 30
- .byte 31
.text
- .globl zfs_blake3_compress_xof_sse41
.p2align 2
- .type zfs_blake3_compress_xof_sse41,@function
-zfs_blake3_compress_xof_sse41:
+ .type compress_pre,@function
+compress_pre:
.cfi_startproc
- ldp q7, q6, [x0]
- ldp q17, q18, [x1]
- add x12, x1, #32
- ld2 { v4.4s, v5.4s }, [x12]
- lsr x10, x3, #32
- fmov s16, w3
- adrp x13, .LCPI1_0
- adrp x11, .LCPI1_1
- and w8, w2, #0xff
- mov v16.s[1], w10
- ldr q0, [x13, :lo12:.LCPI1_0]
- ldr q20, [x11, :lo12:.LCPI1_1]
- adrp x11, .LCPI1_4
- and w9, w4, #0xff
- ldr q2, [x11, :lo12:.LCPI1_4]
- mov v16.s[2], w8
- uzp1 v21.4s, v17.4s, v18.4s
- add v7.4s, v6.4s, v7.4s
- adrp x12, .LCPI1_3
- mov v16.s[3], w9
- uzp2 v18.4s, v17.4s, v18.4s
- add v7.4s, v7.4s, v21.4s
- ext v17.16b, v5.16b, v5.16b, #12
- ldr q3, [x12, :lo12:.LCPI1_3]
- ext v24.16b, v4.16b, v4.16b, #12
- eor v16.16b, v7.16b, v16.16b
- mov v27.16b, v17.16b
- uzp1 v19.4s, v21.4s, v21.4s
- ext v25.16b, v21.16b, v21.16b, #12
- zip2 v28.4s, v18.4s, v17.4s
- tbl v29.16b, { v16.16b }, v0.16b
- mov v27.s[1], v24.s[2]
- zip1 v23.2d, v17.2d, v18.2d
- ext v19.16b, v19.16b, v21.16b, #8
- add v22.4s, v29.4s, v20.4s
- ext v26.16b, v21.16b, v25.16b, #12
- tbl v20.16b, { v23.16b, v24.16b }, v2.16b
- zip1 v21.4s, v28.4s, v24.4s
- zip1 v23.4s, v24.4s, v28.4s
- uzp2 v19.4s, v19.4s, v18.4s
- eor v24.16b, v22.16b, v6.16b
- ext v25.16b, v20.16b, v20.16b, #12
- ext v6.16b, v23.16b, v21.16b, #8
- add v7.4s, v7.4s, v18.4s
- ext v18.16b, v19.16b, v19.16b, #4
- tbl v16.16b, { v26.16b, v27.16b }, v3.16b
- uzp1 v21.4s, v20.4s, v25.4s
- mov v26.16b, v6.16b
- ext v23.16b, v18.16b, v18.16b, #12
- mov v26.s[1], v21.s[2]
- adrp x10, .LCPI1_2
- ext v25.16b, v18.16b, v23.16b, #12
- uzp1 v23.4s, v18.4s, v18.4s
- ldr q1, [x10, :lo12:.LCPI1_2]
- ext v18.16b, v23.16b, v18.16b, #8
- ushr v23.4s, v24.4s, #12
- shl v24.4s, v24.4s, #20
- orr v23.16b, v24.16b, v23.16b
- add v7.4s, v7.4s, v23.4s
- eor v27.16b, v29.16b, v7.16b
- add v4.4s, v7.4s, v4.4s
- tbl v7.16b, { v25.16b, v26.16b }, v3.16b
- tbl v26.16b, { v27.16b }, v1.16b
- add v22.4s, v22.4s, v26.4s
- uzp2 v18.4s, v18.4s, v16.4s
- eor v23.16b, v23.16b, v22.16b
- ext v5.16b, v18.16b, v18.16b, #4
- ushr v27.4s, v23.4s, #7
- shl v23.4s, v23.4s, #25
- uzp1 v25.4s, v5.4s, v5.4s
- orr v23.16b, v23.16b, v27.16b
- ext v28.16b, v4.16b, v4.16b, #12
- ext v4.16b, v25.16b, v5.16b, #8
- ext v25.16b, v26.16b, v26.16b, #8
- add v26.4s, v28.4s, v23.4s
- eor v25.16b, v26.16b, v25.16b
- ext v22.16b, v22.16b, v22.16b, #4
- tbl v25.16b, { v25.16b }, v0.16b
- add v22.4s, v22.4s, v25.4s
- eor v23.16b, v23.16b, v22.16b
- add v17.4s, v26.4s, v17.4s
- ushr v26.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- orr v23.16b, v23.16b, v26.16b
- add v17.4s, v17.4s, v23.4s
- eor v25.16b, v25.16b, v17.16b
- add v17.4s, v17.4s, v19.4s
- tbl v19.16b, { v25.16b }, v1.16b
- add v22.4s, v22.4s, v19.4s
- eor v23.16b, v23.16b, v22.16b
- ushr v25.4s, v23.4s, #7
- shl v23.4s, v23.4s, #25
- ext v17.16b, v17.16b, v17.16b, #4
- orr v23.16b, v23.16b, v25.16b
- ext v19.16b, v19.16b, v19.16b, #8
- add v17.4s, v17.4s, v23.4s
- eor v19.16b, v17.16b, v19.16b
- ext v22.16b, v22.16b, v22.16b, #12
- tbl v19.16b, { v19.16b }, v0.16b
- add v22.4s, v22.4s, v19.4s
- eor v23.16b, v23.16b, v22.16b
- ushr v25.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- add v17.4s, v17.4s, v16.4s
- orr v23.16b, v23.16b, v25.16b
- add v17.4s, v17.4s, v23.4s
- ext v25.16b, v17.16b, v17.16b, #12
- eor v17.16b, v19.16b, v17.16b
- tbl v17.16b, { v17.16b }, v1.16b
- add v19.4s, v22.4s, v17.4s
- eor v22.16b, v23.16b, v19.16b
- add v25.4s, v25.4s, v21.4s
- zip1 v20.2d, v6.2d, v16.2d
- ushr v23.4s, v22.4s, #7
- shl v22.4s, v22.4s, #25
- zip2 v24.4s, v16.4s, v6.4s
- tbl v26.16b, { v20.16b, v21.16b }, v2.16b
- orr v22.16b, v22.16b, v23.16b
- zip1 v16.4s, v24.4s, v21.4s
- zip1 v20.4s, v21.4s, v24.4s
- ext v21.16b, v26.16b, v26.16b, #12
- ext v17.16b, v17.16b, v17.16b, #8
- add v25.4s, v25.4s, v22.4s
- ext v16.16b, v20.16b, v16.16b, #8
- uzp1 v21.4s, v26.4s, v21.4s
- eor v26.16b, v25.16b, v17.16b
- ext v19.16b, v19.16b, v19.16b, #4
- tbl v26.16b, { v26.16b }, v0.16b
- mov v29.16b, v16.16b
- add v19.4s, v19.4s, v26.4s
- ext v27.16b, v5.16b, v5.16b, #12
- mov v29.s[1], v21.s[2]
- eor v22.16b, v22.16b, v19.16b
- ext v28.16b, v5.16b, v27.16b, #12
- ushr v27.4s, v22.4s, #12
- shl v22.4s, v22.4s, #20
- add v6.4s, v25.4s, v6.4s
- orr v22.16b, v22.16b, v27.16b
- add v6.4s, v6.4s, v22.4s
- eor v26.16b, v26.16b, v6.16b
- add v6.4s, v6.4s, v18.4s
- tbl v18.16b, { v26.16b }, v1.16b
- add v19.4s, v19.4s, v18.4s
- eor v22.16b, v22.16b, v19.16b
- ushr v26.4s, v22.4s, #7
- shl v22.4s, v22.4s, #25
- ext v6.16b, v6.16b, v6.16b, #4
- orr v22.16b, v22.16b, v26.16b
- ext v18.16b, v18.16b, v18.16b, #8
- add v6.4s, v6.4s, v22.4s
- eor v18.16b, v6.16b, v18.16b
- ext v19.16b, v19.16b, v19.16b, #12
- tbl v18.16b, { v18.16b }, v0.16b
- add v19.4s, v19.4s, v18.4s
- eor v22.16b, v22.16b, v19.16b
- ushr v26.4s, v22.4s, #12
- shl v22.4s, v22.4s, #20
- add v6.4s, v6.4s, v7.4s
- orr v22.16b, v22.16b, v26.16b
- add v6.4s, v6.4s, v22.4s
- ext v26.16b, v6.16b, v6.16b, #12
- eor v6.16b, v18.16b, v6.16b
- uzp2 v4.4s, v4.4s, v7.4s
- zip2 v25.4s, v7.4s, v16.4s
- add v26.4s, v26.4s, v21.4s
- zip1 v20.2d, v16.2d, v7.2d
- tbl v6.16b, { v6.16b }, v1.16b
- ext v24.16b, v4.16b, v4.16b, #4
- tbl v27.16b, { v20.16b, v21.16b }, v2.16b
- zip1 v7.4s, v25.4s, v21.4s
- zip1 v20.4s, v21.4s, v25.4s
- add v18.4s, v19.4s, v6.4s
- uzp1 v5.4s, v24.4s, v24.4s
- ext v21.16b, v27.16b, v27.16b, #12
- ext v7.16b, v20.16b, v7.16b, #8
- eor v19.16b, v22.16b, v18.16b
- ext v5.16b, v5.16b, v24.16b, #8
- tbl v17.16b, { v28.16b, v29.16b }, v3.16b
- uzp1 v21.4s, v27.4s, v21.4s
- mov v28.16b, v7.16b
- ushr v22.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v23.16b, v24.16b, v24.16b, #12
- uzp2 v5.4s, v5.4s, v17.4s
- mov v28.s[1], v21.s[2]
- orr v19.16b, v19.16b, v22.16b
- ext v27.16b, v24.16b, v23.16b, #12
- ext v23.16b, v5.16b, v5.16b, #4
- ext v6.16b, v6.16b, v6.16b, #8
- ext v25.16b, v18.16b, v18.16b, #4
- add v18.4s, v26.4s, v19.4s
- uzp1 v24.4s, v23.4s, v23.4s
- eor v6.16b, v18.16b, v6.16b
- ext v24.16b, v24.16b, v23.16b, #8
- add v16.4s, v18.4s, v16.4s
- tbl v18.16b, { v27.16b, v28.16b }, v3.16b
- tbl v27.16b, { v6.16b }, v0.16b
- uzp2 v6.4s, v24.4s, v18.4s
- add v24.4s, v25.4s, v27.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v19.16b, v19.16b, v25.16b
- add v16.4s, v16.4s, v19.4s
- eor v25.16b, v27.16b, v16.16b
- add v4.4s, v16.4s, v4.4s
- tbl v16.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v16.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v4.16b, v4.16b, v4.16b, #4
- orr v19.16b, v19.16b, v25.16b
- ext v16.16b, v16.16b, v16.16b, #8
- add v4.4s, v4.4s, v19.4s
- eor v16.16b, v4.16b, v16.16b
- ext v24.16b, v24.16b, v24.16b, #12
- tbl v25.16b, { v16.16b }, v0.16b
- add v24.4s, v24.4s, v25.4s
- eor v16.16b, v19.16b, v24.16b
- ushr v19.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- add v4.4s, v4.4s, v17.4s
- orr v19.16b, v16.16b, v19.16b
- add v27.4s, v4.4s, v19.4s
- eor v25.16b, v25.16b, v27.16b
- tbl v25.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v25.4s
- zip2 v26.4s, v17.4s, v7.4s
- ext v4.16b, v27.16b, v27.16b, #12
- eor v19.16b, v19.16b, v24.16b
- add v28.4s, v4.4s, v21.4s
- zip1 v20.2d, v7.2d, v17.2d
- zip1 v4.4s, v26.4s, v21.4s
- zip1 v17.4s, v21.4s, v26.4s
- ushr v26.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v19.16b, v19.16b, v26.16b
- ext v25.16b, v25.16b, v25.16b, #8
- add v27.4s, v28.4s, v19.4s
- eor v25.16b, v27.16b, v25.16b
- ext v24.16b, v24.16b, v24.16b, #4
- tbl v25.16b, { v25.16b }, v0.16b
- add v24.4s, v24.4s, v25.4s
- eor v19.16b, v19.16b, v24.16b
- add v7.4s, v27.4s, v7.4s
- ushr v27.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v19.16b, v19.16b, v27.16b
- add v7.4s, v7.4s, v19.4s
- eor v25.16b, v25.16b, v7.16b
- add v5.4s, v7.4s, v5.4s
- tbl v7.16b, { v25.16b }, v1.16b
- add v24.4s, v24.4s, v7.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- ext v5.16b, v5.16b, v5.16b, #4
- orr v19.16b, v19.16b, v25.16b
+ hint #34
+ fmov s1, w3
+ movi d0, #0x0000ff000000ff
+ ldr q2, [x1]
+ adrp x8, .LCPI1_0
+ mov v1.s[1], w5
+ str q2, [x0]
+ ldr q4, [x8, :lo12:.LCPI1_0]
+ ldr q5, [x1, #16]
+ adrp x8, .LCPI1_1
+ and v0.8b, v1.8b, v0.8b
+ fmov d1, x4
+ stp q5, q4, [x0, #16]
+ mov v1.d[1], v0.d[0]
+ str q1, [x0, #48]
+ ldp q6, q7, [x2]
+ uzp1 v3.4s, v6.4s, v7.4s
+ add v0.4s, v2.4s, v3.4s
+ uzp2 v2.4s, v6.4s, v7.4s
+ add v16.4s, v0.4s, v5.4s
+ ldr q0, [x8, :lo12:.LCPI1_1]
+ adrp x8, .LCPI1_2
+ eor v1.16b, v16.16b, v1.16b
+ add v7.4s, v16.4s, v2.4s
+ tbl v1.16b, { v1.16b }, v0.16b
+ add v4.4s, v1.4s, v4.4s
+ eor v5.16b, v4.16b, v5.16b
+ ushr v6.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v6.16b
+ add v6.4s, v7.4s, v5.4s
+ eor v7.16b, v1.16b, v6.16b
+ ldr q1, [x8, :lo12:.LCPI1_2]
+ add x8, x2, #32
+ tbl v7.16b, { v7.16b }, v1.16b
+ ld2 { v16.4s, v17.4s }, [x8]
+ add v4.4s, v4.4s, v7.4s
ext v7.16b, v7.16b, v7.16b, #8
- add v5.4s, v5.4s, v19.4s
- eor v7.16b, v5.16b, v7.16b
- ext v24.16b, v24.16b, v24.16b, #12
- tbl v7.16b, { v7.16b }, v0.16b
- add v24.4s, v24.4s, v7.4s
- eor v19.16b, v19.16b, v24.16b
- ushr v25.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- tbl v16.16b, { v20.16b, v21.16b }, v2.16b
- add v5.4s, v5.4s, v18.4s
- orr v19.16b, v19.16b, v25.16b
- ext v20.16b, v16.16b, v16.16b, #12
- ext v4.16b, v17.16b, v4.16b, #8
- add v5.4s, v5.4s, v19.4s
- uzp1 v21.4s, v16.4s, v20.4s
- mov v17.16b, v4.16b
- ext v25.16b, v5.16b, v5.16b, #12
- mov v17.s[1], v21.s[2]
- add v25.4s, v25.4s, v21.4s
- zip1 v20.2d, v4.2d, v18.2d
- ext v22.16b, v23.16b, v23.16b, #12
- zip2 v26.4s, v18.4s, v4.4s
- tbl v18.16b, { v20.16b, v21.16b }, v2.16b
- eor v5.16b, v7.16b, v5.16b
- ext v16.16b, v23.16b, v22.16b, #12
- ext v22.16b, v6.16b, v6.16b, #4
- zip1 v27.4s, v26.4s, v21.4s
- zip1 v20.4s, v21.4s, v26.4s
- ext v21.16b, v18.16b, v18.16b, #12
- tbl v5.16b, { v5.16b }, v1.16b
- ext v20.16b, v20.16b, v27.16b, #8
- uzp1 v27.4s, v18.4s, v21.4s
- uzp1 v18.4s, v22.4s, v22.4s
- add v21.4s, v24.4s, v5.4s
- ext v18.16b, v18.16b, v22.16b, #8
- eor v19.16b, v19.16b, v21.16b
- tbl v7.16b, { v16.16b, v17.16b }, v3.16b
- uzp2 v18.4s, v18.4s, v17.4s
- zip2 v16.4s, v16.4s, v20.4s
- ushr v17.4s, v19.4s, #7
- shl v19.4s, v19.4s, #25
- orr v17.16b, v19.16b, v17.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v19.4s, v25.4s, v17.4s
- eor v5.16b, v19.16b, v5.16b
- ext v21.16b, v21.16b, v21.16b, #4
- tbl v5.16b, { v5.16b }, v0.16b
- add v4.4s, v19.4s, v4.4s
- add v19.4s, v21.4s, v5.4s
- eor v17.16b, v17.16b, v19.16b
- ushr v21.4s, v17.4s, #12
- shl v17.4s, v17.4s, #20
- orr v17.16b, v17.16b, v21.16b
- add v4.4s, v4.4s, v17.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
- add v4.4s, v4.4s, v6.4s
- add v6.4s, v19.4s, v5.4s
- eor v17.16b, v17.16b, v6.16b
- ushr v19.4s, v17.4s, #7
- shl v17.4s, v17.4s, #25
- ext v4.16b, v4.16b, v4.16b, #4
- orr v17.16b, v17.16b, v19.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v4.4s, v17.4s
+ add v6.4s, v6.4s, v16.4s
eor v5.16b, v4.16b, v5.16b
+ ext v4.16b, v4.16b, v4.16b, #4
+ ext v16.16b, v16.16b, v16.16b, #12
ext v6.16b, v6.16b, v6.16b, #12
- tbl v5.16b, { v5.16b }, v0.16b
+ ushr v18.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v18.16b
+ ext v18.16b, v17.16b, v17.16b, #12
add v6.4s, v6.4s, v5.4s
- eor v17.16b, v17.16b, v6.16b
- ushr v19.4s, v17.4s, #12
- shl v17.4s, v17.4s, #20
+ mov v17.16b, v18.16b
+ eor v7.16b, v7.16b, v6.16b
+ add v6.4s, v6.4s, v18.4s
+ mov v17.s[1], v16.s[2]
+ tbl v7.16b, { v7.16b }, v0.16b
add v4.4s, v4.4s, v7.4s
- orr v17.16b, v17.16b, v19.16b
- add v4.4s, v4.4s, v17.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
- mov v29.16b, v20.16b
+ eor v5.16b, v4.16b, v5.16b
+ ushr v19.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v19.16b
+ uzp1 v19.4s, v3.4s, v3.4s
+ add v6.4s, v6.4s, v5.4s
+ ext v19.16b, v19.16b, v3.16b, #8
+ eor v7.16b, v7.16b, v6.16b
+ uzp2 v19.4s, v19.4s, v2.4s
+ tbl v7.16b, { v7.16b }, v1.16b
+ add v6.4s, v6.4s, v19.4s
+ add v4.4s, v4.4s, v7.4s
+ ext v6.16b, v6.16b, v6.16b, #4
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v5.16b, v4.16b, v5.16b
ext v4.16b, v4.16b, v4.16b, #12
+ ushr v20.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v20.16b
+ ext v20.16b, v3.16b, v3.16b, #12
add v6.4s, v6.4s, v5.4s
- mov v29.s[1], v27.s[2]
- add v4.4s, v4.4s, v27.4s
- zip1 v26.2d, v20.2d, v7.2d
- zip1 v7.4s, v16.4s, v27.4s
- zip1 v16.4s, v27.4s, v16.4s
- eor v17.16b, v17.16b, v6.16b
- ext v7.16b, v16.16b, v7.16b, #8
- ushr v16.4s, v17.4s, #7
- shl v17.4s, v17.4s, #25
- orr v16.16b, v17.16b, v16.16b
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v4.4s, v16.4s
+ ext v3.16b, v3.16b, v20.16b, #12
+ eor v7.16b, v7.16b, v6.16b
+ rev64 v3.4s, v3.4s
+ tbl v7.16b, { v7.16b }, v0.16b
+ trn2 v3.4s, v3.4s, v17.4s
+ add v4.4s, v4.4s, v7.4s
+ add v6.4s, v6.4s, v3.4s
eor v5.16b, v4.16b, v5.16b
- ext v6.16b, v6.16b, v6.16b, #4
- tbl v5.16b, { v5.16b }, v0.16b
+ ushr v17.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v17.16b
+ zip1 v17.2d, v18.2d, v2.2d
+ zip2 v2.4s, v2.4s, v18.4s
add v6.4s, v6.4s, v5.4s
- eor v16.16b, v16.16b, v6.16b
- ushr v17.4s, v16.4s, #12
- shl v16.4s, v16.4s, #20
- add v4.4s, v4.4s, v20.4s
- orr v16.16b, v16.16b, v17.16b
- add v4.4s, v4.4s, v16.4s
- eor v5.16b, v5.16b, v4.16b
- tbl v5.16b, { v5.16b }, v1.16b
+ mov v17.s[3], v16.s[3]
+ zip1 v18.4s, v2.4s, v16.4s
+ zip1 v2.4s, v16.4s, v2.4s
+ eor v7.16b, v7.16b, v6.16b
+ ext v6.16b, v6.16b, v6.16b, #12
+ ext v16.16b, v2.16b, v18.16b, #8
+ tbl v7.16b, { v7.16b }, v1.16b
+ add v20.4s, v4.4s, v7.4s
+ ext v4.16b, v17.16b, v17.16b, #12
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v5.16b, v20.16b, v5.16b
+ uzp1 v4.4s, v17.4s, v4.4s
+ ushr v17.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v6.4s, v6.4s, v4.4s
+ orr v5.16b, v5.16b, v17.16b
+ ext v17.16b, v20.16b, v20.16b, #4
add v6.4s, v6.4s, v5.4s
- eor v16.16b, v16.16b, v6.16b
+ eor v7.16b, v7.16b, v6.16b
+ add v6.4s, v6.4s, v16.4s
+ tbl v7.16b, { v7.16b }, v0.16b
+ add v17.4s, v17.4s, v7.4s
+ eor v5.16b, v17.16b, v5.16b
+ ushr v2.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v2.16b, v5.16b, v2.16b
+ add v5.4s, v6.4s, v2.4s
+ ext v6.16b, v19.16b, v19.16b, #4
+ eor v7.16b, v7.16b, v5.16b
+ uzp1 v18.4s, v6.4s, v6.4s
+ tbl v7.16b, { v7.16b }, v1.16b
+ ext v18.16b, v18.16b, v6.16b, #8
+ add v17.4s, v17.4s, v7.4s
+ uzp2 v18.4s, v18.4s, v3.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v2.16b, v17.16b, v2.16b
+ add v5.4s, v5.4s, v18.4s
+ ext v17.16b, v17.16b, v17.16b, #12
+ ushr v19.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ ext v5.16b, v5.16b, v5.16b, #4
+ orr v2.16b, v2.16b, v19.16b
+ ext v19.16b, v6.16b, v6.16b, #12
+ add v5.4s, v5.4s, v2.4s
+ ext v6.16b, v6.16b, v19.16b, #12
+ mov v19.16b, v16.16b
+ eor v7.16b, v7.16b, v5.16b
+ rev64 v6.4s, v6.4s
+ mov v19.s[1], v4.s[2]
+ tbl v7.16b, { v7.16b }, v0.16b
+ add v17.4s, v17.4s, v7.4s
+ eor v20.16b, v17.16b, v2.16b
+ trn2 v2.4s, v6.4s, v19.4s
+ ushr v6.4s, v20.4s, #12
+ shl v19.4s, v20.4s, #20
+ add v5.4s, v5.4s, v2.4s
+ orr v6.16b, v19.16b, v6.16b
+ add v19.4s, v5.4s, v6.4s
+ eor v5.16b, v7.16b, v19.16b
+ zip1 v7.2d, v16.2d, v3.2d
+ zip2 v3.4s, v3.4s, v16.4s
+ tbl v20.16b, { v5.16b }, v1.16b
+ mov v7.s[3], v4.s[3]
+ add v17.4s, v17.4s, v20.4s
+ ext v5.16b, v7.16b, v7.16b, #12
+ eor v6.16b, v17.16b, v6.16b
+ uzp1 v5.4s, v7.4s, v5.4s
+ ext v7.16b, v19.16b, v19.16b, #12
+ ext v17.16b, v17.16b, v17.16b, #4
+ ushr v19.4s, v6.4s, #7
+ shl v6.4s, v6.4s, #25
+ add v7.4s, v7.4s, v5.4s
+ orr v6.16b, v6.16b, v19.16b
+ ext v19.16b, v20.16b, v20.16b, #8
+ add v7.4s, v7.4s, v6.4s
+ eor v19.16b, v19.16b, v7.16b
+ tbl v19.16b, { v19.16b }, v0.16b
+ add v16.4s, v17.4s, v19.4s
+ zip1 v17.4s, v3.4s, v4.4s
+ zip1 v3.4s, v4.4s, v3.4s
+ eor v4.16b, v16.16b, v6.16b
+ ext v17.16b, v3.16b, v17.16b, #8
+ ushr v3.4s, v4.4s, #12
+ shl v4.4s, v4.4s, #20
+ add v6.4s, v7.4s, v17.4s
+ orr v3.16b, v4.16b, v3.16b
+ add v4.4s, v6.4s, v3.4s
+ ext v6.16b, v18.16b, v18.16b, #4
+ eor v7.16b, v19.16b, v4.16b
+ uzp1 v18.4s, v6.4s, v6.4s
+ tbl v7.16b, { v7.16b }, v1.16b
+ ext v18.16b, v18.16b, v6.16b, #8
+ add v16.4s, v16.4s, v7.4s
+ uzp2 v18.4s, v18.4s, v2.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v3.16b, v16.16b, v3.16b
add v4.4s, v4.4s, v18.4s
- ushr v17.4s, v16.4s, #7
- shl v16.4s, v16.4s, #25
- ext v23.16b, v22.16b, v22.16b, #12
+ ext v16.16b, v16.16b, v16.16b, #12
+ ushr v19.4s, v3.4s, #7
+ shl v3.4s, v3.4s, #25
ext v4.16b, v4.16b, v4.16b, #4
- orr v16.16b, v16.16b, v17.16b
- ext v28.16b, v22.16b, v23.16b, #12
- ext v5.16b, v5.16b, v5.16b, #8
- add v4.4s, v16.4s, v4.4s
- tbl v3.16b, { v28.16b, v29.16b }, v3.16b
- eor v5.16b, v4.16b, v5.16b
- ext v6.16b, v6.16b, v6.16b, #12
- add v3.4s, v4.4s, v3.4s
- tbl v4.16b, { v5.16b }, v0.16b
- add v5.4s, v6.4s, v4.4s
- eor v6.16b, v16.16b, v5.16b
- ushr v16.4s, v6.4s, #12
+ orr v3.16b, v3.16b, v19.16b
+ ext v19.16b, v6.16b, v6.16b, #12
+ add v4.4s, v4.4s, v3.4s
+ ext v6.16b, v6.16b, v19.16b, #12
+ mov v19.16b, v17.16b
+ eor v7.16b, v7.16b, v4.16b
+ rev64 v6.4s, v6.4s
+ mov v19.s[1], v5.s[2]
+ tbl v7.16b, { v7.16b }, v0.16b
+ add v16.4s, v16.4s, v7.4s
+ eor v20.16b, v16.16b, v3.16b
+ trn2 v3.4s, v6.4s, v19.4s
+ ushr v6.4s, v20.4s, #12
+ shl v19.4s, v20.4s, #20
+ add v4.4s, v4.4s, v3.4s
+ orr v6.16b, v19.16b, v6.16b
+ zip1 v19.2d, v17.2d, v2.2d
+ zip2 v2.4s, v2.4s, v17.4s
+ add v4.4s, v4.4s, v6.4s
+ mov v19.s[3], v5.s[3]
+ zip1 v17.4s, v2.4s, v5.4s
+ zip1 v2.4s, v5.4s, v2.4s
+ eor v7.16b, v7.16b, v4.16b
+ ext v20.16b, v19.16b, v19.16b, #12
+ ext v4.16b, v4.16b, v4.16b, #12
+ ext v2.16b, v2.16b, v17.16b, #8
+ tbl v7.16b, { v7.16b }, v1.16b
+ add v16.4s, v16.4s, v7.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v21.16b, v16.16b, v6.16b
+ uzp1 v6.4s, v19.4s, v20.4s
+ ext v16.16b, v16.16b, v16.16b, #4
+ ushr v19.4s, v21.4s, #7
+ shl v20.4s, v21.4s, #25
+ add v4.4s, v4.4s, v6.4s
+ orr v19.16b, v20.16b, v19.16b
+ add v4.4s, v4.4s, v19.4s
+ eor v7.16b, v7.16b, v4.16b
+ add v4.4s, v4.4s, v2.4s
+ tbl v7.16b, { v7.16b }, v0.16b
+ add v16.4s, v16.4s, v7.4s
+ eor v5.16b, v16.16b, v19.16b
+ ushr v17.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v17.16b
+ ext v17.16b, v18.16b, v18.16b, #4
+ add v4.4s, v4.4s, v5.4s
+ uzp1 v18.4s, v17.4s, v17.4s
+ eor v7.16b, v7.16b, v4.16b
+ ext v18.16b, v18.16b, v17.16b, #8
+ tbl v7.16b, { v7.16b }, v1.16b
+ uzp2 v18.4s, v18.4s, v3.4s
+ add v16.4s, v16.4s, v7.4s
+ add v4.4s, v4.4s, v18.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v5.16b, v16.16b, v5.16b
+ ext v4.16b, v4.16b, v4.16b, #4
+ ext v16.16b, v16.16b, v16.16b, #12
+ ushr v19.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v19.16b
+ add v19.4s, v4.4s, v5.4s
+ eor v4.16b, v7.16b, v19.16b
+ ext v7.16b, v17.16b, v17.16b, #12
+ tbl v20.16b, { v4.16b }, v0.16b
+ ext v4.16b, v17.16b, v7.16b, #12
+ mov v7.16b, v2.16b
+ add v16.4s, v16.4s, v20.4s
+ rev64 v4.4s, v4.4s
+ mov v7.s[1], v6.s[2]
+ eor v5.16b, v16.16b, v5.16b
+ trn2 v4.4s, v4.4s, v7.4s
+ ushr v7.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v19.4s, v4.4s
+ zip1 v19.2d, v2.2d, v3.2d
+ zip2 v2.4s, v3.4s, v2.4s
+ orr v5.16b, v5.16b, v7.16b
+ mov v19.s[3], v6.s[3]
+ add v7.4s, v17.4s, v5.4s
+ eor v17.16b, v20.16b, v7.16b
+ ext v20.16b, v19.16b, v19.16b, #12
+ ext v7.16b, v7.16b, v7.16b, #12
+ tbl v17.16b, { v17.16b }, v1.16b
+ add v16.4s, v16.4s, v17.4s
+ ext v17.16b, v17.16b, v17.16b, #8
+ eor v21.16b, v16.16b, v5.16b
+ uzp1 v5.4s, v19.4s, v20.4s
+ ext v16.16b, v16.16b, v16.16b, #4
+ ushr v19.4s, v21.4s, #7
+ shl v20.4s, v21.4s, #25
+ add v7.4s, v7.4s, v5.4s
+ orr v19.16b, v20.16b, v19.16b
+ add v7.4s, v7.4s, v19.4s
+ eor v17.16b, v17.16b, v7.16b
+ tbl v17.16b, { v17.16b }, v0.16b
+ add v3.4s, v16.4s, v17.4s
+ zip1 v16.4s, v2.4s, v6.4s
+ zip1 v2.4s, v6.4s, v2.4s
+ eor v6.16b, v3.16b, v19.16b
+ ext v16.16b, v2.16b, v16.16b, #8
+ ushr v2.4s, v6.4s, #12
shl v6.4s, v6.4s, #20
- orr v6.16b, v6.16b, v16.16b
- tbl v2.16b, { v26.16b, v27.16b }, v2.16b
- add v3.4s, v3.4s, v6.4s
- ext v19.16b, v2.16b, v2.16b, #12
- eor v4.16b, v4.16b, v3.16b
- uzp1 v2.4s, v2.4s, v19.4s
+ add v7.4s, v7.4s, v16.4s
+ orr v2.16b, v6.16b, v2.16b
+ add v6.4s, v7.4s, v2.4s
+ ext v7.16b, v18.16b, v18.16b, #4
+ eor v17.16b, v17.16b, v6.16b
+ uzp1 v18.4s, v7.4s, v7.4s
+ tbl v17.16b, { v17.16b }, v1.16b
+ ext v18.16b, v18.16b, v7.16b, #8
+ add v3.4s, v3.4s, v17.4s
+ uzp2 v18.4s, v18.4s, v4.4s
+ eor v2.16b, v3.16b, v2.16b
+ add v6.4s, v6.4s, v18.4s
ext v3.16b, v3.16b, v3.16b, #12
- tbl v4.16b, { v4.16b }, v1.16b
- add v2.4s, v3.4s, v2.4s
- add v3.4s, v5.4s, v4.4s
- eor v5.16b, v6.16b, v3.16b
- ushr v6.4s, v5.4s, #7
+ ext v18.16b, v18.16b, v18.16b, #4
+ ushr v19.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ ext v6.16b, v6.16b, v6.16b, #4
+ orr v19.16b, v2.16b, v19.16b
+ ext v2.16b, v17.16b, v17.16b, #8
+ ext v17.16b, v7.16b, v7.16b, #12
+ add v6.4s, v6.4s, v19.4s
+ eor v2.16b, v2.16b, v6.16b
+ tbl v20.16b, { v2.16b }, v0.16b
+ ext v2.16b, v7.16b, v17.16b, #12
+ mov v7.16b, v16.16b
+ add v17.4s, v3.4s, v20.4s
+ rev64 v3.4s, v2.4s
+ mov v7.s[1], v5.s[2]
+ eor v19.16b, v17.16b, v19.16b
+ trn2 v3.4s, v3.4s, v7.4s
+ ushr v21.4s, v19.4s, #12
+ shl v19.4s, v19.4s, #20
+ add v6.4s, v6.4s, v3.4s
+ orr v19.16b, v19.16b, v21.16b
+ add v21.4s, v6.4s, v19.4s
+ eor v6.16b, v20.16b, v21.16b
+ zip1 v20.2d, v16.2d, v4.2d
+ zip2 v4.4s, v4.4s, v16.4s
+ tbl v22.16b, { v6.16b }, v1.16b
+ mov v20.s[3], v5.s[3]
+ add v17.4s, v17.4s, v22.4s
+ ext v6.16b, v20.16b, v20.16b, #12
+ eor v19.16b, v17.16b, v19.16b
+ uzp1 v6.4s, v20.4s, v6.4s
+ ext v20.16b, v21.16b, v21.16b, #12
+ ext v17.16b, v17.16b, v17.16b, #4
+ ushr v21.4s, v19.4s, #7
+ shl v19.4s, v19.4s, #25
+ add v20.4s, v20.4s, v6.4s
+ orr v19.16b, v19.16b, v21.16b
+ ext v21.16b, v22.16b, v22.16b, #8
+ add v20.4s, v20.4s, v19.4s
+ eor v21.16b, v21.16b, v20.16b
+ tbl v21.16b, { v21.16b }, v0.16b
+ add v16.4s, v17.4s, v21.4s
+ zip1 v17.4s, v4.4s, v5.4s
+ zip1 v4.4s, v5.4s, v4.4s
+ eor v5.16b, v16.16b, v19.16b
+ ext v4.16b, v4.16b, v17.16b, #8
+ ushr v17.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v19.4s, v20.4s, v4.4s
+ ext v20.16b, v18.16b, v18.16b, #8
+ zip1 v3.2d, v4.2d, v3.2d
+ orr v5.16b, v5.16b, v17.16b
+ zip2 v2.4s, v2.4s, v4.4s
+ uzp2 v7.4s, v20.4s, v7.4s
+ mov v3.s[3], v6.s[3]
+ add v17.4s, v19.4s, v5.4s
+ ext v7.16b, v7.16b, v20.16b, #4
+ eor v19.16b, v21.16b, v17.16b
+ ext v17.16b, v17.16b, v17.16b, #4
+ tbl v19.16b, { v19.16b }, v1.16b
+ add v7.4s, v17.4s, v7.4s
+ add v16.4s, v16.4s, v19.4s
+ ext v17.16b, v19.16b, v19.16b, #8
+ ext v19.16b, v18.16b, v18.16b, #12
+ eor v5.16b, v16.16b, v5.16b
+ ext v16.16b, v16.16b, v16.16b, #12
+ ext v18.16b, v18.16b, v19.16b, #12
+ mov v19.16b, v4.16b
+ ushr v20.4s, v5.4s, #7
shl v5.4s, v5.4s, #25
- orr v5.16b, v5.16b, v6.16b
- ext v4.16b, v4.16b, v4.16b, #8
- add v2.4s, v2.4s, v5.4s
- eor v4.16b, v2.16b, v4.16b
- ext v3.16b, v3.16b, v3.16b, #4
- tbl v0.16b, { v4.16b }, v0.16b
- add v3.4s, v3.4s, v0.4s
- eor v4.16b, v5.16b, v3.16b
- ushr v5.4s, v4.4s, #12
- shl v4.4s, v4.4s, #20
- add v2.4s, v2.4s, v7.4s
- orr v4.16b, v4.16b, v5.16b
- add v2.4s, v2.4s, v4.4s
+ rev64 v18.4s, v18.4s
+ mov v19.s[1], v6.s[2]
+ orr v5.16b, v5.16b, v20.16b
+ trn2 v18.4s, v18.4s, v19.4s
+ add v7.4s, v5.4s, v7.4s
+ eor v17.16b, v17.16b, v7.16b
+ add v7.4s, v7.4s, v18.4s
+ ext v18.16b, v3.16b, v3.16b, #12
+ tbl v17.16b, { v17.16b }, v0.16b
+ uzp1 v3.4s, v3.4s, v18.4s
+ add v16.4s, v16.4s, v17.4s
+ eor v5.16b, v16.16b, v5.16b
+ ushr v19.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v5.16b, v5.16b, v19.16b
+ add v7.4s, v7.4s, v5.4s
+ eor v17.16b, v17.16b, v7.16b
+ ext v7.16b, v7.16b, v7.16b, #12
+ tbl v17.16b, { v17.16b }, v1.16b
+ add v3.4s, v7.4s, v3.4s
+ add v16.4s, v16.4s, v17.4s
+ ext v7.16b, v17.16b, v17.16b, #8
+ eor v5.16b, v16.16b, v5.16b
+ ext v16.16b, v16.16b, v16.16b, #4
+ ushr v18.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v5.16b, v5.16b, v18.16b
+ add v3.4s, v3.4s, v5.4s
+ eor v7.16b, v7.16b, v3.16b
+ tbl v0.16b, { v7.16b }, v0.16b
+ zip1 v7.4s, v2.4s, v6.4s
+ zip1 v2.4s, v6.4s, v2.4s
+ add v4.4s, v16.4s, v0.4s
+ ext v2.16b, v2.16b, v7.16b, #8
+ eor v5.16b, v4.16b, v5.16b
+ add v2.4s, v3.4s, v2.4s
+ ushr v6.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ orr v3.16b, v5.16b, v6.16b
+ add v2.4s, v2.4s, v3.4s
eor v0.16b, v0.16b, v2.16b
- tbl v0.16b, { v0.16b }, v1.16b
- add v1.4s, v3.4s, v0.4s
- eor v3.16b, v4.16b, v1.16b
- ushr v4.4s, v3.4s, #7
- shl v3.4s, v3.4s, #25
ext v2.16b, v2.16b, v2.16b, #4
+ tbl v0.16b, { v0.16b }, v1.16b
+ add v1.4s, v4.4s, v0.4s
ext v0.16b, v0.16b, v0.16b, #8
+ eor v3.16b, v1.16b, v3.16b
ext v1.16b, v1.16b, v1.16b, #12
+ ushr v4.4s, v3.4s, #7
+ shl v3.4s, v3.4s, #25
+ stp q1, q0, [x0, #32]
orr v3.16b, v3.16b, v4.16b
- eor v2.16b, v2.16b, v1.16b
- eor v3.16b, v3.16b, v0.16b
- stp q2, q3, [x5]
- ldr q2, [x0]
- eor v1.16b, v2.16b, v1.16b
- str q1, [x5, #32]
- ldr q1, [x0, #16]
- eor v0.16b, v1.16b, v0.16b
- str q0, [x5, #48]
+ stp q2, q3, [x0]
ret
.Lfunc_end1:
- .size zfs_blake3_compress_xof_sse41, .Lfunc_end1-zfs_blake3_compress_xof_sse41
+ .size compress_pre, .Lfunc_end1-compress_pre
+ .cfi_endproc
+
+ .globl zfs_blake3_compress_xof_sse41
+ .p2align 2
+ .type zfs_blake3_compress_xof_sse41,@function
+zfs_blake3_compress_xof_sse41:
+ .cfi_startproc
+ hint #25
+ CFI_NEGATE_RA_STATE
+ sub sp, sp, #96
+ stp x29, x30, [sp, #64]
+ add x29, sp, #64
+ stp x20, x19, [sp, #80]
+ .cfi_def_cfa w29, 32
+ .cfi_offset w19, -8
+ .cfi_offset w20, -16
+ .cfi_offset w30, -24
+ .cfi_offset w29, -32
+ mov x20, x0
+ mov x19, x5
+ mov w5, w4
+ mov x4, x3
+ mov w3, w2
+ mov x2, x1
+ mov x0, sp
+ mov x1, x20
+ bl compress_pre
+ ldp q0, q1, [sp]
+ ldp q2, q3, [sp, #32]
+ eor v0.16b, v2.16b, v0.16b
+ eor v1.16b, v3.16b, v1.16b
+ ldp x29, x30, [sp, #64]
+ stp q0, q1, [x19]
+ ldr q0, [x20]
+ eor v0.16b, v0.16b, v2.16b
+ str q0, [x19, #32]
+ ldr q0, [x20, #16]
+ eor v0.16b, v0.16b, v3.16b
+ str q0, [x19, #48]
+ ldp x20, x19, [sp, #80]
+ add sp, sp, #96
+ hint #29
+ ret
+.Lfunc_end2:
+ .size zfs_blake3_compress_xof_sse41, .Lfunc_end2-zfs_blake3_compress_xof_sse41
.cfi_endproc
.section .rodata.cst16,"aM",@progbits,16
.p2align 4
-.LCPI2_0:
+.LCPI3_0:
.word 0
.word 1
.word 2
.word 3
-.LCPI2_1:
+.LCPI3_1:
.byte 2
.byte 3
.byte 0
@@ -1078,7 +636,7 @@ zfs_blake3_compress_xof_sse41:
.byte 15
.byte 12
.byte 13
-.LCPI2_2:
+.LCPI3_2:
.byte 1
.byte 2
.byte 3
@@ -1095,25 +653,29 @@ zfs_blake3_compress_xof_sse41:
.byte 14
.byte 15
.byte 12
+.LCPI3_3:
+ .word 1779033703
+ .word 3144134277
+ .word 1013904242
+ .word 2773480762
.text
.globl zfs_blake3_hash_many_sse41
.p2align 2
.type zfs_blake3_hash_many_sse41,@function
zfs_blake3_hash_many_sse41:
.cfi_startproc
- stp d15, d14, [sp, #-160]!
+ hint #34
+ stp d15, d14, [sp, #-144]!
stp d13, d12, [sp, #16]
stp d11, d10, [sp, #32]
stp d9, d8, [sp, #48]
- stp x29, x30, [sp, #64]
- stp x28, x27, [sp, #80]
- stp x26, x25, [sp, #96]
- stp x24, x23, [sp, #112]
- stp x22, x21, [sp, #128]
- stp x20, x19, [sp, #144]
- mov x29, sp
- sub sp, sp, #448
- .cfi_def_cfa w29, 160
+ stp x29, x27, [sp, #64]
+ stp x26, x25, [sp, #80]
+ stp x24, x23, [sp, #96]
+ stp x22, x21, [sp, #112]
+ stp x20, x19, [sp, #128]
+ sub sp, sp, #368
+ .cfi_def_cfa_offset 512
.cfi_offset w19, -8
.cfi_offset w20, -16
.cfi_offset w21, -24
@@ -1123,1341 +685,1722 @@ zfs_blake3_hash_many_sse41:
.cfi_offset w25, -56
.cfi_offset w26, -64
.cfi_offset w27, -72
- .cfi_offset w28, -80
- .cfi_offset w30, -88
- .cfi_offset w29, -96
- .cfi_offset b8, -104
- .cfi_offset b9, -112
- .cfi_offset b10, -120
- .cfi_offset b11, -128
- .cfi_offset b12, -136
- .cfi_offset b13, -144
- .cfi_offset b14, -152
- .cfi_offset b15, -160
- ldr x26, [x29, #168]
- ldrb w27, [x29, #160]
- mov w19, w6
- mov x20, x4
- mov x22, x2
- mov x28, x1
+ .cfi_offset w29, -80
+ .cfi_offset b8, -88
+ .cfi_offset b9, -96
+ .cfi_offset b10, -104
+ .cfi_offset b11, -112
+ .cfi_offset b12, -120
+ .cfi_offset b13, -128
+ .cfi_offset b14, -136
+ .cfi_offset b15, -144
+ ldr x8, [sp, #520]
+ adrp x11, .LCPI3_1
+ ldrb w9, [sp, #512]
+ adrp x10, .LCPI3_2
cmp x1, #4
- mov x24, x0
- str x3, [sp, #40]
- b.lo .LBB2_8
- adrp x11, .LCPI2_0
- ldr q0, [x11, :lo12:.LCPI2_0]
+ b.lo .LBB3_6
+ adrp x12, .LCPI3_0
sbfx w13, w5, #0, #1
+ mov w15, #58983
+ mov w16, #44677
+ movk w15, #27145, lsl #16
+ movk w16, #47975, lsl #16
+ ldr q0, [x12, :lo12:.LCPI3_0]
dup v1.4s, w13
- mov w10, #58983
- mov w11, #44677
- mov w12, #62322
+ movi v13.4s, #64
+ mov w13, #62322
+ mov w14, #62778
+ orr w12, w7, w6
and v0.16b, v1.16b, v0.16b
- mov w13, #62778
- orr w8, w7, w19
- adrp x9, .LCPI2_1
- movk w10, #27145, lsl #16
- movk w11, #47975, lsl #16
- movk w12, #15470, lsl #16
- movk w13, #42319, lsl #16
- str q0, [sp, #16]
+ ldr q1, [x11, :lo12:.LCPI3_1]
+ movk w13, #15470, lsl #16
+ movk w14, #42319, lsl #16
+ dup v14.4s, w15
+ stp q0, q1, [sp, #16]
orr v0.4s, #128, lsl #24
- adrp x14, .LCPI2_2
str q0, [sp]
-.LBB2_2:
- ldr x2, [sp, #40]
- mov x15, x2
- ld1r { v7.4s }, [x15], #4
- add x16, x2, #8
- add x17, x2, #12
- add x18, x2, #16
- add x0, x2, #20
- add x3, x2, #24
- add x2, x2, #28
- ld1r { v6.4s }, [x16]
- ld1r { v17.4s }, [x17]
- ld1r { v10.4s }, [x18]
- ld1r { v11.4s }, [x0]
- ld1r { v19.4s }, [x3]
- ld1r { v18.4s }, [x15]
- ld1r { v16.4s }, [x2]
- cbz x22, .LBB2_7
+ dup v0.4s, w16
+ stp q0, q14, [sp, #48]
+ b .LBB3_3
+.LBB3_2:
+ zip1 v0.4s, v29.4s, v8.4s
+ add x15, x4, #4
+ zip1 v1.4s, v30.4s, v31.4s
+ tst w5, #0x1
+ zip1 v2.4s, v24.4s, v18.4s
+ csel x4, x15, x4, ne
+ zip1 v3.4s, v25.4s, v26.4s
+ add x0, x0, #32
+ zip2 v6.4s, v29.4s, v8.4s
+ sub x1, x1, #4
+ zip1 v4.2d, v0.2d, v1.2d
+ cmp x1, #3
+ zip2 v7.4s, v30.4s, v31.4s
+ zip1 v5.2d, v2.2d, v3.2d
+ zip2 v0.2d, v0.2d, v1.2d
+ zip2 v1.2d, v2.2d, v3.2d
+ zip2 v2.4s, v24.4s, v18.4s
+ zip2 v3.4s, v25.4s, v26.4s
+ stp q4, q5, [x8]
+ zip2 v4.2d, v6.2d, v7.2d
+ stp q0, q1, [x8, #32]
+ zip1 v0.2d, v6.2d, v7.2d
+ zip1 v1.2d, v2.2d, v3.2d
+ zip2 v2.2d, v2.2d, v3.2d
+ stp q0, q1, [x8, #64]
+ stp q4, q2, [x8, #96]
+ add x8, x8, #128
+ b.ls .LBB3_6
+.LBB3_3:
+ mov x15, x3
+ add x16, x3, #8
+ add x17, x3, #12
+ add x19, x3, #16
+ add x20, x3, #20
+ ld1r { v29.4s }, [x15], #4
+ ld1r { v30.4s }, [x16]
+ add x16, x3, #24
+ ld1r { v31.4s }, [x17]
+ add x17, x3, #28
+ ld1r { v24.4s }, [x19]
+ ld1r { v18.4s }, [x20]
+ ld1r { v25.4s }, [x16]
+ ld1r { v8.4s }, [x15]
+ ld1r { v26.4s }, [x17]
+ cbz x2, .LBB3_2
ldr q1, [sp, #16]
- dup v0.4s, w20
- ldp x15, x16, [x24]
- ldp x17, x18, [x24, #16]
+ dup v0.4s, w4
+ lsr x17, x4, #32
+ mov x15, xzr
+ ldp x19, x20, [x0, #16]
add v1.4s, v0.4s, v1.4s
+ mov x21, x2
movi v0.4s, #128, lsl #24
- str q1, [sp, #64]
+ mov w26, w12
+ str q1, [sp, #96]
eor v0.16b, v1.16b, v0.16b
ldr q1, [sp]
- lsr x2, x20, #32
- mov x0, xzr
- mov w6, w8
cmgt v0.4s, v1.4s, v0.4s
- dup v1.4s, w2
+ dup v1.4s, w17
+ ldp x16, x17, [x0]
sub v0.4s, v1.4s, v0.4s
- str q0, [sp, #48]
-.LBB2_4:
- mov w4, #16
- stp q16, q17, [sp, #192]
- bfi x4, x0, #6, #58
- ldr q1, [x15, x4]
- ldr q3, [x16, x4]
- ldr q2, [x17, x4]
- ldr q4, [x18, x4]
- mov w4, #32
- bfi x4, x0, #6, #58
- ldr q5, [x15, x4]
- ldr q20, [x16, x4]
- ldr q21, [x17, x4]
- ldr q22, [x18, x4]
- mov w4, #48
- lsl x3, x0, #6
- bfi x4, x0, #6, #58
- add x0, x0, #1
- ldr q0, [x15, x3]
- ldr q23, [x16, x3]
- ldr q16, [x17, x3]
- ldr q17, [x18, x3]
- cmp x0, x22
- ldr q25, [x15, x4]
- ldr q14, [x16, x4]
- ldr q28, [x17, x4]
- ldr q31, [x18, x4]
- csel w4, w27, wzr, eq
- orr w4, w4, w6
- mov x2, xzr
- and w6, w4, #0xff
- add x3, x3, #256
-.LBB2_5:
- ldr x4, [x24, x2]
- add x2, x2, #8
- cmp x2, #32
- add x4, x4, x3
- prfm pldl1keep, [x4]
- b.ne .LBB2_5
- zip1 v29.4s, v0.4s, v23.4s
- zip2 v23.4s, v0.4s, v23.4s
- zip1 v0.4s, v16.4s, v17.4s
- zip2 v24.4s, v16.4s, v17.4s
- zip1 v9.4s, v1.4s, v3.4s
- zip2 v26.4s, v1.4s, v3.4s
- zip1 v27.4s, v2.4s, v4.4s
- zip2 v17.4s, v2.4s, v4.4s
- zip1 v12.4s, v21.4s, v22.4s
- zip2 v13.4s, v21.4s, v22.4s
- add v2.4s, v7.4s, v10.4s
- add v1.4s, v18.4s, v11.4s
- ext v7.16b, v0.16b, v29.16b, #8
- ext v22.16b, v24.16b, v23.16b, #8
- zip1 v30.4s, v5.4s, v20.4s
- zip2 v20.4s, v5.4s, v20.4s
- stp q1, q2, [sp, #112]
- ext v2.16b, v29.16b, v7.16b, #8
- mov v29.d[1], v0.d[0]
- ext v18.16b, v23.16b, v22.16b, #8
- mov v23.d[1], v24.d[0]
- zip1 v21.4s, v25.4s, v14.4s
- zip2 v4.4s, v25.4s, v14.4s
- zip1 v14.4s, v28.4s, v31.4s
- zip2 v15.4s, v28.4s, v31.4s
- add v8.4s, v6.4s, v19.4s
- ext v28.16b, v27.16b, v9.16b, #8
- ext v31.16b, v17.16b, v26.16b, #8
- stur q2, [x29, #-208]
- mov v7.16b, v29.16b
- ext v0.16b, v12.16b, v30.16b, #8
- stp q23, q29, [x29, #-80]
- mov v2.16b, v19.16b
- ext v19.16b, v13.16b, v20.16b, #8
- mov v29.16b, v9.16b
- ext v25.16b, v9.16b, v28.16b, #8
- mov v29.d[1], v27.d[0]
- ext v24.16b, v26.16b, v31.16b, #8
- mov v26.d[1], v17.d[0]
- ext v17.16b, v15.16b, v4.16b, #8
- ext v27.16b, v30.16b, v0.16b, #8
- ext v0.16b, v20.16b, v19.16b, #8
- stp q0, q25, [sp, #80]
- ext v0.16b, v4.16b, v17.16b, #8
- str q0, [sp, #224]
- ldr q0, [sp, #128]
- mov v6.16b, v23.16b
- mov v22.16b, v4.16b
- ldr q16, [x9, :lo12:.LCPI2_1]
- add v17.4s, v0.4s, v7.4s
- ldr q0, [sp, #112]
- mov v30.d[1], v12.d[0]
- add v7.4s, v8.4s, v29.4s
- mov v20.d[1], v13.d[0]
- add v4.4s, v0.4s, v6.4s
- ldr q0, [sp, #64]
- dup v3.4s, w12
- ext v28.16b, v14.16b, v21.16b, #8
- dup v1.4s, w10
- eor v19.16b, v17.16b, v0.16b
- ldr q0, [sp, #48]
- ext v23.16b, v21.16b, v28.16b, #8
- mov v21.d[1], v14.d[0]
- tbl v14.16b, { v19.16b }, v16.16b
- eor v12.16b, v4.16b, v0.16b
- movi v0.4s, #64
- eor v13.16b, v7.16b, v0.16b
- tbl v13.16b, { v13.16b }, v16.16b
- add v6.4s, v13.4s, v3.4s
- dup v5.4s, w11
- tbl v12.16b, { v12.16b }, v16.16b
- add v1.4s, v14.4s, v1.4s
- eor v9.16b, v6.16b, v2.16b
- ldp q2, q0, [sp, #192]
- add v5.4s, v12.4s, v5.4s
- eor v19.16b, v1.16b, v10.16b
- eor v10.16b, v5.16b, v11.16b
- ushr v11.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v11.16b, v19.16b, v11.16b
- ushr v19.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- mov v22.d[1], v15.d[0]
- orr v10.16b, v10.16b, v19.16b
- ushr v19.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- add v15.4s, v0.4s, v2.4s
- orr v9.16b, v9.16b, v19.16b
- dup v19.4s, w6
- add v15.4s, v15.4s, v26.4s
- eor v19.16b, v15.16b, v19.16b
- tbl v3.16b, { v19.16b }, v16.16b
- dup v19.4s, w13
- add v8.4s, v3.4s, v19.4s
- ldur q31, [x29, #-208]
- eor v19.16b, v8.16b, v2.16b
- ushr v0.4s, v19.4s, #12
- shl v19.4s, v19.4s, #20
- orr v2.16b, v19.16b, v0.16b
- ldr q19, [x14, :lo12:.LCPI2_2]
- add v17.4s, v17.4s, v31.4s
- add v17.4s, v17.4s, v11.4s
- eor v14.16b, v14.16b, v17.16b
- tbl v14.16b, { v14.16b }, v19.16b
- add v1.4s, v1.4s, v14.4s
- eor v11.16b, v1.16b, v11.16b
- add v4.4s, v4.4s, v18.4s
- ushr v0.4s, v11.4s, #7
- shl v11.4s, v11.4s, #25
- add v4.4s, v4.4s, v10.4s
- orr v0.16b, v11.16b, v0.16b
- eor v11.16b, v12.16b, v4.16b
- tbl v11.16b, { v11.16b }, v19.16b
- add v5.4s, v5.4s, v11.4s
- eor v10.16b, v5.16b, v10.16b
- add v7.4s, v7.4s, v25.4s
- ushr v12.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- add v7.4s, v7.4s, v9.4s
- orr v10.16b, v10.16b, v12.16b
- eor v12.16b, v13.16b, v7.16b
- tbl v12.16b, { v12.16b }, v19.16b
- add v6.4s, v6.4s, v12.4s
- eor v9.16b, v6.16b, v9.16b
- ushr v13.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- orr v9.16b, v9.16b, v13.16b
- add v13.4s, v15.4s, v24.4s
- add v13.4s, v13.4s, v2.4s
- eor v3.16b, v3.16b, v13.16b
- tbl v3.16b, { v3.16b }, v19.16b
- add v8.4s, v8.4s, v3.4s
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v30.4s
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v20.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v21.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v22.4s
- mov v28.16b, v26.16b
- stur q26, [x29, #-112]
- mov v26.16b, v18.16b
- mov v18.16b, v24.16b
- stur q24, [x29, #-160]
- add v6.4s, v6.4s, v3.4s
- mov v24.16b, v20.16b
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- ldr q20, [sp, #80]
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v13.16b
- stp q30, q22, [x29, #-192]
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- mov v30.16b, v27.16b
- add v17.4s, v17.4s, v27.4s
- ldr q27, [sp, #224]
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v20.4s
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #12
- shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v23.4s
- orr v0.16b, v0.16b, v15.16b
- tbl v3.16b, { v3.16b }, v19.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v27.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v13.16b
- stur q21, [x29, #-144]
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- ldur q21, [x29, #-80]
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
+ str q0, [sp, #80]
+.LBB3_5:
+ add x23, x16, x15
+ add x24, x17, x15
+ add x22, x19, x15
+ add x25, x20, x15
+ subs x21, x21, #1
+ add x15, x15, #64
+ ldp q1, q2, [x23]
+ csel w27, w9, wzr, eq
+ orr w26, w27, w26
+ and w26, w26, #0xff
+ ldp q4, q5, [x24]
+ dup v0.4s, w26
+ mov w26, w6
+ zip1 v22.4s, v1.4s, v4.4s
+ zip2 v20.4s, v1.4s, v4.4s
+ ldp q6, q7, [x22]
+ zip1 v17.4s, v2.4s, v5.4s
+ zip2 v23.4s, v2.4s, v5.4s
+ ldp q16, q21, [x25]
+ zip1 v19.4s, v6.4s, v16.4s
+ zip2 v1.4s, v6.4s, v16.4s
+ ldp q27, q28, [x23, #32]
+ zip1 v4.4s, v7.4s, v21.4s
+ zip2 v5.4s, v7.4s, v21.4s
+ zip2 v15.2d, v17.2d, v4.2d
+ ldp q9, q10, [x24, #32]
+ mov v17.d[1], v4.d[0]
+ add v4.4s, v30.4s, v25.4s
+ zip2 v11.2d, v23.2d, v5.2d
+ zip2 v3.4s, v27.4s, v9.4s
+ zip1 v7.4s, v27.4s, v9.4s
+ ldp q12, q6, [x22, #32]
+ mov v23.d[1], v5.d[0]
+ stp q11, q3, [sp, #256]
+ add v5.4s, v31.4s, v26.4s
+ add v4.4s, v4.4s, v17.4s
+ str q23, [sp, #352]
+ ldp q16, q2, [x25, #32]
+ add v5.4s, v5.4s, v23.4s
+ zip1 v3.4s, v12.4s, v16.4s
eor v0.16b, v5.16b, v0.16b
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #7
- shl v0.4s, v0.4s, #25
- orr v0.16b, v0.16b, v15.16b
- add v17.4s, v17.4s, v21.4s
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v26.4s
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v18.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v29.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
+ zip1 v9.4s, v6.4s, v2.4s
+ zip2 v2.4s, v6.4s, v2.4s
+ stp q7, q3, [sp, #208]
+ zip2 v3.4s, v12.4s, v16.4s
+ zip1 v12.4s, v28.4s, v10.4s
+ zip2 v10.4s, v28.4s, v10.4s
+ stp q17, q2, [sp, #160]
+ zip2 v28.2d, v22.2d, v19.2d
+ mov v22.d[1], v19.d[0]
+ str q3, [sp, #240]
+ add v2.4s, v8.4s, v18.4s
+ eor v16.16b, v4.16b, v13.16b
+ dup v17.4s, w13
+ mov v3.16b, v22.16b
+ stp q22, q28, [sp, #320]
+ zip2 v22.2d, v20.2d, v1.2d
+ mov v20.d[1], v1.d[0]
+ add v1.4s, v29.4s, v24.4s
+ add v4.4s, v4.4s, v15.4s
add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- eor v3.16b, v3.16b, v13.16b
- ldur q22, [x29, #-64]
- ushr v15.4s, v0.4s, #12
+ add v2.4s, v2.4s, v20.4s
+ stp q15, q20, [sp, #288]
+ add v1.4s, v1.4s, v3.4s
+ ldr q3, [sp, #96]
+ dup v20.4s, w14
+ mov v23.16b, v22.16b
+ mov v15.16b, v10.16b
+ eor v6.16b, v1.16b, v3.16b
+ ldr q3, [sp, #80]
+ add v1.4s, v1.4s, v28.4s
+ ldr q28, [sp, #272]
+ str q23, [sp, #128]
+ eor v7.16b, v2.16b, v3.16b
+ ldp q27, q3, [sp, #32]
+ add v2.4s, v2.4s, v22.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v7.16b, { v7.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ tbl v0.16b, { v0.16b }, v27.16b
+ add v19.4s, v6.4s, v14.4s
+ add v21.4s, v7.4s, v3.4s
+ add v30.4s, v16.4s, v17.4s
+ add v31.4s, v0.4s, v20.4s
+ eor v24.16b, v19.16b, v24.16b
+ eor v17.16b, v21.16b, v18.16b
+ ushr v18.4s, v24.4s, #12
+ shl v20.4s, v24.4s, #20
+ eor v24.16b, v30.16b, v25.16b
+ eor v25.16b, v31.16b, v26.16b
+ ushr v26.4s, v17.4s, #12
+ shl v17.4s, v17.4s, #20
+ ushr v29.4s, v24.4s, #12
+ shl v24.4s, v24.4s, #20
+ ushr v8.4s, v25.4s, #12
+ shl v25.4s, v25.4s, #20
+ orr v3.16b, v20.16b, v18.16b
+ ldr q18, [x10, :lo12:.LCPI3_2]
+ orr v13.16b, v17.16b, v26.16b
+ orr v24.16b, v24.16b, v29.16b
+ orr v14.16b, v25.16b, v8.16b
+ add v8.4s, v1.4s, v3.4s
+ add v29.4s, v2.4s, v13.4s
+ add v17.4s, v4.4s, v24.4s
+ add v20.4s, v5.4s, v14.4s
+ eor v1.16b, v6.16b, v8.16b
+ eor v2.16b, v7.16b, v29.16b
+ eor v4.16b, v16.16b, v17.16b
+ eor v0.16b, v0.16b, v20.16b
+ tbl v25.16b, { v1.16b }, v18.16b
+ tbl v16.16b, { v2.16b }, v18.16b
+ tbl v6.16b, { v4.16b }, v18.16b
+ tbl v4.16b, { v0.16b }, v18.16b
+ add v19.4s, v19.4s, v25.4s
+ add v21.4s, v21.4s, v16.4s
+ add v26.4s, v30.4s, v6.4s
+ add v7.4s, v31.4s, v4.4s
+ eor v0.16b, v19.16b, v3.16b
+ eor v1.16b, v21.16b, v13.16b
+ eor v2.16b, v26.16b, v24.16b
+ eor v3.16b, v7.16b, v14.16b
+ ushr v5.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v24.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ushr v30.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ orr v5.16b, v0.16b, v5.16b
+ orr v0.16b, v1.16b, v24.16b
+ ushr v31.4s, v3.4s, #7
+ orr v2.16b, v2.16b, v30.16b
+ ldp q24, q30, [sp, #208]
+ shl v3.4s, v3.4s, #25
+ zip2 v14.2d, v12.2d, v9.2d
+ mov v22.16b, v24.16b
+ orr v1.16b, v3.16b, v31.16b
+ zip2 v3.2d, v24.2d, v30.2d
+ mov v24.16b, v28.16b
+ mov v22.d[1], v30.d[0]
+ ldr q30, [sp, #240]
+ mov v31.16b, v12.16b
+ stp q22, q14, [sp, #224]
+ mov v24.d[1], v30.d[0]
+ add v12.4s, v8.4s, v22.4s
+ mov v31.d[1], v9.d[0]
+ add v22.4s, v29.4s, v24.4s
+ ldr q29, [sp, #176]
+ zip2 v28.2d, v28.2d, v30.2d
+ mov v9.16b, v24.16b
+ mov v15.d[1], v29.d[0]
+ zip2 v8.2d, v10.2d, v29.2d
+ add v10.4s, v12.4s, v0.4s
+ add v22.4s, v22.4s, v2.4s
+ str q9, [sp, #144]
+ add v20.4s, v20.4s, v15.4s
+ add v17.4s, v17.4s, v31.4s
+ stp q3, q8, [sp, #192]
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v16.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- add v17.4s, v17.4s, v28.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v24.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
+ ushr v13.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v22.4s
- orr v2.16b, v2.16b, v15.16b
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v23.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- eor v3.16b, v3.16b, v13.16b
- ldur q22, [x29, #-144]
- ushr v15.4s, v0.4s, #7
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v10.4s, v10.4s, v3.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v22.4s, v22.4s, v28.4s
+ ushr v12.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v13.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v8.4s
+ orr v1.16b, v1.16b, v12.16b
+ add v17.4s, v17.4s, v14.4s
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v19.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v31.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
+ ushr v13.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v22.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v30.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v27.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- ldr q27, [sp, #96]
- mov v21.16b, v26.16b
- stur q26, [x29, #-96]
- mov v28.16b, v31.16b
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v13.16b
- ldp q31, q26, [x29, #-192]
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- add v17.4s, v17.4s, v20.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v27.4s
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #12
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v22.4s, v22.4s, v23.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v17.4s, v17.4s, v11.4s
+ mov v30.16b, v28.16b
+ mov v28.16b, v23.16b
+ ldr q23, [sp, #304]
+ ushr v12.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v22.4s, v22.4s, v0.4s
+ mov v29.16b, v31.16b
+ ldr q31, [sp, #160]
+ orr v5.16b, v5.16b, v13.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v23.4s
+ orr v1.16b, v1.16b, v12.16b
+ str q29, [sp, #272]
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v31.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v27.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v26.4s
- orr v0.16b, v0.16b, v15.16b
- tbl v3.16b, { v3.16b }, v19.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v31.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v13.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- eor v0.16b, v5.16b, v0.16b
- mov v18.16b, v24.16b
- mov v24.16b, v20.16b
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #7
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ eor v5.16b, v5.16b, v19.16b
+ add v22.4s, v22.4s, v24.4s
+ ldr q24, [sp, #320]
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v17.4s, v24.4s
+ ldr q24, [sp, #352]
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v24.4s
+ ldr q24, [sp, #336]
+ orr v1.16b, v1.16b, v13.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v14.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- ldur q20, [x29, #-160]
- orr v0.16b, v0.16b, v15.16b
- add v17.4s, v17.4s, v21.4s
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v18.4s
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v23.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v20.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- eor v3.16b, v3.16b, v13.16b
- ldur q25, [x29, #-80]
- ushr v15.4s, v0.4s, #12
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ eor v5.16b, v19.16b, v5.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ add v10.4s, v10.4s, v24.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v22.4s, v22.4s, v29.4s
+ ushr v13.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v8.4s
+ ldr q8, [sp, #288]
+ orr v1.16b, v1.16b, v13.16b
+ add v17.4s, v17.4s, v3.4s
+ ldr q3, [sp, #352]
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v16.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- add v17.4s, v17.4s, v29.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v22.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
+ ushr v13.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v10.4s, v10.4s, v30.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v22.4s, v22.4s, v8.4s
+ mov v24.16b, v30.16b
+ mov v30.16b, v15.16b
+ add v17.4s, v17.4s, v15.4s
+ ldr q15, [sp, #224]
+ ushr v12.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ str q30, [sp, #176]
+ orr v5.16b, v5.16b, v13.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v15.4s
+ orr v1.16b, v1.16b, v12.16b
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
add v7.4s, v7.4s, v25.4s
- orr v2.16b, v2.16b, v15.16b
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v26.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- ldur q25, [x29, #-112]
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- eor v3.16b, v3.16b, v13.16b
- ushr v15.4s, v0.4s, #7
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v19.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v25.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
+ ushr v13.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v30.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v24.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v31.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- ldur q25, [x29, #-64]
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v13.16b
- ldr q31, [sp, #224]
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- add v17.4s, v17.4s, v27.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v25.4s
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #12
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v22.4s, v22.4s, v9.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v17.4s, v17.4s, v14.4s
+ ushr v12.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v13.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v28.4s
+ orr v1.16b, v1.16b, v12.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v11.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v27.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v31.4s
- orr v0.16b, v0.16b, v15.16b
- tbl v3.16b, { v3.16b }, v19.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v28.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v13.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- eor v0.16b, v5.16b, v0.16b
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #7
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ eor v5.16b, v5.16b, v19.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ add v22.4s, v22.4s, v29.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v17.4s, v23.4s
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v31.4s
+ orr v1.16b, v1.16b, v13.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v30.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- orr v0.16b, v0.16b, v15.16b
- add v17.4s, v17.4s, v18.4s
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v22.4s
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v26.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v23.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- mov v21.16b, v29.16b
- stur q29, [x29, #-128]
- mov v29.16b, v30.16b
- mov v30.16b, v27.16b
- mov v27.16b, v18.16b
- str q18, [sp, #176]
- eor v0.16b, v0.16b, v1.16b
- mov v18.16b, v22.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- eor v3.16b, v3.16b, v13.16b
- ldur q22, [x29, #-96]
- ushr v15.4s, v0.4s, #12
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ eor v5.16b, v19.16b, v5.16b
+ add v10.4s, v10.4s, v3.4s
+ ldr q3, [sp, #192]
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v22.4s, v22.4s, v3.4s
+ ushr v13.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v15.4s
+ ldr q15, [sp, #128]
+ orr v1.16b, v1.16b, v13.16b
+ add v17.4s, v17.4s, v24.4s
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v16.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- add v17.4s, v17.4s, v20.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v29.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
+ ushr v13.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v22.4s
- orr v2.16b, v2.16b, v15.16b
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v31.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- eor v3.16b, v3.16b, v13.16b
- ushr v15.4s, v0.4s, #7
+ eor v5.16b, v21.16b, v5.16b
+ ldp q23, q11, [sp, #320]
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v10.4s, v10.4s, v8.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v22.4s, v22.4s, v23.4s
+ ushr v12.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ mov v28.16b, v31.16b
+ mov v31.16b, v8.16b
+ ldr q8, [sp, #208]
+ orr v5.16b, v5.16b, v13.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v11.4s
+ orr v1.16b, v1.16b, v12.16b
+ add v17.4s, v17.4s, v8.4s
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v19.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v21.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
+ ushr v13.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v24.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v30.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v28.4s
- add v6.4s, v6.4s, v3.4s
- mov v22.16b, v24.16b
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- ldur q24, [x29, #-80]
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- mov v21.16b, v30.16b
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v13.16b
- ldur q30, [x29, #-192]
- mov v20.16b, v29.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- ldur q29, [x29, #-112]
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- add v17.4s, v17.4s, v25.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v24.4s
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #12
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v22.4s, v22.4s, v29.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v17.4s, v17.4s, v30.4s
+ ushr v12.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v13.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v9.4s
+ orr v1.16b, v1.16b, v12.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v14.4s
+ ldr q14, [sp, #256]
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v27.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v30.4s
- orr v0.16b, v0.16b, v15.16b
- tbl v3.16b, { v3.16b }, v19.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v29.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v13.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- eor v0.16b, v5.16b, v0.16b
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #7
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ eor v5.16b, v5.16b, v19.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ add v22.4s, v22.4s, v3.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v17.4s, v15.4s
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v14.4s
+ orr v1.16b, v1.16b, v13.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v8.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- orr v0.16b, v0.16b, v15.16b
- add v17.4s, v17.4s, v18.4s
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v20.4s
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v31.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v26.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- eor v3.16b, v3.16b, v13.16b
- ushr v15.4s, v0.4s, #12
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ eor v5.16b, v19.16b, v5.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ add v10.4s, v10.4s, v28.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v22.4s, v22.4s, v24.4s
+ ushr v13.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v11.4s
+ ldr q11, [sp, #304]
+ orr v1.16b, v1.16b, v13.16b
+ add v17.4s, v17.4s, v31.4s
+ ldr q31, [sp, #224]
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v16.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- add v17.4s, v17.4s, v23.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v22.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
+ ushr v13.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v27.4s
- orr v2.16b, v2.16b, v15.16b
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v30.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- ldur q27, [x29, #-160]
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- eor v3.16b, v3.16b, v13.16b
- ushr v15.4s, v0.4s, #7
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v10.4s, v10.4s, v23.4s
+ ldr q23, [sp, #240]
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v22.4s, v22.4s, v11.4s
+ mov v30.16b, v8.16b
+ mov v8.16b, v24.16b
+ ldr q24, [sp, #352]
+ ushr v12.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v13.16b
+ str q8, [sp, #112]
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v24.4s
+ orr v1.16b, v1.16b, v12.16b
+ add v17.4s, v17.4s, v31.4s
+ eor v4.16b, v4.16b, v10.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ mov v29.16b, v3.16b
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v19.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v27.4s
- mov v28.16b, v25.16b
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
+ ushr v13.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v21.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v28.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v29.4s
- mov v25.16b, v31.16b
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- ldur q31, [x29, #-96]
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v13.16b
- ldur q28, [x29, #-208]
- mov v18.16b, v20.16b
- str q20, [sp, #144]
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- ldur q20, [x29, #-128]
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- add v17.4s, v17.4s, v24.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v31.4s
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #12
+ eor v5.16b, v21.16b, v5.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v22.4s, v22.4s, v29.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v17.4s, v17.4s, v30.4s
+ ldr q30, [sp, #272]
+ ushr v12.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v22.4s, v22.4s, v0.4s
+ mov v3.16b, v28.16b
+ ldr q28, [sp, #176]
+ orr v5.16b, v5.16b, v13.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v30.4s
+ orr v1.16b, v1.16b, v12.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v28.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v27.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v28.4s
- orr v0.16b, v0.16b, v15.16b
- tbl v3.16b, { v3.16b }, v19.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v13.4s, v13.4s, v20.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v0.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v13.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v1.16b, v2.16b
- add v5.4s, v5.4s, v12.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- eor v0.16b, v5.16b, v0.16b
- orr v2.16b, v2.16b, v15.16b
- ushr v15.4s, v0.4s, #7
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ eor v5.16b, v5.16b, v19.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ add v22.4s, v22.4s, v8.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v17.4s, v9.4s
+ ldr q9, [sp, #320]
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v22.4s, v22.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v17.4s, v17.4s, v2.4s
+ add v10.4s, v10.4s, v23.4s
+ orr v1.16b, v1.16b, v13.16b
+ eor v16.16b, v16.16b, v22.16b
+ add v20.4s, v20.4s, v31.4s
+ eor v6.16b, v6.16b, v17.16b
+ add v10.4s, v10.4s, v5.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ add v20.4s, v20.4s, v1.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ eor v25.16b, v25.16b, v10.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v4.16b, v4.16b, v20.16b
+ add v26.4s, v26.4s, v6.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v0.16b, v21.16b, v0.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v2.16b, v26.16b, v2.16b
+ add v19.4s, v19.4s, v25.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- orr v0.16b, v0.16b, v15.16b
- add v17.4s, v17.4s, v18.4s
- add v17.4s, v17.4s, v0.4s
- add v4.4s, v4.4s, v22.4s
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v30.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v25.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v16.16b
- eor v3.16b, v3.16b, v13.16b
- add v17.4s, v17.4s, v26.4s
- mov v26.16b, v21.16b
- add v4.4s, v4.4s, v21.4s
- ldur q21, [x29, #-144]
- ushr v15.4s, v0.4s, #12
+ add v7.4s, v7.4s, v4.4s
+ ushr v13.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ eor v5.16b, v19.16b, v5.16b
+ add v10.4s, v10.4s, v14.4s
+ ldr q14, [sp, #288]
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v7.16b, v1.16b
+ orr v2.16b, v2.16b, v13.16b
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v22.4s, v22.4s, v14.4s
+ ushr v13.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v12.16b
+ add v22.4s, v22.4s, v2.4s
+ add v20.4s, v20.4s, v24.4s
+ orr v1.16b, v1.16b, v13.16b
+ eor v4.16b, v4.16b, v10.16b
+ add v17.4s, v17.4s, v9.4s
+ eor v25.16b, v25.16b, v22.16b
+ add v20.4s, v20.4s, v5.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ add v17.4s, v17.4s, v1.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ add v26.4s, v26.4s, v4.4s
+ eor v16.16b, v16.16b, v17.16b
+ add v7.4s, v7.4s, v25.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v2.16b, v7.16b, v2.16b
+ add v21.4s, v21.4s, v6.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v16.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v8.16b, v2.16b
- add v17.4s, v17.4s, v0.4s
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
+ add v19.4s, v19.4s, v16.4s
+ ushr v13.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- eor v14.16b, v14.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v7.4s, v7.4s, v21.4s
- orr v2.16b, v2.16b, v15.16b
- tbl v14.16b, { v14.16b }, v19.16b
- eor v11.16b, v11.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- add v13.4s, v13.4s, v28.4s
- add v1.4s, v1.4s, v14.4s
- tbl v11.16b, { v11.16b }, v19.16b
- eor v12.16b, v12.16b, v7.16b
- add v13.4s, v13.4s, v2.4s
- str q23, [sp, #160]
- eor v0.16b, v0.16b, v1.16b
- add v5.4s, v5.4s, v11.4s
- tbl v12.16b, { v12.16b }, v19.16b
- eor v3.16b, v3.16b, v13.16b
- add v17.4s, v17.4s, v23.4s
- ldur q23, [x29, #-64]
- ushr v15.4s, v0.4s, #7
+ eor v5.16b, v21.16b, v5.16b
+ orr v0.16b, v0.16b, v12.16b
+ eor v1.16b, v19.16b, v1.16b
+ add v10.4s, v10.4s, v11.4s
+ orr v2.16b, v2.16b, v13.16b
+ ushr v13.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ ushr v12.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ add v22.4s, v22.4s, v15.4s
+ orr v5.16b, v5.16b, v13.16b
+ add v20.4s, v20.4s, v3.4s
+ mov v24.16b, v3.16b
+ ldr q3, [sp, #336]
+ orr v1.16b, v1.16b, v12.16b
+ eor v4.16b, v4.16b, v10.16b
+ add v22.4s, v22.4s, v2.4s
+ add v17.4s, v17.4s, v3.4s
+ add v20.4s, v20.4s, v5.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v25.16b, v25.16b, v22.16b
+ add v17.4s, v17.4s, v1.4s
+ eor v6.16b, v6.16b, v20.16b
+ add v26.4s, v26.4s, v4.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ eor v16.16b, v16.16b, v17.16b
+ tbl v6.16b, { v6.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ add v7.4s, v7.4s, v25.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ add v21.4s, v21.4s, v6.4s
+ ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
- eor v10.16b, v5.16b, v10.16b
- add v6.4s, v6.4s, v12.4s
- tbl v3.16b, { v3.16b }, v19.16b
- orr v0.16b, v0.16b, v15.16b
- ushr v15.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- eor v9.16b, v6.16b, v9.16b
- add v8.4s, v8.4s, v3.4s
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v2.16b, v8.16b, v2.16b
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #7
+ eor v2.16b, v7.16b, v2.16b
+ add v19.4s, v19.4s, v16.4s
+ eor v5.16b, v21.16b, v5.16b
+ orr v0.16b, v0.16b, v12.16b
+ ushr v12.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v23.4s
- orr v2.16b, v2.16b, v15.16b
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v24.4s
- tbl v3.16b, { v3.16b }, v16.16b
- eor v14.16b, v14.16b, v4.16b
- add v7.4s, v7.4s, v2.4s
- add v6.4s, v6.4s, v3.4s
- tbl v14.16b, { v14.16b }, v16.16b
- eor v11.16b, v11.16b, v7.16b
- add v13.4s, v13.4s, v20.4s
- eor v10.16b, v6.16b, v10.16b
- add v8.4s, v8.4s, v14.4s
- tbl v11.16b, { v11.16b }, v16.16b
- add v13.4s, v13.4s, v0.4s
- ldr q20, [sp, #176]
- ushr v15.4s, v10.4s, #12
- shl v10.4s, v10.4s, #20
- eor v9.16b, v8.16b, v9.16b
- add v1.4s, v1.4s, v11.4s
- eor v12.16b, v12.16b, v13.16b
- orr v10.16b, v10.16b, v15.16b
- ushr v15.4s, v9.4s, #12
- shl v9.4s, v9.4s, #20
- eor v2.16b, v1.16b, v2.16b
- tbl v12.16b, { v12.16b }, v16.16b
- orr v9.16b, v9.16b, v15.16b
- ushr v15.4s, v2.4s, #12
- shl v2.4s, v2.4s, #20
- add v5.4s, v5.4s, v12.4s
+ eor v1.16b, v19.16b, v1.16b
+ ushr v13.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v22.4s, v22.4s, v8.4s
+ orr v2.16b, v2.16b, v12.16b
+ ushr v12.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ orr v5.16b, v5.16b, v13.16b
+ add v22.4s, v22.4s, v0.4s
+ add v10.4s, v10.4s, v29.4s
+ ldr q29, [sp, #208]
add v17.4s, v17.4s, v31.4s
- orr v2.16b, v2.16b, v15.16b
- eor v0.16b, v5.16b, v0.16b
- add v17.4s, v17.4s, v10.4s
- add v4.4s, v4.4s, v20.4s
- add v7.4s, v7.4s, v29.4s
- ushr v15.4s, v0.4s, #12
+ orr v1.16b, v1.16b, v12.16b
+ add v20.4s, v20.4s, v29.4s
+ eor v16.16b, v16.16b, v22.16b
+ add v10.4s, v10.4s, v5.4s
+ add v17.4s, v17.4s, v2.4s
+ add v20.4s, v20.4s, v1.4s
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v25.16b, v25.16b, v10.16b
+ eor v6.16b, v6.16b, v17.16b
+ eor v4.16b, v4.16b, v20.16b
+ add v21.4s, v21.4s, v16.4s
+ tbl v25.16b, { v25.16b }, v27.16b
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v0.16b, v21.16b, v0.16b
+ add v19.4s, v19.4s, v25.4s
+ add v26.4s, v26.4s, v6.4s
+ add v7.4s, v7.4s, v4.4s
+ ushr v12.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v3.16b, v3.16b, v17.16b
- add v4.4s, v4.4s, v9.4s
- add v7.4s, v7.4s, v2.4s
- orr v0.16b, v0.16b, v15.16b
- mov v15.16b, v31.16b
- add v17.4s, v17.4s, v22.4s
- eor v31.16b, v14.16b, v4.16b
- eor v22.16b, v11.16b, v7.16b
- add v11.4s, v13.4s, v27.4s
- tbl v3.16b, { v3.16b }, v19.16b
- add v11.4s, v11.4s, v0.4s
- tbl v31.16b, { v31.16b }, v19.16b
- add v6.4s, v6.4s, v3.4s
- eor v12.16b, v12.16b, v11.16b
- tbl v22.16b, { v22.16b }, v19.16b
- add v8.4s, v8.4s, v31.4s
- eor v10.16b, v6.16b, v10.16b
- add v30.4s, v11.4s, v30.4s
- tbl v11.16b, { v12.16b }, v19.16b
- add v1.4s, v1.4s, v22.4s
- eor v9.16b, v8.16b, v9.16b
- ushr v12.4s, v10.4s, #7
- shl v10.4s, v10.4s, #25
- add v5.4s, v5.4s, v11.4s
- eor v2.16b, v1.16b, v2.16b
- orr v10.16b, v10.16b, v12.16b
- ushr v12.4s, v9.4s, #7
- shl v9.4s, v9.4s, #25
- eor v0.16b, v5.16b, v0.16b
- orr v9.16b, v9.16b, v12.16b
- ushr v12.4s, v2.4s, #7
+ eor v5.16b, v5.16b, v19.16b
+ eor v2.16b, v26.16b, v2.16b
+ eor v1.16b, v7.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ ushr v12.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v22.4s, v22.4s, v14.4s
+ mov v8.16b, v31.16b
+ ushr v13.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ mov v31.16b, v14.16b
+ ushr v14.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ orr v5.16b, v5.16b, v12.16b
+ add v22.4s, v22.4s, v0.4s
+ add v10.4s, v10.4s, v28.4s
+ ldr q28, [sp, #352]
+ orr v2.16b, v2.16b, v13.16b
+ orr v1.16b, v1.16b, v14.16b
+ add v17.4s, v17.4s, v30.4s
+ add v20.4s, v20.4s, v3.4s
+ eor v16.16b, v16.16b, v22.16b
+ add v10.4s, v10.4s, v5.4s
+ add v17.4s, v17.4s, v2.4s
+ add v20.4s, v20.4s, v1.4s
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v25.16b, v25.16b, v10.16b
+ eor v6.16b, v6.16b, v17.16b
+ eor v4.16b, v4.16b, v20.16b
+ add v21.4s, v21.4s, v16.4s
+ tbl v25.16b, { v25.16b }, v18.16b
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v0.16b, v21.16b, v0.16b
+ add v19.4s, v19.4s, v25.4s
+ add v26.4s, v26.4s, v6.4s
+ add v7.4s, v7.4s, v4.4s
+ ushr v12.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ eor v5.16b, v19.16b, v5.16b
+ eor v2.16b, v26.16b, v2.16b
+ eor v1.16b, v7.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ add v10.4s, v10.4s, v23.4s
+ ushr v13.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
+ ushr v14.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ orr v5.16b, v5.16b, v12.16b
+ add v10.4s, v10.4s, v0.4s
+ add v20.4s, v20.4s, v24.4s
+ ldr q24, [sp, #144]
+ orr v2.16b, v2.16b, v13.16b
+ orr v1.16b, v1.16b, v14.16b
+ add v22.4s, v22.4s, v9.4s
+ add v17.4s, v17.4s, v11.4s
+ eor v4.16b, v4.16b, v10.16b
+ add v20.4s, v20.4s, v5.4s
+ add v22.4s, v22.4s, v2.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v27.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v25.16b, v25.16b, v22.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ eor v0.16b, v26.16b, v0.16b
+ add v21.4s, v21.4s, v6.4s
+ add v7.4s, v7.4s, v25.4s
+ add v19.4s, v19.4s, v16.4s
+ ushr v12.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ eor v5.16b, v21.16b, v5.16b
+ eor v2.16b, v7.16b, v2.16b
+ eor v1.16b, v19.16b, v1.16b
+ orr v0.16b, v0.16b, v12.16b
+ add v10.4s, v10.4s, v15.4s
+ ushr v14.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ mov v30.16b, v3.16b
+ ldr q3, [sp, #256]
+ ushr v12.4s, v2.4s, #12
+ shl v2.4s, v2.4s, #20
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ add v10.4s, v10.4s, v0.4s
+ orr v5.16b, v5.16b, v14.16b
+ add v20.4s, v20.4s, v3.4s
orr v2.16b, v2.16b, v12.16b
+ orr v1.16b, v1.16b, v13.16b
+ add v22.4s, v22.4s, v24.4s
+ add v17.4s, v17.4s, v28.4s
+ eor v4.16b, v4.16b, v10.16b
+ add v20.4s, v20.4s, v5.4s
+ add v22.4s, v22.4s, v2.4s
+ add v17.4s, v17.4s, v1.4s
+ tbl v4.16b, { v4.16b }, v18.16b
+ eor v6.16b, v6.16b, v20.16b
+ eor v25.16b, v25.16b, v22.16b
+ eor v16.16b, v16.16b, v17.16b
+ add v26.4s, v26.4s, v4.4s
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ eor v0.16b, v26.16b, v0.16b
+ add v21.4s, v21.4s, v6.4s
+ add v7.4s, v7.4s, v25.4s
+ add v19.4s, v19.4s, v16.4s
ushr v12.4s, v0.4s, #7
shl v0.4s, v0.4s, #25
+ eor v5.16b, v21.16b, v5.16b
+ eor v2.16b, v7.16b, v2.16b
+ eor v1.16b, v19.16b, v1.16b
orr v0.16b, v0.16b, v12.16b
- add v4.4s, v4.4s, v26.4s
- add v17.4s, v17.4s, v0.4s
- add v7.4s, v7.4s, v28.4s
- mov v18.16b, v27.16b
- eor v31.16b, v31.16b, v17.16b
- add v4.4s, v4.4s, v10.4s
- add v27.4s, v30.4s, v2.4s
- eor v22.16b, v22.16b, v4.16b
- add v7.4s, v7.4s, v9.4s
- eor v3.16b, v3.16b, v27.16b
- add v26.4s, v27.4s, v29.4s
- tbl v27.16b, { v31.16b }, v16.16b
- eor v28.16b, v11.16b, v7.16b
- tbl v22.16b, { v22.16b }, v16.16b
- add v1.4s, v1.4s, v27.4s
- add v4.4s, v4.4s, v23.4s
- ldr q23, [sp, #144]
- tbl v28.16b, { v28.16b }, v16.16b
- tbl v3.16b, { v3.16b }, v16.16b
- add v5.4s, v5.4s, v22.4s
- eor v0.16b, v0.16b, v1.16b
- add v6.4s, v6.4s, v28.4s
- add v29.4s, v8.4s, v3.4s
- eor v30.16b, v5.16b, v10.16b
- ushr v8.4s, v0.4s, #12
+ ushr v12.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ mov v23.16b, v9.16b
+ ldr q9, [sp, #112]
+ ushr v13.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ ushr v14.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ orr v5.16b, v5.16b, v12.16b
+ add v9.4s, v10.4s, v9.4s
+ orr v2.16b, v2.16b, v13.16b
+ orr v1.16b, v1.16b, v14.16b
+ ldr q14, [sp, #64]
+ add v22.4s, v22.4s, v31.4s
+ add v17.4s, v17.4s, v30.4s
+ add v20.4s, v20.4s, v8.4s
+ add v9.4s, v9.4s, v5.4s
+ add v22.4s, v22.4s, v0.4s
+ add v17.4s, v17.4s, v2.4s
+ add v20.4s, v20.4s, v1.4s
+ eor v25.16b, v25.16b, v9.16b
+ eor v16.16b, v16.16b, v22.16b
+ eor v6.16b, v6.16b, v17.16b
+ eor v4.16b, v4.16b, v20.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ tbl v6.16b, { v6.16b }, v27.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ add v19.4s, v19.4s, v25.4s
+ add v21.4s, v21.4s, v16.4s
+ add v26.4s, v26.4s, v6.4s
+ add v7.4s, v7.4s, v4.4s
+ eor v5.16b, v5.16b, v19.16b
+ eor v0.16b, v21.16b, v0.16b
+ eor v2.16b, v26.16b, v2.16b
+ eor v1.16b, v7.16b, v1.16b
+ ushr v30.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ ushr v10.4s, v0.4s, #12
shl v0.4s, v0.4s, #20
- eor v31.16b, v6.16b, v9.16b
- orr v0.16b, v0.16b, v8.16b
- ushr v8.4s, v30.4s, #12
- shl v30.4s, v30.4s, #20
- eor v2.16b, v29.16b, v2.16b
- orr v30.16b, v30.16b, v8.16b
- ushr v8.4s, v31.4s, #12
- shl v31.4s, v31.4s, #20
- add v17.4s, v17.4s, v25.4s
- add v7.4s, v7.4s, v23.4s
- orr v31.16b, v31.16b, v8.16b
- ushr v8.4s, v2.4s, #12
+ ushr v12.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
- ldur q23, [x29, #-176]
- orr v2.16b, v2.16b, v8.16b
- add v17.4s, v17.4s, v0.4s
- eor v27.16b, v27.16b, v17.16b
- add v4.4s, v4.4s, v30.4s
- add v25.4s, v26.4s, v2.4s
- eor v22.16b, v22.16b, v4.16b
- add v4.4s, v4.4s, v24.4s
- add v7.4s, v7.4s, v31.4s
- eor v3.16b, v3.16b, v25.16b
- add v24.4s, v25.4s, v18.4s
- tbl v25.16b, { v27.16b }, v19.16b
+ ushr v13.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ orr v5.16b, v5.16b, v30.16b
+ add v30.4s, v9.4s, v29.4s
+ add v22.4s, v22.4s, v23.4s
+ ldr q23, [sp, #192]
+ orr v0.16b, v0.16b, v10.16b
+ orr v2.16b, v2.16b, v12.16b
+ orr v1.16b, v1.16b, v13.16b
add v17.4s, v17.4s, v23.4s
- eor v23.16b, v28.16b, v7.16b
- tbl v22.16b, { v22.16b }, v19.16b
- add v1.4s, v1.4s, v25.4s
- tbl v23.16b, { v23.16b }, v19.16b
- tbl v3.16b, { v3.16b }, v19.16b
- add v5.4s, v5.4s, v22.4s
- eor v0.16b, v0.16b, v1.16b
- add v6.4s, v6.4s, v23.4s
- add v26.4s, v29.4s, v3.4s
- eor v27.16b, v5.16b, v30.16b
- ushr v29.4s, v0.4s, #7
- shl v0.4s, v0.4s, #25
- eor v28.16b, v6.16b, v31.16b
- orr v0.16b, v0.16b, v29.16b
- ushr v29.4s, v27.4s, #7
- shl v27.4s, v27.4s, #25
+ add v20.4s, v20.4s, v28.4s
+ add v23.4s, v30.4s, v5.4s
+ add v22.4s, v22.4s, v0.4s
+ add v17.4s, v17.4s, v2.4s
+ add v20.4s, v20.4s, v1.4s
+ eor v25.16b, v25.16b, v23.16b
+ eor v16.16b, v16.16b, v22.16b
+ eor v6.16b, v6.16b, v17.16b
+ eor v4.16b, v4.16b, v20.16b
+ tbl v25.16b, { v25.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ tbl v6.16b, { v6.16b }, v18.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ add v19.4s, v19.4s, v25.4s
+ add v21.4s, v21.4s, v16.4s
+ add v26.4s, v26.4s, v6.4s
+ add v7.4s, v7.4s, v4.4s
+ eor v5.16b, v19.16b, v5.16b
+ eor v0.16b, v21.16b, v0.16b
eor v2.16b, v26.16b, v2.16b
- orr v27.16b, v27.16b, v29.16b
- ushr v29.4s, v28.4s, #7
- shl v28.4s, v28.4s, #25
- ldur q18, [x29, #-128]
- orr v28.16b, v28.16b, v29.16b
- ushr v29.4s, v2.4s, #7
+ eor v1.16b, v7.16b, v1.16b
+ ushr v28.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ ushr v30.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v31.4s, v2.4s, #7
shl v2.4s, v2.4s, #25
- add v7.4s, v7.4s, v15.4s
- orr v2.16b, v2.16b, v29.16b
- add v17.4s, v17.4s, v27.4s
- add v4.4s, v4.4s, v28.4s
- add v7.4s, v7.4s, v2.4s
- eor v3.16b, v3.16b, v17.16b
- add v17.4s, v17.4s, v20.4s
- eor v20.16b, v25.16b, v4.16b
- add v4.4s, v4.4s, v21.4s
- eor v21.16b, v22.16b, v7.16b
- add v7.4s, v7.4s, v18.4s
- add v18.4s, v24.4s, v0.4s
- eor v22.16b, v23.16b, v18.16b
- ldr q23, [sp, #160]
- tbl v3.16b, { v3.16b }, v16.16b
- tbl v20.16b, { v20.16b }, v16.16b
- add v6.4s, v6.4s, v3.4s
- add v18.4s, v18.4s, v23.4s
- tbl v21.16b, { v21.16b }, v16.16b
- tbl v16.16b, { v22.16b }, v16.16b
- add v22.4s, v26.4s, v20.4s
- eor v23.16b, v6.16b, v27.16b
- add v1.4s, v1.4s, v21.4s
- eor v24.16b, v22.16b, v28.16b
- ushr v25.4s, v23.4s, #12
- shl v23.4s, v23.4s, #20
- add v5.4s, v5.4s, v16.4s
- eor v2.16b, v1.16b, v2.16b
- orr v23.16b, v23.16b, v25.16b
- ushr v25.4s, v24.4s, #12
- shl v24.4s, v24.4s, #20
- eor v0.16b, v5.16b, v0.16b
- orr v24.16b, v24.16b, v25.16b
- ushr v25.4s, v2.4s, #12
+ ushr v8.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ orr v5.16b, v5.16b, v28.16b
+ ldr q28, [sp, #176]
+ orr v0.16b, v0.16b, v30.16b
+ orr v2.16b, v2.16b, v31.16b
+ orr v1.16b, v1.16b, v8.16b
+ add v23.4s, v23.4s, v28.4s
+ add v22.4s, v22.4s, v11.4s
+ add v17.4s, v17.4s, v15.4s
+ add v20.4s, v20.4s, v3.4s
+ ldr q3, [sp, #272]
+ add v23.4s, v23.4s, v0.4s
+ add v22.4s, v22.4s, v2.4s
+ add v17.4s, v17.4s, v1.4s
+ add v20.4s, v20.4s, v5.4s
+ eor v4.16b, v4.16b, v23.16b
+ eor v25.16b, v25.16b, v22.16b
+ eor v16.16b, v16.16b, v17.16b
+ eor v6.16b, v6.16b, v20.16b
+ tbl v4.16b, { v4.16b }, v27.16b
+ tbl v25.16b, { v25.16b }, v27.16b
+ tbl v16.16b, { v16.16b }, v27.16b
+ tbl v6.16b, { v6.16b }, v27.16b
+ add v26.4s, v26.4s, v4.4s
+ add v7.4s, v7.4s, v25.4s
+ add v19.4s, v19.4s, v16.4s
+ add v21.4s, v21.4s, v6.4s
+ eor v0.16b, v26.16b, v0.16b
+ eor v2.16b, v7.16b, v2.16b
+ eor v1.16b, v19.16b, v1.16b
+ eor v5.16b, v21.16b, v5.16b
+ add v3.4s, v22.4s, v3.4s
+ ldr q22, [sp, #160]
+ ushr v28.4s, v0.4s, #12
+ shl v0.4s, v0.4s, #20
+ ushr v29.4s, v2.4s, #12
shl v2.4s, v2.4s, #20
+ ushr v30.4s, v1.4s, #12
+ shl v1.4s, v1.4s, #20
+ ushr v31.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ add v17.4s, v17.4s, v22.4s
+ ldr q22, [sp, #240]
+ orr v0.16b, v0.16b, v28.16b
+ prfm pldl1keep, [x23, #256]
+ orr v2.16b, v2.16b, v29.16b
+ prfm pldl1keep, [x24, #256]
+ orr v1.16b, v1.16b, v30.16b
+ prfm pldl1keep, [x22, #256]
+ orr v5.16b, v5.16b, v31.16b
+ prfm pldl1keep, [x25, #256]
+ add v23.4s, v23.4s, v24.4s
+ add v20.4s, v20.4s, v22.4s
+ add v3.4s, v3.4s, v2.4s
+ add v17.4s, v17.4s, v1.4s
+ add v22.4s, v23.4s, v0.4s
+ add v20.4s, v20.4s, v5.4s
+ eor v23.16b, v25.16b, v3.16b
+ eor v16.16b, v16.16b, v17.16b
+ eor v4.16b, v4.16b, v22.16b
+ eor v6.16b, v6.16b, v20.16b
+ tbl v23.16b, { v23.16b }, v18.16b
+ tbl v16.16b, { v16.16b }, v18.16b
+ tbl v4.16b, { v4.16b }, v18.16b
+ tbl v6.16b, { v6.16b }, v18.16b
+ add v7.4s, v7.4s, v23.4s
+ add v19.4s, v19.4s, v16.4s
+ add v18.4s, v26.4s, v4.4s
+ add v21.4s, v21.4s, v6.4s
+ eor v2.16b, v7.16b, v2.16b
+ eor v1.16b, v19.16b, v1.16b
+ eor v0.16b, v18.16b, v0.16b
+ eor v5.16b, v21.16b, v5.16b
+ ushr v25.4s, v2.4s, #7
+ shl v2.4s, v2.4s, #25
+ ushr v24.4s, v0.4s, #7
+ shl v0.4s, v0.4s, #25
+ ushr v26.4s, v1.4s, #7
+ shl v1.4s, v1.4s, #25
+ ushr v27.4s, v5.4s, #7
+ shl v5.4s, v5.4s, #25
+ orr v0.16b, v0.16b, v24.16b
orr v2.16b, v2.16b, v25.16b
- ushr v25.4s, v0.4s, #12
- shl v0.4s, v0.4s, #20
- orr v0.16b, v0.16b, v25.16b
- add v25.4s, v7.4s, v2.4s
- add v26.4s, v18.4s, v0.4s
- eor v18.16b, v21.16b, v25.16b
- add v17.4s, v17.4s, v23.4s
- add v4.4s, v4.4s, v24.4s
- eor v16.16b, v16.16b, v26.16b
- tbl v21.16b, { v18.16b }, v19.16b
- eor v3.16b, v3.16b, v17.16b
- eor v7.16b, v20.16b, v4.16b
- tbl v16.16b, { v16.16b }, v19.16b
- add v1.4s, v1.4s, v21.4s
- tbl v3.16b, { v3.16b }, v19.16b
- tbl v20.16b, { v7.16b }, v19.16b
- eor v2.16b, v1.16b, v2.16b
- eor v7.16b, v1.16b, v17.16b
- add v1.4s, v5.4s, v16.4s
- eor v0.16b, v1.16b, v0.16b
- eor v18.16b, v1.16b, v4.16b
- add v1.4s, v6.4s, v3.4s
- eor v4.16b, v1.16b, v23.16b
- eor v6.16b, v25.16b, v1.16b
- add v1.4s, v22.4s, v20.4s
- eor v5.16b, v1.16b, v24.16b
- eor v17.16b, v26.16b, v1.16b
- ushr v1.4s, v4.4s, #7
+ orr v1.16b, v1.16b, v26.16b
+ orr v5.16b, v5.16b, v27.16b
+ movi v13.4s, #64
+ eor v29.16b, v19.16b, v22.16b
+ eor v8.16b, v21.16b, v3.16b
+ eor v30.16b, v17.16b, v18.16b
+ eor v31.16b, v20.16b, v7.16b
+ eor v24.16b, v5.16b, v23.16b
+ eor v18.16b, v0.16b, v16.16b
+ eor v25.16b, v2.16b, v6.16b
+ eor v26.16b, v1.16b, v4.16b
+ cbnz x21, .LBB3_5
+ b .LBB3_2
+.LBB3_6:
+ cbz x1, .LBB3_14
+ adrp x12, .LCPI3_3
+ ldr q0, [x11, :lo12:.LCPI3_1]
+ orr w11, w7, w6
+ ldr q2, [x10, :lo12:.LCPI3_2]
+ ldr q1, [x12, :lo12:.LCPI3_3]
+ and x12, x5, #0x1
+.LBB3_8:
+ movi v3.4s, #64
+ lsr x13, x4, #32
+ ldp q5, q4, [x3]
+ mov x15, x2
+ mov w14, w11
+ mov v3.s[0], w4
+ ldr x10, [x0]
+ mov v3.s[1], w13
+ b .LBB3_11
+.LBB3_9:
+ orr w14, w14, w9
+.LBB3_10:
+ ldp q6, q7, [x10]
+ mov v16.16b, v3.16b
+ and w14, w14, #0xff
+ add v5.4s, v5.4s, v4.4s
+ mov x15, x13
+ mov v16.s[3], w14
+ add x14, x10, #32
+ uzp1 v17.4s, v6.4s, v7.4s
+ add x10, x10, #64
+ add v5.4s, v5.4s, v17.4s
+ eor v16.16b, v5.16b, v16.16b
+ tbl v16.16b, { v16.16b }, v0.16b
+ add v18.4s, v16.4s, v1.4s
+ eor v19.16b, v18.16b, v4.16b
+ uzp2 v4.4s, v6.4s, v7.4s
+ ushr v6.4s, v19.4s, #12
+ shl v7.4s, v19.4s, #20
+ ld2 { v19.4s, v20.4s }, [x14]
+ add v5.4s, v5.4s, v4.4s
+ mov w14, w6
+ orr v6.16b, v7.16b, v6.16b
+ add v5.4s, v5.4s, v6.4s
+ eor v7.16b, v16.16b, v5.16b
+ add v5.4s, v5.4s, v19.4s
+ tbl v7.16b, { v7.16b }, v2.16b
+ ext v5.16b, v5.16b, v5.16b, #12
+ add v16.4s, v18.4s, v7.4s
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v6.16b, v6.16b, v16.16b
+ ext v16.16b, v16.16b, v16.16b, #4
+ ushr v18.4s, v6.4s, #7
+ shl v6.4s, v6.4s, #25
+ orr v6.16b, v6.16b, v18.16b
+ ext v18.16b, v20.16b, v20.16b, #12
+ add v5.4s, v5.4s, v6.4s
+ eor v7.16b, v5.16b, v7.16b
+ add v5.4s, v5.4s, v18.4s
+ tbl v7.16b, { v7.16b }, v0.16b
+ add v16.4s, v16.4s, v7.4s
+ eor v6.16b, v6.16b, v16.16b
+ ushr v21.4s, v6.4s, #12
+ shl v6.4s, v6.4s, #20
+ orr v6.16b, v6.16b, v21.16b
+ uzp1 v21.4s, v17.4s, v17.4s
+ add v5.4s, v5.4s, v6.4s
+ ext v21.16b, v21.16b, v17.16b, #8
+ eor v7.16b, v7.16b, v5.16b
+ uzp2 v21.4s, v21.4s, v4.4s
+ tbl v7.16b, { v7.16b }, v2.16b
+ add v5.4s, v5.4s, v21.4s
+ add v16.4s, v16.4s, v7.4s
+ ext v5.16b, v5.16b, v5.16b, #4
+ ext v7.16b, v7.16b, v7.16b, #8
+ eor v6.16b, v6.16b, v16.16b
+ ushr v22.4s, v6.4s, #7
+ shl v6.4s, v6.4s, #25
+ orr v6.16b, v6.16b, v22.16b
+ add v22.4s, v5.4s, v6.4s
+ eor v5.16b, v22.16b, v7.16b
+ ext v7.16b, v16.16b, v16.16b, #12
+ tbl v16.16b, { v5.16b }, v0.16b
+ ext v5.16b, v17.16b, v17.16b, #12
+ add v7.4s, v7.4s, v16.4s
+ ext v5.16b, v17.16b, v5.16b, #12
+ ext v17.16b, v19.16b, v19.16b, #12
+ mov v19.16b, v18.16b
+ eor v6.16b, v6.16b, v7.16b
+ rev64 v5.4s, v5.4s
+ mov v19.s[1], v17.s[2]
+ ushr v20.4s, v6.4s, #12
+ shl v6.4s, v6.4s, #20
+ trn2 v5.4s, v5.4s, v19.4s
+ orr v6.16b, v6.16b, v20.16b
+ zip1 v20.2d, v18.2d, v4.2d
+ zip2 v4.4s, v4.4s, v18.4s
+ add v19.4s, v6.4s, v5.4s
+ mov v20.s[3], v17.s[3]
+ add v19.4s, v19.4s, v22.4s
+ ext v22.16b, v20.16b, v20.16b, #12
+ eor v16.16b, v16.16b, v19.16b
+ ext v19.16b, v19.16b, v19.16b, #12
+ tbl v16.16b, { v16.16b }, v2.16b
+ add v7.4s, v7.4s, v16.4s
+ ext v16.16b, v16.16b, v16.16b, #8
+ eor v6.16b, v6.16b, v7.16b
+ ext v7.16b, v7.16b, v7.16b, #4
+ ushr v23.4s, v6.4s, #7
+ shl v24.4s, v6.4s, #25
+ uzp1 v6.4s, v20.4s, v22.4s
+ orr v20.16b, v24.16b, v23.16b
+ add v22.4s, v20.4s, v6.4s
+ add v19.4s, v22.4s, v19.4s
+ eor v16.16b, v19.16b, v16.16b
+ tbl v16.16b, { v16.16b }, v0.16b
+ add v7.4s, v7.4s, v16.4s
+ eor v18.16b, v20.16b, v7.16b
+ zip1 v20.4s, v4.4s, v17.4s
+ zip1 v4.4s, v17.4s, v4.4s
+ ushr v17.4s, v18.4s, #12
+ shl v18.4s, v18.4s, #20
+ ext v20.16b, v4.16b, v20.16b, #8
+ orr v4.16b, v18.16b, v17.16b
+ ext v18.16b, v21.16b, v21.16b, #4
+ add v17.4s, v4.4s, v20.4s
+ add v17.4s, v17.4s, v19.4s
+ uzp1 v19.4s, v18.4s, v18.4s
+ eor v16.16b, v16.16b, v17.16b
+ ext v19.16b, v19.16b, v18.16b, #8
+ tbl v16.16b, { v16.16b }, v2.16b
+ uzp2 v19.4s, v19.4s, v5.4s
+ add v7.4s, v7.4s, v16.4s
+ add v17.4s, v17.4s, v19.4s
+ ext v16.16b, v16.16b, v16.16b, #8
+ eor v4.16b, v4.16b, v7.16b
+ ext v17.16b, v17.16b, v17.16b, #4
+ ext v7.16b, v7.16b, v7.16b, #12
+ ushr v21.4s, v4.4s, #7
shl v4.4s, v4.4s, #25
- orr v1.16b, v4.16b, v1.16b
- ushr v4.4s, v5.4s, #7
+ orr v4.16b, v4.16b, v21.16b
+ ext v21.16b, v18.16b, v18.16b, #12
+ add v17.4s, v17.4s, v4.4s
+ ext v18.16b, v18.16b, v21.16b, #12
+ mov v21.16b, v20.16b
+ eor v16.16b, v17.16b, v16.16b
+ rev64 v18.4s, v18.4s
+ mov v21.s[1], v6.s[2]
+ tbl v16.16b, { v16.16b }, v0.16b
+ add v7.4s, v7.4s, v16.4s
+ eor v4.16b, v4.16b, v7.16b
+ ushr v22.4s, v4.4s, #12
+ shl v23.4s, v4.4s, #20
+ trn2 v4.4s, v18.4s, v21.4s
+ orr v18.16b, v23.16b, v22.16b
+ add v21.4s, v18.4s, v4.4s
+ add v17.4s, v21.4s, v17.4s
+ zip1 v21.2d, v20.2d, v5.2d
+ zip2 v5.4s, v5.4s, v20.4s
+ eor v16.16b, v16.16b, v17.16b
+ mov v21.s[3], v6.s[3]
+ ext v17.16b, v17.16b, v17.16b, #12
+ zip1 v20.4s, v5.4s, v6.4s
+ tbl v16.16b, { v16.16b }, v2.16b
+ zip1 v5.4s, v6.4s, v5.4s
+ add v22.4s, v7.4s, v16.4s
+ ext v16.16b, v16.16b, v16.16b, #8
+ ext v20.16b, v5.16b, v20.16b, #8
+ eor v7.16b, v18.16b, v22.16b
+ ext v18.16b, v21.16b, v21.16b, #12
+ ushr v23.4s, v7.4s, #7
+ shl v24.4s, v7.4s, #25
+ uzp1 v7.4s, v21.4s, v18.4s
+ orr v18.16b, v24.16b, v23.16b
+ add v21.4s, v18.4s, v7.4s
+ add v17.4s, v21.4s, v17.4s
+ ext v21.16b, v22.16b, v22.16b, #4
+ eor v16.16b, v17.16b, v16.16b
+ tbl v16.16b, { v16.16b }, v0.16b
+ add v21.4s, v21.4s, v16.4s
+ eor v18.16b, v18.16b, v21.16b
+ ushr v6.4s, v18.4s, #12
+ shl v18.4s, v18.4s, #20
+ orr v5.16b, v18.16b, v6.16b
+ add v6.4s, v5.4s, v20.4s
+ add v6.4s, v6.4s, v17.4s
+ ext v17.16b, v19.16b, v19.16b, #4
+ eor v16.16b, v16.16b, v6.16b
+ uzp1 v18.4s, v17.4s, v17.4s
+ tbl v16.16b, { v16.16b }, v2.16b
+ ext v18.16b, v18.16b, v17.16b, #8
+ add v19.4s, v21.4s, v16.4s
+ uzp2 v18.4s, v18.4s, v4.4s
+ ext v16.16b, v16.16b, v16.16b, #8
+ eor v5.16b, v5.16b, v19.16b
+ add v6.4s, v6.4s, v18.4s
+ ext v19.16b, v19.16b, v19.16b, #12
+ ushr v21.4s, v5.4s, #7
shl v5.4s, v5.4s, #25
- orr v4.16b, v5.16b, v4.16b
- ushr v5.4s, v2.4s, #7
- shl v2.4s, v2.4s, #25
- orr v2.16b, v2.16b, v5.16b
- ushr v5.4s, v0.4s, #7
- shl v0.4s, v0.4s, #25
- orr v0.16b, v0.16b, v5.16b
- eor v10.16b, v0.16b, v20.16b
- eor v11.16b, v1.16b, v21.16b
- eor v19.16b, v4.16b, v16.16b
- cmp x0, x22
- eor v16.16b, v2.16b, v3.16b
- mov w6, w19
- b.ne .LBB2_4
-.LBB2_7:
- zip1 v0.4s, v7.4s, v18.4s
- zip2 v1.4s, v7.4s, v18.4s
- zip1 v2.4s, v6.4s, v17.4s
- zip2 v3.4s, v6.4s, v17.4s
- zip1 v4.4s, v10.4s, v11.4s
- zip2 v5.4s, v10.4s, v11.4s
- zip1 v6.4s, v19.4s, v16.4s
- zip2 v7.4s, v19.4s, v16.4s
- add x15, x20, #4
- tst w5, #0x1
- sub x28, x28, #4
- zip1 v16.2d, v0.2d, v2.2d
- zip2 v0.2d, v0.2d, v2.2d
- zip1 v2.2d, v1.2d, v3.2d
- zip2 v1.2d, v1.2d, v3.2d
- zip1 v3.2d, v4.2d, v6.2d
- zip2 v4.2d, v4.2d, v6.2d
- zip1 v6.2d, v5.2d, v7.2d
- zip2 v5.2d, v5.2d, v7.2d
- add x24, x24, #32
- csel x20, x15, x20, ne
- cmp x28, #3
- stp q16, q3, [x26]
- stp q0, q4, [x26, #32]
- stp q2, q6, [x26, #64]
- stp q1, q5, [x26, #96]
- add x26, x26, #128
- b.hi .LBB2_2
-.LBB2_8:
- cbz x28, .LBB2_16
- orr w8, w7, w19
- and x21, x5, #0x1
- stur w8, [x29, #-64]
-.LBB2_10:
- ldr x8, [sp, #40]
- ldr x25, [x24]
- ldur w4, [x29, #-64]
- ldp q1, q0, [x8]
- mov x8, x22
- stp q1, q0, [x29, #-48]
-.LBB2_11:
- subs x23, x8, #1
- b.eq .LBB2_13
- cbnz x8, .LBB2_14
- b .LBB2_15
-.LBB2_13:
- orr w4, w4, w27
-.LBB2_14:
- sub x0, x29, #48
- mov w2, #64
- mov x1, x25
- mov x3, x20
- bl zfs_blake3_compress_in_place_sse41
- add x25, x25, #64
- mov x8, x23
- mov w4, w19
- b .LBB2_11
-.LBB2_15:
- ldp q0, q1, [x29, #-48]
- add x20, x20, x21
- add x24, x24, #8
- subs x28, x28, #1
- stp q0, q1, [x26], #32
- b.ne .LBB2_10
-.LBB2_16:
- add sp, sp, #448
- ldp x20, x19, [sp, #144]
- ldp x22, x21, [sp, #128]
- ldp x24, x23, [sp, #112]
- ldp x26, x25, [sp, #96]
- ldp x28, x27, [sp, #80]
- ldp x29, x30, [sp, #64]
+ ext v6.16b, v6.16b, v6.16b, #4
+ orr v5.16b, v5.16b, v21.16b
+ ext v21.16b, v17.16b, v17.16b, #12
+ add v6.4s, v6.4s, v5.4s
+ ext v17.16b, v17.16b, v21.16b, #12
+ mov v21.16b, v20.16b
+ eor v16.16b, v6.16b, v16.16b
+ rev64 v17.4s, v17.4s
+ mov v21.s[1], v7.s[2]
+ tbl v16.16b, { v16.16b }, v0.16b
+ add v19.4s, v19.4s, v16.4s
+ eor v5.16b, v5.16b, v19.16b
+ ushr v22.4s, v5.4s, #12
+ shl v23.4s, v5.4s, #20
+ trn2 v5.4s, v17.4s, v21.4s
+ orr v17.16b, v23.16b, v22.16b
+ add v21.4s, v17.4s, v5.4s
+ add v6.4s, v21.4s, v6.4s
+ eor v16.16b, v16.16b, v6.16b
+ ext v6.16b, v6.16b, v6.16b, #12
+ tbl v21.16b, { v16.16b }, v2.16b
+ zip1 v16.2d, v20.2d, v4.2d
+ zip2 v4.4s, v4.4s, v20.4s
+ add v19.4s, v19.4s, v21.4s
+ mov v16.s[3], v7.s[3]
+ ext v21.16b, v21.16b, v21.16b, #8
+ zip1 v20.4s, v4.4s, v7.4s
+ eor v17.16b, v17.16b, v19.16b
+ ext v22.16b, v16.16b, v16.16b, #12
+ ext v19.16b, v19.16b, v19.16b, #4
+ zip1 v4.4s, v7.4s, v4.4s
+ ushr v23.4s, v17.4s, #7
+ shl v17.4s, v17.4s, #25
+ uzp1 v16.4s, v16.4s, v22.4s
+ ext v4.16b, v4.16b, v20.16b, #8
+ orr v17.16b, v17.16b, v23.16b
+ add v22.4s, v17.4s, v16.4s
+ add v6.4s, v22.4s, v6.4s
+ eor v21.16b, v6.16b, v21.16b
+ tbl v21.16b, { v21.16b }, v0.16b
+ add v19.4s, v19.4s, v21.4s
+ eor v17.16b, v17.16b, v19.16b
+ ushr v7.4s, v17.4s, #12
+ shl v17.4s, v17.4s, #20
+ orr v7.16b, v17.16b, v7.16b
+ add v17.4s, v7.4s, v4.4s
+ add v6.4s, v17.4s, v6.4s
+ ext v17.16b, v18.16b, v18.16b, #4
+ eor v18.16b, v21.16b, v6.16b
+ uzp1 v20.4s, v17.4s, v17.4s
+ tbl v18.16b, { v18.16b }, v2.16b
+ ext v20.16b, v20.16b, v17.16b, #8
+ add v19.4s, v19.4s, v18.4s
+ uzp2 v20.4s, v20.4s, v5.4s
+ ext v18.16b, v18.16b, v18.16b, #8
+ eor v7.16b, v7.16b, v19.16b
+ add v6.4s, v6.4s, v20.4s
+ ushr v21.4s, v7.4s, #7
+ shl v7.4s, v7.4s, #25
+ ext v6.16b, v6.16b, v6.16b, #4
+ orr v7.16b, v7.16b, v21.16b
+ add v21.4s, v6.4s, v7.4s
+ eor v6.16b, v21.16b, v18.16b
+ ext v18.16b, v19.16b, v19.16b, #12
+ tbl v19.16b, { v6.16b }, v0.16b
+ ext v6.16b, v17.16b, v17.16b, #12
+ add v18.4s, v18.4s, v19.4s
+ ext v6.16b, v17.16b, v6.16b, #12
+ mov v17.16b, v4.16b
+ eor v7.16b, v7.16b, v18.16b
+ rev64 v6.4s, v6.4s
+ mov v17.s[1], v16.s[2]
+ ushr v22.4s, v7.4s, #12
+ shl v7.4s, v7.4s, #20
+ trn2 v6.4s, v6.4s, v17.4s
+ orr v7.16b, v7.16b, v22.16b
+ add v17.4s, v7.4s, v6.4s
+ add v17.4s, v17.4s, v21.4s
+ zip1 v21.2d, v4.2d, v5.2d
+ zip2 v4.4s, v5.4s, v4.4s
+ eor v19.16b, v19.16b, v17.16b
+ mov v21.s[3], v16.s[3]
+ ext v17.16b, v17.16b, v17.16b, #12
+ tbl v19.16b, { v19.16b }, v2.16b
+ ext v22.16b, v21.16b, v21.16b, #12
+ add v18.4s, v18.4s, v19.4s
+ ext v19.16b, v19.16b, v19.16b, #8
+ eor v7.16b, v7.16b, v18.16b
+ ext v18.16b, v18.16b, v18.16b, #4
+ ushr v23.4s, v7.4s, #7
+ shl v24.4s, v7.4s, #25
+ uzp1 v7.4s, v21.4s, v22.4s
+ orr v21.16b, v24.16b, v23.16b
+ add v22.4s, v21.4s, v7.4s
+ add v17.4s, v22.4s, v17.4s
+ eor v19.16b, v17.16b, v19.16b
+ tbl v19.16b, { v19.16b }, v0.16b
+ add v18.4s, v18.4s, v19.4s
+ eor v5.16b, v21.16b, v18.16b
+ zip1 v21.4s, v4.4s, v16.4s
+ zip1 v4.4s, v16.4s, v4.4s
+ ushr v16.4s, v5.4s, #12
+ shl v5.4s, v5.4s, #20
+ ext v21.16b, v4.16b, v21.16b, #8
+ orr v4.16b, v5.16b, v16.16b
+ ext v16.16b, v20.16b, v20.16b, #4
+ mov v23.16b, v21.16b
+ add v5.4s, v4.4s, v21.4s
+ mov v23.s[1], v7.s[2]
+ add v5.4s, v5.4s, v17.4s
+ eor v17.16b, v19.16b, v5.16b
+ uzp1 v19.4s, v16.4s, v16.4s
+ tbl v17.16b, { v17.16b }, v2.16b
+ ext v19.16b, v19.16b, v16.16b, #8
+ add v18.4s, v18.4s, v17.4s
+ uzp2 v19.4s, v19.4s, v6.4s
+ eor v4.16b, v4.16b, v18.16b
+ add v5.4s, v5.4s, v19.4s
+ ext v19.16b, v19.16b, v19.16b, #4
+ ushr v20.4s, v4.4s, #7
+ shl v4.4s, v4.4s, #25
+ ext v5.16b, v5.16b, v5.16b, #4
+ orr v20.16b, v4.16b, v20.16b
+ ext v4.16b, v17.16b, v17.16b, #8
+ add v17.4s, v5.4s, v20.4s
+ ext v5.16b, v18.16b, v18.16b, #12
+ eor v4.16b, v17.16b, v4.16b
+ tbl v18.16b, { v4.16b }, v0.16b
+ ext v4.16b, v16.16b, v16.16b, #12
+ add v22.4s, v5.4s, v18.4s
+ ext v4.16b, v16.16b, v4.16b, #12
+ eor v5.16b, v20.16b, v22.16b
+ rev64 v16.4s, v4.4s
+ ushr v20.4s, v5.4s, #12
+ shl v24.4s, v5.4s, #20
+ trn2 v5.4s, v16.4s, v23.4s
+ orr v16.16b, v24.16b, v20.16b
+ add v20.4s, v16.4s, v5.4s
+ add v17.4s, v20.4s, v17.4s
+ zip1 v20.2d, v21.2d, v6.2d
+ zip2 v6.4s, v6.4s, v21.4s
+ eor v18.16b, v18.16b, v17.16b
+ mov v20.s[3], v7.s[3]
+ ext v17.16b, v17.16b, v17.16b, #12
+ zip1 v21.4s, v6.4s, v7.4s
+ tbl v18.16b, { v18.16b }, v2.16b
+ ext v24.16b, v20.16b, v20.16b, #12
+ zip1 v6.4s, v7.4s, v6.4s
+ add v22.4s, v22.4s, v18.4s
+ ext v18.16b, v18.16b, v18.16b, #8
+ ext v6.16b, v6.16b, v21.16b, #8
+ eor v16.16b, v16.16b, v22.16b
+ ext v22.16b, v22.16b, v22.16b, #4
+ zip1 v5.2d, v6.2d, v5.2d
+ zip2 v4.4s, v4.4s, v6.4s
+ ushr v25.4s, v16.4s, #7
+ shl v26.4s, v16.4s, #25
+ uzp1 v16.4s, v20.4s, v24.4s
+ orr v20.16b, v26.16b, v25.16b
+ mov v5.s[3], v16.s[3]
+ add v24.4s, v20.4s, v16.4s
+ add v17.4s, v24.4s, v17.4s
+ eor v18.16b, v17.16b, v18.16b
+ tbl v18.16b, { v18.16b }, v0.16b
+ add v22.4s, v22.4s, v18.4s
+ eor v20.16b, v20.16b, v22.16b
+ ushr v7.4s, v20.4s, #12
+ shl v20.4s, v20.4s, #20
+ orr v7.16b, v20.16b, v7.16b
+ add v20.4s, v7.4s, v6.4s
+ add v17.4s, v20.4s, v17.4s
+ ext v20.16b, v19.16b, v19.16b, #8
+ eor v18.16b, v18.16b, v17.16b
+ ext v17.16b, v17.16b, v17.16b, #4
+ tbl v18.16b, { v18.16b }, v2.16b
+ add v21.4s, v22.4s, v18.4s
+ uzp2 v22.4s, v20.4s, v23.4s
+ ext v18.16b, v18.16b, v18.16b, #8
+ eor v7.16b, v7.16b, v21.16b
+ ext v20.16b, v22.16b, v20.16b, #4
+ ushr v22.4s, v7.4s, #7
+ shl v7.4s, v7.4s, #25
+ add v17.4s, v17.4s, v20.4s
+ ext v20.16b, v21.16b, v21.16b, #12
+ ext v21.16b, v19.16b, v19.16b, #12
+ orr v7.16b, v7.16b, v22.16b
+ ext v19.16b, v19.16b, v21.16b, #12
+ add v17.4s, v17.4s, v7.4s
+ mov v21.16b, v6.16b
+ rev64 v19.4s, v19.4s
+ eor v18.16b, v17.16b, v18.16b
+ mov v21.s[1], v16.s[2]
+ tbl v18.16b, { v18.16b }, v0.16b
+ trn2 v19.4s, v19.4s, v21.4s
+ add v20.4s, v20.4s, v18.4s
+ eor v7.16b, v7.16b, v20.16b
+ ushr v22.4s, v7.4s, #12
+ shl v7.4s, v7.4s, #20
+ orr v7.16b, v7.16b, v22.16b
+ add v19.4s, v7.4s, v19.4s
+ add v17.4s, v19.4s, v17.4s
+ eor v18.16b, v18.16b, v17.16b
+ ext v17.16b, v17.16b, v17.16b, #12
+ tbl v18.16b, { v18.16b }, v2.16b
+ add v19.4s, v20.4s, v18.4s
+ ext v20.16b, v5.16b, v5.16b, #12
+ ext v18.16b, v18.16b, v18.16b, #8
+ eor v7.16b, v7.16b, v19.16b
+ uzp1 v5.4s, v5.4s, v20.4s
+ ushr v21.4s, v7.4s, #7
+ shl v7.4s, v7.4s, #25
+ orr v7.16b, v7.16b, v21.16b
+ add v5.4s, v7.4s, v5.4s
+ add v5.4s, v5.4s, v17.4s
+ eor v17.16b, v5.16b, v18.16b
+ ext v18.16b, v19.16b, v19.16b, #4
+ tbl v17.16b, { v17.16b }, v0.16b
+ add v18.4s, v18.4s, v17.4s
+ eor v6.16b, v7.16b, v18.16b
+ zip1 v7.4s, v4.4s, v16.4s
+ zip1 v4.4s, v16.4s, v4.4s
+ ushr v16.4s, v6.4s, #12
+ shl v6.4s, v6.4s, #20
+ ext v4.16b, v4.16b, v7.16b, #8
+ orr v6.16b, v6.16b, v16.16b
+ add v4.4s, v6.4s, v4.4s
+ add v4.4s, v4.4s, v5.4s
+ eor v5.16b, v17.16b, v4.16b
+ ext v4.16b, v4.16b, v4.16b, #4
+ tbl v5.16b, { v5.16b }, v2.16b
+ add v7.4s, v18.4s, v5.4s
+ eor v6.16b, v6.16b, v7.16b
+ ext v7.16b, v7.16b, v7.16b, #12
+ ushr v16.4s, v6.4s, #7
+ shl v6.4s, v6.4s, #25
+ orr v6.16b, v6.16b, v16.16b
+ ext v16.16b, v5.16b, v5.16b, #8
+ eor v5.16b, v4.16b, v7.16b
+ eor v4.16b, v6.16b, v16.16b
+.LBB3_11:
+ subs x13, x15, #1
+ b.eq .LBB3_9
+ cbnz x15, .LBB3_10
+ add x4, x4, x12
+ add x0, x0, #8
+ subs x1, x1, #1
+ stp q5, q4, [x8], #32
+ b.ne .LBB3_8
+.LBB3_14:
+ add sp, sp, #368
+ ldp x20, x19, [sp, #128]
+ ldp x22, x21, [sp, #112]
+ ldp x24, x23, [sp, #96]
+ ldp x26, x25, [sp, #80]
+ ldp x29, x27, [sp, #64]
ldp d9, d8, [sp, #48]
ldp d11, d10, [sp, #32]
ldp d13, d12, [sp, #16]
- ldp d15, d14, [sp], #160
+ ldp d15, d14, [sp], #144
ret
-.Lfunc_end2:
- .size zfs_blake3_hash_many_sse41, .Lfunc_end2-zfs_blake3_hash_many_sse41
+.Lfunc_end3:
+ .size zfs_blake3_hash_many_sse41, .Lfunc_end3-zfs_blake3_hash_many_sse41
.cfi_endproc
.section ".note.GNU-stack","",@progbits
-#endif
+#endif \ No newline at end of file
diff --git a/module/icp/asm-aarch64/sha2/sha256-armv8.S b/module/icp/asm-aarch64/sha2/sha256-armv8.S
new file mode 100644
index 000000000000..4dcdd3b65d0b
--- /dev/null
+++ b/module/icp/asm-aarch64/sha2/sha256-armv8.S
@@ -0,0 +1,2012 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__aarch64__)
+
+ .section .note.gnu.property,"a",@note
+ .p2align 3
+ .word 4
+ .word 16
+ .word 5
+ .asciz "GNU"
+ .word 3221225472
+ .word 4
+ .word 3
+ .word 0
+.text
+
+.align 6
+.type .LK256,%object
+.LK256:
+ .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+ .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+ .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+ .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+ .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+ .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+ .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+ .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+ .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+ .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+ .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+ .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+ .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+ .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+ .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+ .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+ .long 0 //terminator
+.size .LK256,.-.LK256
+
+.globl zfs_sha256_block_armv7
+.type zfs_sha256_block_armv7,%function
+.align 6
+zfs_sha256_block_armv7:
+ hint #34 // bti c
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*4
+
+ ldp w20,w21,[x0] // load context
+ ldp w22,w23,[x0,#2*4]
+ ldp w24,w25,[x0,#4*4]
+ add x2,x1,x2,lsl#6 // end of input
+ ldp w26,w27,[x0,#6*4]
+ adr x30,.LK256
+ stp x0,x2,[x29,#96]
+
+.Loop:
+ ldp w3,w4,[x1],#2*4
+ ldr w19,[x30],#4 // *K++
+ eor w28,w21,w22 // magic seed
+ str x1,[x29,#112]
+#ifndef __AARCH64EB__
+ rev w3,w3 // 0
+#endif
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ eor w6,w24,w24,ror#14
+ and w17,w25,w24
+ bic w19,w26,w24
+ add w27,w27,w3 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w6,ror#11 // Sigma1(e)
+ ror w6,w20,#2
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ eor w17,w20,w20,ror#9
+ add w27,w27,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w23,w23,w27 // d+=h
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w6,w17,ror#13 // Sigma0(a)
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w27,w27,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w4,w4 // 1
+#endif
+ ldp w5,w6,[x1],#2*4
+ add w27,w27,w17 // h+=Sigma0(a)
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ eor w7,w23,w23,ror#14
+ and w17,w24,w23
+ bic w28,w25,w23
+ add w26,w26,w4 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w7,ror#11 // Sigma1(e)
+ ror w7,w27,#2
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ eor w17,w27,w27,ror#9
+ add w26,w26,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w22,w22,w26 // d+=h
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w7,w17,ror#13 // Sigma0(a)
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w26,w26,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w5,w5 // 2
+#endif
+ add w26,w26,w17 // h+=Sigma0(a)
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ eor w8,w22,w22,ror#14
+ and w17,w23,w22
+ bic w19,w24,w22
+ add w25,w25,w5 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w8,ror#11 // Sigma1(e)
+ ror w8,w26,#2
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ eor w17,w26,w26,ror#9
+ add w25,w25,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w21,w21,w25 // d+=h
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w8,w17,ror#13 // Sigma0(a)
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w25,w25,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w6,w6 // 3
+#endif
+ ldp w7,w8,[x1],#2*4
+ add w25,w25,w17 // h+=Sigma0(a)
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ eor w9,w21,w21,ror#14
+ and w17,w22,w21
+ bic w28,w23,w21
+ add w24,w24,w6 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w9,ror#11 // Sigma1(e)
+ ror w9,w25,#2
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ eor w17,w25,w25,ror#9
+ add w24,w24,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w20,w20,w24 // d+=h
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w9,w17,ror#13 // Sigma0(a)
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w24,w24,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w7,w7 // 4
+#endif
+ add w24,w24,w17 // h+=Sigma0(a)
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ eor w10,w20,w20,ror#14
+ and w17,w21,w20
+ bic w19,w22,w20
+ add w23,w23,w7 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w10,ror#11 // Sigma1(e)
+ ror w10,w24,#2
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ eor w17,w24,w24,ror#9
+ add w23,w23,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w27,w27,w23 // d+=h
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w10,w17,ror#13 // Sigma0(a)
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w23,w23,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w8,w8 // 5
+#endif
+ ldp w9,w10,[x1],#2*4
+ add w23,w23,w17 // h+=Sigma0(a)
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ eor w11,w27,w27,ror#14
+ and w17,w20,w27
+ bic w28,w21,w27
+ add w22,w22,w8 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w11,ror#11 // Sigma1(e)
+ ror w11,w23,#2
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ eor w17,w23,w23,ror#9
+ add w22,w22,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w26,w26,w22 // d+=h
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w11,w17,ror#13 // Sigma0(a)
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w22,w22,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w9,w9 // 6
+#endif
+ add w22,w22,w17 // h+=Sigma0(a)
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ eor w12,w26,w26,ror#14
+ and w17,w27,w26
+ bic w19,w20,w26
+ add w21,w21,w9 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w12,ror#11 // Sigma1(e)
+ ror w12,w22,#2
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ eor w17,w22,w22,ror#9
+ add w21,w21,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w25,w25,w21 // d+=h
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w12,w17,ror#13 // Sigma0(a)
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w21,w21,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w10,w10 // 7
+#endif
+ ldp w11,w12,[x1],#2*4
+ add w21,w21,w17 // h+=Sigma0(a)
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ eor w13,w25,w25,ror#14
+ and w17,w26,w25
+ bic w28,w27,w25
+ add w20,w20,w10 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w13,ror#11 // Sigma1(e)
+ ror w13,w21,#2
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ eor w17,w21,w21,ror#9
+ add w20,w20,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w24,w24,w20 // d+=h
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w13,w17,ror#13 // Sigma0(a)
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w20,w20,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w11,w11 // 8
+#endif
+ add w20,w20,w17 // h+=Sigma0(a)
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ eor w14,w24,w24,ror#14
+ and w17,w25,w24
+ bic w19,w26,w24
+ add w27,w27,w11 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w14,ror#11 // Sigma1(e)
+ ror w14,w20,#2
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ eor w17,w20,w20,ror#9
+ add w27,w27,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w23,w23,w27 // d+=h
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w14,w17,ror#13 // Sigma0(a)
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w27,w27,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w12,w12 // 9
+#endif
+ ldp w13,w14,[x1],#2*4
+ add w27,w27,w17 // h+=Sigma0(a)
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ eor w15,w23,w23,ror#14
+ and w17,w24,w23
+ bic w28,w25,w23
+ add w26,w26,w12 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w15,ror#11 // Sigma1(e)
+ ror w15,w27,#2
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ eor w17,w27,w27,ror#9
+ add w26,w26,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w22,w22,w26 // d+=h
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w15,w17,ror#13 // Sigma0(a)
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w26,w26,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w13,w13 // 10
+#endif
+ add w26,w26,w17 // h+=Sigma0(a)
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ eor w0,w22,w22,ror#14
+ and w17,w23,w22
+ bic w19,w24,w22
+ add w25,w25,w13 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w0,ror#11 // Sigma1(e)
+ ror w0,w26,#2
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ eor w17,w26,w26,ror#9
+ add w25,w25,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w21,w21,w25 // d+=h
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w0,w17,ror#13 // Sigma0(a)
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w25,w25,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w14,w14 // 11
+#endif
+ ldp w15,w0,[x1],#2*4
+ add w25,w25,w17 // h+=Sigma0(a)
+ str w6,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ eor w6,w21,w21,ror#14
+ and w17,w22,w21
+ bic w28,w23,w21
+ add w24,w24,w14 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w6,ror#11 // Sigma1(e)
+ ror w6,w25,#2
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ eor w17,w25,w25,ror#9
+ add w24,w24,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w20,w20,w24 // d+=h
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w6,w17,ror#13 // Sigma0(a)
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w24,w24,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w15,w15 // 12
+#endif
+ add w24,w24,w17 // h+=Sigma0(a)
+ str w7,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ eor w7,w20,w20,ror#14
+ and w17,w21,w20
+ bic w19,w22,w20
+ add w23,w23,w15 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w7,ror#11 // Sigma1(e)
+ ror w7,w24,#2
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ eor w17,w24,w24,ror#9
+ add w23,w23,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w27,w27,w23 // d+=h
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w7,w17,ror#13 // Sigma0(a)
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w23,w23,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w0,w0 // 13
+#endif
+ ldp w1,w2,[x1]
+ add w23,w23,w17 // h+=Sigma0(a)
+ str w8,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ eor w8,w27,w27,ror#14
+ and w17,w20,w27
+ bic w28,w21,w27
+ add w22,w22,w0 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w8,ror#11 // Sigma1(e)
+ ror w8,w23,#2
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ eor w17,w23,w23,ror#9
+ add w22,w22,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w26,w26,w22 // d+=h
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w8,w17,ror#13 // Sigma0(a)
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w22,w22,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w1,w1 // 14
+#endif
+ ldr w6,[sp,#12]
+ add w22,w22,w17 // h+=Sigma0(a)
+ str w9,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ eor w9,w26,w26,ror#14
+ and w17,w27,w26
+ bic w19,w20,w26
+ add w21,w21,w1 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w9,ror#11 // Sigma1(e)
+ ror w9,w22,#2
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ eor w17,w22,w22,ror#9
+ add w21,w21,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w25,w25,w21 // d+=h
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w9,w17,ror#13 // Sigma0(a)
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w21,w21,w17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev w2,w2 // 15
+#endif
+ ldr w7,[sp,#0]
+ add w21,w21,w17 // h+=Sigma0(a)
+ str w10,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w9,w4,#7
+ and w17,w26,w25
+ ror w8,w1,#17
+ bic w28,w27,w25
+ ror w10,w21,#2
+ add w20,w20,w2 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w9,w9,w4,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w10,w10,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w8,w8,w1,ror#19
+ eor w9,w9,w4,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w10,w21,ror#22 // Sigma0(a)
+ eor w8,w8,w1,lsr#10 // sigma1(X[i+14])
+ add w3,w3,w12
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w3,w3,w9
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w3,w3,w8
+.Loop_16_xx:
+ ldr w8,[sp,#4]
+ str w11,[sp,#0]
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ ror w10,w5,#7
+ and w17,w25,w24
+ ror w9,w2,#17
+ bic w19,w26,w24
+ ror w11,w20,#2
+ add w27,w27,w3 // h+=X[i]
+ eor w16,w16,w24,ror#11
+ eor w10,w10,w5,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w24,ror#25 // Sigma1(e)
+ eor w11,w11,w20,ror#13
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w9,w9,w2,ror#19
+ eor w10,w10,w5,lsr#3 // sigma0(X[i+1])
+ add w27,w27,w16 // h+=Sigma1(e)
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w11,w20,ror#22 // Sigma0(a)
+ eor w9,w9,w2,lsr#10 // sigma1(X[i+14])
+ add w4,w4,w13
+ add w23,w23,w27 // d+=h
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w4,w4,w10
+ add w27,w27,w17 // h+=Sigma0(a)
+ add w4,w4,w9
+ ldr w9,[sp,#8]
+ str w12,[sp,#4]
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ ror w11,w6,#7
+ and w17,w24,w23
+ ror w10,w3,#17
+ bic w28,w25,w23
+ ror w12,w27,#2
+ add w26,w26,w4 // h+=X[i]
+ eor w16,w16,w23,ror#11
+ eor w11,w11,w6,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w23,ror#25 // Sigma1(e)
+ eor w12,w12,w27,ror#13
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w10,w10,w3,ror#19
+ eor w11,w11,w6,lsr#3 // sigma0(X[i+1])
+ add w26,w26,w16 // h+=Sigma1(e)
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w12,w27,ror#22 // Sigma0(a)
+ eor w10,w10,w3,lsr#10 // sigma1(X[i+14])
+ add w5,w5,w14
+ add w22,w22,w26 // d+=h
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w5,w5,w11
+ add w26,w26,w17 // h+=Sigma0(a)
+ add w5,w5,w10
+ ldr w10,[sp,#12]
+ str w13,[sp,#8]
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ ror w12,w7,#7
+ and w17,w23,w22
+ ror w11,w4,#17
+ bic w19,w24,w22
+ ror w13,w26,#2
+ add w25,w25,w5 // h+=X[i]
+ eor w16,w16,w22,ror#11
+ eor w12,w12,w7,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w22,ror#25 // Sigma1(e)
+ eor w13,w13,w26,ror#13
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w11,w11,w4,ror#19
+ eor w12,w12,w7,lsr#3 // sigma0(X[i+1])
+ add w25,w25,w16 // h+=Sigma1(e)
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w13,w26,ror#22 // Sigma0(a)
+ eor w11,w11,w4,lsr#10 // sigma1(X[i+14])
+ add w6,w6,w15
+ add w21,w21,w25 // d+=h
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w6,w6,w12
+ add w25,w25,w17 // h+=Sigma0(a)
+ add w6,w6,w11
+ ldr w11,[sp,#0]
+ str w14,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ ror w13,w8,#7
+ and w17,w22,w21
+ ror w12,w5,#17
+ bic w28,w23,w21
+ ror w14,w25,#2
+ add w24,w24,w6 // h+=X[i]
+ eor w16,w16,w21,ror#11
+ eor w13,w13,w8,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w21,ror#25 // Sigma1(e)
+ eor w14,w14,w25,ror#13
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w12,w12,w5,ror#19
+ eor w13,w13,w8,lsr#3 // sigma0(X[i+1])
+ add w24,w24,w16 // h+=Sigma1(e)
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w14,w25,ror#22 // Sigma0(a)
+ eor w12,w12,w5,lsr#10 // sigma1(X[i+14])
+ add w7,w7,w0
+ add w20,w20,w24 // d+=h
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w7,w7,w13
+ add w24,w24,w17 // h+=Sigma0(a)
+ add w7,w7,w12
+ ldr w12,[sp,#4]
+ str w15,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ ror w14,w9,#7
+ and w17,w21,w20
+ ror w13,w6,#17
+ bic w19,w22,w20
+ ror w15,w24,#2
+ add w23,w23,w7 // h+=X[i]
+ eor w16,w16,w20,ror#11
+ eor w14,w14,w9,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w20,ror#25 // Sigma1(e)
+ eor w15,w15,w24,ror#13
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w13,w13,w6,ror#19
+ eor w14,w14,w9,lsr#3 // sigma0(X[i+1])
+ add w23,w23,w16 // h+=Sigma1(e)
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w15,w24,ror#22 // Sigma0(a)
+ eor w13,w13,w6,lsr#10 // sigma1(X[i+14])
+ add w8,w8,w1
+ add w27,w27,w23 // d+=h
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w8,w8,w14
+ add w23,w23,w17 // h+=Sigma0(a)
+ add w8,w8,w13
+ ldr w13,[sp,#8]
+ str w0,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ ror w15,w10,#7
+ and w17,w20,w27
+ ror w14,w7,#17
+ bic w28,w21,w27
+ ror w0,w23,#2
+ add w22,w22,w8 // h+=X[i]
+ eor w16,w16,w27,ror#11
+ eor w15,w15,w10,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w27,ror#25 // Sigma1(e)
+ eor w0,w0,w23,ror#13
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w14,w14,w7,ror#19
+ eor w15,w15,w10,lsr#3 // sigma0(X[i+1])
+ add w22,w22,w16 // h+=Sigma1(e)
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w0,w23,ror#22 // Sigma0(a)
+ eor w14,w14,w7,lsr#10 // sigma1(X[i+14])
+ add w9,w9,w2
+ add w26,w26,w22 // d+=h
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w9,w9,w15
+ add w22,w22,w17 // h+=Sigma0(a)
+ add w9,w9,w14
+ ldr w14,[sp,#12]
+ str w1,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ ror w0,w11,#7
+ and w17,w27,w26
+ ror w15,w8,#17
+ bic w19,w20,w26
+ ror w1,w22,#2
+ add w21,w21,w9 // h+=X[i]
+ eor w16,w16,w26,ror#11
+ eor w0,w0,w11,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w26,ror#25 // Sigma1(e)
+ eor w1,w1,w22,ror#13
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w15,w15,w8,ror#19
+ eor w0,w0,w11,lsr#3 // sigma0(X[i+1])
+ add w21,w21,w16 // h+=Sigma1(e)
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w1,w22,ror#22 // Sigma0(a)
+ eor w15,w15,w8,lsr#10 // sigma1(X[i+14])
+ add w10,w10,w3
+ add w25,w25,w21 // d+=h
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w10,w10,w0
+ add w21,w21,w17 // h+=Sigma0(a)
+ add w10,w10,w15
+ ldr w15,[sp,#0]
+ str w2,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w1,w12,#7
+ and w17,w26,w25
+ ror w0,w9,#17
+ bic w28,w27,w25
+ ror w2,w21,#2
+ add w20,w20,w10 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w1,w1,w12,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w2,w2,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w0,w0,w9,ror#19
+ eor w1,w1,w12,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w2,w21,ror#22 // Sigma0(a)
+ eor w0,w0,w9,lsr#10 // sigma1(X[i+14])
+ add w11,w11,w4
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w11,w11,w1
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w11,w11,w0
+ ldr w0,[sp,#4]
+ str w3,[sp,#0]
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ ror w2,w13,#7
+ and w17,w25,w24
+ ror w1,w10,#17
+ bic w19,w26,w24
+ ror w3,w20,#2
+ add w27,w27,w11 // h+=X[i]
+ eor w16,w16,w24,ror#11
+ eor w2,w2,w13,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w24,ror#25 // Sigma1(e)
+ eor w3,w3,w20,ror#13
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w1,w1,w10,ror#19
+ eor w2,w2,w13,lsr#3 // sigma0(X[i+1])
+ add w27,w27,w16 // h+=Sigma1(e)
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w3,w20,ror#22 // Sigma0(a)
+ eor w1,w1,w10,lsr#10 // sigma1(X[i+14])
+ add w12,w12,w5
+ add w23,w23,w27 // d+=h
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w12,w12,w2
+ add w27,w27,w17 // h+=Sigma0(a)
+ add w12,w12,w1
+ ldr w1,[sp,#8]
+ str w4,[sp,#4]
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ ror w3,w14,#7
+ and w17,w24,w23
+ ror w2,w11,#17
+ bic w28,w25,w23
+ ror w4,w27,#2
+ add w26,w26,w12 // h+=X[i]
+ eor w16,w16,w23,ror#11
+ eor w3,w3,w14,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w23,ror#25 // Sigma1(e)
+ eor w4,w4,w27,ror#13
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w2,w2,w11,ror#19
+ eor w3,w3,w14,lsr#3 // sigma0(X[i+1])
+ add w26,w26,w16 // h+=Sigma1(e)
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w4,w27,ror#22 // Sigma0(a)
+ eor w2,w2,w11,lsr#10 // sigma1(X[i+14])
+ add w13,w13,w6
+ add w22,w22,w26 // d+=h
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w13,w13,w3
+ add w26,w26,w17 // h+=Sigma0(a)
+ add w13,w13,w2
+ ldr w2,[sp,#12]
+ str w5,[sp,#8]
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ ror w4,w15,#7
+ and w17,w23,w22
+ ror w3,w12,#17
+ bic w19,w24,w22
+ ror w5,w26,#2
+ add w25,w25,w13 // h+=X[i]
+ eor w16,w16,w22,ror#11
+ eor w4,w4,w15,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w22,ror#25 // Sigma1(e)
+ eor w5,w5,w26,ror#13
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w3,w3,w12,ror#19
+ eor w4,w4,w15,lsr#3 // sigma0(X[i+1])
+ add w25,w25,w16 // h+=Sigma1(e)
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w5,w26,ror#22 // Sigma0(a)
+ eor w3,w3,w12,lsr#10 // sigma1(X[i+14])
+ add w14,w14,w7
+ add w21,w21,w25 // d+=h
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w14,w14,w4
+ add w25,w25,w17 // h+=Sigma0(a)
+ add w14,w14,w3
+ ldr w3,[sp,#0]
+ str w6,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ ror w5,w0,#7
+ and w17,w22,w21
+ ror w4,w13,#17
+ bic w28,w23,w21
+ ror w6,w25,#2
+ add w24,w24,w14 // h+=X[i]
+ eor w16,w16,w21,ror#11
+ eor w5,w5,w0,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w21,ror#25 // Sigma1(e)
+ eor w6,w6,w25,ror#13
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w4,w4,w13,ror#19
+ eor w5,w5,w0,lsr#3 // sigma0(X[i+1])
+ add w24,w24,w16 // h+=Sigma1(e)
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w6,w25,ror#22 // Sigma0(a)
+ eor w4,w4,w13,lsr#10 // sigma1(X[i+14])
+ add w15,w15,w8
+ add w20,w20,w24 // d+=h
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w15,w15,w5
+ add w24,w24,w17 // h+=Sigma0(a)
+ add w15,w15,w4
+ ldr w4,[sp,#4]
+ str w7,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ ror w6,w1,#7
+ and w17,w21,w20
+ ror w5,w14,#17
+ bic w19,w22,w20
+ ror w7,w24,#2
+ add w23,w23,w15 // h+=X[i]
+ eor w16,w16,w20,ror#11
+ eor w6,w6,w1,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w20,ror#25 // Sigma1(e)
+ eor w7,w7,w24,ror#13
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w5,w5,w14,ror#19
+ eor w6,w6,w1,lsr#3 // sigma0(X[i+1])
+ add w23,w23,w16 // h+=Sigma1(e)
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w7,w24,ror#22 // Sigma0(a)
+ eor w5,w5,w14,lsr#10 // sigma1(X[i+14])
+ add w0,w0,w9
+ add w27,w27,w23 // d+=h
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w0,w0,w6
+ add w23,w23,w17 // h+=Sigma0(a)
+ add w0,w0,w5
+ ldr w5,[sp,#8]
+ str w8,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ ror w7,w2,#7
+ and w17,w20,w27
+ ror w6,w15,#17
+ bic w28,w21,w27
+ ror w8,w23,#2
+ add w22,w22,w0 // h+=X[i]
+ eor w16,w16,w27,ror#11
+ eor w7,w7,w2,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w27,ror#25 // Sigma1(e)
+ eor w8,w8,w23,ror#13
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w6,w6,w15,ror#19
+ eor w7,w7,w2,lsr#3 // sigma0(X[i+1])
+ add w22,w22,w16 // h+=Sigma1(e)
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w8,w23,ror#22 // Sigma0(a)
+ eor w6,w6,w15,lsr#10 // sigma1(X[i+14])
+ add w1,w1,w10
+ add w26,w26,w22 // d+=h
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w1,w1,w7
+ add w22,w22,w17 // h+=Sigma0(a)
+ add w1,w1,w6
+ ldr w6,[sp,#12]
+ str w9,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ ror w8,w3,#7
+ and w17,w27,w26
+ ror w7,w0,#17
+ bic w19,w20,w26
+ ror w9,w22,#2
+ add w21,w21,w1 // h+=X[i]
+ eor w16,w16,w26,ror#11
+ eor w8,w8,w3,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w26,ror#25 // Sigma1(e)
+ eor w9,w9,w22,ror#13
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w7,w7,w0,ror#19
+ eor w8,w8,w3,lsr#3 // sigma0(X[i+1])
+ add w21,w21,w16 // h+=Sigma1(e)
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w9,w22,ror#22 // Sigma0(a)
+ eor w7,w7,w0,lsr#10 // sigma1(X[i+14])
+ add w2,w2,w11
+ add w25,w25,w21 // d+=h
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w2,w2,w8
+ add w21,w21,w17 // h+=Sigma0(a)
+ add w2,w2,w7
+ ldr w7,[sp,#0]
+ str w10,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w9,w4,#7
+ and w17,w26,w25
+ ror w8,w1,#17
+ bic w28,w27,w25
+ ror w10,w21,#2
+ add w20,w20,w2 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w9,w9,w4,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w10,w10,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w8,w8,w1,ror#19
+ eor w9,w9,w4,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w10,w21,ror#22 // Sigma0(a)
+ eor w8,w8,w1,lsr#10 // sigma1(X[i+14])
+ add w3,w3,w12
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w3,w3,w9
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w3,w3,w8
+ cbnz w19,.Loop_16_xx
+
+ ldp x0,x2,[x29,#96]
+ ldr x1,[x29,#112]
+ sub x30,x30,#260 // rewind
+
+ ldp w3,w4,[x0]
+ ldp w5,w6,[x0,#2*4]
+ add x1,x1,#14*4 // advance input pointer
+ ldp w7,w8,[x0,#4*4]
+ add w20,w20,w3
+ ldp w9,w10,[x0,#6*4]
+ add w21,w21,w4
+ add w22,w22,w5
+ add w23,w23,w6
+ stp w20,w21,[x0]
+ add w24,w24,w7
+ add w25,w25,w8
+ stp w22,w23,[x0,#2*4]
+ add w26,w26,w9
+ add w27,w27,w10
+ cmp x1,x2
+ stp w24,w25,[x0,#4*4]
+ stp w26,w27,[x0,#6*4]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*4
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size zfs_sha256_block_armv7,.-zfs_sha256_block_armv7
+
+.globl zfs_sha256_block_armv8
+.type zfs_sha256_block_armv8,%function
+.align 6
+zfs_sha256_block_armv8:
+ hint #34 // bti c
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ ld1 {v0.4s,v1.4s},[x0]
+ adr x3,.LK256
+
+.Loop_hw:
+ ld1 {v4.16b-v7.16b},[x1],#64
+ sub x2,x2,#1
+ ld1 {v16.4s},[x3],#16
+ rev32 v4.16b,v4.16b
+ rev32 v5.16b,v5.16b
+ rev32 v6.16b,v6.16b
+ rev32 v7.16b,v7.16b
+ orr v18.16b,v0.16b,v0.16b // offload
+ orr v19.16b,v1.16b,v1.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+
+ ld1 {v17.4s},[x3]
+ add v16.4s,v16.4s,v6.4s
+ sub x3,x3,#64*4-16 // rewind
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+
+ add v17.4s,v17.4s,v7.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+
+ add v0.4s,v0.4s,v18.4s
+ add v1.4s,v1.4s,v19.4s
+
+ cbnz x2,.Loop_hw
+
+ st1 {v0.4s,v1.4s},[x0]
+
+ ldr x29,[sp],#16
+ ret
+.size zfs_sha256_block_armv8,.-zfs_sha256_block_armv8
+
+.globl zfs_sha256_block_neon
+.type zfs_sha256_block_neon,%function
+.align 4
+zfs_sha256_block_neon:
+ hint #34 // bti c
+.Lneon_entry:
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ sub sp,sp,#16*4
+
+ adr x16,.LK256
+ add x2,x1,x2,lsl#6 // len to point at the end of inp
+
+ ld1 {v0.16b},[x1], #16
+ ld1 {v1.16b},[x1], #16
+ ld1 {v2.16b},[x1], #16
+ ld1 {v3.16b},[x1], #16
+ ld1 {v4.4s},[x16], #16
+ ld1 {v5.4s},[x16], #16
+ ld1 {v6.4s},[x16], #16
+ ld1 {v7.4s},[x16], #16
+ rev32 v0.16b,v0.16b // yes, even on
+ rev32 v1.16b,v1.16b // big-endian
+ rev32 v2.16b,v2.16b
+ rev32 v3.16b,v3.16b
+ mov x17,sp
+ add v4.4s,v4.4s,v0.4s
+ add v5.4s,v5.4s,v1.4s
+ add v6.4s,v6.4s,v2.4s
+ st1 {v4.4s-v5.4s},[x17], #32
+ add v7.4s,v7.4s,v3.4s
+ st1 {v6.4s-v7.4s},[x17]
+ sub x17,x17,#32
+
+ ldp w3,w4,[x0]
+ ldp w5,w6,[x0,#8]
+ ldp w7,w8,[x0,#16]
+ ldp w9,w10,[x0,#24]
+ ldr w12,[sp,#0]
+ mov w13,wzr
+ eor w14,w4,w5
+ mov w15,wzr
+ b .L_00_48
+
+.align 4
+.L_00_48:
+ ext v4.16b,v0.16b,v1.16b,#4
+ add w10,w10,w12
+ add w3,w3,w15
+ and w12,w8,w7
+ bic w15,w9,w7
+ ext v7.16b,v2.16b,v3.16b,#4
+ eor w11,w7,w7,ror#5
+ add w3,w3,w13
+ mov d19,v3.d[1]
+ orr w12,w12,w15
+ eor w11,w11,w7,ror#19
+ ushr v6.4s,v4.4s,#7
+ eor w15,w3,w3,ror#11
+ ushr v5.4s,v4.4s,#3
+ add w10,w10,w12
+ add v0.4s,v0.4s,v7.4s
+ ror w11,w11,#6
+ sli v6.4s,v4.4s,#25
+ eor w13,w3,w4
+ eor w15,w15,w3,ror#20
+ ushr v7.4s,v4.4s,#18
+ add w10,w10,w11
+ ldr w12,[sp,#4]
+ and w14,w14,w13
+ eor v5.16b,v5.16b,v6.16b
+ ror w15,w15,#2
+ add w6,w6,w10
+ sli v7.4s,v4.4s,#14
+ eor w14,w14,w4
+ ushr v16.4s,v19.4s,#17
+ add w9,w9,w12
+ add w10,w10,w15
+ and w12,w7,w6
+ eor v5.16b,v5.16b,v7.16b
+ bic w15,w8,w6
+ eor w11,w6,w6,ror#5
+ sli v16.4s,v19.4s,#15
+ add w10,w10,w14
+ orr w12,w12,w15
+ ushr v17.4s,v19.4s,#10
+ eor w11,w11,w6,ror#19
+ eor w15,w10,w10,ror#11
+ ushr v7.4s,v19.4s,#19
+ add w9,w9,w12
+ ror w11,w11,#6
+ add v0.4s,v0.4s,v5.4s
+ eor w14,w10,w3
+ eor w15,w15,w10,ror#20
+ sli v7.4s,v19.4s,#13
+ add w9,w9,w11
+ ldr w12,[sp,#8]
+ and w13,w13,w14
+ eor v17.16b,v17.16b,v16.16b
+ ror w15,w15,#2
+ add w5,w5,w9
+ eor w13,w13,w3
+ eor v17.16b,v17.16b,v7.16b
+ add w8,w8,w12
+ add w9,w9,w15
+ and w12,w6,w5
+ add v0.4s,v0.4s,v17.4s
+ bic w15,w7,w5
+ eor w11,w5,w5,ror#5
+ add w9,w9,w13
+ ushr v18.4s,v0.4s,#17
+ orr w12,w12,w15
+ ushr v19.4s,v0.4s,#10
+ eor w11,w11,w5,ror#19
+ eor w15,w9,w9,ror#11
+ sli v18.4s,v0.4s,#15
+ add w8,w8,w12
+ ushr v17.4s,v0.4s,#19
+ ror w11,w11,#6
+ eor w13,w9,w10
+ eor v19.16b,v19.16b,v18.16b
+ eor w15,w15,w9,ror#20
+ add w8,w8,w11
+ sli v17.4s,v0.4s,#13
+ ldr w12,[sp,#12]
+ and w14,w14,w13
+ ror w15,w15,#2
+ ld1 {v4.4s},[x16], #16
+ add w4,w4,w8
+ eor v19.16b,v19.16b,v17.16b
+ eor w14,w14,w10
+ eor v17.16b,v17.16b,v17.16b
+ add w7,w7,w12
+ add w8,w8,w15
+ and w12,w5,w4
+ mov v17.d[1],v19.d[0]
+ bic w15,w6,w4
+ eor w11,w4,w4,ror#5
+ add w8,w8,w14
+ add v0.4s,v0.4s,v17.4s
+ orr w12,w12,w15
+ eor w11,w11,w4,ror#19
+ eor w15,w8,w8,ror#11
+ add v4.4s,v4.4s,v0.4s
+ add w7,w7,w12
+ ror w11,w11,#6
+ eor w14,w8,w9
+ eor w15,w15,w8,ror#20
+ add w7,w7,w11
+ ldr w12,[sp,#16]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w3,w3,w7
+ eor w13,w13,w9
+ st1 {v4.4s},[x17], #16
+ ext v4.16b,v1.16b,v2.16b,#4
+ add w6,w6,w12
+ add w7,w7,w15
+ and w12,w4,w3
+ bic w15,w5,w3
+ ext v7.16b,v3.16b,v0.16b,#4
+ eor w11,w3,w3,ror#5
+ add w7,w7,w13
+ mov d19,v0.d[1]
+ orr w12,w12,w15
+ eor w11,w11,w3,ror#19
+ ushr v6.4s,v4.4s,#7
+ eor w15,w7,w7,ror#11
+ ushr v5.4s,v4.4s,#3
+ add w6,w6,w12
+ add v1.4s,v1.4s,v7.4s
+ ror w11,w11,#6
+ sli v6.4s,v4.4s,#25
+ eor w13,w7,w8
+ eor w15,w15,w7,ror#20
+ ushr v7.4s,v4.4s,#18
+ add w6,w6,w11
+ ldr w12,[sp,#20]
+ and w14,w14,w13
+ eor v5.16b,v5.16b,v6.16b
+ ror w15,w15,#2
+ add w10,w10,w6
+ sli v7.4s,v4.4s,#14
+ eor w14,w14,w8
+ ushr v16.4s,v19.4s,#17
+ add w5,w5,w12
+ add w6,w6,w15
+ and w12,w3,w10
+ eor v5.16b,v5.16b,v7.16b
+ bic w15,w4,w10
+ eor w11,w10,w10,ror#5
+ sli v16.4s,v19.4s,#15
+ add w6,w6,w14
+ orr w12,w12,w15
+ ushr v17.4s,v19.4s,#10
+ eor w11,w11,w10,ror#19
+ eor w15,w6,w6,ror#11
+ ushr v7.4s,v19.4s,#19
+ add w5,w5,w12
+ ror w11,w11,#6
+ add v1.4s,v1.4s,v5.4s
+ eor w14,w6,w7
+ eor w15,w15,w6,ror#20
+ sli v7.4s,v19.4s,#13
+ add w5,w5,w11
+ ldr w12,[sp,#24]
+ and w13,w13,w14
+ eor v17.16b,v17.16b,v16.16b
+ ror w15,w15,#2
+ add w9,w9,w5
+ eor w13,w13,w7
+ eor v17.16b,v17.16b,v7.16b
+ add w4,w4,w12
+ add w5,w5,w15
+ and w12,w10,w9
+ add v1.4s,v1.4s,v17.4s
+ bic w15,w3,w9
+ eor w11,w9,w9,ror#5
+ add w5,w5,w13
+ ushr v18.4s,v1.4s,#17
+ orr w12,w12,w15
+ ushr v19.4s,v1.4s,#10
+ eor w11,w11,w9,ror#19
+ eor w15,w5,w5,ror#11
+ sli v18.4s,v1.4s,#15
+ add w4,w4,w12
+ ushr v17.4s,v1.4s,#19
+ ror w11,w11,#6
+ eor w13,w5,w6
+ eor v19.16b,v19.16b,v18.16b
+ eor w15,w15,w5,ror#20
+ add w4,w4,w11
+ sli v17.4s,v1.4s,#13
+ ldr w12,[sp,#28]
+ and w14,w14,w13
+ ror w15,w15,#2
+ ld1 {v4.4s},[x16], #16
+ add w8,w8,w4
+ eor v19.16b,v19.16b,v17.16b
+ eor w14,w14,w6
+ eor v17.16b,v17.16b,v17.16b
+ add w3,w3,w12
+ add w4,w4,w15
+ and w12,w9,w8
+ mov v17.d[1],v19.d[0]
+ bic w15,w10,w8
+ eor w11,w8,w8,ror#5
+ add w4,w4,w14
+ add v1.4s,v1.4s,v17.4s
+ orr w12,w12,w15
+ eor w11,w11,w8,ror#19
+ eor w15,w4,w4,ror#11
+ add v4.4s,v4.4s,v1.4s
+ add w3,w3,w12
+ ror w11,w11,#6
+ eor w14,w4,w5
+ eor w15,w15,w4,ror#20
+ add w3,w3,w11
+ ldr w12,[sp,#32]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w7,w7,w3
+ eor w13,w13,w5
+ st1 {v4.4s},[x17], #16
+ ext v4.16b,v2.16b,v3.16b,#4
+ add w10,w10,w12
+ add w3,w3,w15
+ and w12,w8,w7
+ bic w15,w9,w7
+ ext v7.16b,v0.16b,v1.16b,#4
+ eor w11,w7,w7,ror#5
+ add w3,w3,w13
+ mov d19,v1.d[1]
+ orr w12,w12,w15
+ eor w11,w11,w7,ror#19
+ ushr v6.4s,v4.4s,#7
+ eor w15,w3,w3,ror#11
+ ushr v5.4s,v4.4s,#3
+ add w10,w10,w12
+ add v2.4s,v2.4s,v7.4s
+ ror w11,w11,#6
+ sli v6.4s,v4.4s,#25
+ eor w13,w3,w4
+ eor w15,w15,w3,ror#20
+ ushr v7.4s,v4.4s,#18
+ add w10,w10,w11
+ ldr w12,[sp,#36]
+ and w14,w14,w13
+ eor v5.16b,v5.16b,v6.16b
+ ror w15,w15,#2
+ add w6,w6,w10
+ sli v7.4s,v4.4s,#14
+ eor w14,w14,w4
+ ushr v16.4s,v19.4s,#17
+ add w9,w9,w12
+ add w10,w10,w15
+ and w12,w7,w6
+ eor v5.16b,v5.16b,v7.16b
+ bic w15,w8,w6
+ eor w11,w6,w6,ror#5
+ sli v16.4s,v19.4s,#15
+ add w10,w10,w14
+ orr w12,w12,w15
+ ushr v17.4s,v19.4s,#10
+ eor w11,w11,w6,ror#19
+ eor w15,w10,w10,ror#11
+ ushr v7.4s,v19.4s,#19
+ add w9,w9,w12
+ ror w11,w11,#6
+ add v2.4s,v2.4s,v5.4s
+ eor w14,w10,w3
+ eor w15,w15,w10,ror#20
+ sli v7.4s,v19.4s,#13
+ add w9,w9,w11
+ ldr w12,[sp,#40]
+ and w13,w13,w14
+ eor v17.16b,v17.16b,v16.16b
+ ror w15,w15,#2
+ add w5,w5,w9
+ eor w13,w13,w3
+ eor v17.16b,v17.16b,v7.16b
+ add w8,w8,w12
+ add w9,w9,w15
+ and w12,w6,w5
+ add v2.4s,v2.4s,v17.4s
+ bic w15,w7,w5
+ eor w11,w5,w5,ror#5
+ add w9,w9,w13
+ ushr v18.4s,v2.4s,#17
+ orr w12,w12,w15
+ ushr v19.4s,v2.4s,#10
+ eor w11,w11,w5,ror#19
+ eor w15,w9,w9,ror#11
+ sli v18.4s,v2.4s,#15
+ add w8,w8,w12
+ ushr v17.4s,v2.4s,#19
+ ror w11,w11,#6
+ eor w13,w9,w10
+ eor v19.16b,v19.16b,v18.16b
+ eor w15,w15,w9,ror#20
+ add w8,w8,w11
+ sli v17.4s,v2.4s,#13
+ ldr w12,[sp,#44]
+ and w14,w14,w13
+ ror w15,w15,#2
+ ld1 {v4.4s},[x16], #16
+ add w4,w4,w8
+ eor v19.16b,v19.16b,v17.16b
+ eor w14,w14,w10
+ eor v17.16b,v17.16b,v17.16b
+ add w7,w7,w12
+ add w8,w8,w15
+ and w12,w5,w4
+ mov v17.d[1],v19.d[0]
+ bic w15,w6,w4
+ eor w11,w4,w4,ror#5
+ add w8,w8,w14
+ add v2.4s,v2.4s,v17.4s
+ orr w12,w12,w15
+ eor w11,w11,w4,ror#19
+ eor w15,w8,w8,ror#11
+ add v4.4s,v4.4s,v2.4s
+ add w7,w7,w12
+ ror w11,w11,#6
+ eor w14,w8,w9
+ eor w15,w15,w8,ror#20
+ add w7,w7,w11
+ ldr w12,[sp,#48]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w3,w3,w7
+ eor w13,w13,w9
+ st1 {v4.4s},[x17], #16
+ ext v4.16b,v3.16b,v0.16b,#4
+ add w6,w6,w12
+ add w7,w7,w15
+ and w12,w4,w3
+ bic w15,w5,w3
+ ext v7.16b,v1.16b,v2.16b,#4
+ eor w11,w3,w3,ror#5
+ add w7,w7,w13
+ mov d19,v2.d[1]
+ orr w12,w12,w15
+ eor w11,w11,w3,ror#19
+ ushr v6.4s,v4.4s,#7
+ eor w15,w7,w7,ror#11
+ ushr v5.4s,v4.4s,#3
+ add w6,w6,w12
+ add v3.4s,v3.4s,v7.4s
+ ror w11,w11,#6
+ sli v6.4s,v4.4s,#25
+ eor w13,w7,w8
+ eor w15,w15,w7,ror#20
+ ushr v7.4s,v4.4s,#18
+ add w6,w6,w11
+ ldr w12,[sp,#52]
+ and w14,w14,w13
+ eor v5.16b,v5.16b,v6.16b
+ ror w15,w15,#2
+ add w10,w10,w6
+ sli v7.4s,v4.4s,#14
+ eor w14,w14,w8
+ ushr v16.4s,v19.4s,#17
+ add w5,w5,w12
+ add w6,w6,w15
+ and w12,w3,w10
+ eor v5.16b,v5.16b,v7.16b
+ bic w15,w4,w10
+ eor w11,w10,w10,ror#5
+ sli v16.4s,v19.4s,#15
+ add w6,w6,w14
+ orr w12,w12,w15
+ ushr v17.4s,v19.4s,#10
+ eor w11,w11,w10,ror#19
+ eor w15,w6,w6,ror#11
+ ushr v7.4s,v19.4s,#19
+ add w5,w5,w12
+ ror w11,w11,#6
+ add v3.4s,v3.4s,v5.4s
+ eor w14,w6,w7
+ eor w15,w15,w6,ror#20
+ sli v7.4s,v19.4s,#13
+ add w5,w5,w11
+ ldr w12,[sp,#56]
+ and w13,w13,w14
+ eor v17.16b,v17.16b,v16.16b
+ ror w15,w15,#2
+ add w9,w9,w5
+ eor w13,w13,w7
+ eor v17.16b,v17.16b,v7.16b
+ add w4,w4,w12
+ add w5,w5,w15
+ and w12,w10,w9
+ add v3.4s,v3.4s,v17.4s
+ bic w15,w3,w9
+ eor w11,w9,w9,ror#5
+ add w5,w5,w13
+ ushr v18.4s,v3.4s,#17
+ orr w12,w12,w15
+ ushr v19.4s,v3.4s,#10
+ eor w11,w11,w9,ror#19
+ eor w15,w5,w5,ror#11
+ sli v18.4s,v3.4s,#15
+ add w4,w4,w12
+ ushr v17.4s,v3.4s,#19
+ ror w11,w11,#6
+ eor w13,w5,w6
+ eor v19.16b,v19.16b,v18.16b
+ eor w15,w15,w5,ror#20
+ add w4,w4,w11
+ sli v17.4s,v3.4s,#13
+ ldr w12,[sp,#60]
+ and w14,w14,w13
+ ror w15,w15,#2
+ ld1 {v4.4s},[x16], #16
+ add w8,w8,w4
+ eor v19.16b,v19.16b,v17.16b
+ eor w14,w14,w6
+ eor v17.16b,v17.16b,v17.16b
+ add w3,w3,w12
+ add w4,w4,w15
+ and w12,w9,w8
+ mov v17.d[1],v19.d[0]
+ bic w15,w10,w8
+ eor w11,w8,w8,ror#5
+ add w4,w4,w14
+ add v3.4s,v3.4s,v17.4s
+ orr w12,w12,w15
+ eor w11,w11,w8,ror#19
+ eor w15,w4,w4,ror#11
+ add v4.4s,v4.4s,v3.4s
+ add w3,w3,w12
+ ror w11,w11,#6
+ eor w14,w4,w5
+ eor w15,w15,w4,ror#20
+ add w3,w3,w11
+ ldr w12,[x16]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w7,w7,w3
+ eor w13,w13,w5
+ st1 {v4.4s},[x17], #16
+ cmp w12,#0 // check for K256 terminator
+ ldr w12,[sp,#0]
+ sub x17,x17,#64
+ bne .L_00_48
+
+ sub x16,x16,#256 // rewind x16
+ cmp x1,x2
+ mov x17, #64
+ csel x17, x17, xzr, eq
+ sub x1,x1,x17 // avoid SEGV
+ mov x17,sp
+ add w10,w10,w12
+ add w3,w3,w15
+ and w12,w8,w7
+ ld1 {v0.16b},[x1],#16
+ bic w15,w9,w7
+ eor w11,w7,w7,ror#5
+ ld1 {v4.4s},[x16],#16
+ add w3,w3,w13
+ orr w12,w12,w15
+ eor w11,w11,w7,ror#19
+ eor w15,w3,w3,ror#11
+ rev32 v0.16b,v0.16b
+ add w10,w10,w12
+ ror w11,w11,#6
+ eor w13,w3,w4
+ eor w15,w15,w3,ror#20
+ add v4.4s,v4.4s,v0.4s
+ add w10,w10,w11
+ ldr w12,[sp,#4]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w6,w6,w10
+ eor w14,w14,w4
+ add w9,w9,w12
+ add w10,w10,w15
+ and w12,w7,w6
+ bic w15,w8,w6
+ eor w11,w6,w6,ror#5
+ add w10,w10,w14
+ orr w12,w12,w15
+ eor w11,w11,w6,ror#19
+ eor w15,w10,w10,ror#11
+ add w9,w9,w12
+ ror w11,w11,#6
+ eor w14,w10,w3
+ eor w15,w15,w10,ror#20
+ add w9,w9,w11
+ ldr w12,[sp,#8]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w5,w5,w9
+ eor w13,w13,w3
+ add w8,w8,w12
+ add w9,w9,w15
+ and w12,w6,w5
+ bic w15,w7,w5
+ eor w11,w5,w5,ror#5
+ add w9,w9,w13
+ orr w12,w12,w15
+ eor w11,w11,w5,ror#19
+ eor w15,w9,w9,ror#11
+ add w8,w8,w12
+ ror w11,w11,#6
+ eor w13,w9,w10
+ eor w15,w15,w9,ror#20
+ add w8,w8,w11
+ ldr w12,[sp,#12]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w4,w4,w8
+ eor w14,w14,w10
+ add w7,w7,w12
+ add w8,w8,w15
+ and w12,w5,w4
+ bic w15,w6,w4
+ eor w11,w4,w4,ror#5
+ add w8,w8,w14
+ orr w12,w12,w15
+ eor w11,w11,w4,ror#19
+ eor w15,w8,w8,ror#11
+ add w7,w7,w12
+ ror w11,w11,#6
+ eor w14,w8,w9
+ eor w15,w15,w8,ror#20
+ add w7,w7,w11
+ ldr w12,[sp,#16]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w3,w3,w7
+ eor w13,w13,w9
+ st1 {v4.4s},[x17], #16
+ add w6,w6,w12
+ add w7,w7,w15
+ and w12,w4,w3
+ ld1 {v1.16b},[x1],#16
+ bic w15,w5,w3
+ eor w11,w3,w3,ror#5
+ ld1 {v4.4s},[x16],#16
+ add w7,w7,w13
+ orr w12,w12,w15
+ eor w11,w11,w3,ror#19
+ eor w15,w7,w7,ror#11
+ rev32 v1.16b,v1.16b
+ add w6,w6,w12
+ ror w11,w11,#6
+ eor w13,w7,w8
+ eor w15,w15,w7,ror#20
+ add v4.4s,v4.4s,v1.4s
+ add w6,w6,w11
+ ldr w12,[sp,#20]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w10,w10,w6
+ eor w14,w14,w8
+ add w5,w5,w12
+ add w6,w6,w15
+ and w12,w3,w10
+ bic w15,w4,w10
+ eor w11,w10,w10,ror#5
+ add w6,w6,w14
+ orr w12,w12,w15
+ eor w11,w11,w10,ror#19
+ eor w15,w6,w6,ror#11
+ add w5,w5,w12
+ ror w11,w11,#6
+ eor w14,w6,w7
+ eor w15,w15,w6,ror#20
+ add w5,w5,w11
+ ldr w12,[sp,#24]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w9,w9,w5
+ eor w13,w13,w7
+ add w4,w4,w12
+ add w5,w5,w15
+ and w12,w10,w9
+ bic w15,w3,w9
+ eor w11,w9,w9,ror#5
+ add w5,w5,w13
+ orr w12,w12,w15
+ eor w11,w11,w9,ror#19
+ eor w15,w5,w5,ror#11
+ add w4,w4,w12
+ ror w11,w11,#6
+ eor w13,w5,w6
+ eor w15,w15,w5,ror#20
+ add w4,w4,w11
+ ldr w12,[sp,#28]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w8,w8,w4
+ eor w14,w14,w6
+ add w3,w3,w12
+ add w4,w4,w15
+ and w12,w9,w8
+ bic w15,w10,w8
+ eor w11,w8,w8,ror#5
+ add w4,w4,w14
+ orr w12,w12,w15
+ eor w11,w11,w8,ror#19
+ eor w15,w4,w4,ror#11
+ add w3,w3,w12
+ ror w11,w11,#6
+ eor w14,w4,w5
+ eor w15,w15,w4,ror#20
+ add w3,w3,w11
+ ldr w12,[sp,#32]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w7,w7,w3
+ eor w13,w13,w5
+ st1 {v4.4s},[x17], #16
+ add w10,w10,w12
+ add w3,w3,w15
+ and w12,w8,w7
+ ld1 {v2.16b},[x1],#16
+ bic w15,w9,w7
+ eor w11,w7,w7,ror#5
+ ld1 {v4.4s},[x16],#16
+ add w3,w3,w13
+ orr w12,w12,w15
+ eor w11,w11,w7,ror#19
+ eor w15,w3,w3,ror#11
+ rev32 v2.16b,v2.16b
+ add w10,w10,w12
+ ror w11,w11,#6
+ eor w13,w3,w4
+ eor w15,w15,w3,ror#20
+ add v4.4s,v4.4s,v2.4s
+ add w10,w10,w11
+ ldr w12,[sp,#36]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w6,w6,w10
+ eor w14,w14,w4
+ add w9,w9,w12
+ add w10,w10,w15
+ and w12,w7,w6
+ bic w15,w8,w6
+ eor w11,w6,w6,ror#5
+ add w10,w10,w14
+ orr w12,w12,w15
+ eor w11,w11,w6,ror#19
+ eor w15,w10,w10,ror#11
+ add w9,w9,w12
+ ror w11,w11,#6
+ eor w14,w10,w3
+ eor w15,w15,w10,ror#20
+ add w9,w9,w11
+ ldr w12,[sp,#40]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w5,w5,w9
+ eor w13,w13,w3
+ add w8,w8,w12
+ add w9,w9,w15
+ and w12,w6,w5
+ bic w15,w7,w5
+ eor w11,w5,w5,ror#5
+ add w9,w9,w13
+ orr w12,w12,w15
+ eor w11,w11,w5,ror#19
+ eor w15,w9,w9,ror#11
+ add w8,w8,w12
+ ror w11,w11,#6
+ eor w13,w9,w10
+ eor w15,w15,w9,ror#20
+ add w8,w8,w11
+ ldr w12,[sp,#44]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w4,w4,w8
+ eor w14,w14,w10
+ add w7,w7,w12
+ add w8,w8,w15
+ and w12,w5,w4
+ bic w15,w6,w4
+ eor w11,w4,w4,ror#5
+ add w8,w8,w14
+ orr w12,w12,w15
+ eor w11,w11,w4,ror#19
+ eor w15,w8,w8,ror#11
+ add w7,w7,w12
+ ror w11,w11,#6
+ eor w14,w8,w9
+ eor w15,w15,w8,ror#20
+ add w7,w7,w11
+ ldr w12,[sp,#48]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w3,w3,w7
+ eor w13,w13,w9
+ st1 {v4.4s},[x17], #16
+ add w6,w6,w12
+ add w7,w7,w15
+ and w12,w4,w3
+ ld1 {v3.16b},[x1],#16
+ bic w15,w5,w3
+ eor w11,w3,w3,ror#5
+ ld1 {v4.4s},[x16],#16
+ add w7,w7,w13
+ orr w12,w12,w15
+ eor w11,w11,w3,ror#19
+ eor w15,w7,w7,ror#11
+ rev32 v3.16b,v3.16b
+ add w6,w6,w12
+ ror w11,w11,#6
+ eor w13,w7,w8
+ eor w15,w15,w7,ror#20
+ add v4.4s,v4.4s,v3.4s
+ add w6,w6,w11
+ ldr w12,[sp,#52]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w10,w10,w6
+ eor w14,w14,w8
+ add w5,w5,w12
+ add w6,w6,w15
+ and w12,w3,w10
+ bic w15,w4,w10
+ eor w11,w10,w10,ror#5
+ add w6,w6,w14
+ orr w12,w12,w15
+ eor w11,w11,w10,ror#19
+ eor w15,w6,w6,ror#11
+ add w5,w5,w12
+ ror w11,w11,#6
+ eor w14,w6,w7
+ eor w15,w15,w6,ror#20
+ add w5,w5,w11
+ ldr w12,[sp,#56]
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w9,w9,w5
+ eor w13,w13,w7
+ add w4,w4,w12
+ add w5,w5,w15
+ and w12,w10,w9
+ bic w15,w3,w9
+ eor w11,w9,w9,ror#5
+ add w5,w5,w13
+ orr w12,w12,w15
+ eor w11,w11,w9,ror#19
+ eor w15,w5,w5,ror#11
+ add w4,w4,w12
+ ror w11,w11,#6
+ eor w13,w5,w6
+ eor w15,w15,w5,ror#20
+ add w4,w4,w11
+ ldr w12,[sp,#60]
+ and w14,w14,w13
+ ror w15,w15,#2
+ add w8,w8,w4
+ eor w14,w14,w6
+ add w3,w3,w12
+ add w4,w4,w15
+ and w12,w9,w8
+ bic w15,w10,w8
+ eor w11,w8,w8,ror#5
+ add w4,w4,w14
+ orr w12,w12,w15
+ eor w11,w11,w8,ror#19
+ eor w15,w4,w4,ror#11
+ add w3,w3,w12
+ ror w11,w11,#6
+ eor w14,w4,w5
+ eor w15,w15,w4,ror#20
+ add w3,w3,w11
+ and w13,w13,w14
+ ror w15,w15,#2
+ add w7,w7,w3
+ eor w13,w13,w5
+ st1 {v4.4s},[x17], #16
+ add w3,w3,w15 // h+=Sigma0(a) from the past
+ ldp w11,w12,[x0,#0]
+ add w3,w3,w13 // h+=Maj(a,b,c) from the past
+ ldp w13,w14,[x0,#8]
+ add w3,w3,w11 // accumulate
+ add w4,w4,w12
+ ldp w11,w12,[x0,#16]
+ add w5,w5,w13
+ add w6,w6,w14
+ ldp w13,w14,[x0,#24]
+ add w7,w7,w11
+ add w8,w8,w12
+ ldr w12,[sp,#0]
+ stp w3,w4,[x0,#0]
+ add w9,w9,w13
+ mov w13,wzr
+ stp w5,w6,[x0,#8]
+ add w10,w10,w14
+ stp w7,w8,[x0,#16]
+ eor w14,w4,w5
+ stp w9,w10,[x0,#24]
+ mov w15,wzr
+ mov x17,sp
+ b.ne .L_00_48
+
+ ldr x29,[x29]
+ add sp,sp,#16*4+16
+ ret
+.size zfs_sha256_block_neon,.-zfs_sha256_block_neon
+
+#endif
diff --git a/module/icp/asm-aarch64/sha2/sha512-armv8.S b/module/icp/asm-aarch64/sha2/sha512-armv8.S
new file mode 100644
index 000000000000..f6c8f7742912
--- /dev/null
+++ b/module/icp/asm-aarch64/sha2/sha512-armv8.S
@@ -0,0 +1,1570 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__aarch64__)
+
+ .section .note.gnu.property,"a",@note
+ .p2align 3
+ .word 4
+ .word 16
+ .word 5
+ .asciz "GNU"
+ .word 3221225472
+ .word 4
+ .word 3
+ .word 0
+.text
+
+.align 6
+.type .LK512,%object
+.LK512:
+ .quad 0x428a2f98d728ae22,0x7137449123ef65cd
+ .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+ .quad 0x3956c25bf348b538,0x59f111f1b605d019
+ .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+ .quad 0xd807aa98a3030242,0x12835b0145706fbe
+ .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+ .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+ .quad 0x9bdc06a725c71235,0xc19bf174cf692694
+ .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+ .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+ .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+ .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+ .quad 0x983e5152ee66dfab,0xa831c66d2db43210
+ .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+ .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+ .quad 0x06ca6351e003826f,0x142929670a0e6e70
+ .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+ .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+ .quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+ .quad 0x81c2c92e47edaee6,0x92722c851482353b
+ .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+ .quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+ .quad 0xd192e819d6ef5218,0xd69906245565a910
+ .quad 0xf40e35855771202a,0x106aa07032bbd1b8
+ .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+ .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+ .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+ .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+ .quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+ .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+ .quad 0x90befffa23631e28,0xa4506cebde82bde9
+ .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+ .quad 0xca273eceea26619c,0xd186b8c721c0c207
+ .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+ .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+ .quad 0x113f9804bef90dae,0x1b710b35131c471b
+ .quad 0x28db77f523047d84,0x32caab7b40c72493
+ .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+ .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+ .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+ .quad 0 // terminator
+.size .LK512,.-.LK512
+
+.globl zfs_sha512_block_armv7
+.type zfs_sha512_block_armv7,%function
+.align 6
+zfs_sha512_block_armv7:
+ hint #34 // bti c
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*8
+
+ ldp x20,x21,[x0] // load context
+ ldp x22,x23,[x0,#2*8]
+ ldp x24,x25,[x0,#4*8]
+ add x2,x1,x2,lsl#7 // end of input
+ ldp x26,x27,[x0,#6*8]
+ adr x30,.LK512
+ stp x0,x2,[x29,#96]
+
+.Loop:
+ ldp x3,x4,[x1],#2*8
+ ldr x19,[x30],#8 // *K++
+ eor x28,x21,x22 // magic seed
+ str x1,[x29,#112]
+#ifndef __AARCH64EB__
+ rev x3,x3 // 0
+#endif
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ eor x6,x24,x24,ror#23
+ and x17,x25,x24
+ bic x19,x26,x24
+ add x27,x27,x3 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x6,ror#18 // Sigma1(e)
+ ror x6,x20,#28
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ eor x17,x20,x20,ror#5
+ add x27,x27,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x23,x23,x27 // d+=h
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x6,x17,ror#34 // Sigma0(a)
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x27,x27,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x4,x4 // 1
+#endif
+ ldp x5,x6,[x1],#2*8
+ add x27,x27,x17 // h+=Sigma0(a)
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ eor x7,x23,x23,ror#23
+ and x17,x24,x23
+ bic x28,x25,x23
+ add x26,x26,x4 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x7,ror#18 // Sigma1(e)
+ ror x7,x27,#28
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ eor x17,x27,x27,ror#5
+ add x26,x26,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x22,x22,x26 // d+=h
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x7,x17,ror#34 // Sigma0(a)
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x26,x26,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x5,x5 // 2
+#endif
+ add x26,x26,x17 // h+=Sigma0(a)
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ eor x8,x22,x22,ror#23
+ and x17,x23,x22
+ bic x19,x24,x22
+ add x25,x25,x5 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x8,ror#18 // Sigma1(e)
+ ror x8,x26,#28
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ eor x17,x26,x26,ror#5
+ add x25,x25,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x21,x21,x25 // d+=h
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x8,x17,ror#34 // Sigma0(a)
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x25,x25,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x6,x6 // 3
+#endif
+ ldp x7,x8,[x1],#2*8
+ add x25,x25,x17 // h+=Sigma0(a)
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ eor x9,x21,x21,ror#23
+ and x17,x22,x21
+ bic x28,x23,x21
+ add x24,x24,x6 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x9,ror#18 // Sigma1(e)
+ ror x9,x25,#28
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ eor x17,x25,x25,ror#5
+ add x24,x24,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x20,x20,x24 // d+=h
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x9,x17,ror#34 // Sigma0(a)
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x24,x24,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x7,x7 // 4
+#endif
+ add x24,x24,x17 // h+=Sigma0(a)
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ eor x10,x20,x20,ror#23
+ and x17,x21,x20
+ bic x19,x22,x20
+ add x23,x23,x7 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x10,ror#18 // Sigma1(e)
+ ror x10,x24,#28
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ eor x17,x24,x24,ror#5
+ add x23,x23,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x27,x27,x23 // d+=h
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x10,x17,ror#34 // Sigma0(a)
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x23,x23,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x8,x8 // 5
+#endif
+ ldp x9,x10,[x1],#2*8
+ add x23,x23,x17 // h+=Sigma0(a)
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ eor x11,x27,x27,ror#23
+ and x17,x20,x27
+ bic x28,x21,x27
+ add x22,x22,x8 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x11,ror#18 // Sigma1(e)
+ ror x11,x23,#28
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ eor x17,x23,x23,ror#5
+ add x22,x22,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x26,x26,x22 // d+=h
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x11,x17,ror#34 // Sigma0(a)
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x22,x22,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x9,x9 // 6
+#endif
+ add x22,x22,x17 // h+=Sigma0(a)
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ eor x12,x26,x26,ror#23
+ and x17,x27,x26
+ bic x19,x20,x26
+ add x21,x21,x9 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x12,ror#18 // Sigma1(e)
+ ror x12,x22,#28
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ eor x17,x22,x22,ror#5
+ add x21,x21,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x25,x25,x21 // d+=h
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x12,x17,ror#34 // Sigma0(a)
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x21,x21,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x10,x10 // 7
+#endif
+ ldp x11,x12,[x1],#2*8
+ add x21,x21,x17 // h+=Sigma0(a)
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ eor x13,x25,x25,ror#23
+ and x17,x26,x25
+ bic x28,x27,x25
+ add x20,x20,x10 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x13,ror#18 // Sigma1(e)
+ ror x13,x21,#28
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ eor x17,x21,x21,ror#5
+ add x20,x20,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x24,x24,x20 // d+=h
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x13,x17,ror#34 // Sigma0(a)
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x20,x20,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x11,x11 // 8
+#endif
+ add x20,x20,x17 // h+=Sigma0(a)
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ eor x14,x24,x24,ror#23
+ and x17,x25,x24
+ bic x19,x26,x24
+ add x27,x27,x11 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x14,ror#18 // Sigma1(e)
+ ror x14,x20,#28
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ eor x17,x20,x20,ror#5
+ add x27,x27,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x23,x23,x27 // d+=h
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x14,x17,ror#34 // Sigma0(a)
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x27,x27,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x12,x12 // 9
+#endif
+ ldp x13,x14,[x1],#2*8
+ add x27,x27,x17 // h+=Sigma0(a)
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ eor x15,x23,x23,ror#23
+ and x17,x24,x23
+ bic x28,x25,x23
+ add x26,x26,x12 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x15,ror#18 // Sigma1(e)
+ ror x15,x27,#28
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ eor x17,x27,x27,ror#5
+ add x26,x26,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x22,x22,x26 // d+=h
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x15,x17,ror#34 // Sigma0(a)
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x26,x26,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x13,x13 // 10
+#endif
+ add x26,x26,x17 // h+=Sigma0(a)
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ eor x0,x22,x22,ror#23
+ and x17,x23,x22
+ bic x19,x24,x22
+ add x25,x25,x13 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x0,ror#18 // Sigma1(e)
+ ror x0,x26,#28
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ eor x17,x26,x26,ror#5
+ add x25,x25,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x21,x21,x25 // d+=h
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x0,x17,ror#34 // Sigma0(a)
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x25,x25,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x14,x14 // 11
+#endif
+ ldp x15,x0,[x1],#2*8
+ add x25,x25,x17 // h+=Sigma0(a)
+ str x6,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ eor x6,x21,x21,ror#23
+ and x17,x22,x21
+ bic x28,x23,x21
+ add x24,x24,x14 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x6,ror#18 // Sigma1(e)
+ ror x6,x25,#28
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ eor x17,x25,x25,ror#5
+ add x24,x24,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x20,x20,x24 // d+=h
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x6,x17,ror#34 // Sigma0(a)
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x24,x24,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x15,x15 // 12
+#endif
+ add x24,x24,x17 // h+=Sigma0(a)
+ str x7,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ eor x7,x20,x20,ror#23
+ and x17,x21,x20
+ bic x19,x22,x20
+ add x23,x23,x15 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x7,ror#18 // Sigma1(e)
+ ror x7,x24,#28
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ eor x17,x24,x24,ror#5
+ add x23,x23,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x27,x27,x23 // d+=h
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x7,x17,ror#34 // Sigma0(a)
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x23,x23,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x0,x0 // 13
+#endif
+ ldp x1,x2,[x1]
+ add x23,x23,x17 // h+=Sigma0(a)
+ str x8,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ eor x8,x27,x27,ror#23
+ and x17,x20,x27
+ bic x28,x21,x27
+ add x22,x22,x0 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x8,ror#18 // Sigma1(e)
+ ror x8,x23,#28
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ eor x17,x23,x23,ror#5
+ add x22,x22,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x26,x26,x22 // d+=h
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x8,x17,ror#34 // Sigma0(a)
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x22,x22,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x1,x1 // 14
+#endif
+ ldr x6,[sp,#24]
+ add x22,x22,x17 // h+=Sigma0(a)
+ str x9,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ eor x9,x26,x26,ror#23
+ and x17,x27,x26
+ bic x19,x20,x26
+ add x21,x21,x1 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x9,ror#18 // Sigma1(e)
+ ror x9,x22,#28
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ eor x17,x22,x22,ror#5
+ add x21,x21,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x25,x25,x21 // d+=h
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x9,x17,ror#34 // Sigma0(a)
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x21,x21,x17 // h+=Sigma0(a)
+#ifndef __AARCH64EB__
+ rev x2,x2 // 15
+#endif
+ ldr x7,[sp,#0]
+ add x21,x21,x17 // h+=Sigma0(a)
+ str x10,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x9,x4,#1
+ and x17,x26,x25
+ ror x8,x1,#19
+ bic x28,x27,x25
+ ror x10,x21,#28
+ add x20,x20,x2 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x9,x9,x4,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x10,x10,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x8,x8,x1,ror#61
+ eor x9,x9,x4,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x10,x21,ror#39 // Sigma0(a)
+ eor x8,x8,x1,lsr#6 // sigma1(X[i+14])
+ add x3,x3,x12
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x3,x3,x9
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x3,x3,x8
+.Loop_16_xx:
+ ldr x8,[sp,#8]
+ str x11,[sp,#0]
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ ror x10,x5,#1
+ and x17,x25,x24
+ ror x9,x2,#19
+ bic x19,x26,x24
+ ror x11,x20,#28
+ add x27,x27,x3 // h+=X[i]
+ eor x16,x16,x24,ror#18
+ eor x10,x10,x5,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x24,ror#41 // Sigma1(e)
+ eor x11,x11,x20,ror#34
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x9,x9,x2,ror#61
+ eor x10,x10,x5,lsr#7 // sigma0(X[i+1])
+ add x27,x27,x16 // h+=Sigma1(e)
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x11,x20,ror#39 // Sigma0(a)
+ eor x9,x9,x2,lsr#6 // sigma1(X[i+14])
+ add x4,x4,x13
+ add x23,x23,x27 // d+=h
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x4,x4,x10
+ add x27,x27,x17 // h+=Sigma0(a)
+ add x4,x4,x9
+ ldr x9,[sp,#16]
+ str x12,[sp,#8]
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ ror x11,x6,#1
+ and x17,x24,x23
+ ror x10,x3,#19
+ bic x28,x25,x23
+ ror x12,x27,#28
+ add x26,x26,x4 // h+=X[i]
+ eor x16,x16,x23,ror#18
+ eor x11,x11,x6,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x23,ror#41 // Sigma1(e)
+ eor x12,x12,x27,ror#34
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x10,x10,x3,ror#61
+ eor x11,x11,x6,lsr#7 // sigma0(X[i+1])
+ add x26,x26,x16 // h+=Sigma1(e)
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x12,x27,ror#39 // Sigma0(a)
+ eor x10,x10,x3,lsr#6 // sigma1(X[i+14])
+ add x5,x5,x14
+ add x22,x22,x26 // d+=h
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x5,x5,x11
+ add x26,x26,x17 // h+=Sigma0(a)
+ add x5,x5,x10
+ ldr x10,[sp,#24]
+ str x13,[sp,#16]
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ ror x12,x7,#1
+ and x17,x23,x22
+ ror x11,x4,#19
+ bic x19,x24,x22
+ ror x13,x26,#28
+ add x25,x25,x5 // h+=X[i]
+ eor x16,x16,x22,ror#18
+ eor x12,x12,x7,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x22,ror#41 // Sigma1(e)
+ eor x13,x13,x26,ror#34
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x11,x11,x4,ror#61
+ eor x12,x12,x7,lsr#7 // sigma0(X[i+1])
+ add x25,x25,x16 // h+=Sigma1(e)
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x13,x26,ror#39 // Sigma0(a)
+ eor x11,x11,x4,lsr#6 // sigma1(X[i+14])
+ add x6,x6,x15
+ add x21,x21,x25 // d+=h
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x6,x6,x12
+ add x25,x25,x17 // h+=Sigma0(a)
+ add x6,x6,x11
+ ldr x11,[sp,#0]
+ str x14,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ ror x13,x8,#1
+ and x17,x22,x21
+ ror x12,x5,#19
+ bic x28,x23,x21
+ ror x14,x25,#28
+ add x24,x24,x6 // h+=X[i]
+ eor x16,x16,x21,ror#18
+ eor x13,x13,x8,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x21,ror#41 // Sigma1(e)
+ eor x14,x14,x25,ror#34
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x12,x12,x5,ror#61
+ eor x13,x13,x8,lsr#7 // sigma0(X[i+1])
+ add x24,x24,x16 // h+=Sigma1(e)
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x14,x25,ror#39 // Sigma0(a)
+ eor x12,x12,x5,lsr#6 // sigma1(X[i+14])
+ add x7,x7,x0
+ add x20,x20,x24 // d+=h
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x7,x7,x13
+ add x24,x24,x17 // h+=Sigma0(a)
+ add x7,x7,x12
+ ldr x12,[sp,#8]
+ str x15,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ ror x14,x9,#1
+ and x17,x21,x20
+ ror x13,x6,#19
+ bic x19,x22,x20
+ ror x15,x24,#28
+ add x23,x23,x7 // h+=X[i]
+ eor x16,x16,x20,ror#18
+ eor x14,x14,x9,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x20,ror#41 // Sigma1(e)
+ eor x15,x15,x24,ror#34
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x13,x13,x6,ror#61
+ eor x14,x14,x9,lsr#7 // sigma0(X[i+1])
+ add x23,x23,x16 // h+=Sigma1(e)
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x15,x24,ror#39 // Sigma0(a)
+ eor x13,x13,x6,lsr#6 // sigma1(X[i+14])
+ add x8,x8,x1
+ add x27,x27,x23 // d+=h
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x8,x8,x14
+ add x23,x23,x17 // h+=Sigma0(a)
+ add x8,x8,x13
+ ldr x13,[sp,#16]
+ str x0,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ ror x15,x10,#1
+ and x17,x20,x27
+ ror x14,x7,#19
+ bic x28,x21,x27
+ ror x0,x23,#28
+ add x22,x22,x8 // h+=X[i]
+ eor x16,x16,x27,ror#18
+ eor x15,x15,x10,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x27,ror#41 // Sigma1(e)
+ eor x0,x0,x23,ror#34
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x14,x14,x7,ror#61
+ eor x15,x15,x10,lsr#7 // sigma0(X[i+1])
+ add x22,x22,x16 // h+=Sigma1(e)
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x0,x23,ror#39 // Sigma0(a)
+ eor x14,x14,x7,lsr#6 // sigma1(X[i+14])
+ add x9,x9,x2
+ add x26,x26,x22 // d+=h
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x9,x9,x15
+ add x22,x22,x17 // h+=Sigma0(a)
+ add x9,x9,x14
+ ldr x14,[sp,#24]
+ str x1,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ ror x0,x11,#1
+ and x17,x27,x26
+ ror x15,x8,#19
+ bic x19,x20,x26
+ ror x1,x22,#28
+ add x21,x21,x9 // h+=X[i]
+ eor x16,x16,x26,ror#18
+ eor x0,x0,x11,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x26,ror#41 // Sigma1(e)
+ eor x1,x1,x22,ror#34
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x15,x15,x8,ror#61
+ eor x0,x0,x11,lsr#7 // sigma0(X[i+1])
+ add x21,x21,x16 // h+=Sigma1(e)
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x1,x22,ror#39 // Sigma0(a)
+ eor x15,x15,x8,lsr#6 // sigma1(X[i+14])
+ add x10,x10,x3
+ add x25,x25,x21 // d+=h
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x10,x10,x0
+ add x21,x21,x17 // h+=Sigma0(a)
+ add x10,x10,x15
+ ldr x15,[sp,#0]
+ str x2,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x1,x12,#1
+ and x17,x26,x25
+ ror x0,x9,#19
+ bic x28,x27,x25
+ ror x2,x21,#28
+ add x20,x20,x10 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x1,x1,x12,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x2,x2,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x0,x0,x9,ror#61
+ eor x1,x1,x12,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x2,x21,ror#39 // Sigma0(a)
+ eor x0,x0,x9,lsr#6 // sigma1(X[i+14])
+ add x11,x11,x4
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x11,x11,x1
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x11,x11,x0
+ ldr x0,[sp,#8]
+ str x3,[sp,#0]
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ ror x2,x13,#1
+ and x17,x25,x24
+ ror x1,x10,#19
+ bic x19,x26,x24
+ ror x3,x20,#28
+ add x27,x27,x11 // h+=X[i]
+ eor x16,x16,x24,ror#18
+ eor x2,x2,x13,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x24,ror#41 // Sigma1(e)
+ eor x3,x3,x20,ror#34
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x1,x1,x10,ror#61
+ eor x2,x2,x13,lsr#7 // sigma0(X[i+1])
+ add x27,x27,x16 // h+=Sigma1(e)
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x3,x20,ror#39 // Sigma0(a)
+ eor x1,x1,x10,lsr#6 // sigma1(X[i+14])
+ add x12,x12,x5
+ add x23,x23,x27 // d+=h
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x12,x12,x2
+ add x27,x27,x17 // h+=Sigma0(a)
+ add x12,x12,x1
+ ldr x1,[sp,#16]
+ str x4,[sp,#8]
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ ror x3,x14,#1
+ and x17,x24,x23
+ ror x2,x11,#19
+ bic x28,x25,x23
+ ror x4,x27,#28
+ add x26,x26,x12 // h+=X[i]
+ eor x16,x16,x23,ror#18
+ eor x3,x3,x14,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x23,ror#41 // Sigma1(e)
+ eor x4,x4,x27,ror#34
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x2,x2,x11,ror#61
+ eor x3,x3,x14,lsr#7 // sigma0(X[i+1])
+ add x26,x26,x16 // h+=Sigma1(e)
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x4,x27,ror#39 // Sigma0(a)
+ eor x2,x2,x11,lsr#6 // sigma1(X[i+14])
+ add x13,x13,x6
+ add x22,x22,x26 // d+=h
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x13,x13,x3
+ add x26,x26,x17 // h+=Sigma0(a)
+ add x13,x13,x2
+ ldr x2,[sp,#24]
+ str x5,[sp,#16]
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ ror x4,x15,#1
+ and x17,x23,x22
+ ror x3,x12,#19
+ bic x19,x24,x22
+ ror x5,x26,#28
+ add x25,x25,x13 // h+=X[i]
+ eor x16,x16,x22,ror#18
+ eor x4,x4,x15,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x22,ror#41 // Sigma1(e)
+ eor x5,x5,x26,ror#34
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x3,x3,x12,ror#61
+ eor x4,x4,x15,lsr#7 // sigma0(X[i+1])
+ add x25,x25,x16 // h+=Sigma1(e)
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x5,x26,ror#39 // Sigma0(a)
+ eor x3,x3,x12,lsr#6 // sigma1(X[i+14])
+ add x14,x14,x7
+ add x21,x21,x25 // d+=h
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x14,x14,x4
+ add x25,x25,x17 // h+=Sigma0(a)
+ add x14,x14,x3
+ ldr x3,[sp,#0]
+ str x6,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ ror x5,x0,#1
+ and x17,x22,x21
+ ror x4,x13,#19
+ bic x28,x23,x21
+ ror x6,x25,#28
+ add x24,x24,x14 // h+=X[i]
+ eor x16,x16,x21,ror#18
+ eor x5,x5,x0,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x21,ror#41 // Sigma1(e)
+ eor x6,x6,x25,ror#34
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x4,x4,x13,ror#61
+ eor x5,x5,x0,lsr#7 // sigma0(X[i+1])
+ add x24,x24,x16 // h+=Sigma1(e)
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x6,x25,ror#39 // Sigma0(a)
+ eor x4,x4,x13,lsr#6 // sigma1(X[i+14])
+ add x15,x15,x8
+ add x20,x20,x24 // d+=h
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x15,x15,x5
+ add x24,x24,x17 // h+=Sigma0(a)
+ add x15,x15,x4
+ ldr x4,[sp,#8]
+ str x7,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ ror x6,x1,#1
+ and x17,x21,x20
+ ror x5,x14,#19
+ bic x19,x22,x20
+ ror x7,x24,#28
+ add x23,x23,x15 // h+=X[i]
+ eor x16,x16,x20,ror#18
+ eor x6,x6,x1,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x20,ror#41 // Sigma1(e)
+ eor x7,x7,x24,ror#34
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x5,x5,x14,ror#61
+ eor x6,x6,x1,lsr#7 // sigma0(X[i+1])
+ add x23,x23,x16 // h+=Sigma1(e)
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x7,x24,ror#39 // Sigma0(a)
+ eor x5,x5,x14,lsr#6 // sigma1(X[i+14])
+ add x0,x0,x9
+ add x27,x27,x23 // d+=h
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x0,x0,x6
+ add x23,x23,x17 // h+=Sigma0(a)
+ add x0,x0,x5
+ ldr x5,[sp,#16]
+ str x8,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ ror x7,x2,#1
+ and x17,x20,x27
+ ror x6,x15,#19
+ bic x28,x21,x27
+ ror x8,x23,#28
+ add x22,x22,x0 // h+=X[i]
+ eor x16,x16,x27,ror#18
+ eor x7,x7,x2,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x27,ror#41 // Sigma1(e)
+ eor x8,x8,x23,ror#34
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x6,x6,x15,ror#61
+ eor x7,x7,x2,lsr#7 // sigma0(X[i+1])
+ add x22,x22,x16 // h+=Sigma1(e)
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x8,x23,ror#39 // Sigma0(a)
+ eor x6,x6,x15,lsr#6 // sigma1(X[i+14])
+ add x1,x1,x10
+ add x26,x26,x22 // d+=h
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x1,x1,x7
+ add x22,x22,x17 // h+=Sigma0(a)
+ add x1,x1,x6
+ ldr x6,[sp,#24]
+ str x9,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ ror x8,x3,#1
+ and x17,x27,x26
+ ror x7,x0,#19
+ bic x19,x20,x26
+ ror x9,x22,#28
+ add x21,x21,x1 // h+=X[i]
+ eor x16,x16,x26,ror#18
+ eor x8,x8,x3,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x26,ror#41 // Sigma1(e)
+ eor x9,x9,x22,ror#34
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x7,x7,x0,ror#61
+ eor x8,x8,x3,lsr#7 // sigma0(X[i+1])
+ add x21,x21,x16 // h+=Sigma1(e)
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x9,x22,ror#39 // Sigma0(a)
+ eor x7,x7,x0,lsr#6 // sigma1(X[i+14])
+ add x2,x2,x11
+ add x25,x25,x21 // d+=h
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x2,x2,x8
+ add x21,x21,x17 // h+=Sigma0(a)
+ add x2,x2,x7
+ ldr x7,[sp,#0]
+ str x10,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x9,x4,#1
+ and x17,x26,x25
+ ror x8,x1,#19
+ bic x28,x27,x25
+ ror x10,x21,#28
+ add x20,x20,x2 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x9,x9,x4,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x10,x10,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x8,x8,x1,ror#61
+ eor x9,x9,x4,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x10,x21,ror#39 // Sigma0(a)
+ eor x8,x8,x1,lsr#6 // sigma1(X[i+14])
+ add x3,x3,x12
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x3,x3,x9
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x3,x3,x8
+ cbnz x19,.Loop_16_xx
+
+ ldp x0,x2,[x29,#96]
+ ldr x1,[x29,#112]
+ sub x30,x30,#648 // rewind
+
+ ldp x3,x4,[x0]
+ ldp x5,x6,[x0,#2*8]
+ add x1,x1,#14*8 // advance input pointer
+ ldp x7,x8,[x0,#4*8]
+ add x20,x20,x3
+ ldp x9,x10,[x0,#6*8]
+ add x21,x21,x4
+ add x22,x22,x5
+ add x23,x23,x6
+ stp x20,x21,[x0]
+ add x24,x24,x7
+ add x25,x25,x8
+ stp x22,x23,[x0,#2*8]
+ add x26,x26,x9
+ add x27,x27,x10
+ cmp x1,x2
+ stp x24,x25,[x0,#4*8]
+ stp x26,x27,[x0,#6*8]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*8
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size zfs_sha512_block_armv7,.-zfs_sha512_block_armv7
+
+
+.globl zfs_sha512_block_armv8
+.type zfs_sha512_block_armv8,%function
+.align 6
+zfs_sha512_block_armv8:
+ hint #34 // bti c
+.Lv8_entry:
+ // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ ld1 {v16.16b-v19.16b},[x1],#64 // load input
+ ld1 {v20.16b-v23.16b},[x1],#64
+
+ ld1 {v0.2d-v3.2d},[x0] // load context
+ adr x3,.LK512
+
+ rev64 v16.16b,v16.16b
+ rev64 v17.16b,v17.16b
+ rev64 v18.16b,v18.16b
+ rev64 v19.16b,v19.16b
+ rev64 v20.16b,v20.16b
+ rev64 v21.16b,v21.16b
+ rev64 v22.16b,v22.16b
+ rev64 v23.16b,v23.16b
+ b .Loop_hw
+
+.align 4
+.Loop_hw:
+ ld1 {v24.2d},[x3],#16
+ subs x2,x2,#1
+ sub x4,x1,#128
+ orr v26.16b,v0.16b,v0.16b // offload
+ orr v27.16b,v1.16b,v1.16b
+ orr v28.16b,v2.16b,v2.16b
+ orr v29.16b,v3.16b,v3.16b
+ csel x1,x1,x4,ne // conditional rewind
+ add v24.2d,v24.2d,v16.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08230 //sha512su0 v16.16b,v17.16b
+ ext v7.16b,v20.16b,v21.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678af0 //sha512su1 v16.16b,v23.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v25.2d,v25.2d,v17.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08251 //sha512su0 v17.16b,v18.16b
+ ext v7.16b,v21.16b,v22.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678a11 //sha512su1 v17.16b,v16.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v24.2d,v24.2d,v18.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08272 //sha512su0 v18.16b,v19.16b
+ ext v7.16b,v22.16b,v23.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678a32 //sha512su1 v18.16b,v17.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v25.2d,v25.2d,v19.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08293 //sha512su0 v19.16b,v20.16b
+ ext v7.16b,v23.16b,v16.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678a53 //sha512su1 v19.16b,v18.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v24.2d,v24.2d,v20.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082b4 //sha512su0 v20.16b,v21.16b
+ ext v7.16b,v16.16b,v17.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678a74 //sha512su1 v20.16b,v19.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v25.2d,v25.2d,v21.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec082d5 //sha512su0 v21.16b,v22.16b
+ ext v7.16b,v17.16b,v18.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678a95 //sha512su1 v21.16b,v20.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v24.2d,v24.2d,v22.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082f6 //sha512su0 v22.16b,v23.16b
+ ext v7.16b,v18.16b,v19.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678ab6 //sha512su1 v22.16b,v21.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v25.2d,v25.2d,v23.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08217 //sha512su0 v23.16b,v16.16b
+ ext v7.16b,v19.16b,v20.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678ad7 //sha512su1 v23.16b,v22.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v24.2d,v24.2d,v16.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08230 //sha512su0 v16.16b,v17.16b
+ ext v7.16b,v20.16b,v21.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678af0 //sha512su1 v16.16b,v23.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v25.2d,v25.2d,v17.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08251 //sha512su0 v17.16b,v18.16b
+ ext v7.16b,v21.16b,v22.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678a11 //sha512su1 v17.16b,v16.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v24.2d,v24.2d,v18.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08272 //sha512su0 v18.16b,v19.16b
+ ext v7.16b,v22.16b,v23.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678a32 //sha512su1 v18.16b,v17.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v25.2d,v25.2d,v19.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08293 //sha512su0 v19.16b,v20.16b
+ ext v7.16b,v23.16b,v16.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678a53 //sha512su1 v19.16b,v18.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v24.2d,v24.2d,v20.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082b4 //sha512su0 v20.16b,v21.16b
+ ext v7.16b,v16.16b,v17.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678a74 //sha512su1 v20.16b,v19.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v25.2d,v25.2d,v21.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec082d5 //sha512su0 v21.16b,v22.16b
+ ext v7.16b,v17.16b,v18.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678a95 //sha512su1 v21.16b,v20.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v24.2d,v24.2d,v22.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082f6 //sha512su0 v22.16b,v23.16b
+ ext v7.16b,v18.16b,v19.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678ab6 //sha512su1 v22.16b,v21.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v25.2d,v25.2d,v23.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08217 //sha512su0 v23.16b,v16.16b
+ ext v7.16b,v19.16b,v20.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678ad7 //sha512su1 v23.16b,v22.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v24.2d,v24.2d,v16.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08230 //sha512su0 v16.16b,v17.16b
+ ext v7.16b,v20.16b,v21.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678af0 //sha512su1 v16.16b,v23.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v25.2d,v25.2d,v17.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08251 //sha512su0 v17.16b,v18.16b
+ ext v7.16b,v21.16b,v22.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678a11 //sha512su1 v17.16b,v16.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v24.2d,v24.2d,v18.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08272 //sha512su0 v18.16b,v19.16b
+ ext v7.16b,v22.16b,v23.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678a32 //sha512su1 v18.16b,v17.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v25.2d,v25.2d,v19.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08293 //sha512su0 v19.16b,v20.16b
+ ext v7.16b,v23.16b,v16.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678a53 //sha512su1 v19.16b,v18.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v24.2d,v24.2d,v20.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082b4 //sha512su0 v20.16b,v21.16b
+ ext v7.16b,v16.16b,v17.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678a74 //sha512su1 v20.16b,v19.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v25.2d,v25.2d,v21.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec082d5 //sha512su0 v21.16b,v22.16b
+ ext v7.16b,v17.16b,v18.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678a95 //sha512su1 v21.16b,v20.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v24.2d,v24.2d,v22.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082f6 //sha512su0 v22.16b,v23.16b
+ ext v7.16b,v18.16b,v19.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678ab6 //sha512su1 v22.16b,v21.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v25.2d,v25.2d,v23.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08217 //sha512su0 v23.16b,v16.16b
+ ext v7.16b,v19.16b,v20.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678ad7 //sha512su1 v23.16b,v22.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v24.2d,v24.2d,v16.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08230 //sha512su0 v16.16b,v17.16b
+ ext v7.16b,v20.16b,v21.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678af0 //sha512su1 v16.16b,v23.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v25.2d,v25.2d,v17.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08251 //sha512su0 v17.16b,v18.16b
+ ext v7.16b,v21.16b,v22.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678a11 //sha512su1 v17.16b,v16.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v24.2d,v24.2d,v18.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec08272 //sha512su0 v18.16b,v19.16b
+ ext v7.16b,v22.16b,v23.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678a32 //sha512su1 v18.16b,v17.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ add v25.2d,v25.2d,v19.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08293 //sha512su0 v19.16b,v20.16b
+ ext v7.16b,v23.16b,v16.16b,#8
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ .inst 0xce678a53 //sha512su1 v19.16b,v18.16b,v7.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ add v24.2d,v24.2d,v20.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082b4 //sha512su0 v20.16b,v21.16b
+ ext v7.16b,v16.16b,v17.16b,#8
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ .inst 0xce678a74 //sha512su1 v20.16b,v19.16b,v7.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ add v25.2d,v25.2d,v21.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec082d5 //sha512su0 v21.16b,v22.16b
+ ext v7.16b,v17.16b,v18.16b,#8
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ .inst 0xce678a95 //sha512su1 v21.16b,v20.16b,v7.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v24.2d,v24.2d,v22.2d
+ ld1 {v25.2d},[x3],#16
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xcec082f6 //sha512su0 v22.16b,v23.16b
+ ext v7.16b,v18.16b,v19.16b,#8
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ .inst 0xce678ab6 //sha512su1 v22.16b,v21.16b,v7.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ add v25.2d,v25.2d,v23.2d
+ ld1 {v24.2d},[x3],#16
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xcec08217 //sha512su0 v23.16b,v16.16b
+ ext v7.16b,v19.16b,v20.16b,#8
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ .inst 0xce678ad7 //sha512su1 v23.16b,v22.16b,v7.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ ld1 {v25.2d},[x3],#16
+ add v24.2d,v24.2d,v16.2d
+ ld1 {v16.16b},[x1],#16 // load next input
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ rev64 v16.16b,v16.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ ld1 {v24.2d},[x3],#16
+ add v25.2d,v25.2d,v17.2d
+ ld1 {v17.16b},[x1],#16 // load next input
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ rev64 v17.16b,v17.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ ld1 {v25.2d},[x3],#16
+ add v24.2d,v24.2d,v18.2d
+ ld1 {v18.16b},[x1],#16 // load next input
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ rev64 v18.16b,v18.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ ld1 {v24.2d},[x3],#16
+ add v25.2d,v25.2d,v19.2d
+ ld1 {v19.16b},[x1],#16 // load next input
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v2.16b,v3.16b,#8
+ ext v6.16b,v1.16b,v2.16b,#8
+ add v3.2d,v3.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a3 //sha512h v3.16b,v5.16b,v6.16b
+ rev64 v19.16b,v19.16b
+ add v4.2d,v1.2d,v3.2d // "D + T1"
+ .inst 0xce608423 //sha512h2 v3.16b,v1.16b,v0.16b
+ ld1 {v25.2d},[x3],#16
+ add v24.2d,v24.2d,v20.2d
+ ld1 {v20.16b},[x1],#16 // load next input
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v4.16b,v2.16b,#8
+ ext v6.16b,v0.16b,v4.16b,#8
+ add v2.2d,v2.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a2 //sha512h v2.16b,v5.16b,v6.16b
+ rev64 v20.16b,v20.16b
+ add v1.2d,v0.2d,v2.2d // "D + T1"
+ .inst 0xce638402 //sha512h2 v2.16b,v0.16b,v3.16b
+ ld1 {v24.2d},[x3],#16
+ add v25.2d,v25.2d,v21.2d
+ ld1 {v21.16b},[x1],#16 // load next input
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v1.16b,v4.16b,#8
+ ext v6.16b,v3.16b,v1.16b,#8
+ add v4.2d,v4.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a4 //sha512h v4.16b,v5.16b,v6.16b
+ rev64 v21.16b,v21.16b
+ add v0.2d,v3.2d,v4.2d // "D + T1"
+ .inst 0xce628464 //sha512h2 v4.16b,v3.16b,v2.16b
+ ld1 {v25.2d},[x3],#16
+ add v24.2d,v24.2d,v22.2d
+ ld1 {v22.16b},[x1],#16 // load next input
+ ext v24.16b,v24.16b,v24.16b,#8
+ ext v5.16b,v0.16b,v1.16b,#8
+ ext v6.16b,v2.16b,v0.16b,#8
+ add v1.2d,v1.2d,v24.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a1 //sha512h v1.16b,v5.16b,v6.16b
+ rev64 v22.16b,v22.16b
+ add v3.2d,v2.2d,v1.2d // "D + T1"
+ .inst 0xce648441 //sha512h2 v1.16b,v2.16b,v4.16b
+ sub x3,x3,#80*8 // rewind
+ add v25.2d,v25.2d,v23.2d
+ ld1 {v23.16b},[x1],#16 // load next input
+ ext v25.16b,v25.16b,v25.16b,#8
+ ext v5.16b,v3.16b,v0.16b,#8
+ ext v6.16b,v4.16b,v3.16b,#8
+ add v0.2d,v0.2d,v25.2d // "T1 + H + K512[i]"
+ .inst 0xce6680a0 //sha512h v0.16b,v5.16b,v6.16b
+ rev64 v23.16b,v23.16b
+ add v2.2d,v4.2d,v0.2d // "D + T1"
+ .inst 0xce618480 //sha512h2 v0.16b,v4.16b,v1.16b
+ add v0.2d,v0.2d,v26.2d // accumulate
+ add v1.2d,v1.2d,v27.2d
+ add v2.2d,v2.2d,v28.2d
+ add v3.2d,v3.2d,v29.2d
+
+ cbnz x2,.Loop_hw
+
+ st1 {v0.2d-v3.2d},[x0] // store context
+
+ ldr x29,[sp],#16
+ ret
+.size zfs_sha512_block_armv8,.-zfs_sha512_block_armv8
+#endif
diff --git a/module/icp/asm-arm/sha2/sha256-armv7.S b/module/icp/asm-arm/sha2/sha256-armv7.S
new file mode 100644
index 000000000000..3ae66626df31
--- /dev/null
+++ b/module/icp/asm-arm/sha2/sha256-armv7.S
@@ -0,0 +1,2774 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__arm__)
+
+#ifndef __ARM_ARCH
+# define __ARM_ARCH__ 7
+#else
+# define __ARM_ARCH__ __ARM_ARCH
+#endif
+
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+#else
+.code 32
+#endif
+
+.text
+
+.type K256,%object
+.align 5
+K256:
+.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.size K256,.-K256
+.word 0 @ terminator
+
+.align 5
+.globl zfs_sha256_block_armv7
+.type zfs_sha256_block_armv7,%function
+zfs_sha256_block_armv7:
+.Lzfs_sha256_block_armv7:
+
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+ sub r3,pc,#8 @ zfs_sha256_block_armv7
+#else
+ adr r3,.Lzfs_sha256_block_armv7
+#endif
+
+ add r2,r1,r2,lsl#6 @ len to point at the end of inp
+ stmdb sp!,{r0,r1,r2,r4-r11,lr}
+ ldmia r0,{r4,r5,r6,r7,r8,r9,r10,r11}
+ sub r14,r3,#256+32 @ K256
+ sub sp,sp,#16*4 @ alloca(X[16])
+.Loop:
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ magic
+ eor r12,r12,r12
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 0
+# if 0==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 0
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 0==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#0*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 0==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 0<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#2*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#15*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 1
+# if 1==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 1
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 1==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#1*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 1==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 1<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#3*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#0*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 2
+# if 2==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 2
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 2==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#2*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 2==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 2<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#4*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#1*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 3
+# if 3==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 3
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 3==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#3*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 3==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 3<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#5*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#2*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 4
+# if 4==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 4
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 4==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#4*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 4==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 4<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#6*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#3*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 5
+# if 5==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 5==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#5*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 5==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 5<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#7*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#4*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 6
+# if 6==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 6
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 6==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#6*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 6==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 6<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#8*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#5*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 7
+# if 7==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 7==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#7*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 7==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 7<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#9*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#6*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 8
+# if 8==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 8
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 8==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#8*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 8==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 8<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#10*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#7*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 9
+# if 9==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 9
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 9==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#9*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 9==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 9<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#11*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#8*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 10
+# if 10==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 10
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 10==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#10*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 10==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 10<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#12*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#9*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 11
+# if 11==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 11
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 11==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#11*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 11==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 11<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#13*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#10*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 12
+# if 12==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 12
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 12==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#12*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 12==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 12<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#14*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#11*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 13
+# if 13==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 13
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 13==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#13*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 13==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 13<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#15*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#12*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 14
+# if 14==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 14
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 14==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#14*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 14==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 14<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#0*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#13*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 15
+# if 15==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+# ifndef __ARMEB__
+ rev r2,r2
+# endif
+#else
+ @ ldrb r2,[r1,#3] @ 15
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 15==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#15*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 15==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 15<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#1*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#14*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+.Lrounds_16_xx:
+ @ ldr r2,[sp,#1*4] @ 16
+ @ ldr r1,[sp,#14*4]
+ mov r0,r2,ror#7
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#0*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#9*4]
+
+ add r12,r12,r0
+ eor r0,r8,r8,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#0*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 16==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 16<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#2*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#15*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#2*4] @ 17
+ @ ldr r1,[sp,#15*4]
+ mov r0,r2,ror#7
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#1*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#10*4]
+
+ add r3,r3,r0
+ eor r0,r7,r7,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#1*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 17==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 17<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#3*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#0*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#3*4] @ 18
+ @ ldr r1,[sp,#0*4]
+ mov r0,r2,ror#7
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#2*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#11*4]
+
+ add r12,r12,r0
+ eor r0,r6,r6,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#2*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 18==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 18<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#4*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#1*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#4*4] @ 19
+ @ ldr r1,[sp,#1*4]
+ mov r0,r2,ror#7
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#3*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#12*4]
+
+ add r3,r3,r0
+ eor r0,r5,r5,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#3*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 19==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 19<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#5*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#2*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#5*4] @ 20
+ @ ldr r1,[sp,#2*4]
+ mov r0,r2,ror#7
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#4*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#13*4]
+
+ add r12,r12,r0
+ eor r0,r4,r4,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#4*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 20==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 20<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#6*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#3*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#6*4] @ 21
+ @ ldr r1,[sp,#3*4]
+ mov r0,r2,ror#7
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#5*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#14*4]
+
+ add r3,r3,r0
+ eor r0,r11,r11,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#5*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 21==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 21<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#7*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#4*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#7*4] @ 22
+ @ ldr r1,[sp,#4*4]
+ mov r0,r2,ror#7
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#6*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#15*4]
+
+ add r12,r12,r0
+ eor r0,r10,r10,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#6*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 22==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 22<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#8*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#5*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#8*4] @ 23
+ @ ldr r1,[sp,#5*4]
+ mov r0,r2,ror#7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#7*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#0*4]
+
+ add r3,r3,r0
+ eor r0,r9,r9,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#7*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 23==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 23<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#9*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#6*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#9*4] @ 24
+ @ ldr r1,[sp,#6*4]
+ mov r0,r2,ror#7
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#8*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#1*4]
+
+ add r12,r12,r0
+ eor r0,r8,r8,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#8*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 24==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 24<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#10*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#7*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#10*4] @ 25
+ @ ldr r1,[sp,#7*4]
+ mov r0,r2,ror#7
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#9*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#2*4]
+
+ add r3,r3,r0
+ eor r0,r7,r7,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#9*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 25==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 25<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#11*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#8*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#11*4] @ 26
+ @ ldr r1,[sp,#8*4]
+ mov r0,r2,ror#7
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#10*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#3*4]
+
+ add r12,r12,r0
+ eor r0,r6,r6,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#10*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 26==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 26<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#12*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#9*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#12*4] @ 27
+ @ ldr r1,[sp,#9*4]
+ mov r0,r2,ror#7
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#11*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#4*4]
+
+ add r3,r3,r0
+ eor r0,r5,r5,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#11*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 27==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 27<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#13*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#10*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#13*4] @ 28
+ @ ldr r1,[sp,#10*4]
+ mov r0,r2,ror#7
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#12*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#5*4]
+
+ add r12,r12,r0
+ eor r0,r4,r4,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#12*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 28==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 28<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#14*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#11*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#14*4] @ 29
+ @ ldr r1,[sp,#11*4]
+ mov r0,r2,ror#7
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#13*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#6*4]
+
+ add r3,r3,r0
+ eor r0,r11,r11,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#13*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 29==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 29<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#15*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#12*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#15*4] @ 30
+ @ ldr r1,[sp,#12*4]
+ mov r0,r2,ror#7
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#14*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#7*4]
+
+ add r12,r12,r0
+ eor r0,r10,r10,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#14*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 30==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 30<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#0*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#13*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#0*4] @ 31
+ @ ldr r1,[sp,#13*4]
+ mov r0,r2,ror#7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#15*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#8*4]
+
+ add r3,r3,r0
+ eor r0,r9,r9,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#15*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 31==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 31<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#1*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#14*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+#ifdef __thumb2__
+ ite eq @ Thumb2 thing, sanity check in ARM
+#endif
+ ldreq r3,[sp,#16*4] @ pull ctx
+ bne .Lrounds_16_xx
+
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldr r0,[r3,#0]
+ ldr r2,[r3,#4]
+ ldr r12,[r3,#8]
+ add r4,r4,r0
+ ldr r0,[r3,#12]
+ add r5,r5,r2
+ ldr r2,[r3,#16]
+ add r6,r6,r12
+ ldr r12,[r3,#20]
+ add r7,r7,r0
+ ldr r0,[r3,#24]
+ add r8,r8,r2
+ ldr r2,[r3,#28]
+ add r9,r9,r12
+ ldr r1,[sp,#17*4] @ pull inp
+ ldr r12,[sp,#18*4] @ pull inp+len
+ add r10,r10,r0
+ add r11,r11,r2
+ stmia r3,{r4,r5,r6,r7,r8,r9,r10,r11}
+ cmp r1,r12
+ sub r14,r14,#256 @ rewind Ktbl
+ bne .Loop
+
+ add sp,sp,#19*4 @ destroy frame
+#if __ARM_ARCH__>=5
+ ldmia sp!,{r4-r11,pc}
+#else
+ ldmia sp!,{r4-r11,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ .word 0xe12fff1e @ interoperable with Thumb ISA:-)
+#endif
+.size zfs_sha256_block_armv7,.-zfs_sha256_block_armv7
+
+#if __ARM_ARCH__ >= 7
+.arch armv7-a
+.fpu neon
+
+.globl zfs_sha256_block_neon
+.type zfs_sha256_block_neon,%function
+.align 5
+.skip 16
+zfs_sha256_block_neon:
+.LNEON:
+ stmdb sp!,{r4-r12,lr}
+
+ sub r11,sp,#16*4+16
+ adr r14,K256
+ bic r11,r11,#15 @ align for 128-bit stores
+ mov r12,sp
+ mov sp,r11 @ alloca
+ add r2,r1,r2,lsl#6 @ len to point at the end of inp
+
+ vld1.8 {q0},[r1]!
+ vld1.8 {q1},[r1]!
+ vld1.8 {q2},[r1]!
+ vld1.8 {q3},[r1]!
+ vld1.32 {q8},[r14,:128]!
+ vld1.32 {q9},[r14,:128]!
+ vld1.32 {q10},[r14,:128]!
+ vld1.32 {q11},[r14,:128]!
+ vrev32.8 q0,q0 @ yes, even on
+ str r0,[sp,#64]
+ vrev32.8 q1,q1 @ big-endian
+ str r1,[sp,#68]
+ mov r1,sp
+ vrev32.8 q2,q2
+ str r2,[sp,#72]
+ vrev32.8 q3,q3
+ str r12,[sp,#76] @ save original sp
+ vadd.i32 q8,q8,q0
+ vadd.i32 q9,q9,q1
+ vst1.32 {q8},[r1,:128]!
+ vadd.i32 q10,q10,q2
+ vst1.32 {q9},[r1,:128]!
+ vadd.i32 q11,q11,q3
+ vst1.32 {q10},[r1,:128]!
+ vst1.32 {q11},[r1,:128]!
+
+ ldmia r0,{r4-r11}
+ sub r1,r1,#64
+ ldr r2,[sp,#0]
+ eor r12,r12,r12
+ eor r3,r5,r6
+ b .L_00_48
+
+.align 4
+.L_00_48:
+ vext.8 q8,q0,q1,#4
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ vext.8 q9,q2,q3,#4
+ add r4,r4,r12
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vadd.i32 q0,q0,q9
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#4]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ veor q9,q9,q10
+ add r10,r10,r2
+ vsli.32 q11,q8,#14
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ vshr.u32 d24,d7,#17
+ add r11,r11,r3
+ and r2,r2,r7
+ veor q9,q9,q11
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ vsli.32 d24,d7,#15
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ vshr.u32 d25,d7,#10
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ vadd.i32 q0,q0,q9
+ add r10,r10,r2
+ ldr r2,[sp,#8]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r6,r6,r10
+ vshr.u32 d24,d7,#19
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ vsli.32 d24,d7,#13
+ add r9,r9,r2
+ eor r2,r7,r8
+ veor d25,d25,d24
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ vadd.i32 d0,d0,d25
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ vshr.u32 d24,d0,#17
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ vsli.32 d24,d0,#15
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ vshr.u32 d25,d0,#10
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#12]
+ and r3,r3,r12
+ vshr.u32 d24,d0,#19
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ vld1.32 {q8},[r14,:128]!
+ add r8,r8,r2
+ vsli.32 d24,d0,#13
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ veor d25,d25,d24
+ add r9,r9,r3
+ and r2,r2,r5
+ vadd.i32 d1,d1,d25
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ vadd.i32 q8,q8,q0
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#16]
+ and r12,r12,r3
+ add r4,r4,r8
+ vst1.32 {q8},[r1,:128]!
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vext.8 q8,q1,q2,#4
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ vext.8 q9,q3,q0,#4
+ add r8,r8,r12
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vadd.i32 q1,q1,q9
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#20]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ veor q9,q9,q10
+ add r6,r6,r2
+ vsli.32 q11,q8,#14
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ vshr.u32 d24,d1,#17
+ add r7,r7,r3
+ and r2,r2,r11
+ veor q9,q9,q11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ vsli.32 d24,d1,#15
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ vshr.u32 d25,d1,#10
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ vadd.i32 q1,q1,q9
+ add r6,r6,r2
+ ldr r2,[sp,#24]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r10,r10,r6
+ vshr.u32 d24,d1,#19
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ vsli.32 d24,d1,#13
+ add r5,r5,r2
+ eor r2,r11,r4
+ veor d25,d25,d24
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ vadd.i32 d2,d2,d25
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ vshr.u32 d24,d2,#17
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ vsli.32 d24,d2,#15
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ vshr.u32 d25,d2,#10
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#28]
+ and r3,r3,r12
+ vshr.u32 d24,d2,#19
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ vld1.32 {q8},[r14,:128]!
+ add r4,r4,r2
+ vsli.32 d24,d2,#13
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ veor d25,d25,d24
+ add r5,r5,r3
+ and r2,r2,r9
+ vadd.i32 d3,d3,d25
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ vadd.i32 q8,q8,q1
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#32]
+ and r12,r12,r3
+ add r8,r8,r4
+ vst1.32 {q8},[r1,:128]!
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vext.8 q8,q2,q3,#4
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ vext.8 q9,q0,q1,#4
+ add r4,r4,r12
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vadd.i32 q2,q2,q9
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#36]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ veor q9,q9,q10
+ add r10,r10,r2
+ vsli.32 q11,q8,#14
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ vshr.u32 d24,d3,#17
+ add r11,r11,r3
+ and r2,r2,r7
+ veor q9,q9,q11
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ vsli.32 d24,d3,#15
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ vshr.u32 d25,d3,#10
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ vadd.i32 q2,q2,q9
+ add r10,r10,r2
+ ldr r2,[sp,#40]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r6,r6,r10
+ vshr.u32 d24,d3,#19
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ vsli.32 d24,d3,#13
+ add r9,r9,r2
+ eor r2,r7,r8
+ veor d25,d25,d24
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ vadd.i32 d4,d4,d25
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ vshr.u32 d24,d4,#17
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ vsli.32 d24,d4,#15
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ vshr.u32 d25,d4,#10
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#44]
+ and r3,r3,r12
+ vshr.u32 d24,d4,#19
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ vld1.32 {q8},[r14,:128]!
+ add r8,r8,r2
+ vsli.32 d24,d4,#13
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ veor d25,d25,d24
+ add r9,r9,r3
+ and r2,r2,r5
+ vadd.i32 d5,d5,d25
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ vadd.i32 q8,q8,q2
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#48]
+ and r12,r12,r3
+ add r4,r4,r8
+ vst1.32 {q8},[r1,:128]!
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vext.8 q8,q3,q0,#4
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ vext.8 q9,q1,q2,#4
+ add r8,r8,r12
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vadd.i32 q3,q3,q9
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#52]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ veor q9,q9,q10
+ add r6,r6,r2
+ vsli.32 q11,q8,#14
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ vshr.u32 d24,d5,#17
+ add r7,r7,r3
+ and r2,r2,r11
+ veor q9,q9,q11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ vsli.32 d24,d5,#15
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ vshr.u32 d25,d5,#10
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ vadd.i32 q3,q3,q9
+ add r6,r6,r2
+ ldr r2,[sp,#56]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r10,r10,r6
+ vshr.u32 d24,d5,#19
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ vsli.32 d24,d5,#13
+ add r5,r5,r2
+ eor r2,r11,r4
+ veor d25,d25,d24
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ vadd.i32 d6,d6,d25
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ vshr.u32 d24,d6,#17
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ vsli.32 d24,d6,#15
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ vshr.u32 d25,d6,#10
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#60]
+ and r3,r3,r12
+ vshr.u32 d24,d6,#19
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ vld1.32 {q8},[r14,:128]!
+ add r4,r4,r2
+ vsli.32 d24,d6,#13
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ veor d25,d25,d24
+ add r5,r5,r3
+ and r2,r2,r9
+ vadd.i32 d7,d7,d25
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ vadd.i32 q8,q8,q3
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[r14]
+ and r12,r12,r3
+ add r8,r8,r4
+ vst1.32 {q8},[r1,:128]!
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ teq r2,#0 @ check for K256 terminator
+ ldr r2,[sp,#0]
+ sub r1,r1,#64
+ bne .L_00_48
+
+ ldr r1,[sp,#68]
+ ldr r0,[sp,#72]
+ sub r14,r14,#256 @ rewind r14
+ teq r1,r0
+ it eq
+ subeq r1,r1,#64 @ avoid SEGV
+ vld1.8 {q0},[r1]! @ load next input block
+ vld1.8 {q1},[r1]!
+ vld1.8 {q2},[r1]!
+ vld1.8 {q3},[r1]!
+ it ne
+ strne r1,[sp,#68]
+ mov r1,sp
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vrev32.8 q0,q0
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vadd.i32 q8,q8,q0
+ ldr r2,[sp,#4]
+ and r3,r3,r12
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ add r10,r10,r2
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3
+ and r2,r2,r7
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ add r10,r10,r2
+ ldr r2,[sp,#8]
+ and r12,r12,r3
+ add r6,r6,r10
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ add r9,r9,r2
+ eor r2,r7,r8
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ ldr r2,[sp,#12]
+ and r3,r3,r12
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ add r8,r8,r2
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3
+ and r2,r2,r5
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#16]
+ and r12,r12,r3
+ add r4,r4,r8
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vst1.32 {q8},[r1,:128]!
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vrev32.8 q1,q1
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vadd.i32 q8,q8,q1
+ ldr r2,[sp,#20]
+ and r3,r3,r12
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ add r6,r6,r2
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3
+ and r2,r2,r11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ add r6,r6,r2
+ ldr r2,[sp,#24]
+ and r12,r12,r3
+ add r10,r10,r6
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ add r5,r5,r2
+ eor r2,r11,r4
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ ldr r2,[sp,#28]
+ and r3,r3,r12
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ add r4,r4,r2
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3
+ and r2,r2,r9
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#32]
+ and r12,r12,r3
+ add r8,r8,r4
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vst1.32 {q8},[r1,:128]!
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vrev32.8 q2,q2
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vadd.i32 q8,q8,q2
+ ldr r2,[sp,#36]
+ and r3,r3,r12
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ add r10,r10,r2
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3
+ and r2,r2,r7
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ add r10,r10,r2
+ ldr r2,[sp,#40]
+ and r12,r12,r3
+ add r6,r6,r10
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ add r9,r9,r2
+ eor r2,r7,r8
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ ldr r2,[sp,#44]
+ and r3,r3,r12
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ add r8,r8,r2
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3
+ and r2,r2,r5
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#48]
+ and r12,r12,r3
+ add r4,r4,r8
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vst1.32 {q8},[r1,:128]!
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vrev32.8 q3,q3
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vadd.i32 q8,q8,q3
+ ldr r2,[sp,#52]
+ and r3,r3,r12
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ add r6,r6,r2
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3
+ and r2,r2,r11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ add r6,r6,r2
+ ldr r2,[sp,#56]
+ and r12,r12,r3
+ add r10,r10,r6
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ add r5,r5,r2
+ eor r2,r11,r4
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ ldr r2,[sp,#60]
+ and r3,r3,r12
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ add r4,r4,r2
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3
+ and r2,r2,r9
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#64]
+ and r12,r12,r3
+ add r8,r8,r4
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vst1.32 {q8},[r1,:128]!
+ ldr r0,[r2,#0]
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldr r12,[r2,#4]
+ ldr r3,[r2,#8]
+ ldr r1,[r2,#12]
+ add r4,r4,r0 @ accumulate
+ ldr r0,[r2,#16]
+ add r5,r5,r12
+ ldr r12,[r2,#20]
+ add r6,r6,r3
+ ldr r3,[r2,#24]
+ add r7,r7,r1
+ ldr r1,[r2,#28]
+ add r8,r8,r0
+ str r4,[r2],#4
+ add r9,r9,r12
+ str r5,[r2],#4
+ add r10,r10,r3
+ str r6,[r2],#4
+ add r11,r11,r1
+ str r7,[r2],#4
+ stmia r2,{r8-r11}
+
+ ittte ne
+ movne r1,sp
+ ldrne r2,[sp,#0]
+ eorne r12,r12,r12
+ ldreq sp,[sp,#76] @ restore original sp
+ itt ne
+ eorne r3,r5,r6
+ bne .L_00_48
+
+ ldmia sp!,{r4-r12,pc}
+.size zfs_sha256_block_neon,.-zfs_sha256_block_neon
+
+# if defined(__thumb2__)
+# define INST(a,b,c,d) .byte c,d|0xc,a,b
+# else
+# define INST(a,b,c,d) .byte a,b,c,d
+# endif
+
+.globl zfs_sha256_block_armv8
+.type zfs_sha256_block_armv8,%function
+.align 5
+zfs_sha256_block_armv8:
+.LARMv8:
+ vld1.32 {q0,q1},[r0]
+ sub r3,r3,#256+32
+ add r2,r1,r2,lsl#6 @ len to point at the end of inp
+ b .Loop_v8
+
+.align 4
+.Loop_v8:
+ vld1.8 {q8-q9},[r1]!
+ vld1.8 {q10-q11},[r1]!
+ vld1.32 {q12},[r3]!
+ vrev32.8 q8,q8
+ vrev32.8 q9,q9
+ vrev32.8 q10,q10
+ vrev32.8 q11,q11
+ vmov q14,q0 @ offload
+ vmov q15,q1
+ teq r1,r2
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ INST(0xe2,0x03,0xfa,0xf3) @ sha256su0 q8,q9
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe6,0x0c,0x64,0xf3) @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ INST(0xe4,0x23,0xfa,0xf3) @ sha256su0 q9,q10
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe0,0x2c,0x66,0xf3) @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ INST(0xe6,0x43,0xfa,0xf3) @ sha256su0 q10,q11
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+ INST(0xe2,0x4c,0x60,0xf3) @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ INST(0xe0,0x63,0xfa,0xf3) @ sha256su0 q11,q8
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+ INST(0xe4,0x6c,0x62,0xf3) @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+
+ vld1.32 {q13},[r3]
+ vadd.i32 q12,q12,q10
+ sub r3,r3,#256-16 @ rewind
+ vmov q2,q0
+ INST(0x68,0x0c,0x02,0xf3) @ sha256h q0,q1,q12
+ INST(0x68,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q12
+
+ vadd.i32 q13,q13,q11
+ vmov q2,q0
+ INST(0x6a,0x0c,0x02,0xf3) @ sha256h q0,q1,q13
+ INST(0x6a,0x2c,0x14,0xf3) @ sha256h2 q1,q2,q13
+
+ vadd.i32 q0,q0,q14
+ vadd.i32 q1,q1,q15
+ it ne
+ bne .Loop_v8
+
+ vst1.32 {q0,q1},[r0]
+
+ bx lr @ bx lr
+.size zfs_sha256_block_armv8,.-zfs_sha256_block_armv8
+
+#endif // #if __ARM_ARCH__ >= 7
+#endif // #if defined(__arm__)
diff --git a/module/icp/asm-arm/sha2/sha512-armv7.S b/module/icp/asm-arm/sha2/sha512-armv7.S
new file mode 100644
index 000000000000..66d7dd3cf0f7
--- /dev/null
+++ b/module/icp/asm-arm/sha2/sha512-armv7.S
@@ -0,0 +1,1827 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__arm__)
+
+#ifndef __ARM_ARCH
+# define __ARM_ARCH__ 7
+#else
+# define __ARM_ARCH__ __ARM_ARCH
+#endif
+
+#ifndef __KERNEL__
+# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
+# define VFP_ABI_POP vldmia sp!,{d8-d15}
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+#endif
+
+#ifdef __ARMEL__
+# define LO 0
+# define HI 4
+# define WORD64(hi0,lo0,hi1,lo1) .word lo0,hi0, lo1,hi1
+#else
+# define HI 0
+# define LO 4
+# define WORD64(hi0,lo0,hi1,lo1) .word hi0,lo0, hi1,lo1
+#endif
+
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+# define adrl adr
+#else
+.code 32
+#endif
+
+.text
+
+.type K512,%object
+.align 5
+K512:
+ WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd)
+ WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc)
+ WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019)
+ WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118)
+ WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe)
+ WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2)
+ WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1)
+ WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694)
+ WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3)
+ WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65)
+ WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483)
+ WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5)
+ WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210)
+ WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4)
+ WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725)
+ WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70)
+ WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926)
+ WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df)
+ WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8)
+ WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b)
+ WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001)
+ WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30)
+ WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910)
+ WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8)
+ WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53)
+ WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8)
+ WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb)
+ WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3)
+ WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60)
+ WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec)
+ WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9)
+ WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b)
+ WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207)
+ WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178)
+ WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6)
+ WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b)
+ WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493)
+ WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c)
+ WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a)
+ WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
+.size K512,.-K512
+.word 0 @ terminator
+
+.align 5
+.globl zfs_sha512_block_armv7
+.type zfs_sha512_block_armv7,%function
+zfs_sha512_block_armv7:
+.Lzfs_sha512_block_armv7:
+
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+ sub r3,pc,#8 @ zfs_sha512_block_armv7
+#else
+ adr r3,.Lzfs_sha512_block_armv7
+#endif
+
+ add r2,r1,r2,lsl#7 @ len to point at the end of inp
+ stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+ sub r14,r3,#672 @ K512
+ sub sp,sp,#9*8
+
+ ldr r7,[r0,#32+LO]
+ ldr r8,[r0,#32+HI]
+ ldr r9, [r0,#48+LO]
+ ldr r10, [r0,#48+HI]
+ ldr r11, [r0,#56+LO]
+ ldr r12, [r0,#56+HI]
+.Loop:
+ str r9, [sp,#48+0]
+ str r10, [sp,#48+4]
+ str r11, [sp,#56+0]
+ str r12, [sp,#56+4]
+ ldr r5,[r0,#0+LO]
+ ldr r6,[r0,#0+HI]
+ ldr r3,[r0,#8+LO]
+ ldr r4,[r0,#8+HI]
+ ldr r9, [r0,#16+LO]
+ ldr r10, [r0,#16+HI]
+ ldr r11, [r0,#24+LO]
+ ldr r12, [r0,#24+HI]
+ str r3,[sp,#8+0]
+ str r4,[sp,#8+4]
+ str r9, [sp,#16+0]
+ str r10, [sp,#16+4]
+ str r11, [sp,#24+0]
+ str r12, [sp,#24+4]
+ ldr r3,[r0,#40+LO]
+ ldr r4,[r0,#40+HI]
+ str r3,[sp,#40+0]
+ str r4,[sp,#40+4]
+
+.L00_15:
+#if __ARM_ARCH__<7
+ ldrb r3,[r1,#7]
+ ldrb r9, [r1,#6]
+ ldrb r10, [r1,#5]
+ ldrb r11, [r1,#4]
+ ldrb r4,[r1,#3]
+ ldrb r12, [r1,#2]
+ orr r3,r3,r9,lsl#8
+ ldrb r9, [r1,#1]
+ orr r3,r3,r10,lsl#16
+ ldrb r10, [r1],#8
+ orr r3,r3,r11,lsl#24
+ orr r4,r4,r12,lsl#8
+ orr r4,r4,r9,lsl#16
+ orr r4,r4,r10,lsl#24
+#else
+ ldr r3,[r1,#4]
+ ldr r4,[r1],#8
+#ifdef __ARMEL__
+ rev r3,r3
+ rev r4,r4
+#endif
+#endif
+ @ Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
+ @ LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+ @ HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+ mov r9,r7,lsr#14
+ str r3,[sp,#64+0]
+ mov r10,r8,lsr#14
+ str r4,[sp,#64+4]
+ eor r9,r9,r8,lsl#18
+ ldr r11,[sp,#56+0] @ h.lo
+ eor r10,r10,r7,lsl#18
+ ldr r12,[sp,#56+4] @ h.hi
+ eor r9,r9,r7,lsr#18
+ eor r10,r10,r8,lsr#18
+ eor r9,r9,r8,lsl#14
+ eor r10,r10,r7,lsl#14
+ eor r9,r9,r8,lsr#9
+ eor r10,r10,r7,lsr#9
+ eor r9,r9,r7,lsl#23
+ eor r10,r10,r8,lsl#23 @ Sigma1(e)
+ adds r3,r3,r9
+ ldr r9,[sp,#40+0] @ f.lo
+ adc r4,r4,r10 @ T += Sigma1(e)
+ ldr r10,[sp,#40+4] @ f.hi
+ adds r3,r3,r11
+ ldr r11,[sp,#48+0] @ g.lo
+ adc r4,r4,r12 @ T += h
+ ldr r12,[sp,#48+4] @ g.hi
+
+ eor r9,r9,r11
+ str r7,[sp,#32+0]
+ eor r10,r10,r12
+ str r8,[sp,#32+4]
+ and r9,r9,r7
+ str r5,[sp,#0+0]
+ and r10,r10,r8
+ str r6,[sp,#0+4]
+ eor r9,r9,r11
+ ldr r11,[r14,#LO] @ K[i].lo
+ eor r10,r10,r12 @ Ch(e,f,g)
+ ldr r12,[r14,#HI] @ K[i].hi
+
+ adds r3,r3,r9
+ ldr r7,[sp,#24+0] @ d.lo
+ adc r4,r4,r10 @ T += Ch(e,f,g)
+ ldr r8,[sp,#24+4] @ d.hi
+ adds r3,r3,r11
+ and r9,r11,#0xff
+ adc r4,r4,r12 @ T += K[i]
+ adds r7,r7,r3
+ ldr r11,[sp,#8+0] @ b.lo
+ adc r8,r8,r4 @ d += T
+ teq r9,#148
+
+ ldr r12,[sp,#16+0] @ c.lo
+#ifdef __thumb2__
+ it eq @ Thumb2 thing, sanity check in ARM
+#endif
+ orreq r14,r14,#1
+ @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+ @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+ @ HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+ mov r9,r5,lsr#28
+ mov r10,r6,lsr#28
+ eor r9,r9,r6,lsl#4
+ eor r10,r10,r5,lsl#4
+ eor r9,r9,r6,lsr#2
+ eor r10,r10,r5,lsr#2
+ eor r9,r9,r5,lsl#30
+ eor r10,r10,r6,lsl#30
+ eor r9,r9,r6,lsr#7
+ eor r10,r10,r5,lsr#7
+ eor r9,r9,r5,lsl#25
+ eor r10,r10,r6,lsl#25 @ Sigma0(a)
+ adds r3,r3,r9
+ and r9,r5,r11
+ adc r4,r4,r10 @ T += Sigma0(a)
+
+ ldr r10,[sp,#8+4] @ b.hi
+ orr r5,r5,r11
+ ldr r11,[sp,#16+4] @ c.hi
+ and r5,r5,r12
+ and r12,r6,r10
+ orr r6,r6,r10
+ orr r5,r5,r9 @ Maj(a,b,c).lo
+ and r6,r6,r11
+ adds r5,r5,r3
+ orr r6,r6,r12 @ Maj(a,b,c).hi
+ sub sp,sp,#8
+ adc r6,r6,r4 @ h += T
+ tst r14,#1
+ add r14,r14,#8
+ tst r14,#1
+ beq .L00_15
+ ldr r9,[sp,#184+0]
+ ldr r10,[sp,#184+4]
+ bic r14,r14,#1
+.L16_79:
+ @ sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
+ @ LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25
+ @ HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7
+ mov r3,r9,lsr#1
+ ldr r11,[sp,#80+0]
+ mov r4,r10,lsr#1
+ ldr r12,[sp,#80+4]
+ eor r3,r3,r10,lsl#31
+ eor r4,r4,r9,lsl#31
+ eor r3,r3,r9,lsr#8
+ eor r4,r4,r10,lsr#8
+ eor r3,r3,r10,lsl#24
+ eor r4,r4,r9,lsl#24
+ eor r3,r3,r9,lsr#7
+ eor r4,r4,r10,lsr#7
+ eor r3,r3,r10,lsl#25
+
+ @ sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
+ @ LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26
+ @ HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6
+ mov r9,r11,lsr#19
+ mov r10,r12,lsr#19
+ eor r9,r9,r12,lsl#13
+ eor r10,r10,r11,lsl#13
+ eor r9,r9,r12,lsr#29
+ eor r10,r10,r11,lsr#29
+ eor r9,r9,r11,lsl#3
+ eor r10,r10,r12,lsl#3
+ eor r9,r9,r11,lsr#6
+ eor r10,r10,r12,lsr#6
+ ldr r11,[sp,#120+0]
+ eor r9,r9,r12,lsl#26
+
+ ldr r12,[sp,#120+4]
+ adds r3,r3,r9
+ ldr r9,[sp,#192+0]
+ adc r4,r4,r10
+
+ ldr r10,[sp,#192+4]
+ adds r3,r3,r11
+ adc r4,r4,r12
+ adds r3,r3,r9
+ adc r4,r4,r10
+ @ Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41))
+ @ LO lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+ @ HI hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+ mov r9,r7,lsr#14
+ str r3,[sp,#64+0]
+ mov r10,r8,lsr#14
+ str r4,[sp,#64+4]
+ eor r9,r9,r8,lsl#18
+ ldr r11,[sp,#56+0] @ h.lo
+ eor r10,r10,r7,lsl#18
+ ldr r12,[sp,#56+4] @ h.hi
+ eor r9,r9,r7,lsr#18
+ eor r10,r10,r8,lsr#18
+ eor r9,r9,r8,lsl#14
+ eor r10,r10,r7,lsl#14
+ eor r9,r9,r8,lsr#9
+ eor r10,r10,r7,lsr#9
+ eor r9,r9,r7,lsl#23
+ eor r10,r10,r8,lsl#23 @ Sigma1(e)
+ adds r3,r3,r9
+ ldr r9,[sp,#40+0] @ f.lo
+ adc r4,r4,r10 @ T += Sigma1(e)
+ ldr r10,[sp,#40+4] @ f.hi
+ adds r3,r3,r11
+ ldr r11,[sp,#48+0] @ g.lo
+ adc r4,r4,r12 @ T += h
+ ldr r12,[sp,#48+4] @ g.hi
+
+ eor r9,r9,r11
+ str r7,[sp,#32+0]
+ eor r10,r10,r12
+ str r8,[sp,#32+4]
+ and r9,r9,r7
+ str r5,[sp,#0+0]
+ and r10,r10,r8
+ str r6,[sp,#0+4]
+ eor r9,r9,r11
+ ldr r11,[r14,#LO] @ K[i].lo
+ eor r10,r10,r12 @ Ch(e,f,g)
+ ldr r12,[r14,#HI] @ K[i].hi
+
+ adds r3,r3,r9
+ ldr r7,[sp,#24+0] @ d.lo
+ adc r4,r4,r10 @ T += Ch(e,f,g)
+ ldr r8,[sp,#24+4] @ d.hi
+ adds r3,r3,r11
+ and r9,r11,#0xff
+ adc r4,r4,r12 @ T += K[i]
+ adds r7,r7,r3
+ ldr r11,[sp,#8+0] @ b.lo
+ adc r8,r8,r4 @ d += T
+ teq r9,#23
+
+ ldr r12,[sp,#16+0] @ c.lo
+#ifdef __thumb2__
+ it eq @ Thumb2 thing, sanity check in ARM
+#endif
+ orreq r14,r14,#1
+ @ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+ @ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+ @ HI hi>>28^lo<<4 ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+ mov r9,r5,lsr#28
+ mov r10,r6,lsr#28
+ eor r9,r9,r6,lsl#4
+ eor r10,r10,r5,lsl#4
+ eor r9,r9,r6,lsr#2
+ eor r10,r10,r5,lsr#2
+ eor r9,r9,r5,lsl#30
+ eor r10,r10,r6,lsl#30
+ eor r9,r9,r6,lsr#7
+ eor r10,r10,r5,lsr#7
+ eor r9,r9,r5,lsl#25
+ eor r10,r10,r6,lsl#25 @ Sigma0(a)
+ adds r3,r3,r9
+ and r9,r5,r11
+ adc r4,r4,r10 @ T += Sigma0(a)
+
+ ldr r10,[sp,#8+4] @ b.hi
+ orr r5,r5,r11
+ ldr r11,[sp,#16+4] @ c.hi
+ and r5,r5,r12
+ and r12,r6,r10
+ orr r6,r6,r10
+ orr r5,r5,r9 @ Maj(a,b,c).lo
+ and r6,r6,r11
+ adds r5,r5,r3
+ orr r6,r6,r12 @ Maj(a,b,c).hi
+ sub sp,sp,#8
+ adc r6,r6,r4 @ h += T
+ tst r14,#1
+ add r14,r14,#8
+#ifdef __thumb2__
+ ittt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ ldreq r9,[sp,#184+0]
+ ldreq r10,[sp,#184+4]
+ beq .L16_79
+ bic r14,r14,#1
+
+ ldr r3,[sp,#8+0]
+ ldr r4,[sp,#8+4]
+ ldr r9, [r0,#0+LO]
+ ldr r10, [r0,#0+HI]
+ ldr r11, [r0,#8+LO]
+ ldr r12, [r0,#8+HI]
+ adds r9,r5,r9
+ str r9, [r0,#0+LO]
+ adc r10,r6,r10
+ str r10, [r0,#0+HI]
+ adds r11,r3,r11
+ str r11, [r0,#8+LO]
+ adc r12,r4,r12
+ str r12, [r0,#8+HI]
+
+ ldr r5,[sp,#16+0]
+ ldr r6,[sp,#16+4]
+ ldr r3,[sp,#24+0]
+ ldr r4,[sp,#24+4]
+ ldr r9, [r0,#16+LO]
+ ldr r10, [r0,#16+HI]
+ ldr r11, [r0,#24+LO]
+ ldr r12, [r0,#24+HI]
+ adds r9,r5,r9
+ str r9, [r0,#16+LO]
+ adc r10,r6,r10
+ str r10, [r0,#16+HI]
+ adds r11,r3,r11
+ str r11, [r0,#24+LO]
+ adc r12,r4,r12
+ str r12, [r0,#24+HI]
+
+ ldr r3,[sp,#40+0]
+ ldr r4,[sp,#40+4]
+ ldr r9, [r0,#32+LO]
+ ldr r10, [r0,#32+HI]
+ ldr r11, [r0,#40+LO]
+ ldr r12, [r0,#40+HI]
+ adds r7,r7,r9
+ str r7,[r0,#32+LO]
+ adc r8,r8,r10
+ str r8,[r0,#32+HI]
+ adds r11,r3,r11
+ str r11, [r0,#40+LO]
+ adc r12,r4,r12
+ str r12, [r0,#40+HI]
+
+ ldr r5,[sp,#48+0]
+ ldr r6,[sp,#48+4]
+ ldr r3,[sp,#56+0]
+ ldr r4,[sp,#56+4]
+ ldr r9, [r0,#48+LO]
+ ldr r10, [r0,#48+HI]
+ ldr r11, [r0,#56+LO]
+ ldr r12, [r0,#56+HI]
+ adds r9,r5,r9
+ str r9, [r0,#48+LO]
+ adc r10,r6,r10
+ str r10, [r0,#48+HI]
+ adds r11,r3,r11
+ str r11, [r0,#56+LO]
+ adc r12,r4,r12
+ str r12, [r0,#56+HI]
+
+ add sp,sp,#640
+ sub r14,r14,#640
+
+ teq r1,r2
+ bne .Loop
+
+ add sp,sp,#8*9 @ destroy frame
+
+#if __ARM_ARCH__>=5
+ ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
+#else
+ ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+.word 0xe12fff1e @ interoperable with Thumb ISA:-)
+#endif
+.size zfs_sha512_block_armv7,.-zfs_sha512_block_armv7
+
+#if __ARM_ARCH__ >= 7
+.arch armv7-a
+.fpu neon
+
+.globl zfs_sha512_block_neon
+.type zfs_sha512_block_neon,%function
+.align 4
+zfs_sha512_block_neon:
+.LNEON:
+ dmb @ errata #451034 on early Cortex A8
+ add r2,r1,r2,lsl#7 @ len to point at the end of inp
+ adr r3,K512
+ VFP_ABI_PUSH
+ vldmia r0,{d16,d17,d18,d19,d20,d21,d22,d23} @ load context
+.Loop_neon:
+ vshr.u64 d24,d20,#14 @ 0
+#if 0<16
+ vld1.64 {d0},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d20,#18
+#if 0>0
+ vadd.i64 d16,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d20,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 0<16 && defined(__ARMEL__)
+ vrev64.8 d0,d0
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d0
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d23,d30
+ vshr.u64 d24,d19,#14 @ 1
+#if 1<16
+ vld1.64 {d1},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d19,#18
+#if 1>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 1<16 && defined(__ARMEL__)
+ vrev64.8 d1,d1
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d1
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 d24,d18,#14 @ 2
+#if 2<16
+ vld1.64 {d2},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d18,#18
+#if 2>0
+ vadd.i64 d22,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d18,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 2<16 && defined(__ARMEL__)
+ vrev64.8 d2,d2
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d2
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d21,d30
+ vshr.u64 d24,d17,#14 @ 3
+#if 3<16
+ vld1.64 {d3},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d17,#18
+#if 3>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 3<16 && defined(__ARMEL__)
+ vrev64.8 d3,d3
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d3
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 d24,d16,#14 @ 4
+#if 4<16
+ vld1.64 {d4},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d16,#18
+#if 4>0
+ vadd.i64 d20,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d16,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 4<16 && defined(__ARMEL__)
+ vrev64.8 d4,d4
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d4
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d19,d30
+ vshr.u64 d24,d23,#14 @ 5
+#if 5<16
+ vld1.64 {d5},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d23,#18
+#if 5>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 5<16 && defined(__ARMEL__)
+ vrev64.8 d5,d5
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d5
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 d24,d22,#14 @ 6
+#if 6<16
+ vld1.64 {d6},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d22,#18
+#if 6>0
+ vadd.i64 d18,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d22,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 6<16 && defined(__ARMEL__)
+ vrev64.8 d6,d6
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d6
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d17,d30
+ vshr.u64 d24,d21,#14 @ 7
+#if 7<16
+ vld1.64 {d7},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d21,#18
+#if 7>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 7<16 && defined(__ARMEL__)
+ vrev64.8 d7,d7
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d7
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ vshr.u64 d24,d20,#14 @ 8
+#if 8<16
+ vld1.64 {d8},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d20,#18
+#if 8>0
+ vadd.i64 d16,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d20,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 8<16 && defined(__ARMEL__)
+ vrev64.8 d8,d8
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d8
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d23,d30
+ vshr.u64 d24,d19,#14 @ 9
+#if 9<16
+ vld1.64 {d9},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d19,#18
+#if 9>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 9<16 && defined(__ARMEL__)
+ vrev64.8 d9,d9
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d9
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 d24,d18,#14 @ 10
+#if 10<16
+ vld1.64 {d10},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d18,#18
+#if 10>0
+ vadd.i64 d22,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d18,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 10<16 && defined(__ARMEL__)
+ vrev64.8 d10,d10
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d10
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d21,d30
+ vshr.u64 d24,d17,#14 @ 11
+#if 11<16
+ vld1.64 {d11},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d17,#18
+#if 11>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 11<16 && defined(__ARMEL__)
+ vrev64.8 d11,d11
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d11
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 d24,d16,#14 @ 12
+#if 12<16
+ vld1.64 {d12},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d16,#18
+#if 12>0
+ vadd.i64 d20,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d16,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 12<16 && defined(__ARMEL__)
+ vrev64.8 d12,d12
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d12
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d19,d30
+ vshr.u64 d24,d23,#14 @ 13
+#if 13<16
+ vld1.64 {d13},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d23,#18
+#if 13>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 13<16 && defined(__ARMEL__)
+ vrev64.8 d13,d13
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d13
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 d24,d22,#14 @ 14
+#if 14<16
+ vld1.64 {d14},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d22,#18
+#if 14>0
+ vadd.i64 d18,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d22,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 14<16 && defined(__ARMEL__)
+ vrev64.8 d14,d14
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d14
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d17,d30
+ vshr.u64 d24,d21,#14 @ 15
+#if 15<16
+ vld1.64 {d15},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d21,#18
+#if 15>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 15<16 && defined(__ARMEL__)
+ vrev64.8 d15,d15
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d15
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ mov r12,#4
+.L16_79_neon:
+ subs r12,#1
+ vshr.u64 q12,q7,#19
+ vshr.u64 q13,q7,#61
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ vshr.u64 q15,q7,#6
+ vsli.64 q12,q7,#45
+ vext.8 q14,q0,q1,#8 @ X[i+1]
+ vsli.64 q13,q7,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q0,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q4,q5,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d20,#14 @ from NEON_00_15
+ vadd.i64 q0,q14
+ vshr.u64 d25,d20,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d20,#41 @ from NEON_00_15
+ vadd.i64 q0,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 16<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d0
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d23,d30
+ vshr.u64 d24,d19,#14 @ 17
+#if 17<16
+ vld1.64 {d1},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d19,#18
+#if 17>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 17<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d1
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 q12,q0,#19
+ vshr.u64 q13,q0,#61
+ vadd.i64 d22,d30 @ h+=Maj from the past
+ vshr.u64 q15,q0,#6
+ vsli.64 q12,q0,#45
+ vext.8 q14,q1,q2,#8 @ X[i+1]
+ vsli.64 q13,q0,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q1,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q5,q6,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d18,#14 @ from NEON_00_15
+ vadd.i64 q1,q14
+ vshr.u64 d25,d18,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d18,#41 @ from NEON_00_15
+ vadd.i64 q1,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 18<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d2
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d21,d30
+ vshr.u64 d24,d17,#14 @ 19
+#if 19<16
+ vld1.64 {d3},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d17,#18
+#if 19>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 19<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d3
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 q12,q1,#19
+ vshr.u64 q13,q1,#61
+ vadd.i64 d20,d30 @ h+=Maj from the past
+ vshr.u64 q15,q1,#6
+ vsli.64 q12,q1,#45
+ vext.8 q14,q2,q3,#8 @ X[i+1]
+ vsli.64 q13,q1,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q2,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q6,q7,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d16,#14 @ from NEON_00_15
+ vadd.i64 q2,q14
+ vshr.u64 d25,d16,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d16,#41 @ from NEON_00_15
+ vadd.i64 q2,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 20<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d4
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d19,d30
+ vshr.u64 d24,d23,#14 @ 21
+#if 21<16
+ vld1.64 {d5},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d23,#18
+#if 21>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 21<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d5
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 q12,q2,#19
+ vshr.u64 q13,q2,#61
+ vadd.i64 d18,d30 @ h+=Maj from the past
+ vshr.u64 q15,q2,#6
+ vsli.64 q12,q2,#45
+ vext.8 q14,q3,q4,#8 @ X[i+1]
+ vsli.64 q13,q2,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q3,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q7,q0,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d22,#14 @ from NEON_00_15
+ vadd.i64 q3,q14
+ vshr.u64 d25,d22,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d22,#41 @ from NEON_00_15
+ vadd.i64 q3,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 22<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d6
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d17,d30
+ vshr.u64 d24,d21,#14 @ 23
+#if 23<16
+ vld1.64 {d7},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d21,#18
+#if 23>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 23<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d7
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ vshr.u64 q12,q3,#19
+ vshr.u64 q13,q3,#61
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ vshr.u64 q15,q3,#6
+ vsli.64 q12,q3,#45
+ vext.8 q14,q4,q5,#8 @ X[i+1]
+ vsli.64 q13,q3,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q4,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q0,q1,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d20,#14 @ from NEON_00_15
+ vadd.i64 q4,q14
+ vshr.u64 d25,d20,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d20,#41 @ from NEON_00_15
+ vadd.i64 q4,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 24<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d8
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d23,d30
+ vshr.u64 d24,d19,#14 @ 25
+#if 25<16
+ vld1.64 {d9},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d19,#18
+#if 25>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 25<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d9
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 q12,q4,#19
+ vshr.u64 q13,q4,#61
+ vadd.i64 d22,d30 @ h+=Maj from the past
+ vshr.u64 q15,q4,#6
+ vsli.64 q12,q4,#45
+ vext.8 q14,q5,q6,#8 @ X[i+1]
+ vsli.64 q13,q4,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q5,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q1,q2,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d18,#14 @ from NEON_00_15
+ vadd.i64 q5,q14
+ vshr.u64 d25,d18,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d18,#41 @ from NEON_00_15
+ vadd.i64 q5,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 26<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d10
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d21,d30
+ vshr.u64 d24,d17,#14 @ 27
+#if 27<16
+ vld1.64 {d11},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d17,#18
+#if 27>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 27<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d11
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 q12,q5,#19
+ vshr.u64 q13,q5,#61
+ vadd.i64 d20,d30 @ h+=Maj from the past
+ vshr.u64 q15,q5,#6
+ vsli.64 q12,q5,#45
+ vext.8 q14,q6,q7,#8 @ X[i+1]
+ vsli.64 q13,q5,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q6,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q2,q3,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d16,#14 @ from NEON_00_15
+ vadd.i64 q6,q14
+ vshr.u64 d25,d16,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d16,#41 @ from NEON_00_15
+ vadd.i64 q6,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 28<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d12
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d19,d30
+ vshr.u64 d24,d23,#14 @ 29
+#if 29<16
+ vld1.64 {d13},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d23,#18
+#if 29>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 29<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d13
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 q12,q6,#19
+ vshr.u64 q13,q6,#61
+ vadd.i64 d18,d30 @ h+=Maj from the past
+ vshr.u64 q15,q6,#6
+ vsli.64 q12,q6,#45
+ vext.8 q14,q7,q0,#8 @ X[i+1]
+ vsli.64 q13,q6,#3
+ veor q15,q12
+ vshr.u64 q12,q14,#1
+ veor q15,q13 @ sigma1(X[i+14])
+ vshr.u64 q13,q14,#8
+ vadd.i64 q7,q15
+ vshr.u64 q15,q14,#7
+ vsli.64 q12,q14,#63
+ vsli.64 q13,q14,#56
+ vext.8 q14,q3,q4,#8 @ X[i+9]
+ veor q15,q12
+ vshr.u64 d24,d22,#14 @ from NEON_00_15
+ vadd.i64 q7,q14
+ vshr.u64 d25,d22,#18 @ from NEON_00_15
+ veor q15,q13 @ sigma0(X[i+1])
+ vshr.u64 d26,d22,#41 @ from NEON_00_15
+ vadd.i64 q7,q15
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 30<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d14
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d17,d30
+ vshr.u64 d24,d21,#14 @ 31
+#if 31<16
+ vld1.64 {d15},[r1]! @ handles unaligned
+#endif
+ vshr.u64 d25,d21,#18
+#if 31>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 31<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d15
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ bne .L16_79_neon
+
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ vldmia r0,{d24,d25,d26,d27,d28,d29,d30,d31} @ load context to temp
+ vadd.i64 q8,q12 @ vectorized accumulate
+ vadd.i64 q9,q13
+ vadd.i64 q10,q14
+ vadd.i64 q11,q15
+ vstmia r0,{d16,d17,d18,d19,d20,d21,d22,d23} @ save context
+ teq r1,r2
+ sub r3,#640 @ rewind K512
+ bne .Loop_neon
+
+ VFP_ABI_POP
+ bx lr @ .word 0xe12fff1e
+.size zfs_sha512_block_neon,.-zfs_sha512_block_neon
+#endif // #if __ARM_ARCH__ >= 7
+#endif // #if defined(__arm__)
diff --git a/module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S b/module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S
index 9deba202fde8..ae8d0fad7c83 100644
--- a/module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S
+++ b/module/icp/asm-ppc64/blake3/b3_ppc64le_sse2.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S b/module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S
index a8b2627f12b0..315561d4497a 100644
--- a/module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S
+++ b/module/icp/asm-ppc64/blake3/b3_ppc64le_sse41.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/asm-ppc64/sha2/sha256-p8.S b/module/icp/asm-ppc64/sha2/sha256-p8.S
new file mode 100644
index 000000000000..dc3c4cea669c
--- /dev/null
+++ b/module/icp/asm-ppc64/sha2/sha256-p8.S
@@ -0,0 +1,1520 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if (defined(__PPC64__) && defined(__BIG_ENDIAN__))
+
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.text
+
+.globl zfs_sha256_power8
+.globl .zfs_sha256_power8
+.type zfs_sha256_power8,@function
+.section ".opd","aw"
+.align 3
+zfs_sha256_power8:
+.quad .zfs_sha256_power8,.TOC.@tocbase,0
+.previous
+.align 6
+.zfs_sha256_power8:
+#else
+.abiversion 2
+.text
+
+.globl zfs_sha256_power8
+.type zfs_sha256_power8,@function
+.align 6
+zfs_sha256_power8:
+.localentry zfs_sha256_power8,0
+#endif
+ stdu 1,-384(1)
+ mflr 8
+ li 10,207
+ li 11,223
+ stvx 24,10,1
+ addi 10,10,32
+ mfspr 12,256
+ stvx 25,11,1
+ addi 11,11,32
+ stvx 26,10,1
+ addi 10,10,32
+ stvx 27,11,1
+ addi 11,11,32
+ stvx 28,10,1
+ addi 10,10,32
+ stvx 29,11,1
+ addi 11,11,32
+ stvx 30,10,1
+ stvx 31,11,1
+ li 11,-4096+255
+ stw 12,332(1)
+ li 10,0x10
+ std 26,336(1)
+ li 26,0x20
+ std 27,344(1)
+ li 27,0x30
+ std 28,352(1)
+ li 28,0x40
+ std 29,360(1)
+ li 29,0x50
+ std 30,368(1)
+ li 30,0x60
+ std 31,376(1)
+ li 31,0x70
+ std 8,400(1)
+ mtspr 256,11
+
+ bl .LPICmeup
+ addi 11,1,79
+ .long 0x7C001E19
+ .long 0x7C8A1E19
+ vsldoi 1,0,0,4
+ vsldoi 2,0,0,8
+ vsldoi 3,0,0,12
+ vsldoi 5,4,4,4
+ vsldoi 6,4,4,8
+ vsldoi 7,4,4,12
+ li 0,3
+ b .Loop
+.align 5
+.Loop:
+ lvx 28,0,6
+ .long 0x7D002699
+ addi 4,4,16
+ mr 7,6
+ stvx 0,0,11
+ stvx 1,10,11
+ stvx 2,26,11
+ stvx 3,27,11
+ stvx 4,28,11
+ stvx 5,29,11
+ stvx 6,30,11
+ stvx 7,31,11
+ vadduwm 7,7,28
+ lvx 28,10,6
+ vadduwm 7,7,8
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ vsldoi 9,8,8,4
+ vadduwm 6,6,9
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ vsldoi 10,9,9,4
+ vadduwm 5,5,10
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x7D802699
+ addi 4,4,16
+ vsldoi 11,10,10,4
+ vadduwm 4,4,11
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ vadduwm 3,3,12
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ vsldoi 13,12,12,4
+ vadduwm 2,2,13
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ vsldoi 14,13,13,4
+ vadduwm 1,1,14
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x7E002699
+ addi 4,4,16
+ vsldoi 15,14,14,4
+ vadduwm 0,0,15
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ vadduwm 7,7,16
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ vsldoi 17,16,16,4
+ vadduwm 6,6,17
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ vsldoi 18,17,17,4
+ vadduwm 5,5,18
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x7F002699
+ addi 4,4,16
+ vsldoi 19,18,18,4
+ vadduwm 4,4,19
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ vadduwm 3,3,24
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ vsldoi 25,24,24,4
+ vadduwm 2,2,25
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ vsldoi 26,25,25,4
+ vadduwm 1,1,26
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ vsldoi 27,26,26,4
+ .long 0x13C90682
+ vadduwm 8,8,30
+ .long 0x13DA7E82
+ vadduwm 8,8,30
+ vadduwm 8,8,17
+ vadduwm 0,0,27
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ mtctr 0
+ b .L16_xx
+.align 5
+.L16_xx:
+ .long 0x13CA0682
+ vadduwm 9,9,30
+ .long 0x13DB7E82
+ vadduwm 9,9,30
+ vadduwm 9,9,18
+ vadduwm 7,7,8
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ .long 0x13CB0682
+ vadduwm 10,10,30
+ .long 0x13C87E82
+ vadduwm 10,10,30
+ vadduwm 10,10,19
+ vadduwm 6,6,9
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ .long 0x13CC0682
+ vadduwm 11,11,30
+ .long 0x13C97E82
+ vadduwm 11,11,30
+ vadduwm 11,11,24
+ vadduwm 5,5,10
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x13CD0682
+ vadduwm 12,12,30
+ .long 0x13CA7E82
+ vadduwm 12,12,30
+ vadduwm 12,12,25
+ vadduwm 4,4,11
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ .long 0x13CE0682
+ vadduwm 13,13,30
+ .long 0x13CB7E82
+ vadduwm 13,13,30
+ vadduwm 13,13,26
+ vadduwm 3,3,12
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ .long 0x13CF0682
+ vadduwm 14,14,30
+ .long 0x13CC7E82
+ vadduwm 14,14,30
+ vadduwm 14,14,27
+ vadduwm 2,2,13
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13D00682
+ vadduwm 15,15,30
+ .long 0x13CD7E82
+ vadduwm 15,15,30
+ vadduwm 15,15,8
+ vadduwm 1,1,14
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x13D10682
+ vadduwm 16,16,30
+ .long 0x13CE7E82
+ vadduwm 16,16,30
+ vadduwm 16,16,9
+ vadduwm 0,0,15
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ .long 0x13D20682
+ vadduwm 17,17,30
+ .long 0x13CF7E82
+ vadduwm 17,17,30
+ vadduwm 17,17,10
+ vadduwm 7,7,16
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ .long 0x13D30682
+ vadduwm 18,18,30
+ .long 0x13D07E82
+ vadduwm 18,18,30
+ vadduwm 18,18,11
+ vadduwm 6,6,17
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ .long 0x13D80682
+ vadduwm 19,19,30
+ .long 0x13D17E82
+ vadduwm 19,19,30
+ vadduwm 19,19,12
+ vadduwm 5,5,18
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x13D90682
+ vadduwm 24,24,30
+ .long 0x13D27E82
+ vadduwm 24,24,30
+ vadduwm 24,24,13
+ vadduwm 4,4,19
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ .long 0x13DA0682
+ vadduwm 25,25,30
+ .long 0x13D37E82
+ vadduwm 25,25,30
+ vadduwm 25,25,14
+ vadduwm 3,3,24
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ .long 0x13DB0682
+ vadduwm 26,26,30
+ .long 0x13D87E82
+ vadduwm 26,26,30
+ vadduwm 26,26,15
+ vadduwm 2,2,25
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13C80682
+ vadduwm 27,27,30
+ .long 0x13D97E82
+ vadduwm 27,27,30
+ vadduwm 27,27,16
+ vadduwm 1,1,26
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x13C90682
+ vadduwm 8,8,30
+ .long 0x13DA7E82
+ vadduwm 8,8,30
+ vadduwm 8,8,17
+ vadduwm 0,0,27
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ bdnz .L16_xx
+
+ lvx 10,0,11
+ subic. 5,5,1
+ lvx 11,10,11
+ vadduwm 0,0,10
+ lvx 12,26,11
+ vadduwm 1,1,11
+ lvx 13,27,11
+ vadduwm 2,2,12
+ lvx 14,28,11
+ vadduwm 3,3,13
+ lvx 15,29,11
+ vadduwm 4,4,14
+ lvx 16,30,11
+ vadduwm 5,5,15
+ lvx 17,31,11
+ vadduwm 6,6,16
+ vadduwm 7,7,17
+ bne .Loop
+ lvx 8,26,7
+ vperm 0,0,1,28
+ lvx 9,27,7
+ vperm 4,4,5,28
+ vperm 0,0,2,8
+ vperm 4,4,6,8
+ vperm 0,0,3,9
+ vperm 4,4,7,9
+ .long 0x7C001F19
+ .long 0x7C8A1F19
+ addi 11,1,207
+ mtlr 8
+ mtspr 256,12
+ lvx 24,0,11
+ lvx 25,10,11
+ lvx 26,26,11
+ lvx 27,27,11
+ lvx 28,28,11
+ lvx 29,29,11
+ lvx 30,30,11
+ lvx 31,31,11
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,6,3,0
+.long 0
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.size .zfs_sha256_power8,.-.zfs_sha256_power8
+.size zfs_sha256_power8,.-.zfs_sha256_power8
+#else
+.size zfs_sha256_power8,.-zfs_sha256_power8
+#endif
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 6
+ addi 6,6,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0x428a2f98,0x428a2f98,0x428a2f98
+.long 0x71374491,0x71374491,0x71374491,0x71374491
+.long 0xb5c0fbcf,0xb5c0fbcf,0xb5c0fbcf,0xb5c0fbcf
+.long 0xe9b5dba5,0xe9b5dba5,0xe9b5dba5,0xe9b5dba5
+.long 0x3956c25b,0x3956c25b,0x3956c25b,0x3956c25b
+.long 0x59f111f1,0x59f111f1,0x59f111f1,0x59f111f1
+.long 0x923f82a4,0x923f82a4,0x923f82a4,0x923f82a4
+.long 0xab1c5ed5,0xab1c5ed5,0xab1c5ed5,0xab1c5ed5
+.long 0xd807aa98,0xd807aa98,0xd807aa98,0xd807aa98
+.long 0x12835b01,0x12835b01,0x12835b01,0x12835b01
+.long 0x243185be,0x243185be,0x243185be,0x243185be
+.long 0x550c7dc3,0x550c7dc3,0x550c7dc3,0x550c7dc3
+.long 0x72be5d74,0x72be5d74,0x72be5d74,0x72be5d74
+.long 0x80deb1fe,0x80deb1fe,0x80deb1fe,0x80deb1fe
+.long 0x9bdc06a7,0x9bdc06a7,0x9bdc06a7,0x9bdc06a7
+.long 0xc19bf174,0xc19bf174,0xc19bf174,0xc19bf174
+.long 0xe49b69c1,0xe49b69c1,0xe49b69c1,0xe49b69c1
+.long 0xefbe4786,0xefbe4786,0xefbe4786,0xefbe4786
+.long 0x0fc19dc6,0x0fc19dc6,0x0fc19dc6,0x0fc19dc6
+.long 0x240ca1cc,0x240ca1cc,0x240ca1cc,0x240ca1cc
+.long 0x2de92c6f,0x2de92c6f,0x2de92c6f,0x2de92c6f
+.long 0x4a7484aa,0x4a7484aa,0x4a7484aa,0x4a7484aa
+.long 0x5cb0a9dc,0x5cb0a9dc,0x5cb0a9dc,0x5cb0a9dc
+.long 0x76f988da,0x76f988da,0x76f988da,0x76f988da
+.long 0x983e5152,0x983e5152,0x983e5152,0x983e5152
+.long 0xa831c66d,0xa831c66d,0xa831c66d,0xa831c66d
+.long 0xb00327c8,0xb00327c8,0xb00327c8,0xb00327c8
+.long 0xbf597fc7,0xbf597fc7,0xbf597fc7,0xbf597fc7
+.long 0xc6e00bf3,0xc6e00bf3,0xc6e00bf3,0xc6e00bf3
+.long 0xd5a79147,0xd5a79147,0xd5a79147,0xd5a79147
+.long 0x06ca6351,0x06ca6351,0x06ca6351,0x06ca6351
+.long 0x14292967,0x14292967,0x14292967,0x14292967
+.long 0x27b70a85,0x27b70a85,0x27b70a85,0x27b70a85
+.long 0x2e1b2138,0x2e1b2138,0x2e1b2138,0x2e1b2138
+.long 0x4d2c6dfc,0x4d2c6dfc,0x4d2c6dfc,0x4d2c6dfc
+.long 0x53380d13,0x53380d13,0x53380d13,0x53380d13
+.long 0x650a7354,0x650a7354,0x650a7354,0x650a7354
+.long 0x766a0abb,0x766a0abb,0x766a0abb,0x766a0abb
+.long 0x81c2c92e,0x81c2c92e,0x81c2c92e,0x81c2c92e
+.long 0x92722c85,0x92722c85,0x92722c85,0x92722c85
+.long 0xa2bfe8a1,0xa2bfe8a1,0xa2bfe8a1,0xa2bfe8a1
+.long 0xa81a664b,0xa81a664b,0xa81a664b,0xa81a664b
+.long 0xc24b8b70,0xc24b8b70,0xc24b8b70,0xc24b8b70
+.long 0xc76c51a3,0xc76c51a3,0xc76c51a3,0xc76c51a3
+.long 0xd192e819,0xd192e819,0xd192e819,0xd192e819
+.long 0xd6990624,0xd6990624,0xd6990624,0xd6990624
+.long 0xf40e3585,0xf40e3585,0xf40e3585,0xf40e3585
+.long 0x106aa070,0x106aa070,0x106aa070,0x106aa070
+.long 0x19a4c116,0x19a4c116,0x19a4c116,0x19a4c116
+.long 0x1e376c08,0x1e376c08,0x1e376c08,0x1e376c08
+.long 0x2748774c,0x2748774c,0x2748774c,0x2748774c
+.long 0x34b0bcb5,0x34b0bcb5,0x34b0bcb5,0x34b0bcb5
+.long 0x391c0cb3,0x391c0cb3,0x391c0cb3,0x391c0cb3
+.long 0x4ed8aa4a,0x4ed8aa4a,0x4ed8aa4a,0x4ed8aa4a
+.long 0x5b9cca4f,0x5b9cca4f,0x5b9cca4f,0x5b9cca4f
+.long 0x682e6ff3,0x682e6ff3,0x682e6ff3,0x682e6ff3
+.long 0x748f82ee,0x748f82ee,0x748f82ee,0x748f82ee
+.long 0x78a5636f,0x78a5636f,0x78a5636f,0x78a5636f
+.long 0x84c87814,0x84c87814,0x84c87814,0x84c87814
+.long 0x8cc70208,0x8cc70208,0x8cc70208,0x8cc70208
+.long 0x90befffa,0x90befffa,0x90befffa,0x90befffa
+.long 0xa4506ceb,0xa4506ceb,0xa4506ceb,0xa4506ceb
+.long 0xbef9a3f7,0xbef9a3f7,0xbef9a3f7,0xbef9a3f7
+.long 0xc67178f2,0xc67178f2,0xc67178f2,0xc67178f2
+.long 0,0,0,0
+.long 0x00010203,0x10111213,0x10111213,0x10111213
+.long 0x00010203,0x04050607,0x10111213,0x10111213
+.long 0x00010203,0x04050607,0x08090a0b,0x10111213
+
+#elif (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+
+.abiversion 2
+.text
+
+.globl zfs_sha256_power8
+.type zfs_sha256_power8,@function
+.align 6
+zfs_sha256_power8:
+.localentry zfs_sha256_power8,0
+
+ stdu 1,-384(1)
+ mflr 8
+ li 10,207
+ li 11,223
+ stvx 24,10,1
+ addi 10,10,32
+ li 12,-1
+ stvx 25,11,1
+ addi 11,11,32
+ stvx 26,10,1
+ addi 10,10,32
+ stvx 27,11,1
+ addi 11,11,32
+ stvx 28,10,1
+ addi 10,10,32
+ stvx 29,11,1
+ addi 11,11,32
+ stvx 30,10,1
+ stvx 31,11,1
+ li 11,-4096+255
+ stw 12,332(1)
+ li 10,0x10
+ std 26,336(1)
+ li 26,0x20
+ std 27,344(1)
+ li 27,0x30
+ std 28,352(1)
+ li 28,0x40
+ std 29,360(1)
+ li 29,0x50
+ std 30,368(1)
+ li 30,0x60
+ std 31,376(1)
+ li 31,0x70
+ std 8,400(1)
+ or 11,11,11
+
+ bl .LPICmeup
+ addi 11,1,79
+ li 7,8
+ lvsl 31,0,7
+ vspltisb 28,0x0f
+ vxor 31,31,28
+ .long 0x7C001E19
+ .long 0x7C8A1E19
+ vsldoi 1,0,0,4
+ vsldoi 2,0,0,8
+ vsldoi 3,0,0,12
+ vsldoi 5,4,4,4
+ vsldoi 6,4,4,8
+ vsldoi 7,4,4,12
+ li 0,3
+ b .Loop
+.align 5
+.Loop:
+ lvx 28,0,6
+ .long 0x7D002699
+ addi 4,4,16
+ mr 7,6
+ stvx 0,0,11
+ stvx 1,10,11
+ stvx 2,26,11
+ stvx 3,27,11
+ stvx 4,28,11
+ stvx 5,29,11
+ stvx 6,30,11
+ stvx 7,31,11
+ vadduwm 7,7,28
+ lvx 28,10,6
+ vperm 8,8,8,31
+ vadduwm 7,7,8
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ vsldoi 9,8,8,4
+ vadduwm 6,6,9
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ vsldoi 10,9,9,4
+ vadduwm 5,5,10
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x7D802699
+ addi 4,4,16
+ vsldoi 11,10,10,4
+ vadduwm 4,4,11
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ vperm 12,12,12,31
+ vadduwm 3,3,12
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ vsldoi 13,12,12,4
+ vadduwm 2,2,13
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ vsldoi 14,13,13,4
+ vadduwm 1,1,14
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x7E002699
+ addi 4,4,16
+ vsldoi 15,14,14,4
+ vadduwm 0,0,15
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ vperm 16,16,16,31
+ vadduwm 7,7,16
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ vsldoi 17,16,16,4
+ vadduwm 6,6,17
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ vsldoi 18,17,17,4
+ vadduwm 5,5,18
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x7F002699
+ addi 4,4,16
+ vsldoi 19,18,18,4
+ vadduwm 4,4,19
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ vperm 24,24,24,31
+ vadduwm 3,3,24
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ vsldoi 25,24,24,4
+ vadduwm 2,2,25
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ vsldoi 26,25,25,4
+ vadduwm 1,1,26
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ vsldoi 27,26,26,4
+ .long 0x13C90682
+ vadduwm 8,8,30
+ .long 0x13DA7E82
+ vadduwm 8,8,30
+ vadduwm 8,8,17
+ vadduwm 0,0,27
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ mtctr 0
+ b .L16_xx
+.align 5
+.L16_xx:
+ .long 0x13CA0682
+ vadduwm 9,9,30
+ .long 0x13DB7E82
+ vadduwm 9,9,30
+ vadduwm 9,9,18
+ vadduwm 7,7,8
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ .long 0x13CB0682
+ vadduwm 10,10,30
+ .long 0x13C87E82
+ vadduwm 10,10,30
+ vadduwm 10,10,19
+ vadduwm 6,6,9
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ .long 0x13CC0682
+ vadduwm 11,11,30
+ .long 0x13C97E82
+ vadduwm 11,11,30
+ vadduwm 11,11,24
+ vadduwm 5,5,10
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x13CD0682
+ vadduwm 12,12,30
+ .long 0x13CA7E82
+ vadduwm 12,12,30
+ vadduwm 12,12,25
+ vadduwm 4,4,11
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ .long 0x13CE0682
+ vadduwm 13,13,30
+ .long 0x13CB7E82
+ vadduwm 13,13,30
+ vadduwm 13,13,26
+ vadduwm 3,3,12
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ .long 0x13CF0682
+ vadduwm 14,14,30
+ .long 0x13CC7E82
+ vadduwm 14,14,30
+ vadduwm 14,14,27
+ vadduwm 2,2,13
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13D00682
+ vadduwm 15,15,30
+ .long 0x13CD7E82
+ vadduwm 15,15,30
+ vadduwm 15,15,8
+ vadduwm 1,1,14
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x13D10682
+ vadduwm 16,16,30
+ .long 0x13CE7E82
+ vadduwm 16,16,30
+ vadduwm 16,16,9
+ vadduwm 0,0,15
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ .long 0x13D20682
+ vadduwm 17,17,30
+ .long 0x13CF7E82
+ vadduwm 17,17,30
+ vadduwm 17,17,10
+ vadduwm 7,7,16
+ vsel 29,6,5,4
+ vadduwm 6,6,28
+ vadduwm 7,7,29
+ .long 0x13C4FE82
+ vadduwm 7,7,30
+ vxor 29,0,1
+ vsel 29,1,2,29
+ vadduwm 3,3,7
+ .long 0x13C08682
+ vadduwm 30,30,29
+ vadduwm 7,7,30
+ lvx 28,26,7
+ .long 0x13D30682
+ vadduwm 18,18,30
+ .long 0x13D07E82
+ vadduwm 18,18,30
+ vadduwm 18,18,11
+ vadduwm 6,6,17
+ vsel 29,5,4,3
+ vadduwm 5,5,28
+ vadduwm 6,6,29
+ .long 0x13C3FE82
+ vadduwm 6,6,30
+ vxor 29,7,0
+ vsel 29,0,1,29
+ vadduwm 2,2,6
+ .long 0x13C78682
+ vadduwm 30,30,29
+ vadduwm 6,6,30
+ lvx 28,27,7
+ .long 0x13D80682
+ vadduwm 19,19,30
+ .long 0x13D17E82
+ vadduwm 19,19,30
+ vadduwm 19,19,12
+ vadduwm 5,5,18
+ vsel 29,4,3,2
+ vadduwm 4,4,28
+ vadduwm 5,5,29
+ .long 0x13C2FE82
+ vadduwm 5,5,30
+ vxor 29,6,7
+ vsel 29,7,0,29
+ vadduwm 1,1,5
+ .long 0x13C68682
+ vadduwm 30,30,29
+ vadduwm 5,5,30
+ lvx 28,28,7
+ .long 0x13D90682
+ vadduwm 24,24,30
+ .long 0x13D27E82
+ vadduwm 24,24,30
+ vadduwm 24,24,13
+ vadduwm 4,4,19
+ vsel 29,3,2,1
+ vadduwm 3,3,28
+ vadduwm 4,4,29
+ .long 0x13C1FE82
+ vadduwm 4,4,30
+ vxor 29,5,6
+ vsel 29,6,7,29
+ vadduwm 0,0,4
+ .long 0x13C58682
+ vadduwm 30,30,29
+ vadduwm 4,4,30
+ lvx 28,29,7
+ .long 0x13DA0682
+ vadduwm 25,25,30
+ .long 0x13D37E82
+ vadduwm 25,25,30
+ vadduwm 25,25,14
+ vadduwm 3,3,24
+ vsel 29,2,1,0
+ vadduwm 2,2,28
+ vadduwm 3,3,29
+ .long 0x13C0FE82
+ vadduwm 3,3,30
+ vxor 29,4,5
+ vsel 29,5,6,29
+ vadduwm 7,7,3
+ .long 0x13C48682
+ vadduwm 30,30,29
+ vadduwm 3,3,30
+ lvx 28,30,7
+ .long 0x13DB0682
+ vadduwm 26,26,30
+ .long 0x13D87E82
+ vadduwm 26,26,30
+ vadduwm 26,26,15
+ vadduwm 2,2,25
+ vsel 29,1,0,7
+ vadduwm 1,1,28
+ vadduwm 2,2,29
+ .long 0x13C7FE82
+ vadduwm 2,2,30
+ vxor 29,3,4
+ vsel 29,4,5,29
+ vadduwm 6,6,2
+ .long 0x13C38682
+ vadduwm 30,30,29
+ vadduwm 2,2,30
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13C80682
+ vadduwm 27,27,30
+ .long 0x13D97E82
+ vadduwm 27,27,30
+ vadduwm 27,27,16
+ vadduwm 1,1,26
+ vsel 29,0,7,6
+ vadduwm 0,0,28
+ vadduwm 1,1,29
+ .long 0x13C6FE82
+ vadduwm 1,1,30
+ vxor 29,2,3
+ vsel 29,3,4,29
+ vadduwm 5,5,1
+ .long 0x13C28682
+ vadduwm 30,30,29
+ vadduwm 1,1,30
+ lvx 28,0,7
+ .long 0x13C90682
+ vadduwm 8,8,30
+ .long 0x13DA7E82
+ vadduwm 8,8,30
+ vadduwm 8,8,17
+ vadduwm 0,0,27
+ vsel 29,7,6,5
+ vadduwm 7,7,28
+ vadduwm 0,0,29
+ .long 0x13C5FE82
+ vadduwm 0,0,30
+ vxor 29,1,2
+ vsel 29,2,3,29
+ vadduwm 4,4,0
+ .long 0x13C18682
+ vadduwm 30,30,29
+ vadduwm 0,0,30
+ lvx 28,10,7
+ bdnz .L16_xx
+
+ lvx 10,0,11
+ subic. 5,5,1
+ lvx 11,10,11
+ vadduwm 0,0,10
+ lvx 12,26,11
+ vadduwm 1,1,11
+ lvx 13,27,11
+ vadduwm 2,2,12
+ lvx 14,28,11
+ vadduwm 3,3,13
+ lvx 15,29,11
+ vadduwm 4,4,14
+ lvx 16,30,11
+ vadduwm 5,5,15
+ lvx 17,31,11
+ vadduwm 6,6,16
+ vadduwm 7,7,17
+ bne .Loop
+ lvx 8,26,7
+ vperm 0,0,1,28
+ lvx 9,27,7
+ vperm 4,4,5,28
+ vperm 0,0,2,8
+ vperm 4,4,6,8
+ vperm 0,0,3,9
+ vperm 4,4,7,9
+ .long 0x7C001F19
+ .long 0x7C8A1F19
+ addi 11,1,207
+ mtlr 8
+ or 12,12,12
+ lvx 24,0,11
+ lvx 25,10,11
+ lvx 26,26,11
+ lvx 27,27,11
+ lvx 28,28,11
+ lvx 29,29,11
+ lvx 30,30,11
+ lvx 31,31,11
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,6,3,0
+.long 0
+.size zfs_sha256_power8,.-zfs_sha256_power8
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 6
+ addi 6,6,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0x428a2f98,0x428a2f98,0x428a2f98
+.long 0x71374491,0x71374491,0x71374491,0x71374491
+.long 0xb5c0fbcf,0xb5c0fbcf,0xb5c0fbcf,0xb5c0fbcf
+.long 0xe9b5dba5,0xe9b5dba5,0xe9b5dba5,0xe9b5dba5
+.long 0x3956c25b,0x3956c25b,0x3956c25b,0x3956c25b
+.long 0x59f111f1,0x59f111f1,0x59f111f1,0x59f111f1
+.long 0x923f82a4,0x923f82a4,0x923f82a4,0x923f82a4
+.long 0xab1c5ed5,0xab1c5ed5,0xab1c5ed5,0xab1c5ed5
+.long 0xd807aa98,0xd807aa98,0xd807aa98,0xd807aa98
+.long 0x12835b01,0x12835b01,0x12835b01,0x12835b01
+.long 0x243185be,0x243185be,0x243185be,0x243185be
+.long 0x550c7dc3,0x550c7dc3,0x550c7dc3,0x550c7dc3
+.long 0x72be5d74,0x72be5d74,0x72be5d74,0x72be5d74
+.long 0x80deb1fe,0x80deb1fe,0x80deb1fe,0x80deb1fe
+.long 0x9bdc06a7,0x9bdc06a7,0x9bdc06a7,0x9bdc06a7
+.long 0xc19bf174,0xc19bf174,0xc19bf174,0xc19bf174
+.long 0xe49b69c1,0xe49b69c1,0xe49b69c1,0xe49b69c1
+.long 0xefbe4786,0xefbe4786,0xefbe4786,0xefbe4786
+.long 0x0fc19dc6,0x0fc19dc6,0x0fc19dc6,0x0fc19dc6
+.long 0x240ca1cc,0x240ca1cc,0x240ca1cc,0x240ca1cc
+.long 0x2de92c6f,0x2de92c6f,0x2de92c6f,0x2de92c6f
+.long 0x4a7484aa,0x4a7484aa,0x4a7484aa,0x4a7484aa
+.long 0x5cb0a9dc,0x5cb0a9dc,0x5cb0a9dc,0x5cb0a9dc
+.long 0x76f988da,0x76f988da,0x76f988da,0x76f988da
+.long 0x983e5152,0x983e5152,0x983e5152,0x983e5152
+.long 0xa831c66d,0xa831c66d,0xa831c66d,0xa831c66d
+.long 0xb00327c8,0xb00327c8,0xb00327c8,0xb00327c8
+.long 0xbf597fc7,0xbf597fc7,0xbf597fc7,0xbf597fc7
+.long 0xc6e00bf3,0xc6e00bf3,0xc6e00bf3,0xc6e00bf3
+.long 0xd5a79147,0xd5a79147,0xd5a79147,0xd5a79147
+.long 0x06ca6351,0x06ca6351,0x06ca6351,0x06ca6351
+.long 0x14292967,0x14292967,0x14292967,0x14292967
+.long 0x27b70a85,0x27b70a85,0x27b70a85,0x27b70a85
+.long 0x2e1b2138,0x2e1b2138,0x2e1b2138,0x2e1b2138
+.long 0x4d2c6dfc,0x4d2c6dfc,0x4d2c6dfc,0x4d2c6dfc
+.long 0x53380d13,0x53380d13,0x53380d13,0x53380d13
+.long 0x650a7354,0x650a7354,0x650a7354,0x650a7354
+.long 0x766a0abb,0x766a0abb,0x766a0abb,0x766a0abb
+.long 0x81c2c92e,0x81c2c92e,0x81c2c92e,0x81c2c92e
+.long 0x92722c85,0x92722c85,0x92722c85,0x92722c85
+.long 0xa2bfe8a1,0xa2bfe8a1,0xa2bfe8a1,0xa2bfe8a1
+.long 0xa81a664b,0xa81a664b,0xa81a664b,0xa81a664b
+.long 0xc24b8b70,0xc24b8b70,0xc24b8b70,0xc24b8b70
+.long 0xc76c51a3,0xc76c51a3,0xc76c51a3,0xc76c51a3
+.long 0xd192e819,0xd192e819,0xd192e819,0xd192e819
+.long 0xd6990624,0xd6990624,0xd6990624,0xd6990624
+.long 0xf40e3585,0xf40e3585,0xf40e3585,0xf40e3585
+.long 0x106aa070,0x106aa070,0x106aa070,0x106aa070
+.long 0x19a4c116,0x19a4c116,0x19a4c116,0x19a4c116
+.long 0x1e376c08,0x1e376c08,0x1e376c08,0x1e376c08
+.long 0x2748774c,0x2748774c,0x2748774c,0x2748774c
+.long 0x34b0bcb5,0x34b0bcb5,0x34b0bcb5,0x34b0bcb5
+.long 0x391c0cb3,0x391c0cb3,0x391c0cb3,0x391c0cb3
+.long 0x4ed8aa4a,0x4ed8aa4a,0x4ed8aa4a,0x4ed8aa4a
+.long 0x5b9cca4f,0x5b9cca4f,0x5b9cca4f,0x5b9cca4f
+.long 0x682e6ff3,0x682e6ff3,0x682e6ff3,0x682e6ff3
+.long 0x748f82ee,0x748f82ee,0x748f82ee,0x748f82ee
+.long 0x78a5636f,0x78a5636f,0x78a5636f,0x78a5636f
+.long 0x84c87814,0x84c87814,0x84c87814,0x84c87814
+.long 0x8cc70208,0x8cc70208,0x8cc70208,0x8cc70208
+.long 0x90befffa,0x90befffa,0x90befffa,0x90befffa
+.long 0xa4506ceb,0xa4506ceb,0xa4506ceb,0xa4506ceb
+.long 0xbef9a3f7,0xbef9a3f7,0xbef9a3f7,0xbef9a3f7
+.long 0xc67178f2,0xc67178f2,0xc67178f2,0xc67178f2
+.long 0,0,0,0
+.long 0x10111213,0x10111213,0x10111213,0x00010203
+.long 0x10111213,0x10111213,0x04050607,0x00010203
+.long 0x10111213,0x08090a0b,0x04050607,0x00010203
+#endif
diff --git a/module/icp/asm-ppc64/sha2/sha256-ppc.S b/module/icp/asm-ppc64/sha2/sha256-ppc.S
new file mode 100644
index 000000000000..d039bc36ee11
--- /dev/null
+++ b/module/icp/asm-ppc64/sha2/sha256-ppc.S
@@ -0,0 +1,2727 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if (defined(__PPC64__) && defined(__BIG_ENDIAN__))
+
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.text
+
+.globl zfs_sha256_ppc
+.globl .zfs_sha256_ppc
+.type zfs_sha256_ppc,@function
+.section ".opd","aw"
+.align 3
+zfs_sha256_ppc:
+.quad .zfs_sha256_ppc,.TOC.@tocbase,0
+.previous
+.align 6
+.zfs_sha256_ppc:
+#else
+.abiversion 2
+.text
+
+.globl zfs_sha256_ppc
+.type zfs_sha256_ppc,@function
+.align 6
+zfs_sha256_ppc:
+.localentry zfs_sha256_ppc,0
+#endif
+ stdu 1,-320(1)
+ mflr 0
+ sldi 5,5,6
+
+ std 3,144(1)
+
+ std 14,176(1)
+ std 15,184(1)
+ std 16,192(1)
+ std 17,200(1)
+ std 18,208(1)
+ std 19,216(1)
+ std 20,224(1)
+ std 21,232(1)
+ std 22,240(1)
+ std 23,248(1)
+ std 24,256(1)
+ std 25,264(1)
+ std 26,272(1)
+ std 27,280(1)
+ std 28,288(1)
+ std 29,296(1)
+ std 30,304(1)
+ std 31,312(1)
+ std 0,336(1)
+ lwz 8,0(3)
+ mr 31,4
+ lwz 9,4(3)
+ lwz 10,8(3)
+ lwz 11,12(3)
+ lwz 12,16(3)
+ lwz 6,20(3)
+ lwz 14,24(3)
+ lwz 15,28(3)
+ bl .LPICmeup
+.LPICedup:
+ andi. 0,31,3
+ bne .Lunaligned
+.Laligned:
+ add 5,31,5
+ std 5,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+ b .Ldone
+
+.align 4
+.Lunaligned:
+ subfic 0,31,4096
+ andi. 0,0,4032
+ beq .Lcross_page
+ cmpld 5,0
+ ble .Laligned
+ subfc 5,0,5
+ add 0,31,0
+ std 5,120(1)
+ std 0,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+
+ ld 5,120(1)
+.Lcross_page:
+ li 0,16
+ mtctr 0
+ addi 20,1,48
+.Lmemcpy:
+ lbz 16,0(31)
+ lbz 17,1(31)
+ lbz 18,2(31)
+ lbz 19,3(31)
+ addi 31,31,4
+ stb 16,0(20)
+ stb 17,1(20)
+ stb 18,2(20)
+ stb 19,3(20)
+ addi 20,20,4
+ bdnz .Lmemcpy
+ std 31,112(1)
+ addi 0,1,112
+ addi 31,1,48
+ std 5,120(1)
+ std 0,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+ ld 31,112(1)
+ ld 5,120(1)
+ addic. 5,5,-64
+ bne .Lunaligned
+
+.Ldone:
+ ld 0,336(1)
+ ld 14,176(1)
+ ld 15,184(1)
+ ld 16,192(1)
+ ld 17,200(1)
+ ld 18,208(1)
+ ld 19,216(1)
+ ld 20,224(1)
+ ld 21,232(1)
+ ld 22,240(1)
+ ld 23,248(1)
+ ld 24,256(1)
+ ld 25,264(1)
+ ld 26,272(1)
+ ld 27,280(1)
+ ld 28,288(1)
+ ld 29,296(1)
+ ld 30,304(1)
+ ld 31,312(1)
+ mtlr 0
+ addi 1,1,320
+ blr
+.long 0
+.byte 0,12,4,1,0x80,18,3,0
+.long 0
+.align 4
+.Lsha2_block_private:
+ lwz 0,0(7)
+ lwz 16,0(31)
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ lwz 0,4(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 17,4(31)
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ lwz 0,8(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 18,8(31)
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ lwz 0,12(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 19,12(31)
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ lwz 0,16(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 20,16(31)
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ lwz 0,20(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 21,20(31)
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ lwz 0,24(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 22,24(31)
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ lwz 0,28(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 23,28(31)
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ lwz 0,32(7)
+ add 8,8,3
+ add 8,8,5
+
+ lwz 24,32(31)
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ lwz 0,36(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 25,36(31)
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ lwz 0,40(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 26,40(31)
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ lwz 0,44(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 27,44(31)
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ lwz 0,48(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 28,48(31)
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ lwz 0,52(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 29,52(31)
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ lwz 0,56(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 30,56(31)
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ lwz 0,60(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 31,60(31)
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ li 5,3
+ mtctr 5
+.align 4
+.Lrounds:
+ addi 7,7,64
+ rotrwi 3,17,7
+ rotrwi 4,17,18
+ rotrwi 5,30,17
+ rotrwi 0,30,19
+ xor 3,3,4
+ srwi 4,17,3
+ xor 5,5,0
+ srwi 0,30,10
+ add 16,16,25
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,0(7)
+ add 16,16,3
+ add 16,16,5
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrwi 3,18,7
+ rotrwi 4,18,18
+ rotrwi 5,31,17
+ rotrwi 0,31,19
+ xor 3,3,4
+ srwi 4,18,3
+ xor 5,5,0
+ srwi 0,31,10
+ add 17,17,26
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,4(7)
+ add 17,17,3
+ add 17,17,5
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrwi 3,19,7
+ rotrwi 4,19,18
+ rotrwi 5,16,17
+ rotrwi 0,16,19
+ xor 3,3,4
+ srwi 4,19,3
+ xor 5,5,0
+ srwi 0,16,10
+ add 18,18,27
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,8(7)
+ add 18,18,3
+ add 18,18,5
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrwi 3,20,7
+ rotrwi 4,20,18
+ rotrwi 5,17,17
+ rotrwi 0,17,19
+ xor 3,3,4
+ srwi 4,20,3
+ xor 5,5,0
+ srwi 0,17,10
+ add 19,19,28
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,12(7)
+ add 19,19,3
+ add 19,19,5
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrwi 3,21,7
+ rotrwi 4,21,18
+ rotrwi 5,18,17
+ rotrwi 0,18,19
+ xor 3,3,4
+ srwi 4,21,3
+ xor 5,5,0
+ srwi 0,18,10
+ add 20,20,29
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,16(7)
+ add 20,20,3
+ add 20,20,5
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrwi 3,22,7
+ rotrwi 4,22,18
+ rotrwi 5,19,17
+ rotrwi 0,19,19
+ xor 3,3,4
+ srwi 4,22,3
+ xor 5,5,0
+ srwi 0,19,10
+ add 21,21,30
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,20(7)
+ add 21,21,3
+ add 21,21,5
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrwi 3,23,7
+ rotrwi 4,23,18
+ rotrwi 5,20,17
+ rotrwi 0,20,19
+ xor 3,3,4
+ srwi 4,23,3
+ xor 5,5,0
+ srwi 0,20,10
+ add 22,22,31
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,24(7)
+ add 22,22,3
+ add 22,22,5
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrwi 3,24,7
+ rotrwi 4,24,18
+ rotrwi 5,21,17
+ rotrwi 0,21,19
+ xor 3,3,4
+ srwi 4,24,3
+ xor 5,5,0
+ srwi 0,21,10
+ add 23,23,16
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,28(7)
+ add 23,23,3
+ add 23,23,5
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ rotrwi 3,25,7
+ rotrwi 4,25,18
+ rotrwi 5,22,17
+ rotrwi 0,22,19
+ xor 3,3,4
+ srwi 4,25,3
+ xor 5,5,0
+ srwi 0,22,10
+ add 24,24,17
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,32(7)
+ add 24,24,3
+ add 24,24,5
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrwi 3,26,7
+ rotrwi 4,26,18
+ rotrwi 5,23,17
+ rotrwi 0,23,19
+ xor 3,3,4
+ srwi 4,26,3
+ xor 5,5,0
+ srwi 0,23,10
+ add 25,25,18
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,36(7)
+ add 25,25,3
+ add 25,25,5
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrwi 3,27,7
+ rotrwi 4,27,18
+ rotrwi 5,24,17
+ rotrwi 0,24,19
+ xor 3,3,4
+ srwi 4,27,3
+ xor 5,5,0
+ srwi 0,24,10
+ add 26,26,19
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,40(7)
+ add 26,26,3
+ add 26,26,5
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrwi 3,28,7
+ rotrwi 4,28,18
+ rotrwi 5,25,17
+ rotrwi 0,25,19
+ xor 3,3,4
+ srwi 4,28,3
+ xor 5,5,0
+ srwi 0,25,10
+ add 27,27,20
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,44(7)
+ add 27,27,3
+ add 27,27,5
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrwi 3,29,7
+ rotrwi 4,29,18
+ rotrwi 5,26,17
+ rotrwi 0,26,19
+ xor 3,3,4
+ srwi 4,29,3
+ xor 5,5,0
+ srwi 0,26,10
+ add 28,28,21
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,48(7)
+ add 28,28,3
+ add 28,28,5
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrwi 3,30,7
+ rotrwi 4,30,18
+ rotrwi 5,27,17
+ rotrwi 0,27,19
+ xor 3,3,4
+ srwi 4,30,3
+ xor 5,5,0
+ srwi 0,27,10
+ add 29,29,22
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,52(7)
+ add 29,29,3
+ add 29,29,5
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrwi 3,31,7
+ rotrwi 4,31,18
+ rotrwi 5,28,17
+ rotrwi 0,28,19
+ xor 3,3,4
+ srwi 4,31,3
+ xor 5,5,0
+ srwi 0,28,10
+ add 30,30,23
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,56(7)
+ add 30,30,3
+ add 30,30,5
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrwi 3,16,7
+ rotrwi 4,16,18
+ rotrwi 5,29,17
+ rotrwi 0,29,19
+ xor 3,3,4
+ srwi 4,16,3
+ xor 5,5,0
+ srwi 0,29,10
+ add 31,31,24
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,60(7)
+ add 31,31,3
+ add 31,31,5
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ bdnz .Lrounds
+
+ ld 3,144(1)
+ ld 31,136(1)
+ ld 5,128(1)
+ subi 7,7,192
+
+ lwz 16,0(3)
+ lwz 17,4(3)
+ lwz 18,8(3)
+ lwz 19,12(3)
+ lwz 20,16(3)
+ lwz 21,20(3)
+ lwz 22,24(3)
+ addi 31,31,64
+ lwz 23,28(3)
+ add 8,8,16
+ add 9,9,17
+ std 31,136(1)
+ add 10,10,18
+ stw 8,0(3)
+ add 11,11,19
+ stw 9,4(3)
+ add 12,12,20
+ stw 10,8(3)
+ add 6,6,21
+ stw 11,12(3)
+ add 14,14,22
+ stw 12,16(3)
+ add 15,15,23
+ stw 6,20(3)
+ stw 14,24(3)
+ cmpld 31,5
+ stw 15,28(3)
+ bne .Lsha2_block_private
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.size .zfs_sha256_ppc,.-.zfs_sha256_ppc
+.size zfs_sha256_ppc,.-.zfs_sha256_ppc
+#else
+.size zfs_sha256_ppc,.-zfs_sha256_ppc
+#endif
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 7
+ addi 7,7,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+#elif (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+
+.abiversion 2
+.text
+
+.globl zfs_sha256_ppc
+.type zfs_sha256_ppc,@function
+.align 6
+zfs_sha256_ppc:
+.localentry zfs_sha256_ppc,0
+
+ stdu 1,-320(1)
+ mflr 0
+ sldi 5,5,6
+
+ std 3,144(1)
+
+ std 14,176(1)
+ std 15,184(1)
+ std 16,192(1)
+ std 17,200(1)
+ std 18,208(1)
+ std 19,216(1)
+ std 20,224(1)
+ std 21,232(1)
+ std 22,240(1)
+ std 23,248(1)
+ std 24,256(1)
+ std 25,264(1)
+ std 26,272(1)
+ std 27,280(1)
+ std 28,288(1)
+ std 29,296(1)
+ std 30,304(1)
+ std 31,312(1)
+ std 0,336(1)
+ lwz 8,0(3)
+ mr 31,4
+ lwz 9,4(3)
+ lwz 10,8(3)
+ lwz 11,12(3)
+ lwz 12,16(3)
+ lwz 6,20(3)
+ lwz 14,24(3)
+ lwz 15,28(3)
+ bl .LPICmeup
+.LPICedup:
+ andi. 0,31,3
+ bne .Lunaligned
+.Laligned:
+ add 5,31,5
+ std 5,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+ b .Ldone
+
+.align 4
+.Lunaligned:
+ subfic 0,31,4096
+ andi. 0,0,4032
+ beq .Lcross_page
+ cmpld 5,0
+ ble .Laligned
+ subfc 5,0,5
+ add 0,31,0
+ std 5,120(1)
+ std 0,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+
+ ld 5,120(1)
+.Lcross_page:
+ li 0,16
+ mtctr 0
+ addi 20,1,48
+.Lmemcpy:
+ lbz 16,0(31)
+ lbz 17,1(31)
+ lbz 18,2(31)
+ lbz 19,3(31)
+ addi 31,31,4
+ stb 16,0(20)
+ stb 17,1(20)
+ stb 18,2(20)
+ stb 19,3(20)
+ addi 20,20,4
+ bdnz .Lmemcpy
+ std 31,112(1)
+ addi 0,1,112
+ addi 31,1,48
+ std 5,120(1)
+ std 0,128(1)
+ std 31,136(1)
+ bl .Lsha2_block_private
+ ld 31,112(1)
+ ld 5,120(1)
+ addic. 5,5,-64
+ bne .Lunaligned
+
+.Ldone:
+ ld 0,336(1)
+ ld 14,176(1)
+ ld 15,184(1)
+ ld 16,192(1)
+ ld 17,200(1)
+ ld 18,208(1)
+ ld 19,216(1)
+ ld 20,224(1)
+ ld 21,232(1)
+ ld 22,240(1)
+ ld 23,248(1)
+ ld 24,256(1)
+ ld 25,264(1)
+ ld 26,272(1)
+ ld 27,280(1)
+ ld 28,288(1)
+ ld 29,296(1)
+ ld 30,304(1)
+ ld 31,312(1)
+ mtlr 0
+ addi 1,1,320
+ blr
+.long 0
+.byte 0,12,4,1,0x80,18,3,0
+.long 0
+.align 4
+.Lsha2_block_private:
+ lwz 0,0(7)
+ lwz 3,0(31)
+ rotlwi 16,3,8
+ rlwimi 16,3,24,0,7
+ rlwimi 16,3,24,16,23
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ lwz 0,4(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 3,4(31)
+ rotlwi 17,3,8
+ rlwimi 17,3,24,0,7
+ rlwimi 17,3,24,16,23
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ lwz 0,8(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 3,8(31)
+ rotlwi 18,3,8
+ rlwimi 18,3,24,0,7
+ rlwimi 18,3,24,16,23
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ lwz 0,12(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 3,12(31)
+ rotlwi 19,3,8
+ rlwimi 19,3,24,0,7
+ rlwimi 19,3,24,16,23
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ lwz 0,16(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 3,16(31)
+ rotlwi 20,3,8
+ rlwimi 20,3,24,0,7
+ rlwimi 20,3,24,16,23
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ lwz 0,20(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 3,20(31)
+ rotlwi 21,3,8
+ rlwimi 21,3,24,0,7
+ rlwimi 21,3,24,16,23
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ lwz 0,24(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 3,24(31)
+ rotlwi 22,3,8
+ rlwimi 22,3,24,0,7
+ rlwimi 22,3,24,16,23
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ lwz 0,28(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 3,28(31)
+ rotlwi 23,3,8
+ rlwimi 23,3,24,0,7
+ rlwimi 23,3,24,16,23
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ lwz 0,32(7)
+ add 8,8,3
+ add 8,8,5
+
+ lwz 3,32(31)
+ rotlwi 24,3,8
+ rlwimi 24,3,24,0,7
+ rlwimi 24,3,24,16,23
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ lwz 0,36(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 3,36(31)
+ rotlwi 25,3,8
+ rlwimi 25,3,24,0,7
+ rlwimi 25,3,24,16,23
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ lwz 0,40(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 3,40(31)
+ rotlwi 26,3,8
+ rlwimi 26,3,24,0,7
+ rlwimi 26,3,24,16,23
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ lwz 0,44(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 3,44(31)
+ rotlwi 27,3,8
+ rlwimi 27,3,24,0,7
+ rlwimi 27,3,24,16,23
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ lwz 0,48(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 3,48(31)
+ rotlwi 28,3,8
+ rlwimi 28,3,24,0,7
+ rlwimi 28,3,24,16,23
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ lwz 0,52(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 3,52(31)
+ rotlwi 29,3,8
+ rlwimi 29,3,24,0,7
+ rlwimi 29,3,24,16,23
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ lwz 0,56(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 3,56(31)
+ rotlwi 30,3,8
+ rlwimi 30,3,24,0,7
+ rlwimi 30,3,24,16,23
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ lwz 0,60(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 3,60(31)
+ rotlwi 31,3,8
+ rlwimi 31,3,24,0,7
+ rlwimi 31,3,24,16,23
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ li 5,3
+ mtctr 5
+.align 4
+.Lrounds:
+ addi 7,7,64
+ rotrwi 3,17,7
+ rotrwi 4,17,18
+ rotrwi 5,30,17
+ rotrwi 0,30,19
+ xor 3,3,4
+ srwi 4,17,3
+ xor 5,5,0
+ srwi 0,30,10
+ add 16,16,25
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,0(7)
+ add 16,16,3
+ add 16,16,5
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrwi 3,18,7
+ rotrwi 4,18,18
+ rotrwi 5,31,17
+ rotrwi 0,31,19
+ xor 3,3,4
+ srwi 4,18,3
+ xor 5,5,0
+ srwi 0,31,10
+ add 17,17,26
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,4(7)
+ add 17,17,3
+ add 17,17,5
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrwi 3,19,7
+ rotrwi 4,19,18
+ rotrwi 5,16,17
+ rotrwi 0,16,19
+ xor 3,3,4
+ srwi 4,19,3
+ xor 5,5,0
+ srwi 0,16,10
+ add 18,18,27
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,8(7)
+ add 18,18,3
+ add 18,18,5
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrwi 3,20,7
+ rotrwi 4,20,18
+ rotrwi 5,17,17
+ rotrwi 0,17,19
+ xor 3,3,4
+ srwi 4,20,3
+ xor 5,5,0
+ srwi 0,17,10
+ add 19,19,28
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,12(7)
+ add 19,19,3
+ add 19,19,5
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrwi 3,21,7
+ rotrwi 4,21,18
+ rotrwi 5,18,17
+ rotrwi 0,18,19
+ xor 3,3,4
+ srwi 4,21,3
+ xor 5,5,0
+ srwi 0,18,10
+ add 20,20,29
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,16(7)
+ add 20,20,3
+ add 20,20,5
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrwi 3,22,7
+ rotrwi 4,22,18
+ rotrwi 5,19,17
+ rotrwi 0,19,19
+ xor 3,3,4
+ srwi 4,22,3
+ xor 5,5,0
+ srwi 0,19,10
+ add 21,21,30
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,20(7)
+ add 21,21,3
+ add 21,21,5
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrwi 3,23,7
+ rotrwi 4,23,18
+ rotrwi 5,20,17
+ rotrwi 0,20,19
+ xor 3,3,4
+ srwi 4,23,3
+ xor 5,5,0
+ srwi 0,20,10
+ add 22,22,31
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,24(7)
+ add 22,22,3
+ add 22,22,5
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrwi 3,24,7
+ rotrwi 4,24,18
+ rotrwi 5,21,17
+ rotrwi 0,21,19
+ xor 3,3,4
+ srwi 4,24,3
+ xor 5,5,0
+ srwi 0,21,10
+ add 23,23,16
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,28(7)
+ add 23,23,3
+ add 23,23,5
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ rotrwi 3,25,7
+ rotrwi 4,25,18
+ rotrwi 5,22,17
+ rotrwi 0,22,19
+ xor 3,3,4
+ srwi 4,25,3
+ xor 5,5,0
+ srwi 0,22,10
+ add 24,24,17
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,32(7)
+ add 24,24,3
+ add 24,24,5
+ rotrwi 3,12,6
+ rotrwi 4,12,11
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrwi 4,4,14
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrwi 3,8,2
+ rotrwi 4,8,13
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrwi 3,26,7
+ rotrwi 4,26,18
+ rotrwi 5,23,17
+ rotrwi 0,23,19
+ xor 3,3,4
+ srwi 4,26,3
+ xor 5,5,0
+ srwi 0,23,10
+ add 25,25,18
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,36(7)
+ add 25,25,3
+ add 25,25,5
+ rotrwi 3,11,6
+ rotrwi 4,11,11
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrwi 4,4,14
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrwi 3,15,2
+ rotrwi 4,15,13
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrwi 3,27,7
+ rotrwi 4,27,18
+ rotrwi 5,24,17
+ rotrwi 0,24,19
+ xor 3,3,4
+ srwi 4,27,3
+ xor 5,5,0
+ srwi 0,24,10
+ add 26,26,19
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,40(7)
+ add 26,26,3
+ add 26,26,5
+ rotrwi 3,10,6
+ rotrwi 4,10,11
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrwi 4,4,14
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrwi 3,14,2
+ rotrwi 4,14,13
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrwi 3,28,7
+ rotrwi 4,28,18
+ rotrwi 5,25,17
+ rotrwi 0,25,19
+ xor 3,3,4
+ srwi 4,28,3
+ xor 5,5,0
+ srwi 0,25,10
+ add 27,27,20
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,44(7)
+ add 27,27,3
+ add 27,27,5
+ rotrwi 3,9,6
+ rotrwi 4,9,11
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrwi 4,4,14
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrwi 3,6,2
+ rotrwi 4,6,13
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrwi 3,29,7
+ rotrwi 4,29,18
+ rotrwi 5,26,17
+ rotrwi 0,26,19
+ xor 3,3,4
+ srwi 4,29,3
+ xor 5,5,0
+ srwi 0,26,10
+ add 28,28,21
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,48(7)
+ add 28,28,3
+ add 28,28,5
+ rotrwi 3,8,6
+ rotrwi 4,8,11
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrwi 4,4,14
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrwi 3,12,2
+ rotrwi 4,12,13
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrwi 3,30,7
+ rotrwi 4,30,18
+ rotrwi 5,27,17
+ rotrwi 0,27,19
+ xor 3,3,4
+ srwi 4,30,3
+ xor 5,5,0
+ srwi 0,27,10
+ add 29,29,22
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,52(7)
+ add 29,29,3
+ add 29,29,5
+ rotrwi 3,15,6
+ rotrwi 4,15,11
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrwi 4,4,14
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrwi 3,11,2
+ rotrwi 4,11,13
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrwi 3,31,7
+ rotrwi 4,31,18
+ rotrwi 5,28,17
+ rotrwi 0,28,19
+ xor 3,3,4
+ srwi 4,31,3
+ xor 5,5,0
+ srwi 0,28,10
+ add 30,30,23
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,56(7)
+ add 30,30,3
+ add 30,30,5
+ rotrwi 3,14,6
+ rotrwi 4,14,11
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrwi 4,4,14
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrwi 3,10,2
+ rotrwi 4,10,13
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrwi 3,16,7
+ rotrwi 4,16,18
+ rotrwi 5,29,17
+ rotrwi 0,29,19
+ xor 3,3,4
+ srwi 4,16,3
+ xor 5,5,0
+ srwi 0,29,10
+ add 31,31,24
+ xor 3,3,4
+ xor 5,5,0
+ lwz 0,60(7)
+ add 31,31,3
+ add 31,31,5
+ rotrwi 3,6,6
+ rotrwi 4,6,11
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrwi 4,4,14
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrwi 3,9,2
+ rotrwi 4,9,13
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrwi 4,4,9
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ bdnz .Lrounds
+
+ ld 3,144(1)
+ ld 31,136(1)
+ ld 5,128(1)
+ subi 7,7,192
+
+ lwz 16,0(3)
+ lwz 17,4(3)
+ lwz 18,8(3)
+ lwz 19,12(3)
+ lwz 20,16(3)
+ lwz 21,20(3)
+ lwz 22,24(3)
+ addi 31,31,64
+ lwz 23,28(3)
+ add 8,8,16
+ add 9,9,17
+ std 31,136(1)
+ add 10,10,18
+ stw 8,0(3)
+ add 11,11,19
+ stw 9,4(3)
+ add 12,12,20
+ stw 10,8(3)
+ add 6,6,21
+ stw 11,12(3)
+ add 14,14,22
+ stw 12,16(3)
+ add 15,15,23
+ stw 6,20(3)
+ stw 14,24(3)
+ cmpld 31,5
+ stw 15,28(3)
+ bne .Lsha2_block_private
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.size zfs_sha256_ppc,.-zfs_sha256_ppc
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 7
+ addi 7,7,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+#endif
diff --git a/module/icp/asm-ppc64/sha2/sha512-p8.S b/module/icp/asm-ppc64/sha2/sha512-p8.S
new file mode 100644
index 000000000000..2409c53385d6
--- /dev/null
+++ b/module/icp/asm-ppc64/sha2/sha512-p8.S
@@ -0,0 +1,1722 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if (defined(__PPC64__) && defined(__BIG_ENDIAN__))
+
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.text
+
+.globl zfs_sha512_power8
+.globl .zfs_sha512_power8
+.type zfs_sha512_power8,@function
+.section ".opd","aw"
+.align 3
+zfs_sha512_power8:
+.quad .zfs_sha512_power8,.TOC.@tocbase,0
+.previous
+.align 6
+.zfs_sha512_power8:
+#else
+.abiversion 2
+.text
+
+.globl zfs_sha512_power8
+.type zfs_sha512_power8,@function
+.align 6
+zfs_sha512_power8:
+.localentry zfs_sha512_power8,0
+#endif
+
+ stdu 1,-384(1)
+ mflr 8
+ li 10,207
+ li 11,223
+ stvx 24,10,1
+ addi 10,10,32
+ mfspr 12,256
+ stvx 25,11,1
+ addi 11,11,32
+ stvx 26,10,1
+ addi 10,10,32
+ stvx 27,11,1
+ addi 11,11,32
+ stvx 28,10,1
+ addi 10,10,32
+ stvx 29,11,1
+ addi 11,11,32
+ stvx 30,10,1
+ stvx 31,11,1
+ li 11,-4096+255
+ stw 12,332(1)
+ li 10,0x10
+ std 26,336(1)
+ li 26,0x20
+ std 27,344(1)
+ li 27,0x30
+ std 28,352(1)
+ li 28,0x40
+ std 29,360(1)
+ li 29,0x50
+ std 30,368(1)
+ li 30,0x60
+ std 31,376(1)
+ li 31,0x70
+ std 8,400(1)
+ mtspr 256,11
+
+ bl .LPICmeup
+ addi 11,1,79
+ .long 0x7C001E99
+ .long 0x7C4A1E99
+ .long 0x7C9A1E99
+ vsldoi 1,0,0,8
+ .long 0x7CDB1E99
+ vsldoi 3,2,2,8
+ vsldoi 5,4,4,8
+ vsldoi 7,6,6,8
+ li 0,4
+ b .Loop
+.align 5
+.Loop:
+ lvx 28,0,6
+ .long 0x7D002699
+ addi 4,4,16
+ mr 7,6
+ stvx 0,0,11
+ stvx 1,10,11
+ stvx 2,26,11
+ stvx 3,27,11
+ stvx 4,28,11
+ stvx 5,29,11
+ stvx 6,30,11
+ stvx 7,31,11
+ .long 0x10E7E0C0
+ lvx 28,10,6
+ .long 0x10E740C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x7D402699
+ addi 4,4,16
+ vsldoi 9,8,8,8
+ .long 0x10C648C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x10A550C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x7D802699
+ addi 4,4,16
+ vsldoi 11,10,10,8
+ .long 0x108458C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x106360C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x7DC02699
+ addi 4,4,16
+ vsldoi 13,12,12,8
+ .long 0x104268C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x102170C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x7E002699
+ addi 4,4,16
+ vsldoi 15,14,14,8
+ .long 0x100078C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ .long 0x10E780C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x7E402699
+ addi 4,4,16
+ vsldoi 17,16,16,8
+ .long 0x10C688C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x10A590C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x7F002699
+ addi 4,4,16
+ vsldoi 19,18,18,8
+ .long 0x108498C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x1063C0C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x7F402699
+ addi 4,4,16
+ vsldoi 25,24,24,8
+ .long 0x1042C8C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x1021D0C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ vsldoi 27,26,26,8
+ .long 0x13C906C2
+ .long 0x1108F0C0
+ .long 0x13DA7EC2
+ .long 0x1108F0C0
+ .long 0x110888C0
+ .long 0x1000D8C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ mtctr 0
+ b .L16_xx
+.align 5
+.L16_xx:
+ .long 0x13CA06C2
+ .long 0x1129F0C0
+ .long 0x13DB7EC2
+ .long 0x1129F0C0
+ .long 0x112990C0
+ .long 0x10E740C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x13CB06C2
+ .long 0x114AF0C0
+ .long 0x13C87EC2
+ .long 0x114AF0C0
+ .long 0x114A98C0
+ .long 0x10C648C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x13CC06C2
+ .long 0x116BF0C0
+ .long 0x13C97EC2
+ .long 0x116BF0C0
+ .long 0x116BC0C0
+ .long 0x10A550C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x13CD06C2
+ .long 0x118CF0C0
+ .long 0x13CA7EC2
+ .long 0x118CF0C0
+ .long 0x118CC8C0
+ .long 0x108458C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x13CE06C2
+ .long 0x11ADF0C0
+ .long 0x13CB7EC2
+ .long 0x11ADF0C0
+ .long 0x11ADD0C0
+ .long 0x106360C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x13CF06C2
+ .long 0x11CEF0C0
+ .long 0x13CC7EC2
+ .long 0x11CEF0C0
+ .long 0x11CED8C0
+ .long 0x104268C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13D006C2
+ .long 0x11EFF0C0
+ .long 0x13CD7EC2
+ .long 0x11EFF0C0
+ .long 0x11EF40C0
+ .long 0x102170C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x13D106C2
+ .long 0x1210F0C0
+ .long 0x13CE7EC2
+ .long 0x1210F0C0
+ .long 0x121048C0
+ .long 0x100078C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ .long 0x13D206C2
+ .long 0x1231F0C0
+ .long 0x13CF7EC2
+ .long 0x1231F0C0
+ .long 0x123150C0
+ .long 0x10E780C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x13D306C2
+ .long 0x1252F0C0
+ .long 0x13D07EC2
+ .long 0x1252F0C0
+ .long 0x125258C0
+ .long 0x10C688C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x13D806C2
+ .long 0x1273F0C0
+ .long 0x13D17EC2
+ .long 0x1273F0C0
+ .long 0x127360C0
+ .long 0x10A590C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x13D906C2
+ .long 0x1318F0C0
+ .long 0x13D27EC2
+ .long 0x1318F0C0
+ .long 0x131868C0
+ .long 0x108498C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x13DA06C2
+ .long 0x1339F0C0
+ .long 0x13D37EC2
+ .long 0x1339F0C0
+ .long 0x133970C0
+ .long 0x1063C0C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x13DB06C2
+ .long 0x135AF0C0
+ .long 0x13D87EC2
+ .long 0x135AF0C0
+ .long 0x135A78C0
+ .long 0x1042C8C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13C806C2
+ .long 0x137BF0C0
+ .long 0x13D97EC2
+ .long 0x137BF0C0
+ .long 0x137B80C0
+ .long 0x1021D0C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x13C906C2
+ .long 0x1108F0C0
+ .long 0x13DA7EC2
+ .long 0x1108F0C0
+ .long 0x110888C0
+ .long 0x1000D8C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ bdnz .L16_xx
+
+ lvx 10,0,11
+ subic. 5,5,1
+ lvx 11,10,11
+ .long 0x100050C0
+ lvx 12,26,11
+ .long 0x102158C0
+ lvx 13,27,11
+ .long 0x104260C0
+ lvx 14,28,11
+ .long 0x106368C0
+ lvx 15,29,11
+ .long 0x108470C0
+ lvx 16,30,11
+ .long 0x10A578C0
+ lvx 17,31,11
+ .long 0x10C680C0
+ .long 0x10E788C0
+ bne .Loop
+ vperm 0,0,1,28
+ vperm 2,2,3,28
+ vperm 4,4,5,28
+ vperm 6,6,7,28
+ .long 0x7C001F99
+ .long 0x7C4A1F99
+ .long 0x7C9A1F99
+ .long 0x7CDB1F99
+ addi 11,1,207
+ mtlr 8
+ mtspr 256,12
+ lvx 24,0,11
+ lvx 25,10,11
+ lvx 26,26,11
+ lvx 27,27,11
+ lvx 28,28,11
+ lvx 29,29,11
+ lvx 30,30,11
+ lvx 31,31,11
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,6,3,0
+.long 0
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.size .zfs_sha512_power8,.-.zfs_sha512_power8
+.size zfs_sha512_power8,.-.zfs_sha512_power8
+#else
+.size zfs_sha512_power8,.-zfs_sha512_power8
+#endif
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 6
+ addi 6,6,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0xd728ae22
+.long 0x428a2f98,0xd728ae22
+.long 0x71374491,0x23ef65cd
+.long 0x71374491,0x23ef65cd
+.long 0xb5c0fbcf,0xec4d3b2f
+.long 0xb5c0fbcf,0xec4d3b2f
+.long 0xe9b5dba5,0x8189dbbc
+.long 0xe9b5dba5,0x8189dbbc
+.long 0x3956c25b,0xf348b538
+.long 0x3956c25b,0xf348b538
+.long 0x59f111f1,0xb605d019
+.long 0x59f111f1,0xb605d019
+.long 0x923f82a4,0xaf194f9b
+.long 0x923f82a4,0xaf194f9b
+.long 0xab1c5ed5,0xda6d8118
+.long 0xab1c5ed5,0xda6d8118
+.long 0xd807aa98,0xa3030242
+.long 0xd807aa98,0xa3030242
+.long 0x12835b01,0x45706fbe
+.long 0x12835b01,0x45706fbe
+.long 0x243185be,0x4ee4b28c
+.long 0x243185be,0x4ee4b28c
+.long 0x550c7dc3,0xd5ffb4e2
+.long 0x550c7dc3,0xd5ffb4e2
+.long 0x72be5d74,0xf27b896f
+.long 0x72be5d74,0xf27b896f
+.long 0x80deb1fe,0x3b1696b1
+.long 0x80deb1fe,0x3b1696b1
+.long 0x9bdc06a7,0x25c71235
+.long 0x9bdc06a7,0x25c71235
+.long 0xc19bf174,0xcf692694
+.long 0xc19bf174,0xcf692694
+.long 0xe49b69c1,0x9ef14ad2
+.long 0xe49b69c1,0x9ef14ad2
+.long 0xefbe4786,0x384f25e3
+.long 0xefbe4786,0x384f25e3
+.long 0x0fc19dc6,0x8b8cd5b5
+.long 0x0fc19dc6,0x8b8cd5b5
+.long 0x240ca1cc,0x77ac9c65
+.long 0x240ca1cc,0x77ac9c65
+.long 0x2de92c6f,0x592b0275
+.long 0x2de92c6f,0x592b0275
+.long 0x4a7484aa,0x6ea6e483
+.long 0x4a7484aa,0x6ea6e483
+.long 0x5cb0a9dc,0xbd41fbd4
+.long 0x5cb0a9dc,0xbd41fbd4
+.long 0x76f988da,0x831153b5
+.long 0x76f988da,0x831153b5
+.long 0x983e5152,0xee66dfab
+.long 0x983e5152,0xee66dfab
+.long 0xa831c66d,0x2db43210
+.long 0xa831c66d,0x2db43210
+.long 0xb00327c8,0x98fb213f
+.long 0xb00327c8,0x98fb213f
+.long 0xbf597fc7,0xbeef0ee4
+.long 0xbf597fc7,0xbeef0ee4
+.long 0xc6e00bf3,0x3da88fc2
+.long 0xc6e00bf3,0x3da88fc2
+.long 0xd5a79147,0x930aa725
+.long 0xd5a79147,0x930aa725
+.long 0x06ca6351,0xe003826f
+.long 0x06ca6351,0xe003826f
+.long 0x14292967,0x0a0e6e70
+.long 0x14292967,0x0a0e6e70
+.long 0x27b70a85,0x46d22ffc
+.long 0x27b70a85,0x46d22ffc
+.long 0x2e1b2138,0x5c26c926
+.long 0x2e1b2138,0x5c26c926
+.long 0x4d2c6dfc,0x5ac42aed
+.long 0x4d2c6dfc,0x5ac42aed
+.long 0x53380d13,0x9d95b3df
+.long 0x53380d13,0x9d95b3df
+.long 0x650a7354,0x8baf63de
+.long 0x650a7354,0x8baf63de
+.long 0x766a0abb,0x3c77b2a8
+.long 0x766a0abb,0x3c77b2a8
+.long 0x81c2c92e,0x47edaee6
+.long 0x81c2c92e,0x47edaee6
+.long 0x92722c85,0x1482353b
+.long 0x92722c85,0x1482353b
+.long 0xa2bfe8a1,0x4cf10364
+.long 0xa2bfe8a1,0x4cf10364
+.long 0xa81a664b,0xbc423001
+.long 0xa81a664b,0xbc423001
+.long 0xc24b8b70,0xd0f89791
+.long 0xc24b8b70,0xd0f89791
+.long 0xc76c51a3,0x0654be30
+.long 0xc76c51a3,0x0654be30
+.long 0xd192e819,0xd6ef5218
+.long 0xd192e819,0xd6ef5218
+.long 0xd6990624,0x5565a910
+.long 0xd6990624,0x5565a910
+.long 0xf40e3585,0x5771202a
+.long 0xf40e3585,0x5771202a
+.long 0x106aa070,0x32bbd1b8
+.long 0x106aa070,0x32bbd1b8
+.long 0x19a4c116,0xb8d2d0c8
+.long 0x19a4c116,0xb8d2d0c8
+.long 0x1e376c08,0x5141ab53
+.long 0x1e376c08,0x5141ab53
+.long 0x2748774c,0xdf8eeb99
+.long 0x2748774c,0xdf8eeb99
+.long 0x34b0bcb5,0xe19b48a8
+.long 0x34b0bcb5,0xe19b48a8
+.long 0x391c0cb3,0xc5c95a63
+.long 0x391c0cb3,0xc5c95a63
+.long 0x4ed8aa4a,0xe3418acb
+.long 0x4ed8aa4a,0xe3418acb
+.long 0x5b9cca4f,0x7763e373
+.long 0x5b9cca4f,0x7763e373
+.long 0x682e6ff3,0xd6b2b8a3
+.long 0x682e6ff3,0xd6b2b8a3
+.long 0x748f82ee,0x5defb2fc
+.long 0x748f82ee,0x5defb2fc
+.long 0x78a5636f,0x43172f60
+.long 0x78a5636f,0x43172f60
+.long 0x84c87814,0xa1f0ab72
+.long 0x84c87814,0xa1f0ab72
+.long 0x8cc70208,0x1a6439ec
+.long 0x8cc70208,0x1a6439ec
+.long 0x90befffa,0x23631e28
+.long 0x90befffa,0x23631e28
+.long 0xa4506ceb,0xde82bde9
+.long 0xa4506ceb,0xde82bde9
+.long 0xbef9a3f7,0xb2c67915
+.long 0xbef9a3f7,0xb2c67915
+.long 0xc67178f2,0xe372532b
+.long 0xc67178f2,0xe372532b
+.long 0xca273ece,0xea26619c
+.long 0xca273ece,0xea26619c
+.long 0xd186b8c7,0x21c0c207
+.long 0xd186b8c7,0x21c0c207
+.long 0xeada7dd6,0xcde0eb1e
+.long 0xeada7dd6,0xcde0eb1e
+.long 0xf57d4f7f,0xee6ed178
+.long 0xf57d4f7f,0xee6ed178
+.long 0x06f067aa,0x72176fba
+.long 0x06f067aa,0x72176fba
+.long 0x0a637dc5,0xa2c898a6
+.long 0x0a637dc5,0xa2c898a6
+.long 0x113f9804,0xbef90dae
+.long 0x113f9804,0xbef90dae
+.long 0x1b710b35,0x131c471b
+.long 0x1b710b35,0x131c471b
+.long 0x28db77f5,0x23047d84
+.long 0x28db77f5,0x23047d84
+.long 0x32caab7b,0x40c72493
+.long 0x32caab7b,0x40c72493
+.long 0x3c9ebe0a,0x15c9bebc
+.long 0x3c9ebe0a,0x15c9bebc
+.long 0x431d67c4,0x9c100d4c
+.long 0x431d67c4,0x9c100d4c
+.long 0x4cc5d4be,0xcb3e42b6
+.long 0x4cc5d4be,0xcb3e42b6
+.long 0x597f299c,0xfc657e2a
+.long 0x597f299c,0xfc657e2a
+.long 0x5fcb6fab,0x3ad6faec
+.long 0x5fcb6fab,0x3ad6faec
+.long 0x6c44198c,0x4a475817
+.long 0x6c44198c,0x4a475817
+.long 0,0
+.long 0,0
+.long 0x00010203,0x04050607
+.long 0x10111213,0x14151617
+
+#elif (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+
+.abiversion 2
+.text
+
+.globl zfs_sha512_power8
+.type zfs_sha512_power8,@function
+.align 6
+zfs_sha512_power8:
+.localentry zfs_sha512_power8,0
+
+ stdu 1,-384(1)
+ mflr 8
+ li 10,207
+ li 11,223
+ stvx 24,10,1
+ addi 10,10,32
+ li 12,-1
+ stvx 25,11,1
+ addi 11,11,32
+ stvx 26,10,1
+ addi 10,10,32
+ stvx 27,11,1
+ addi 11,11,32
+ stvx 28,10,1
+ addi 10,10,32
+ stvx 29,11,1
+ addi 11,11,32
+ stvx 30,10,1
+ stvx 31,11,1
+ li 11,-4096+255
+ stw 12,332(1)
+ li 10,0x10
+ std 26,336(1)
+ li 26,0x20
+ std 27,344(1)
+ li 27,0x30
+ std 28,352(1)
+ li 28,0x40
+ std 29,360(1)
+ li 29,0x50
+ std 30,368(1)
+ li 30,0x60
+ std 31,376(1)
+ li 31,0x70
+ std 8,400(1)
+ or 11,11,11
+
+ bl .LPICmeup
+ addi 11,1,79
+ li 7,8
+ lvsl 31,0,7
+ vspltisb 28,0x0f
+ vxor 31,31,28
+ .long 0x7C001E99
+ .long 0x7C4A1E99
+ .long 0x7C9A1E99
+ vsldoi 1,0,0,8
+ .long 0x7CDB1E99
+ vsldoi 3,2,2,8
+ vsldoi 5,4,4,8
+ vsldoi 7,6,6,8
+ li 0,4
+ b .Loop
+.align 5
+.Loop:
+ lvx 28,0,6
+ .long 0x7D002699
+ addi 4,4,16
+ mr 7,6
+ stvx 0,0,11
+ stvx 1,10,11
+ stvx 2,26,11
+ stvx 3,27,11
+ stvx 4,28,11
+ stvx 5,29,11
+ stvx 6,30,11
+ stvx 7,31,11
+ .long 0x10E7E0C0
+ lvx 28,10,6
+ vperm 8,8,8,31
+ .long 0x10E740C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x7D402699
+ addi 4,4,16
+ vsldoi 9,8,8,8
+ .long 0x10C648C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ vperm 10,10,10,31
+ .long 0x10A550C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x7D802699
+ addi 4,4,16
+ vsldoi 11,10,10,8
+ .long 0x108458C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ vperm 12,12,12,31
+ .long 0x106360C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x7DC02699
+ addi 4,4,16
+ vsldoi 13,12,12,8
+ .long 0x104268C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ vperm 14,14,14,31
+ .long 0x102170C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x7E002699
+ addi 4,4,16
+ vsldoi 15,14,14,8
+ .long 0x100078C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ vperm 16,16,16,31
+ .long 0x10E780C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x7E402699
+ addi 4,4,16
+ vsldoi 17,16,16,8
+ .long 0x10C688C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ vperm 18,18,18,31
+ .long 0x10A590C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x7F002699
+ addi 4,4,16
+ vsldoi 19,18,18,8
+ .long 0x108498C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ vperm 24,24,24,31
+ .long 0x1063C0C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x7F402699
+ addi 4,4,16
+ vsldoi 25,24,24,8
+ .long 0x1042C8C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ vperm 26,26,26,31
+ .long 0x1021D0C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ vsldoi 27,26,26,8
+ .long 0x13C906C2
+ .long 0x1108F0C0
+ .long 0x13DA7EC2
+ .long 0x1108F0C0
+ .long 0x110888C0
+ .long 0x1000D8C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ mtctr 0
+ b .L16_xx
+.align 5
+.L16_xx:
+ .long 0x13CA06C2
+ .long 0x1129F0C0
+ .long 0x13DB7EC2
+ .long 0x1129F0C0
+ .long 0x112990C0
+ .long 0x10E740C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x13CB06C2
+ .long 0x114AF0C0
+ .long 0x13C87EC2
+ .long 0x114AF0C0
+ .long 0x114A98C0
+ .long 0x10C648C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x13CC06C2
+ .long 0x116BF0C0
+ .long 0x13C97EC2
+ .long 0x116BF0C0
+ .long 0x116BC0C0
+ .long 0x10A550C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x13CD06C2
+ .long 0x118CF0C0
+ .long 0x13CA7EC2
+ .long 0x118CF0C0
+ .long 0x118CC8C0
+ .long 0x108458C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x13CE06C2
+ .long 0x11ADF0C0
+ .long 0x13CB7EC2
+ .long 0x11ADF0C0
+ .long 0x11ADD0C0
+ .long 0x106360C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x13CF06C2
+ .long 0x11CEF0C0
+ .long 0x13CC7EC2
+ .long 0x11CEF0C0
+ .long 0x11CED8C0
+ .long 0x104268C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13D006C2
+ .long 0x11EFF0C0
+ .long 0x13CD7EC2
+ .long 0x11EFF0C0
+ .long 0x11EF40C0
+ .long 0x102170C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x13D106C2
+ .long 0x1210F0C0
+ .long 0x13CE7EC2
+ .long 0x1210F0C0
+ .long 0x121048C0
+ .long 0x100078C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ .long 0x13D206C2
+ .long 0x1231F0C0
+ .long 0x13CF7EC2
+ .long 0x1231F0C0
+ .long 0x123150C0
+ .long 0x10E780C0
+ vsel 29,6,5,4
+ .long 0x10C6E0C0
+ .long 0x10E7E8C0
+ .long 0x13C4FEC2
+ .long 0x10E7F0C0
+ vxor 29,0,1
+ vsel 29,1,2,29
+ .long 0x106338C0
+ .long 0x13C086C2
+ .long 0x13DEE8C0
+ .long 0x10E7F0C0
+ lvx 28,26,7
+ .long 0x13D306C2
+ .long 0x1252F0C0
+ .long 0x13D07EC2
+ .long 0x1252F0C0
+ .long 0x125258C0
+ .long 0x10C688C0
+ vsel 29,5,4,3
+ .long 0x10A5E0C0
+ .long 0x10C6E8C0
+ .long 0x13C3FEC2
+ .long 0x10C6F0C0
+ vxor 29,7,0
+ vsel 29,0,1,29
+ .long 0x104230C0
+ .long 0x13C786C2
+ .long 0x13DEE8C0
+ .long 0x10C6F0C0
+ lvx 28,27,7
+ .long 0x13D806C2
+ .long 0x1273F0C0
+ .long 0x13D17EC2
+ .long 0x1273F0C0
+ .long 0x127360C0
+ .long 0x10A590C0
+ vsel 29,4,3,2
+ .long 0x1084E0C0
+ .long 0x10A5E8C0
+ .long 0x13C2FEC2
+ .long 0x10A5F0C0
+ vxor 29,6,7
+ vsel 29,7,0,29
+ .long 0x102128C0
+ .long 0x13C686C2
+ .long 0x13DEE8C0
+ .long 0x10A5F0C0
+ lvx 28,28,7
+ .long 0x13D906C2
+ .long 0x1318F0C0
+ .long 0x13D27EC2
+ .long 0x1318F0C0
+ .long 0x131868C0
+ .long 0x108498C0
+ vsel 29,3,2,1
+ .long 0x1063E0C0
+ .long 0x1084E8C0
+ .long 0x13C1FEC2
+ .long 0x1084F0C0
+ vxor 29,5,6
+ vsel 29,6,7,29
+ .long 0x100020C0
+ .long 0x13C586C2
+ .long 0x13DEE8C0
+ .long 0x1084F0C0
+ lvx 28,29,7
+ .long 0x13DA06C2
+ .long 0x1339F0C0
+ .long 0x13D37EC2
+ .long 0x1339F0C0
+ .long 0x133970C0
+ .long 0x1063C0C0
+ vsel 29,2,1,0
+ .long 0x1042E0C0
+ .long 0x1063E8C0
+ .long 0x13C0FEC2
+ .long 0x1063F0C0
+ vxor 29,4,5
+ vsel 29,5,6,29
+ .long 0x10E718C0
+ .long 0x13C486C2
+ .long 0x13DEE8C0
+ .long 0x1063F0C0
+ lvx 28,30,7
+ .long 0x13DB06C2
+ .long 0x135AF0C0
+ .long 0x13D87EC2
+ .long 0x135AF0C0
+ .long 0x135A78C0
+ .long 0x1042C8C0
+ vsel 29,1,0,7
+ .long 0x1021E0C0
+ .long 0x1042E8C0
+ .long 0x13C7FEC2
+ .long 0x1042F0C0
+ vxor 29,3,4
+ vsel 29,4,5,29
+ .long 0x10C610C0
+ .long 0x13C386C2
+ .long 0x13DEE8C0
+ .long 0x1042F0C0
+ lvx 28,31,7
+ addi 7,7,0x80
+ .long 0x13C806C2
+ .long 0x137BF0C0
+ .long 0x13D97EC2
+ .long 0x137BF0C0
+ .long 0x137B80C0
+ .long 0x1021D0C0
+ vsel 29,0,7,6
+ .long 0x1000E0C0
+ .long 0x1021E8C0
+ .long 0x13C6FEC2
+ .long 0x1021F0C0
+ vxor 29,2,3
+ vsel 29,3,4,29
+ .long 0x10A508C0
+ .long 0x13C286C2
+ .long 0x13DEE8C0
+ .long 0x1021F0C0
+ lvx 28,0,7
+ .long 0x13C906C2
+ .long 0x1108F0C0
+ .long 0x13DA7EC2
+ .long 0x1108F0C0
+ .long 0x110888C0
+ .long 0x1000D8C0
+ vsel 29,7,6,5
+ .long 0x10E7E0C0
+ .long 0x1000E8C0
+ .long 0x13C5FEC2
+ .long 0x1000F0C0
+ vxor 29,1,2
+ vsel 29,2,3,29
+ .long 0x108400C0
+ .long 0x13C186C2
+ .long 0x13DEE8C0
+ .long 0x1000F0C0
+ lvx 28,10,7
+ bdnz .L16_xx
+
+ lvx 10,0,11
+ subic. 5,5,1
+ lvx 11,10,11
+ .long 0x100050C0
+ lvx 12,26,11
+ .long 0x102158C0
+ lvx 13,27,11
+ .long 0x104260C0
+ lvx 14,28,11
+ .long 0x106368C0
+ lvx 15,29,11
+ .long 0x108470C0
+ lvx 16,30,11
+ .long 0x10A578C0
+ lvx 17,31,11
+ .long 0x10C680C0
+ .long 0x10E788C0
+ bne .Loop
+ vperm 0,0,1,28
+ vperm 2,2,3,28
+ vperm 4,4,5,28
+ vperm 6,6,7,28
+ .long 0x7C001F99
+ .long 0x7C4A1F99
+ .long 0x7C9A1F99
+ .long 0x7CDB1F99
+ addi 11,1,207
+ mtlr 8
+ or 12,12,12
+ lvx 24,0,11
+ lvx 25,10,11
+ lvx 26,26,11
+ lvx 27,27,11
+ lvx 28,28,11
+ lvx 29,29,11
+ lvx 30,30,11
+ lvx 31,31,11
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,6,3,0
+.long 0
+.size zfs_sha512_power8,.-zfs_sha512_power8
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 6
+ addi 6,6,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0xd728ae22,0x428a2f98
+.long 0xd728ae22,0x428a2f98
+.long 0x23ef65cd,0x71374491
+.long 0x23ef65cd,0x71374491
+.long 0xec4d3b2f,0xb5c0fbcf
+.long 0xec4d3b2f,0xb5c0fbcf
+.long 0x8189dbbc,0xe9b5dba5
+.long 0x8189dbbc,0xe9b5dba5
+.long 0xf348b538,0x3956c25b
+.long 0xf348b538,0x3956c25b
+.long 0xb605d019,0x59f111f1
+.long 0xb605d019,0x59f111f1
+.long 0xaf194f9b,0x923f82a4
+.long 0xaf194f9b,0x923f82a4
+.long 0xda6d8118,0xab1c5ed5
+.long 0xda6d8118,0xab1c5ed5
+.long 0xa3030242,0xd807aa98
+.long 0xa3030242,0xd807aa98
+.long 0x45706fbe,0x12835b01
+.long 0x45706fbe,0x12835b01
+.long 0x4ee4b28c,0x243185be
+.long 0x4ee4b28c,0x243185be
+.long 0xd5ffb4e2,0x550c7dc3
+.long 0xd5ffb4e2,0x550c7dc3
+.long 0xf27b896f,0x72be5d74
+.long 0xf27b896f,0x72be5d74
+.long 0x3b1696b1,0x80deb1fe
+.long 0x3b1696b1,0x80deb1fe
+.long 0x25c71235,0x9bdc06a7
+.long 0x25c71235,0x9bdc06a7
+.long 0xcf692694,0xc19bf174
+.long 0xcf692694,0xc19bf174
+.long 0x9ef14ad2,0xe49b69c1
+.long 0x9ef14ad2,0xe49b69c1
+.long 0x384f25e3,0xefbe4786
+.long 0x384f25e3,0xefbe4786
+.long 0x8b8cd5b5,0x0fc19dc6
+.long 0x8b8cd5b5,0x0fc19dc6
+.long 0x77ac9c65,0x240ca1cc
+.long 0x77ac9c65,0x240ca1cc
+.long 0x592b0275,0x2de92c6f
+.long 0x592b0275,0x2de92c6f
+.long 0x6ea6e483,0x4a7484aa
+.long 0x6ea6e483,0x4a7484aa
+.long 0xbd41fbd4,0x5cb0a9dc
+.long 0xbd41fbd4,0x5cb0a9dc
+.long 0x831153b5,0x76f988da
+.long 0x831153b5,0x76f988da
+.long 0xee66dfab,0x983e5152
+.long 0xee66dfab,0x983e5152
+.long 0x2db43210,0xa831c66d
+.long 0x2db43210,0xa831c66d
+.long 0x98fb213f,0xb00327c8
+.long 0x98fb213f,0xb00327c8
+.long 0xbeef0ee4,0xbf597fc7
+.long 0xbeef0ee4,0xbf597fc7
+.long 0x3da88fc2,0xc6e00bf3
+.long 0x3da88fc2,0xc6e00bf3
+.long 0x930aa725,0xd5a79147
+.long 0x930aa725,0xd5a79147
+.long 0xe003826f,0x06ca6351
+.long 0xe003826f,0x06ca6351
+.long 0x0a0e6e70,0x14292967
+.long 0x0a0e6e70,0x14292967
+.long 0x46d22ffc,0x27b70a85
+.long 0x46d22ffc,0x27b70a85
+.long 0x5c26c926,0x2e1b2138
+.long 0x5c26c926,0x2e1b2138
+.long 0x5ac42aed,0x4d2c6dfc
+.long 0x5ac42aed,0x4d2c6dfc
+.long 0x9d95b3df,0x53380d13
+.long 0x9d95b3df,0x53380d13
+.long 0x8baf63de,0x650a7354
+.long 0x8baf63de,0x650a7354
+.long 0x3c77b2a8,0x766a0abb
+.long 0x3c77b2a8,0x766a0abb
+.long 0x47edaee6,0x81c2c92e
+.long 0x47edaee6,0x81c2c92e
+.long 0x1482353b,0x92722c85
+.long 0x1482353b,0x92722c85
+.long 0x4cf10364,0xa2bfe8a1
+.long 0x4cf10364,0xa2bfe8a1
+.long 0xbc423001,0xa81a664b
+.long 0xbc423001,0xa81a664b
+.long 0xd0f89791,0xc24b8b70
+.long 0xd0f89791,0xc24b8b70
+.long 0x0654be30,0xc76c51a3
+.long 0x0654be30,0xc76c51a3
+.long 0xd6ef5218,0xd192e819
+.long 0xd6ef5218,0xd192e819
+.long 0x5565a910,0xd6990624
+.long 0x5565a910,0xd6990624
+.long 0x5771202a,0xf40e3585
+.long 0x5771202a,0xf40e3585
+.long 0x32bbd1b8,0x106aa070
+.long 0x32bbd1b8,0x106aa070
+.long 0xb8d2d0c8,0x19a4c116
+.long 0xb8d2d0c8,0x19a4c116
+.long 0x5141ab53,0x1e376c08
+.long 0x5141ab53,0x1e376c08
+.long 0xdf8eeb99,0x2748774c
+.long 0xdf8eeb99,0x2748774c
+.long 0xe19b48a8,0x34b0bcb5
+.long 0xe19b48a8,0x34b0bcb5
+.long 0xc5c95a63,0x391c0cb3
+.long 0xc5c95a63,0x391c0cb3
+.long 0xe3418acb,0x4ed8aa4a
+.long 0xe3418acb,0x4ed8aa4a
+.long 0x7763e373,0x5b9cca4f
+.long 0x7763e373,0x5b9cca4f
+.long 0xd6b2b8a3,0x682e6ff3
+.long 0xd6b2b8a3,0x682e6ff3
+.long 0x5defb2fc,0x748f82ee
+.long 0x5defb2fc,0x748f82ee
+.long 0x43172f60,0x78a5636f
+.long 0x43172f60,0x78a5636f
+.long 0xa1f0ab72,0x84c87814
+.long 0xa1f0ab72,0x84c87814
+.long 0x1a6439ec,0x8cc70208
+.long 0x1a6439ec,0x8cc70208
+.long 0x23631e28,0x90befffa
+.long 0x23631e28,0x90befffa
+.long 0xde82bde9,0xa4506ceb
+.long 0xde82bde9,0xa4506ceb
+.long 0xb2c67915,0xbef9a3f7
+.long 0xb2c67915,0xbef9a3f7
+.long 0xe372532b,0xc67178f2
+.long 0xe372532b,0xc67178f2
+.long 0xea26619c,0xca273ece
+.long 0xea26619c,0xca273ece
+.long 0x21c0c207,0xd186b8c7
+.long 0x21c0c207,0xd186b8c7
+.long 0xcde0eb1e,0xeada7dd6
+.long 0xcde0eb1e,0xeada7dd6
+.long 0xee6ed178,0xf57d4f7f
+.long 0xee6ed178,0xf57d4f7f
+.long 0x72176fba,0x06f067aa
+.long 0x72176fba,0x06f067aa
+.long 0xa2c898a6,0x0a637dc5
+.long 0xa2c898a6,0x0a637dc5
+.long 0xbef90dae,0x113f9804
+.long 0xbef90dae,0x113f9804
+.long 0x131c471b,0x1b710b35
+.long 0x131c471b,0x1b710b35
+.long 0x23047d84,0x28db77f5
+.long 0x23047d84,0x28db77f5
+.long 0x40c72493,0x32caab7b
+.long 0x40c72493,0x32caab7b
+.long 0x15c9bebc,0x3c9ebe0a
+.long 0x15c9bebc,0x3c9ebe0a
+.long 0x9c100d4c,0x431d67c4
+.long 0x9c100d4c,0x431d67c4
+.long 0xcb3e42b6,0x4cc5d4be
+.long 0xcb3e42b6,0x4cc5d4be
+.long 0xfc657e2a,0x597f299c
+.long 0xfc657e2a,0x597f299c
+.long 0x3ad6faec,0x5fcb6fab
+.long 0x3ad6faec,0x5fcb6fab
+.long 0x4a475817,0x6c44198c
+.long 0x4a475817,0x6c44198c
+.long 0,0
+.long 0,0
+.long 0x14151617,0x10111213
+.long 0x04050607,0x00010203
+
+#endif
diff --git a/module/icp/asm-ppc64/sha2/sha512-ppc.S b/module/icp/asm-ppc64/sha2/sha512-ppc.S
new file mode 100644
index 000000000000..57213f68abc5
--- /dev/null
+++ b/module/icp/asm-ppc64/sha2/sha512-ppc.S
@@ -0,0 +1,2973 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if (defined(__PPC64__) && defined(__BIG_ENDIAN__))
+
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.text
+
+.globl zfs_sha512_ppc
+.globl .zfs_sha512_ppc
+.type zfs_sha512_ppc,@function
+.section ".opd","aw"
+.align 3
+zfs_sha512_ppc:
+.quad .zfs_sha512_ppc,.TOC.@tocbase,0
+.previous
+.align 6
+.zfs_sha512_ppc:
+#else
+.abiversion 2
+.text
+
+.globl zfs_sha512_ppc
+.type zfs_sha512_ppc,@function
+.align 6
+zfs_sha512_ppc:
+.localentry zfs_sha512_ppc,0
+#endif
+ stdu 1,-384(1)
+ mflr 0
+ sldi 5,5,7
+
+ std 3,208(1)
+
+ std 14,240(1)
+ std 15,248(1)
+ std 16,256(1)
+ std 17,264(1)
+ std 18,272(1)
+ std 19,280(1)
+ std 20,288(1)
+ std 21,296(1)
+ std 22,304(1)
+ std 23,312(1)
+ std 24,320(1)
+ std 25,328(1)
+ std 26,336(1)
+ std 27,344(1)
+ std 28,352(1)
+ std 29,360(1)
+ std 30,368(1)
+ std 31,376(1)
+ std 0,400(1)
+ ld 8,0(3)
+ mr 31,4
+ ld 9,8(3)
+ ld 10,16(3)
+ ld 11,24(3)
+ ld 12,32(3)
+ ld 6,40(3)
+ ld 14,48(3)
+ ld 15,56(3)
+ bl .LPICmeup
+.LPICedup:
+ andi. 0,31,3
+ bne .Lunaligned
+.Laligned:
+ add 5,31,5
+ std 5,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+ b .Ldone
+
+
+
+
+
+
+
+.align 4
+.Lunaligned:
+ subfic 0,31,4096
+ andi. 0,0,3968
+ beq .Lcross_page
+ cmpld 5,0
+ ble .Laligned
+ subfc 5,0,5
+ add 0,31,0
+ std 5,184(1)
+ std 0,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+
+ ld 5,184(1)
+.Lcross_page:
+ li 0,32
+ mtctr 0
+ addi 20,1,48
+.Lmemcpy:
+ lbz 16,0(31)
+ lbz 17,1(31)
+ lbz 18,2(31)
+ lbz 19,3(31)
+ addi 31,31,4
+ stb 16,0(20)
+ stb 17,1(20)
+ stb 18,2(20)
+ stb 19,3(20)
+ addi 20,20,4
+ bdnz .Lmemcpy
+ std 31,176(1)
+ addi 0,1,176
+ addi 31,1,48
+ std 5,184(1)
+ std 0,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+ ld 31,176(1)
+ ld 5,184(1)
+ addic. 5,5,-128
+ bne .Lunaligned
+
+.Ldone:
+ ld 0,400(1)
+ ld 14,240(1)
+ ld 15,248(1)
+ ld 16,256(1)
+ ld 17,264(1)
+ ld 18,272(1)
+ ld 19,280(1)
+ ld 20,288(1)
+ ld 21,296(1)
+ ld 22,304(1)
+ ld 23,312(1)
+ ld 24,320(1)
+ ld 25,328(1)
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ mtlr 0
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,18,3,0
+.long 0
+.align 4
+.Lsha2_block_private:
+ ld 0,0(7)
+ lwz 5,0(31)
+ lwz 16,4(31)
+ insrdi 16,5,32,0
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ ld 0,8(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 5,8(31)
+ lwz 17,12(31)
+ insrdi 17,5,32,0
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ ld 0,16(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 5,16(31)
+ lwz 18,20(31)
+ insrdi 18,5,32,0
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ ld 0,24(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 5,24(31)
+ lwz 19,28(31)
+ insrdi 19,5,32,0
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ ld 0,32(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 5,32(31)
+ lwz 20,36(31)
+ insrdi 20,5,32,0
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ ld 0,40(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 5,40(31)
+ lwz 21,44(31)
+ insrdi 21,5,32,0
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ ld 0,48(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 5,48(31)
+ lwz 22,52(31)
+ insrdi 22,5,32,0
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ ld 0,56(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 5,56(31)
+ lwz 23,60(31)
+ insrdi 23,5,32,0
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ ld 0,64(7)
+ add 8,8,3
+ add 8,8,5
+
+ lwz 5,64(31)
+ lwz 24,68(31)
+ insrdi 24,5,32,0
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ ld 0,72(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 5,72(31)
+ lwz 25,76(31)
+ insrdi 25,5,32,0
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ ld 0,80(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 5,80(31)
+ lwz 26,84(31)
+ insrdi 26,5,32,0
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ ld 0,88(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 5,88(31)
+ lwz 27,92(31)
+ insrdi 27,5,32,0
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ ld 0,96(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 5,96(31)
+ lwz 28,100(31)
+ insrdi 28,5,32,0
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ ld 0,104(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 5,104(31)
+ lwz 29,108(31)
+ insrdi 29,5,32,0
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ ld 0,112(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 5,112(31)
+ lwz 30,116(31)
+ insrdi 30,5,32,0
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ ld 0,120(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 5,120(31)
+ lwz 31,124(31)
+ insrdi 31,5,32,0
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ li 5,4
+ mtctr 5
+.align 4
+.Lrounds:
+ addi 7,7,128
+ rotrdi 3,17,1
+ rotrdi 4,17,8
+ rotrdi 5,30,19
+ rotrdi 0,30,61
+ xor 3,3,4
+ srdi 4,17,7
+ xor 5,5,0
+ srdi 0,30,6
+ add 16,16,25
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,0(7)
+ add 16,16,3
+ add 16,16,5
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrdi 3,18,1
+ rotrdi 4,18,8
+ rotrdi 5,31,19
+ rotrdi 0,31,61
+ xor 3,3,4
+ srdi 4,18,7
+ xor 5,5,0
+ srdi 0,31,6
+ add 17,17,26
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,8(7)
+ add 17,17,3
+ add 17,17,5
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrdi 3,19,1
+ rotrdi 4,19,8
+ rotrdi 5,16,19
+ rotrdi 0,16,61
+ xor 3,3,4
+ srdi 4,19,7
+ xor 5,5,0
+ srdi 0,16,6
+ add 18,18,27
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,16(7)
+ add 18,18,3
+ add 18,18,5
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrdi 3,20,1
+ rotrdi 4,20,8
+ rotrdi 5,17,19
+ rotrdi 0,17,61
+ xor 3,3,4
+ srdi 4,20,7
+ xor 5,5,0
+ srdi 0,17,6
+ add 19,19,28
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,24(7)
+ add 19,19,3
+ add 19,19,5
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrdi 3,21,1
+ rotrdi 4,21,8
+ rotrdi 5,18,19
+ rotrdi 0,18,61
+ xor 3,3,4
+ srdi 4,21,7
+ xor 5,5,0
+ srdi 0,18,6
+ add 20,20,29
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,32(7)
+ add 20,20,3
+ add 20,20,5
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrdi 3,22,1
+ rotrdi 4,22,8
+ rotrdi 5,19,19
+ rotrdi 0,19,61
+ xor 3,3,4
+ srdi 4,22,7
+ xor 5,5,0
+ srdi 0,19,6
+ add 21,21,30
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,40(7)
+ add 21,21,3
+ add 21,21,5
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrdi 3,23,1
+ rotrdi 4,23,8
+ rotrdi 5,20,19
+ rotrdi 0,20,61
+ xor 3,3,4
+ srdi 4,23,7
+ xor 5,5,0
+ srdi 0,20,6
+ add 22,22,31
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,48(7)
+ add 22,22,3
+ add 22,22,5
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrdi 3,24,1
+ rotrdi 4,24,8
+ rotrdi 5,21,19
+ rotrdi 0,21,61
+ xor 3,3,4
+ srdi 4,24,7
+ xor 5,5,0
+ srdi 0,21,6
+ add 23,23,16
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,56(7)
+ add 23,23,3
+ add 23,23,5
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ rotrdi 3,25,1
+ rotrdi 4,25,8
+ rotrdi 5,22,19
+ rotrdi 0,22,61
+ xor 3,3,4
+ srdi 4,25,7
+ xor 5,5,0
+ srdi 0,22,6
+ add 24,24,17
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,64(7)
+ add 24,24,3
+ add 24,24,5
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrdi 3,26,1
+ rotrdi 4,26,8
+ rotrdi 5,23,19
+ rotrdi 0,23,61
+ xor 3,3,4
+ srdi 4,26,7
+ xor 5,5,0
+ srdi 0,23,6
+ add 25,25,18
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,72(7)
+ add 25,25,3
+ add 25,25,5
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrdi 3,27,1
+ rotrdi 4,27,8
+ rotrdi 5,24,19
+ rotrdi 0,24,61
+ xor 3,3,4
+ srdi 4,27,7
+ xor 5,5,0
+ srdi 0,24,6
+ add 26,26,19
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,80(7)
+ add 26,26,3
+ add 26,26,5
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrdi 3,28,1
+ rotrdi 4,28,8
+ rotrdi 5,25,19
+ rotrdi 0,25,61
+ xor 3,3,4
+ srdi 4,28,7
+ xor 5,5,0
+ srdi 0,25,6
+ add 27,27,20
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,88(7)
+ add 27,27,3
+ add 27,27,5
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrdi 3,29,1
+ rotrdi 4,29,8
+ rotrdi 5,26,19
+ rotrdi 0,26,61
+ xor 3,3,4
+ srdi 4,29,7
+ xor 5,5,0
+ srdi 0,26,6
+ add 28,28,21
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,96(7)
+ add 28,28,3
+ add 28,28,5
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrdi 3,30,1
+ rotrdi 4,30,8
+ rotrdi 5,27,19
+ rotrdi 0,27,61
+ xor 3,3,4
+ srdi 4,30,7
+ xor 5,5,0
+ srdi 0,27,6
+ add 29,29,22
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,104(7)
+ add 29,29,3
+ add 29,29,5
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrdi 3,31,1
+ rotrdi 4,31,8
+ rotrdi 5,28,19
+ rotrdi 0,28,61
+ xor 3,3,4
+ srdi 4,31,7
+ xor 5,5,0
+ srdi 0,28,6
+ add 30,30,23
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,112(7)
+ add 30,30,3
+ add 30,30,5
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrdi 3,16,1
+ rotrdi 4,16,8
+ rotrdi 5,29,19
+ rotrdi 0,29,61
+ xor 3,3,4
+ srdi 4,16,7
+ xor 5,5,0
+ srdi 0,29,6
+ add 31,31,24
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,120(7)
+ add 31,31,3
+ add 31,31,5
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ bdnz .Lrounds
+
+ ld 3,208(1)
+ ld 31,200(1)
+ ld 5,192(1)
+ subi 7,7,512
+
+ ld 16,0(3)
+ ld 17,8(3)
+ ld 18,16(3)
+ ld 19,24(3)
+ ld 20,32(3)
+ ld 21,40(3)
+ ld 22,48(3)
+ addi 31,31,128
+ ld 23,56(3)
+ add 8,8,16
+ add 9,9,17
+ std 31,200(1)
+ add 10,10,18
+ std 8,0(3)
+ add 11,11,19
+ std 9,8(3)
+ add 12,12,20
+ std 10,16(3)
+ add 6,6,21
+ std 11,24(3)
+ add 14,14,22
+ std 12,32(3)
+ add 15,15,23
+ std 6,40(3)
+ std 14,48(3)
+ cmpld 31,5
+ std 15,56(3)
+ bne .Lsha2_block_private
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+#if (!defined(_CALL_ELF) || _CALL_ELF == 1)
+.size .zfs_sha512_ppc,.-.zfs_sha512_ppc
+.size zfs_sha512_ppc,.-.zfs_sha512_ppc
+#else
+.size zfs_sha512_ppc,.-zfs_sha512_ppc
+#endif
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 7
+ addi 7,7,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0x428a2f98,0xd728ae22
+.long 0x71374491,0x23ef65cd
+.long 0xb5c0fbcf,0xec4d3b2f
+.long 0xe9b5dba5,0x8189dbbc
+.long 0x3956c25b,0xf348b538
+.long 0x59f111f1,0xb605d019
+.long 0x923f82a4,0xaf194f9b
+.long 0xab1c5ed5,0xda6d8118
+.long 0xd807aa98,0xa3030242
+.long 0x12835b01,0x45706fbe
+.long 0x243185be,0x4ee4b28c
+.long 0x550c7dc3,0xd5ffb4e2
+.long 0x72be5d74,0xf27b896f
+.long 0x80deb1fe,0x3b1696b1
+.long 0x9bdc06a7,0x25c71235
+.long 0xc19bf174,0xcf692694
+.long 0xe49b69c1,0x9ef14ad2
+.long 0xefbe4786,0x384f25e3
+.long 0x0fc19dc6,0x8b8cd5b5
+.long 0x240ca1cc,0x77ac9c65
+.long 0x2de92c6f,0x592b0275
+.long 0x4a7484aa,0x6ea6e483
+.long 0x5cb0a9dc,0xbd41fbd4
+.long 0x76f988da,0x831153b5
+.long 0x983e5152,0xee66dfab
+.long 0xa831c66d,0x2db43210
+.long 0xb00327c8,0x98fb213f
+.long 0xbf597fc7,0xbeef0ee4
+.long 0xc6e00bf3,0x3da88fc2
+.long 0xd5a79147,0x930aa725
+.long 0x06ca6351,0xe003826f
+.long 0x14292967,0x0a0e6e70
+.long 0x27b70a85,0x46d22ffc
+.long 0x2e1b2138,0x5c26c926
+.long 0x4d2c6dfc,0x5ac42aed
+.long 0x53380d13,0x9d95b3df
+.long 0x650a7354,0x8baf63de
+.long 0x766a0abb,0x3c77b2a8
+.long 0x81c2c92e,0x47edaee6
+.long 0x92722c85,0x1482353b
+.long 0xa2bfe8a1,0x4cf10364
+.long 0xa81a664b,0xbc423001
+.long 0xc24b8b70,0xd0f89791
+.long 0xc76c51a3,0x0654be30
+.long 0xd192e819,0xd6ef5218
+.long 0xd6990624,0x5565a910
+.long 0xf40e3585,0x5771202a
+.long 0x106aa070,0x32bbd1b8
+.long 0x19a4c116,0xb8d2d0c8
+.long 0x1e376c08,0x5141ab53
+.long 0x2748774c,0xdf8eeb99
+.long 0x34b0bcb5,0xe19b48a8
+.long 0x391c0cb3,0xc5c95a63
+.long 0x4ed8aa4a,0xe3418acb
+.long 0x5b9cca4f,0x7763e373
+.long 0x682e6ff3,0xd6b2b8a3
+.long 0x748f82ee,0x5defb2fc
+.long 0x78a5636f,0x43172f60
+.long 0x84c87814,0xa1f0ab72
+.long 0x8cc70208,0x1a6439ec
+.long 0x90befffa,0x23631e28
+.long 0xa4506ceb,0xde82bde9
+.long 0xbef9a3f7,0xb2c67915
+.long 0xc67178f2,0xe372532b
+.long 0xca273ece,0xea26619c
+.long 0xd186b8c7,0x21c0c207
+.long 0xeada7dd6,0xcde0eb1e
+.long 0xf57d4f7f,0xee6ed178
+.long 0x06f067aa,0x72176fba
+.long 0x0a637dc5,0xa2c898a6
+.long 0x113f9804,0xbef90dae
+.long 0x1b710b35,0x131c471b
+.long 0x28db77f5,0x23047d84
+.long 0x32caab7b,0x40c72493
+.long 0x3c9ebe0a,0x15c9bebc
+.long 0x431d67c4,0x9c100d4c
+.long 0x4cc5d4be,0xcb3e42b6
+.long 0x597f299c,0xfc657e2a
+.long 0x5fcb6fab,0x3ad6faec
+.long 0x6c44198c,0x4a475817
+
+#elif (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
+
+.abiversion 2
+.text
+
+.globl zfs_sha512_ppc
+.type zfs_sha512_ppc,@function
+.align 6
+zfs_sha512_ppc:
+.localentry zfs_sha512_ppc,0
+
+ stdu 1,-384(1)
+ mflr 0
+ sldi 5,5,7
+
+ std 3,208(1)
+
+ std 14,240(1)
+ std 15,248(1)
+ std 16,256(1)
+ std 17,264(1)
+ std 18,272(1)
+ std 19,280(1)
+ std 20,288(1)
+ std 21,296(1)
+ std 22,304(1)
+ std 23,312(1)
+ std 24,320(1)
+ std 25,328(1)
+ std 26,336(1)
+ std 27,344(1)
+ std 28,352(1)
+ std 29,360(1)
+ std 30,368(1)
+ std 31,376(1)
+ std 0,400(1)
+ ld 8,0(3)
+ mr 31,4
+ ld 9,8(3)
+ ld 10,16(3)
+ ld 11,24(3)
+ ld 12,32(3)
+ ld 6,40(3)
+ ld 14,48(3)
+ ld 15,56(3)
+ bl .LPICmeup
+.LPICedup:
+ andi. 0,31,3
+ bne .Lunaligned
+.Laligned:
+ add 5,31,5
+ std 5,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+ b .Ldone
+
+.align 4
+.Lunaligned:
+ subfic 0,31,4096
+ andi. 0,0,3968
+ beq .Lcross_page
+ cmpld 5,0
+ ble .Laligned
+ subfc 5,0,5
+ add 0,31,0
+ std 5,184(1)
+ std 0,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+
+ ld 5,184(1)
+.Lcross_page:
+ li 0,32
+ mtctr 0
+ addi 20,1,48
+.Lmemcpy:
+ lbz 16,0(31)
+ lbz 17,1(31)
+ lbz 18,2(31)
+ lbz 19,3(31)
+ addi 31,31,4
+ stb 16,0(20)
+ stb 17,1(20)
+ stb 18,2(20)
+ stb 19,3(20)
+ addi 20,20,4
+ bdnz .Lmemcpy
+ std 31,176(1)
+ addi 0,1,176
+ addi 31,1,48
+ std 5,184(1)
+ std 0,192(1)
+ std 31,200(1)
+ bl .Lsha2_block_private
+ ld 31,176(1)
+ ld 5,184(1)
+ addic. 5,5,-128
+ bne .Lunaligned
+
+.Ldone:
+ ld 0,400(1)
+ ld 14,240(1)
+ ld 15,248(1)
+ ld 16,256(1)
+ ld 17,264(1)
+ ld 18,272(1)
+ ld 19,280(1)
+ ld 20,288(1)
+ ld 21,296(1)
+ ld 22,304(1)
+ ld 23,312(1)
+ ld 24,320(1)
+ ld 25,328(1)
+ ld 26,336(1)
+ ld 27,344(1)
+ ld 28,352(1)
+ ld 29,360(1)
+ ld 30,368(1)
+ ld 31,376(1)
+ mtlr 0
+ addi 1,1,384
+ blr
+.long 0
+.byte 0,12,4,1,0x80,18,3,0
+.long 0
+.align 4
+.Lsha2_block_private:
+ ld 0,0(7)
+ lwz 3,0(31)
+ lwz 4,4(31)
+ rotlwi 5,3,8
+ rotlwi 16,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 16,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 16,4,24,16,23
+ insrdi 16,5,32,0
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ ld 0,8(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 3,8(31)
+ lwz 4,12(31)
+ rotlwi 5,3,8
+ rotlwi 17,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 17,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 17,4,24,16,23
+ insrdi 17,5,32,0
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ ld 0,16(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 3,16(31)
+ lwz 4,20(31)
+ rotlwi 5,3,8
+ rotlwi 18,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 18,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 18,4,24,16,23
+ insrdi 18,5,32,0
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ ld 0,24(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 3,24(31)
+ lwz 4,28(31)
+ rotlwi 5,3,8
+ rotlwi 19,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 19,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 19,4,24,16,23
+ insrdi 19,5,32,0
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ ld 0,32(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 3,32(31)
+ lwz 4,36(31)
+ rotlwi 5,3,8
+ rotlwi 20,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 20,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 20,4,24,16,23
+ insrdi 20,5,32,0
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ ld 0,40(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 3,40(31)
+ lwz 4,44(31)
+ rotlwi 5,3,8
+ rotlwi 21,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 21,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 21,4,24,16,23
+ insrdi 21,5,32,0
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ ld 0,48(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 3,48(31)
+ lwz 4,52(31)
+ rotlwi 5,3,8
+ rotlwi 22,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 22,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 22,4,24,16,23
+ insrdi 22,5,32,0
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ ld 0,56(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 3,56(31)
+ lwz 4,60(31)
+ rotlwi 5,3,8
+ rotlwi 23,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 23,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 23,4,24,16,23
+ insrdi 23,5,32,0
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ ld 0,64(7)
+ add 8,8,3
+ add 8,8,5
+
+ lwz 3,64(31)
+ lwz 4,68(31)
+ rotlwi 5,3,8
+ rotlwi 24,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 24,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 24,4,24,16,23
+ insrdi 24,5,32,0
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ ld 0,72(7)
+ add 15,15,3
+ add 15,15,5
+
+ lwz 3,72(31)
+ lwz 4,76(31)
+ rotlwi 5,3,8
+ rotlwi 25,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 25,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 25,4,24,16,23
+ insrdi 25,5,32,0
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ ld 0,80(7)
+ add 14,14,3
+ add 14,14,5
+
+ lwz 3,80(31)
+ lwz 4,84(31)
+ rotlwi 5,3,8
+ rotlwi 26,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 26,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 26,4,24,16,23
+ insrdi 26,5,32,0
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ ld 0,88(7)
+ add 6,6,3
+ add 6,6,5
+
+ lwz 3,88(31)
+ lwz 4,92(31)
+ rotlwi 5,3,8
+ rotlwi 27,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 27,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 27,4,24,16,23
+ insrdi 27,5,32,0
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ ld 0,96(7)
+ add 12,12,3
+ add 12,12,5
+
+ lwz 3,96(31)
+ lwz 4,100(31)
+ rotlwi 5,3,8
+ rotlwi 28,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 28,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 28,4,24,16,23
+ insrdi 28,5,32,0
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ ld 0,104(7)
+ add 11,11,3
+ add 11,11,5
+
+ lwz 3,104(31)
+ lwz 4,108(31)
+ rotlwi 5,3,8
+ rotlwi 29,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 29,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 29,4,24,16,23
+ insrdi 29,5,32,0
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ ld 0,112(7)
+ add 10,10,3
+ add 10,10,5
+
+ lwz 3,112(31)
+ lwz 4,116(31)
+ rotlwi 5,3,8
+ rotlwi 30,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 30,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 30,4,24,16,23
+ insrdi 30,5,32,0
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ ld 0,120(7)
+ add 9,9,3
+ add 9,9,5
+
+ lwz 3,120(31)
+ lwz 4,124(31)
+ rotlwi 5,3,8
+ rotlwi 31,4,8
+ rlwimi 5,3,24,0,7
+ rlwimi 31,4,24,0,7
+ rlwimi 5,3,24,16,23
+ rlwimi 31,4,24,16,23
+ insrdi 31,5,32,0
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ li 5,4
+ mtctr 5
+.align 4
+.Lrounds:
+ addi 7,7,128
+ rotrdi 3,17,1
+ rotrdi 4,17,8
+ rotrdi 5,30,19
+ rotrdi 0,30,61
+ xor 3,3,4
+ srdi 4,17,7
+ xor 5,5,0
+ srdi 0,30,6
+ add 16,16,25
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,0(7)
+ add 16,16,3
+ add 16,16,5
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,16
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrdi 3,18,1
+ rotrdi 4,18,8
+ rotrdi 5,31,19
+ rotrdi 0,31,61
+ xor 3,3,4
+ srdi 4,18,7
+ xor 5,5,0
+ srdi 0,31,6
+ add 17,17,26
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,8(7)
+ add 17,17,3
+ add 17,17,5
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,17
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrdi 3,19,1
+ rotrdi 4,19,8
+ rotrdi 5,16,19
+ rotrdi 0,16,61
+ xor 3,3,4
+ srdi 4,19,7
+ xor 5,5,0
+ srdi 0,16,6
+ add 18,18,27
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,16(7)
+ add 18,18,3
+ add 18,18,5
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,18
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrdi 3,20,1
+ rotrdi 4,20,8
+ rotrdi 5,17,19
+ rotrdi 0,17,61
+ xor 3,3,4
+ srdi 4,20,7
+ xor 5,5,0
+ srdi 0,17,6
+ add 19,19,28
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,24(7)
+ add 19,19,3
+ add 19,19,5
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,19
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrdi 3,21,1
+ rotrdi 4,21,8
+ rotrdi 5,18,19
+ rotrdi 0,18,61
+ xor 3,3,4
+ srdi 4,21,7
+ xor 5,5,0
+ srdi 0,18,6
+ add 20,20,29
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,32(7)
+ add 20,20,3
+ add 20,20,5
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,20
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrdi 3,22,1
+ rotrdi 4,22,8
+ rotrdi 5,19,19
+ rotrdi 0,19,61
+ xor 3,3,4
+ srdi 4,22,7
+ xor 5,5,0
+ srdi 0,19,6
+ add 21,21,30
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,40(7)
+ add 21,21,3
+ add 21,21,5
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,21
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrdi 3,23,1
+ rotrdi 4,23,8
+ rotrdi 5,20,19
+ rotrdi 0,20,61
+ xor 3,3,4
+ srdi 4,23,7
+ xor 5,5,0
+ srdi 0,20,6
+ add 22,22,31
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,48(7)
+ add 22,22,3
+ add 22,22,5
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,22
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrdi 3,24,1
+ rotrdi 4,24,8
+ rotrdi 5,21,19
+ rotrdi 0,21,61
+ xor 3,3,4
+ srdi 4,24,7
+ xor 5,5,0
+ srdi 0,21,6
+ add 23,23,16
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,56(7)
+ add 23,23,3
+ add 23,23,5
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,23
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ rotrdi 3,25,1
+ rotrdi 4,25,8
+ rotrdi 5,22,19
+ rotrdi 0,22,61
+ xor 3,3,4
+ srdi 4,25,7
+ xor 5,5,0
+ srdi 0,22,6
+ add 24,24,17
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,64(7)
+ add 24,24,3
+ add 24,24,5
+ rotrdi 3,12,14
+ rotrdi 4,12,18
+ and 5,6,12
+ xor 3,3,4
+ add 15,15,0
+ andc 0,14,12
+ rotrdi 4,4,23
+ or 5,5,0
+ add 15,15,24
+ xor 3,3,4
+ add 15,15,5
+ add 15,15,3
+
+ rotrdi 3,8,28
+ rotrdi 4,8,34
+ and 5,8,9
+ and 0,8,10
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,9,10
+ xor 3,3,4
+ add 11,11,15
+ xor 5,5,0
+ add 15,15,3
+ add 15,15,5
+
+ rotrdi 3,26,1
+ rotrdi 4,26,8
+ rotrdi 5,23,19
+ rotrdi 0,23,61
+ xor 3,3,4
+ srdi 4,26,7
+ xor 5,5,0
+ srdi 0,23,6
+ add 25,25,18
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,72(7)
+ add 25,25,3
+ add 25,25,5
+ rotrdi 3,11,14
+ rotrdi 4,11,18
+ and 5,12,11
+ xor 3,3,4
+ add 14,14,0
+ andc 0,6,11
+ rotrdi 4,4,23
+ or 5,5,0
+ add 14,14,25
+ xor 3,3,4
+ add 14,14,5
+ add 14,14,3
+
+ rotrdi 3,15,28
+ rotrdi 4,15,34
+ and 5,15,8
+ and 0,15,9
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,8,9
+ xor 3,3,4
+ add 10,10,14
+ xor 5,5,0
+ add 14,14,3
+ add 14,14,5
+
+ rotrdi 3,27,1
+ rotrdi 4,27,8
+ rotrdi 5,24,19
+ rotrdi 0,24,61
+ xor 3,3,4
+ srdi 4,27,7
+ xor 5,5,0
+ srdi 0,24,6
+ add 26,26,19
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,80(7)
+ add 26,26,3
+ add 26,26,5
+ rotrdi 3,10,14
+ rotrdi 4,10,18
+ and 5,11,10
+ xor 3,3,4
+ add 6,6,0
+ andc 0,12,10
+ rotrdi 4,4,23
+ or 5,5,0
+ add 6,6,26
+ xor 3,3,4
+ add 6,6,5
+ add 6,6,3
+
+ rotrdi 3,14,28
+ rotrdi 4,14,34
+ and 5,14,15
+ and 0,14,8
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,15,8
+ xor 3,3,4
+ add 9,9,6
+ xor 5,5,0
+ add 6,6,3
+ add 6,6,5
+
+ rotrdi 3,28,1
+ rotrdi 4,28,8
+ rotrdi 5,25,19
+ rotrdi 0,25,61
+ xor 3,3,4
+ srdi 4,28,7
+ xor 5,5,0
+ srdi 0,25,6
+ add 27,27,20
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,88(7)
+ add 27,27,3
+ add 27,27,5
+ rotrdi 3,9,14
+ rotrdi 4,9,18
+ and 5,10,9
+ xor 3,3,4
+ add 12,12,0
+ andc 0,11,9
+ rotrdi 4,4,23
+ or 5,5,0
+ add 12,12,27
+ xor 3,3,4
+ add 12,12,5
+ add 12,12,3
+
+ rotrdi 3,6,28
+ rotrdi 4,6,34
+ and 5,6,14
+ and 0,6,15
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,14,15
+ xor 3,3,4
+ add 8,8,12
+ xor 5,5,0
+ add 12,12,3
+ add 12,12,5
+
+ rotrdi 3,29,1
+ rotrdi 4,29,8
+ rotrdi 5,26,19
+ rotrdi 0,26,61
+ xor 3,3,4
+ srdi 4,29,7
+ xor 5,5,0
+ srdi 0,26,6
+ add 28,28,21
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,96(7)
+ add 28,28,3
+ add 28,28,5
+ rotrdi 3,8,14
+ rotrdi 4,8,18
+ and 5,9,8
+ xor 3,3,4
+ add 11,11,0
+ andc 0,10,8
+ rotrdi 4,4,23
+ or 5,5,0
+ add 11,11,28
+ xor 3,3,4
+ add 11,11,5
+ add 11,11,3
+
+ rotrdi 3,12,28
+ rotrdi 4,12,34
+ and 5,12,6
+ and 0,12,14
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,6,14
+ xor 3,3,4
+ add 15,15,11
+ xor 5,5,0
+ add 11,11,3
+ add 11,11,5
+
+ rotrdi 3,30,1
+ rotrdi 4,30,8
+ rotrdi 5,27,19
+ rotrdi 0,27,61
+ xor 3,3,4
+ srdi 4,30,7
+ xor 5,5,0
+ srdi 0,27,6
+ add 29,29,22
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,104(7)
+ add 29,29,3
+ add 29,29,5
+ rotrdi 3,15,14
+ rotrdi 4,15,18
+ and 5,8,15
+ xor 3,3,4
+ add 10,10,0
+ andc 0,9,15
+ rotrdi 4,4,23
+ or 5,5,0
+ add 10,10,29
+ xor 3,3,4
+ add 10,10,5
+ add 10,10,3
+
+ rotrdi 3,11,28
+ rotrdi 4,11,34
+ and 5,11,12
+ and 0,11,6
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,12,6
+ xor 3,3,4
+ add 14,14,10
+ xor 5,5,0
+ add 10,10,3
+ add 10,10,5
+
+ rotrdi 3,31,1
+ rotrdi 4,31,8
+ rotrdi 5,28,19
+ rotrdi 0,28,61
+ xor 3,3,4
+ srdi 4,31,7
+ xor 5,5,0
+ srdi 0,28,6
+ add 30,30,23
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,112(7)
+ add 30,30,3
+ add 30,30,5
+ rotrdi 3,14,14
+ rotrdi 4,14,18
+ and 5,15,14
+ xor 3,3,4
+ add 9,9,0
+ andc 0,8,14
+ rotrdi 4,4,23
+ or 5,5,0
+ add 9,9,30
+ xor 3,3,4
+ add 9,9,5
+ add 9,9,3
+
+ rotrdi 3,10,28
+ rotrdi 4,10,34
+ and 5,10,11
+ and 0,10,12
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,11,12
+ xor 3,3,4
+ add 6,6,9
+ xor 5,5,0
+ add 9,9,3
+ add 9,9,5
+
+ rotrdi 3,16,1
+ rotrdi 4,16,8
+ rotrdi 5,29,19
+ rotrdi 0,29,61
+ xor 3,3,4
+ srdi 4,16,7
+ xor 5,5,0
+ srdi 0,29,6
+ add 31,31,24
+ xor 3,3,4
+ xor 5,5,0
+ ld 0,120(7)
+ add 31,31,3
+ add 31,31,5
+ rotrdi 3,6,14
+ rotrdi 4,6,18
+ and 5,14,6
+ xor 3,3,4
+ add 8,8,0
+ andc 0,15,6
+ rotrdi 4,4,23
+ or 5,5,0
+ add 8,8,31
+ xor 3,3,4
+ add 8,8,5
+ add 8,8,3
+
+ rotrdi 3,9,28
+ rotrdi 4,9,34
+ and 5,9,10
+ and 0,9,11
+ xor 3,3,4
+ rotrdi 4,4,5
+ xor 5,5,0
+ and 0,10,11
+ xor 3,3,4
+ add 12,12,8
+ xor 5,5,0
+ add 8,8,3
+ add 8,8,5
+
+ bdnz .Lrounds
+
+ ld 3,208(1)
+ ld 31,200(1)
+ ld 5,192(1)
+ subi 7,7,512
+
+ ld 16,0(3)
+ ld 17,8(3)
+ ld 18,16(3)
+ ld 19,24(3)
+ ld 20,32(3)
+ ld 21,40(3)
+ ld 22,48(3)
+ addi 31,31,128
+ ld 23,56(3)
+ add 8,8,16
+ add 9,9,17
+ std 31,200(1)
+ add 10,10,18
+ std 8,0(3)
+ add 11,11,19
+ std 9,8(3)
+ add 12,12,20
+ std 10,16(3)
+ add 6,6,21
+ std 11,24(3)
+ add 14,14,22
+ std 12,32(3)
+ add 15,15,23
+ std 6,40(3)
+ std 14,48(3)
+ cmpld 31,5
+ std 15,56(3)
+ bne .Lsha2_block_private
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.size zfs_sha512_ppc,.-zfs_sha512_ppc
+.align 6
+.LPICmeup:
+ mflr 0
+ bcl 20,31,$+4
+ mflr 7
+ addi 7,7,56
+ mtlr 0
+ blr
+.long 0
+.byte 0,12,0x14,0,0,0,0,0
+.space 28
+.long 0xd728ae22,0x428a2f98
+.long 0x23ef65cd,0x71374491
+.long 0xec4d3b2f,0xb5c0fbcf
+.long 0x8189dbbc,0xe9b5dba5
+.long 0xf348b538,0x3956c25b
+.long 0xb605d019,0x59f111f1
+.long 0xaf194f9b,0x923f82a4
+.long 0xda6d8118,0xab1c5ed5
+.long 0xa3030242,0xd807aa98
+.long 0x45706fbe,0x12835b01
+.long 0x4ee4b28c,0x243185be
+.long 0xd5ffb4e2,0x550c7dc3
+.long 0xf27b896f,0x72be5d74
+.long 0x3b1696b1,0x80deb1fe
+.long 0x25c71235,0x9bdc06a7
+.long 0xcf692694,0xc19bf174
+.long 0x9ef14ad2,0xe49b69c1
+.long 0x384f25e3,0xefbe4786
+.long 0x8b8cd5b5,0x0fc19dc6
+.long 0x77ac9c65,0x240ca1cc
+.long 0x592b0275,0x2de92c6f
+.long 0x6ea6e483,0x4a7484aa
+.long 0xbd41fbd4,0x5cb0a9dc
+.long 0x831153b5,0x76f988da
+.long 0xee66dfab,0x983e5152
+.long 0x2db43210,0xa831c66d
+.long 0x98fb213f,0xb00327c8
+.long 0xbeef0ee4,0xbf597fc7
+.long 0x3da88fc2,0xc6e00bf3
+.long 0x930aa725,0xd5a79147
+.long 0xe003826f,0x06ca6351
+.long 0x0a0e6e70,0x14292967
+.long 0x46d22ffc,0x27b70a85
+.long 0x5c26c926,0x2e1b2138
+.long 0x5ac42aed,0x4d2c6dfc
+.long 0x9d95b3df,0x53380d13
+.long 0x8baf63de,0x650a7354
+.long 0x3c77b2a8,0x766a0abb
+.long 0x47edaee6,0x81c2c92e
+.long 0x1482353b,0x92722c85
+.long 0x4cf10364,0xa2bfe8a1
+.long 0xbc423001,0xa81a664b
+.long 0xd0f89791,0xc24b8b70
+.long 0x0654be30,0xc76c51a3
+.long 0xd6ef5218,0xd192e819
+.long 0x5565a910,0xd6990624
+.long 0x5771202a,0xf40e3585
+.long 0x32bbd1b8,0x106aa070
+.long 0xb8d2d0c8,0x19a4c116
+.long 0x5141ab53,0x1e376c08
+.long 0xdf8eeb99,0x2748774c
+.long 0xe19b48a8,0x34b0bcb5
+.long 0xc5c95a63,0x391c0cb3
+.long 0xe3418acb,0x4ed8aa4a
+.long 0x7763e373,0x5b9cca4f
+.long 0xd6b2b8a3,0x682e6ff3
+.long 0x5defb2fc,0x748f82ee
+.long 0x43172f60,0x78a5636f
+.long 0xa1f0ab72,0x84c87814
+.long 0x1a6439ec,0x8cc70208
+.long 0x23631e28,0x90befffa
+.long 0xde82bde9,0xa4506ceb
+.long 0xb2c67915,0xbef9a3f7
+.long 0xe372532b,0xc67178f2
+.long 0xea26619c,0xca273ece
+.long 0x21c0c207,0xd186b8c7
+.long 0xcde0eb1e,0xeada7dd6
+.long 0xee6ed178,0xf57d4f7f
+.long 0x72176fba,0x06f067aa
+.long 0xa2c898a6,0x0a637dc5
+.long 0xbef90dae,0x113f9804
+.long 0x131c471b,0x1b710b35
+.long 0x23047d84,0x28db77f5
+.long 0x40c72493,0x32caab7b
+.long 0x15c9bebc,0x3c9ebe0a
+.long 0x9c100d4c,0x431d67c4
+.long 0xcb3e42b6,0x4cc5d4be
+.long 0xfc657e2a,0x597f299c
+.long 0x3ad6faec,0x5fcb6fab
+.long 0x4a475817,0x6c44198c
+
+#endif
diff --git a/module/icp/asm-x86_64/aes/aes_aesni.S b/module/icp/asm-x86_64/aes/aes_aesni.S
index f622235bd15b..4f3fe3ec65d6 100644
--- a/module/icp/asm-x86_64/aes/aes_aesni.S
+++ b/module/icp/asm-x86_64/aes/aes_aesni.S
@@ -378,7 +378,7 @@ rijndael_key_setup_enc_intel_local:
FRAME_END
RET
-.align 4
+.balign 4
.Lenc_key192:
cmp $192, %KEYSIZE32
jnz .Lenc_key128
@@ -415,7 +415,7 @@ rijndael_key_setup_enc_intel_local:
FRAME_END
RET
-.align 4
+.balign 4
.Lenc_key128:
cmp $128, %KEYSIZE32
jnz .Lenc_key_invalid_key_bits
@@ -522,7 +522,7 @@ FRAME_BEGIN
add %AESKEY, %ROUNDS64
mov %ROUNDS64, %ENDAESKEY
-.align 4
+.balign 4
.Ldec_key_reorder_loop:
movups (%AESKEY), %xmm0
movups (%ROUNDS64), %xmm1
@@ -533,7 +533,7 @@ FRAME_BEGIN
cmp %AESKEY, %ROUNDS64
ja .Ldec_key_reorder_loop
-.align 4
+.balign 4
.Ldec_key_inv_loop:
movups (%rcx), %xmm0
// Convert an encryption round key to a form usable for decryption
@@ -622,7 +622,7 @@ ENTRY_NP(aes_encrypt_intel)
movups -0x50(%KEYP), %KEY
aesenc %KEY, %STATE
-.align 4
+.balign 4
.Lenc192:
// AES 192 and 256
movups -0x40(%KEYP), %KEY
@@ -630,7 +630,7 @@ ENTRY_NP(aes_encrypt_intel)
movups -0x30(%KEYP), %KEY
aesenc %KEY, %STATE
-.align 4
+.balign 4
.Lenc128:
// AES 128, 192, and 256
movups -0x20(%KEYP), %KEY
@@ -705,7 +705,7 @@ ENTRY_NP(aes_decrypt_intel)
movups -0x50(%KEYP), %KEY
aesdec %KEY, %STATE
-.align 4
+.balign 4
.Ldec192:
// AES 192 and 256
movups -0x40(%KEYP), %KEY
@@ -713,7 +713,7 @@ ENTRY_NP(aes_decrypt_intel)
movups -0x30(%KEYP), %KEY
aesdec %KEY, %STATE
-.align 4
+.balign 4
.Ldec128:
// AES 128, 192, and 256
movups -0x20(%KEYP), %KEY
diff --git a/module/icp/asm-x86_64/aes/aes_amd64.S b/module/icp/asm-x86_64/aes/aes_amd64.S
index f546e8933be1..c4870a28ead6 100644
--- a/module/icp/asm-x86_64/aes/aes_amd64.S
+++ b/module/icp/asm-x86_64/aes/aes_amd64.S
@@ -188,13 +188,13 @@
#include <sys/types.h>
void
aes_encrypt_amd64(const uint32_t rk[], int Nr, const uint32_t pt[4],
- uint32_t ct[4]) {
- (void) rk, (void) Nr, (void) pt, (void) ct;
+ uint32_t ct[4]) {
+ (void) rk, (void) Nr, (void) pt, (void) ct;
}
void
aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4],
- uint32_t pt[4]) {
- (void) rk, (void) Nr, (void) pt, (void) ct;
+ uint32_t pt[4]) {
+ (void) rk, (void) Nr, (void) pt, (void) ct;
}
@@ -221,23 +221,23 @@ aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4],
// finite field multiplies by {02}, {04} and {08}
-#define f2(x) [[x<<1]^[[[x>>7]&1]*0x11b]]
-#define f4(x) [[x<<2]^[[[x>>6]&1]*0x11b]^[[[x>>6]&2]*0x11b]]
-#define f8(x) [[x<<3]^[[[x>>5]&1]*0x11b]^[[[x>>5]&2]*0x11b]^[[[x>>5]&4]*0x11b]]
+#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b))
+#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
+#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
// finite field multiplies required in table generation
-#define f3(x) [[f2(x)] ^ [x]]
-#define f9(x) [[f8(x)] ^ [x]]
-#define fb(x) [[f8(x)] ^ [f2(x)] ^ [x]]
-#define fd(x) [[f8(x)] ^ [f4(x)] ^ [x]]
-#define fe(x) [[f8(x)] ^ [f4(x)] ^ [f2(x)]]
+#define f3(x) ((f2(x)) ^ (x))
+#define f9(x) ((f8(x)) ^ (x))
+#define fb(x) ((f8(x)) ^ (f2(x)) ^ (x))
+#define fd(x) ((f8(x)) ^ (f4(x)) ^ (x))
+#define fe(x) ((f8(x)) ^ (f4(x)) ^ (f2(x)))
// macros for expanding S-box data
-#define u8(x) [f2(x)], [x], [x], [f3(x)], [f2(x)], [x], [x], [f3(x)]
-#define v8(x) [fe(x)], [f9(x)], [fd(x)], [fb(x)], [fe(x)], [f9(x)], [fd(x)], [x]
-#define w8(x) [x], 0, 0, 0, [x], 0, 0, 0
+#define u8(x) (f2(x)), (x), (x), (f3(x)), (f2(x)), (x), (x), (f3(x))
+#define v8(x) (fe(x)), (f9(x)), (fd(x)), (fb(x)), (fe(x)), (f9(x)), (fd(x)), (x)
+#define w8(x) (x), 0, 0, 0, (x), 0, 0, 0
#define enc_vals(x) \
.byte x(0x63),x(0x7c),x(0x77),x(0x7b),x(0xf2),x(0x6b),x(0x6f),x(0xc5); \
@@ -693,8 +693,8 @@ aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4],
* int aes_encrypt(const unsigned char *in,
* unsigned char *out, const aes_encrypt_ctx cx[1])/
*/
-.section .rodata
-.align 64
+SECTION_STATIC
+.balign 64
enc_tab:
enc_vals(u8)
#ifdef LAST_ROUND_TABLES
@@ -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
@@ -717,7 +718,7 @@ ENTRY_NP(aes_encrypt_amd64)
#else
// OpenSolaris OS interface
- sub $[4*8], %rsp // Make room on stack to save registers
+ sub $(4*8), %rsp // Make room on stack to save registers
mov %rcx, (%rsp) // Save output pointer (P4) on stack
mov %rdi, %r8 // context (P1)
mov %rdx, %rdi // P3: save input pointer
@@ -748,11 +749,11 @@ ENTRY_NP(aes_encrypt_amd64)
lea (kptr,%rsi), kptr
// Jump based on byte key length * 16:
- cmp $[10*16], %esi
+ cmp $(10*16), %esi
je 3f
- cmp $[12*16], %esi
+ cmp $(12*16), %esi
je 2f
- cmp $[14*16], %esi
+ cmp $(14*16), %esi
je 1f
mov $-1, %rax // error
jmp 4f
@@ -784,7 +785,7 @@ ENTRY_NP(aes_encrypt_amd64)
mov 1*8(%rsp), %rbx
mov 2*8(%rsp), %rbp
mov 3*8(%rsp), %r12
- add $[4*8], %rsp
+ add $(4*8), %rsp
RET
SET_SIZE(aes_encrypt_amd64)
@@ -798,8 +799,8 @@ ENTRY_NP(aes_encrypt_amd64)
* int aes_decrypt(const unsigned char *in,
* unsigned char *out, const aes_encrypt_ctx cx[1])/
*/
-.section .rodata
-.align 64
+SECTION_STATIC
+.balign 64
dec_tab:
dec_vals(v8)
#ifdef LAST_ROUND_TABLES
@@ -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
@@ -822,7 +824,7 @@ ENTRY_NP(aes_decrypt_amd64)
#else
// OpenSolaris OS interface
- sub $[4*8], %rsp // Make room on stack to save registers
+ sub $(4*8), %rsp // Make room on stack to save registers
mov %rcx, (%rsp) // Save output pointer (P4) on stack
mov %rdi, %r8 // context (P1)
mov %rdx, %rdi // P3: save input pointer
@@ -859,11 +861,11 @@ ENTRY_NP(aes_decrypt_amd64)
xor rofs+12(%rdi), %edx
// Jump based on byte key length * 16:
- cmp $[10*16], %esi
+ cmp $(10*16), %esi
je 3f
- cmp $[12*16], %esi
+ cmp $(12*16), %esi
je 2f
- cmp $[14*16], %esi
+ cmp $(14*16), %esi
je 1f
mov $-1, %rax // error
jmp 4f
@@ -895,11 +897,11 @@ ENTRY_NP(aes_decrypt_amd64)
mov 1*8(%rsp), %rbx
mov 2*8(%rsp), %rbp
mov 3*8(%rsp), %r12
- add $[4*8], %rsp
+ add $(4*8), %rsp
RET
SET_SIZE(aes_decrypt_amd64)
-#endif /* lint || __lint */
+#endif /* lint || __lint */
#ifdef __ELF__
.section .note.GNU-stack,"",%progbits
diff --git a/module/icp/asm-x86_64/aes/aestab2.h b/module/icp/asm-x86_64/aes/aestab2.h
index eb13f72b10d8..003534e0fa50 100644
--- a/module/icp/asm-x86_64/aes/aestab2.h
+++ b/module/icp/asm-x86_64/aes/aestab2.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/asm-x86_64/blake3/blake3_avx2.S b/module/icp/asm-x86_64/blake3/blake3_avx2.S
index 3a7094f12b39..0ebec5c1095e 100644
--- a/module/icp/asm-x86_64/blake3/blake3_avx2.S
+++ b/module/icp/asm-x86_64/blake3/blake3_avx2.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,24 +30,11 @@
#define _ASM
#include <sys/asm_linkage.h>
-#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
-#if __has_include(<cet.h>)
-#include <cet.h>
-#endif
-#endif
-
-#if !defined(_CET_ENDBR)
-#define _CET_ENDBR
-#endif
-
.intel_syntax noprefix
-.global zfs_blake3_hash_many_avx2
.text
-.type zfs_blake3_hash_many_avx2,@function
-.p2align 6
-zfs_blake3_hash_many_avx2:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_hash_many_avx2, 64)
+ ENDBR
push r15
push r14
push r13
@@ -1801,13 +1788,9 @@ zfs_blake3_hash_many_avx2:
vmovdqu xmmword ptr [rbx+0x10], xmm1
jmp 4b
-.size zfs_blake3_hash_many_avx2, . - zfs_blake3_hash_many_avx2
+SET_SIZE(zfs_blake3_hash_many_avx2)
-#ifdef __APPLE__
-.static_data
-#else
-.section .rodata
-#endif
+SECTION_STATIC
.p2align 6
ADD0:
diff --git a/module/icp/asm-x86_64/blake3/blake3_avx512.S b/module/icp/asm-x86_64/blake3/blake3_avx512.S
index 4bfdb74123d4..39830f1556bb 100644
--- a/module/icp/asm-x86_64/blake3/blake3_avx512.S
+++ b/module/icp/asm-x86_64/blake3/blake3_avx512.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,29 +30,11 @@
#define _ASM
#include <sys/asm_linkage.h>
-#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
-#if __has_include(<cet.h>)
-#include <cet.h>
-#endif
-#endif
-
-#if !defined(_CET_ENDBR)
-#define _CET_ENDBR
-#endif
-
.intel_syntax noprefix
-.global zfs_blake3_hash_many_avx512
-.global zfs_blake3_compress_in_place_avx512
-.global zfs_blake3_compress_xof_avx512
.text
-.type zfs_blake3_hash_many_avx512,@function
-.type zfs_blake3_compress_xof_avx512,@function
-.type zfs_blake3_compress_in_place_avx512,@function
-
-.p2align 6
-zfs_blake3_hash_many_avx512:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_hash_many_avx512, 64)
+ ENDBR
push r15
push r14
push r13
@@ -2407,9 +2389,10 @@ zfs_blake3_hash_many_avx512:
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+0x10], xmm1
jmp 4b
-.p2align 6
-zfs_blake3_compress_in_place_avx512:
- _CET_ENDBR
+SET_SIZE(zfs_blake3_hash_many_avx512)
+
+ENTRY_ALIGN(zfs_blake3_compress_in_place_avx512, 64)
+ ENDBR
vmovdqu xmm0, xmmword ptr [rdi]
vmovdqu xmm1, xmmword ptr [rdi+0x10]
movzx eax, r8b
@@ -2488,10 +2471,10 @@ zfs_blake3_compress_in_place_avx512:
vmovdqu xmmword ptr [rdi], xmm0
vmovdqu xmmword ptr [rdi+0x10], xmm1
RET
+SET_SIZE(zfs_blake3_compress_in_place_avx512)
-.p2align 6
-zfs_blake3_compress_xof_avx512:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_compress_xof_avx512, 64)
+ ENDBR
vmovdqu xmm0, xmmword ptr [rdi]
vmovdqu xmm1, xmmword ptr [rdi+0x10]
movzx eax, r8b
@@ -2574,16 +2557,9 @@ zfs_blake3_compress_xof_avx512:
vmovdqu xmmword ptr [r9+0x20], xmm2
vmovdqu xmmword ptr [r9+0x30], xmm3
RET
+SET_SIZE(zfs_blake3_compress_xof_avx512)
-.size zfs_blake3_hash_many_avx512, . - zfs_blake3_hash_many_avx512
-.size zfs_blake3_compress_in_place_avx512, . - zfs_blake3_compress_in_place_avx512
-.size zfs_blake3_compress_xof_avx512, . - zfs_blake3_compress_xof_avx512
-
-#ifdef __APPLE__
-.static_data
-#else
-.section .rodata
-#endif
+SECTION_STATIC
.p2align 6
INDEX0:
diff --git a/module/icp/asm-x86_64/blake3/blake3_sse2.S b/module/icp/asm-x86_64/blake3/blake3_sse2.S
index 8e891dd524c0..78c4ffac53a8 100644
--- a/module/icp/asm-x86_64/blake3/blake3_sse2.S
+++ b/module/icp/asm-x86_64/blake3/blake3_sse2.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,29 +30,12 @@
#define _ASM
#include <sys/asm_linkage.h>
-#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
-#if __has_include(<cet.h>)
-#include <cet.h>
-#endif
-#endif
-
-#if !defined(_CET_ENDBR)
-#define _CET_ENDBR
-#endif
-
.intel_syntax noprefix
-.global zfs_blake3_hash_many_sse2
-.global zfs_blake3_compress_in_place_sse2
-.global zfs_blake3_compress_xof_sse2
-.text
-.type zfs_blake3_hash_many_sse2,@function
-.type zfs_blake3_compress_in_place_sse2,@function
-.type zfs_blake3_compress_xof_sse2,@function
+SECTION_TEXT
- .p2align 6
-zfs_blake3_hash_many_sse2:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_hash_many_sse2, 64)
+ ENDBR
push r15
push r14
push r13
@@ -2047,10 +2030,10 @@ zfs_blake3_hash_many_sse2:
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+0x10], xmm1
jmp 4b
+SET_SIZE(zfs_blake3_hash_many_sse2)
-.p2align 6
-zfs_blake3_compress_in_place_sse2:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_compress_in_place_sse2, 64)
+ ENDBR
movups xmm0, xmmword ptr [rdi]
movups xmm1, xmmword ptr [rdi+0x10]
movaps xmm2, xmmword ptr [BLAKE3_IV+rip]
@@ -2158,10 +2141,10 @@ zfs_blake3_compress_in_place_sse2:
movups xmmword ptr [rdi], xmm0
movups xmmword ptr [rdi+0x10], xmm1
RET
+SET_SIZE(zfs_blake3_compress_in_place_sse2)
-.p2align 6
-zfs_blake3_compress_xof_sse2:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_compress_xof_sse2, 64)
+ ENDBR
movups xmm0, xmmword ptr [rdi]
movups xmm1, xmmword ptr [rdi+0x10]
movaps xmm2, xmmword ptr [BLAKE3_IV+rip]
@@ -2277,21 +2260,14 @@ zfs_blake3_compress_xof_sse2:
movups xmmword ptr [r9+0x20], xmm2
movups xmmword ptr [r9+0x30], xmm3
RET
+SET_SIZE(zfs_blake3_compress_xof_sse2)
-.size zfs_blake3_hash_many_sse2, . - zfs_blake3_hash_many_sse2
-.size zfs_blake3_compress_in_place_sse2, . - zfs_blake3_compress_in_place_sse2
-.size zfs_blake3_compress_xof_sse2, . - zfs_blake3_compress_xof_sse2
-
-#ifdef __APPLE__
-.static_data
-#else
-.section .rodata
-#endif
+SECTION_STATIC
.p2align 6
BLAKE3_IV:
.long 0x6A09E667, 0xBB67AE85
.long 0x3C6EF372, 0xA54FF53A
-ADD0:
+ADD0:
.long 0, 1, 2, 3
ADD1:
.long 4, 4, 4, 4
diff --git a/module/icp/asm-x86_64/blake3/blake3_sse41.S b/module/icp/asm-x86_64/blake3/blake3_sse41.S
index 51477232371f..8ee7be75a0e1 100644
--- a/module/icp/asm-x86_64/blake3/blake3_sse41.S
+++ b/module/icp/asm-x86_64/blake3/blake3_sse41.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,29 +30,12 @@
#define _ASM
#include <sys/asm_linkage.h>
-#if defined(__ELF__) && defined(__CET__) && defined(__has_include)
-#if __has_include(<cet.h>)
-#include <cet.h>
-#endif
-#endif
-
-#if !defined(_CET_ENDBR)
-#define _CET_ENDBR
-#endif
-
.intel_syntax noprefix
-.global zfs_blake3_compress_in_place_sse41
-.global zfs_blake3_compress_xof_sse41
-.global zfs_blake3_hash_many_sse41
.text
-.type zfs_blake3_hash_many_sse41,@function
-.type zfs_blake3_compress_in_place_sse41,@function
-.type zfs_blake3_compress_xof_sse41,@function
-.p2align 6
-zfs_blake3_hash_many_sse41:
- _CET_ENDBR
+ENTRY_ALIGN(zfs_blake3_hash_many_sse41, 64)
+ ENDBR
push r15
push r14
push r13
@@ -1810,9 +1793,10 @@ zfs_blake3_hash_many_sse41:
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+0x10], xmm1
jmp 4b
-.p2align 6
-zfs_blake3_compress_in_place_sse41:
- _CET_ENDBR
+SET_SIZE(zfs_blake3_hash_many_sse41)
+
+ENTRY_ALIGN(zfs_blake3_compress_in_place_sse41, 64)
+ ENDBR
movups xmm0, xmmword ptr [rdi]
movups xmm1, xmmword ptr [rdi+0x10]
movaps xmm2, xmmword ptr [BLAKE3_IV+rip]
@@ -1909,9 +1893,10 @@ zfs_blake3_compress_in_place_sse41:
movups xmmword ptr [rdi], xmm0
movups xmmword ptr [rdi+0x10], xmm1
RET
-.p2align 6
-zfs_blake3_compress_xof_sse41:
- _CET_ENDBR
+SET_SIZE(zfs_blake3_compress_in_place_sse41)
+
+ENTRY_ALIGN(zfs_blake3_compress_xof_sse41, 64)
+ ENDBR
movups xmm0, xmmword ptr [rdi]
movups xmm1, xmmword ptr [rdi+0x10]
movaps xmm2, xmmword ptr [BLAKE3_IV+rip]
@@ -2016,16 +2001,10 @@ zfs_blake3_compress_xof_sse41:
movups xmmword ptr [r9+0x20], xmm2
movups xmmword ptr [r9+0x30], xmm3
RET
+SET_SIZE(zfs_blake3_compress_xof_sse41)
-.size zfs_blake3_hash_many_sse41, . - zfs_blake3_hash_many_sse41
-.size zfs_blake3_compress_in_place_sse41, . - zfs_blake3_compress_in_place_sse41
-.size zfs_blake3_compress_xof_sse41, . - zfs_blake3_compress_xof_sse41
+SECTION_STATIC
-#ifdef __APPLE__
-.static_data
-#else
-.section .rodata
-#endif
.p2align 6
BLAKE3_IV:
.long 0x6A09E667, 0xBB67AE85
@@ -2034,7 +2013,7 @@ ROT16:
.byte 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13
ROT8:
.byte 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12
-ADD0:
+ADD0:
.long 0, 1, 2, 3
ADD1:
.long 4, 4, 4, 4
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..909b2147dff9 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,15 +47,26 @@
#if defined(__x86_64__) && defined(HAVE_AVX) && \
defined(HAVE_AES) && defined(HAVE_PCLMULQDQ)
+#define _ASM
+#include <sys/asm_linkage.h>
+
+/* Windows userland links with OpenSSL */
+#if !defined (_WIN32) || defined (_KERNEL)
+
+/* Apple needs _ */
+#if defined (__APPLE__)
+#define gcm_avx_can_use_movbe _gcm_avx_can_use_movbe
+#endif
+
.extern gcm_avx_can_use_movbe
.text
#ifdef HAVE_MOVBE
-.type _aesni_ctr32_ghash_6x,@function
-.align 32
-_aesni_ctr32_ghash_6x:
+.balign 32
+FUNCTION(_aesni_ctr32_ghash_6x)
.cfi_startproc
+ ENDBR
vmovdqu 32(%r11),%xmm2
subq $6,%rdx
vpxor %xmm4,%xmm4,%xmm4
@@ -69,7 +80,7 @@ _aesni_ctr32_ghash_6x:
vmovdqu %xmm4,16+8(%rsp)
jmp .Loop6x
-.align 32
+.balign 32
.Loop6x:
addl $100663296,%ebx
jc .Lhandle_ctr32
@@ -281,7 +292,7 @@ _aesni_ctr32_ghash_6x:
vmovups 224-128(%rcx),%xmm1
jmp .Lenc_tail
-.align 32
+.balign 32
.Lhandle_ctr32:
vmovdqu (%r11),%xmm0
vpshufb %xmm0,%xmm1,%xmm6
@@ -303,7 +314,7 @@ _aesni_ctr32_ghash_6x:
vpshufb %xmm0,%xmm1,%xmm1
jmp .Lresume_ctr32
-.align 32
+.balign 32
.Lenc_tail:
vaesenc %xmm15,%xmm9,%xmm9
vmovdqu %xmm7,16+8(%rsp)
@@ -363,15 +374,15 @@ _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
+SET_SIZE(_aesni_ctr32_ghash_6x)
#endif /* ifdef HAVE_MOVBE */
-.type _aesni_ctr32_ghash_no_movbe_6x,@function
-.align 32
-_aesni_ctr32_ghash_no_movbe_6x:
+.balign 32
+FUNCTION(_aesni_ctr32_ghash_no_movbe_6x)
.cfi_startproc
+ ENDBR
vmovdqu 32(%r11),%xmm2
subq $6,%rdx
vpxor %xmm4,%xmm4,%xmm4
@@ -385,7 +396,7 @@ _aesni_ctr32_ghash_no_movbe_6x:
vmovdqu %xmm4,16+8(%rsp)
jmp .Loop6x_nmb
-.align 32
+.balign 32
.Loop6x_nmb:
addl $100663296,%ebx
jc .Lhandle_ctr32_nmb
@@ -609,7 +620,7 @@ _aesni_ctr32_ghash_no_movbe_6x:
vmovups 224-128(%rcx),%xmm1
jmp .Lenc_tail_nmb
-.align 32
+.balign 32
.Lhandle_ctr32_nmb:
vmovdqu (%r11),%xmm0
vpshufb %xmm0,%xmm1,%xmm6
@@ -631,7 +642,7 @@ _aesni_ctr32_ghash_no_movbe_6x:
vpshufb %xmm0,%xmm1,%xmm1
jmp .Lresume_ctr32_nmb
-.align 32
+.balign 32
.Lenc_tail_nmb:
vaesenc %xmm15,%xmm9,%xmm9
vmovdqu %xmm7,16+8(%rsp)
@@ -691,15 +702,13 @@ _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
+SET_SIZE(_aesni_ctr32_ghash_no_movbe_6x)
-.globl aesni_gcm_decrypt
-.type aesni_gcm_decrypt,@function
-.align 32
-aesni_gcm_decrypt:
+ENTRY_ALIGN(aesni_gcm_decrypt, 32)
.cfi_startproc
+ ENDBR
xorq %r10,%r10
cmpq $0x60,%rdx
jb .Lgcm_dec_abort
@@ -810,13 +819,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:
+SET_SIZE(aesni_gcm_decrypt)
+
+.balign 32
+FUNCTION(_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.
@@ -838,7 +848,7 @@ _aesni_ctr32_6x:
vpxor %xmm4,%xmm14,%xmm14
jmp .Loop_ctr32
-.align 16
+.balign 16
.Loop_ctr32:
vaesenc %xmm15,%xmm9,%xmm9
vaesenc %xmm15,%xmm10,%xmm10
@@ -880,8 +890,8 @@ _aesni_ctr32_6x:
vmovups %xmm14,80(%rsi)
leaq 96(%rsi),%rsi
- .byte 0xf3,0xc3
-.align 32
+ RET
+.balign 32
.Lhandle_ctr32_2:
vpshufb %xmm0,%xmm1,%xmm6
vmovdqu 48(%r11),%xmm5
@@ -904,13 +914,11 @@ _aesni_ctr32_6x:
vpxor %xmm4,%xmm14,%xmm14
jmp .Loop_ctr32
.cfi_endproc
-.size _aesni_ctr32_6x,.-_aesni_ctr32_6x
+SET_SIZE(_aesni_ctr32_6x)
-.globl aesni_gcm_encrypt
-.type aesni_gcm_encrypt,@function
-.align 32
-aesni_gcm_encrypt:
+ENTRY_ALIGN(aesni_gcm_encrypt, 32)
.cfi_startproc
+ ENDBR
xorq %r10,%r10
cmpq $288,%rdx
jb .Lgcm_enc_abort
@@ -1186,9 +1194,11 @@ 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
+SET_SIZE(aesni_gcm_encrypt)
+
+#endif /* !_WIN32 || _KERNEL */
/* Some utility routines */
@@ -1196,13 +1206,10 @@ aesni_gcm_encrypt:
* clear all fpu registers
* void clear_fpu_regs_avx(void);
*/
-.globl clear_fpu_regs_avx
-.type clear_fpu_regs_avx,@function
-.align 32
-clear_fpu_regs_avx:
+ENTRY_ALIGN(clear_fpu_regs_avx, 32)
vzeroall
RET
-.size clear_fpu_regs_avx,.-clear_fpu_regs_avx
+SET_SIZE(clear_fpu_regs_avx)
/*
* void gcm_xor_avx(const uint8_t *src, uint8_t *dst);
@@ -1211,25 +1218,19 @@ clear_fpu_regs_avx:
* stores the result at `dst'. The XOR is performed using FPU registers,
* so make sure FPU state is saved when running this in the kernel.
*/
-.globl gcm_xor_avx
-.type gcm_xor_avx,@function
-.align 32
-gcm_xor_avx:
+ENTRY_ALIGN(gcm_xor_avx, 32)
movdqu (%rdi), %xmm0
movdqu (%rsi), %xmm1
pxor %xmm1, %xmm0
movdqu %xmm0, (%rsi)
RET
-.size gcm_xor_avx,.-gcm_xor_avx
+SET_SIZE(gcm_xor_avx)
/*
* Toggle a boolean_t value atomically and return the new value.
* boolean_t atomic_toggle_boolean_nv(volatile boolean_t *);
*/
-.globl atomic_toggle_boolean_nv
-.type atomic_toggle_boolean_nv,@function
-.align 32
-atomic_toggle_boolean_nv:
+ENTRY_ALIGN(atomic_toggle_boolean_nv, 32)
xorl %eax, %eax
lock
xorl $1, (%rdi)
@@ -1237,9 +1238,11 @@ atomic_toggle_boolean_nv:
movl $1, %eax
1:
RET
-.size atomic_toggle_boolean_nv,.-atomic_toggle_boolean_nv
+SET_SIZE(atomic_toggle_boolean_nv)
+
+SECTION_STATIC
-.align 64
+.balign 64
.Lbswap_mask:
.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
.Lpoly:
@@ -1251,7 +1254,7 @@ atomic_toggle_boolean_nv:
.Lone_lsb:
.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
+.balign 64
/* Mark the stack non-executable. */
#if defined(__linux__) && defined(__ELF__)
diff --git a/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S b/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S
index 6c0540321884..dec782fda33e 100644
--- a/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S
+++ b/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -101,8 +101,8 @@ gcm_mul_pclmulqdq(uint64_t *x_in, uint64_t *y, uint64_t *res) {
// static uint8_t byte_swap16_mask[] = {
// 15, 14, 13, 12, 11, 10, 9, 8, 7, 6 ,5, 4, 3, 2, 1, 0 };
-.section .rodata
-.align XMM_ALIGN
+SECTION_STATIC
+.balign XMM_ALIGN
.Lbyte_swap16_mask:
.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
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..f62e056d4b64 100644
--- a/module/icp/asm-x86_64/modes/ghash-x86_64.S
+++ b/module/icp/asm-x86_64/modes/ghash-x86_64.S
@@ -97,13 +97,18 @@
#if defined(__x86_64__) && defined(HAVE_AVX) && \
defined(HAVE_AES) && defined(HAVE_PCLMULQDQ)
+#define _ASM
+#include <sys/asm_linkage.h>
+
.text
-.globl gcm_gmult_clmul
-.type gcm_gmult_clmul,@function
-.align 16
-gcm_gmult_clmul:
+/* Windows userland links with OpenSSL */
+#if !defined (_WIN32) || defined (_KERNEL)
+ENTRY_ALIGN(gcm_gmult_clmul, 16)
+
.cfi_startproc
+ ENDBR
+
.L_gmult_clmul:
movdqu (%rdi),%xmm0
movdqa .Lbswap_mask(%rip),%xmm5
@@ -149,15 +154,14 @@ 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
+SET_SIZE(gcm_gmult_clmul)
+#endif /* !_WIN32 || _KERNEL */
-.globl gcm_init_htab_avx
-.type gcm_init_htab_avx,@function
-.align 32
-gcm_init_htab_avx:
+ENTRY_ALIGN(gcm_init_htab_avx, 32)
.cfi_startproc
+ ENDBR
vzeroupper
vmovdqu (%rsi),%xmm2
@@ -184,7 +188,7 @@ gcm_init_htab_avx:
vpxor %xmm2,%xmm6,%xmm6
movq $4,%r10
jmp .Linit_start_avx
-.align 32
+.balign 32
.Linit_loop_avx:
vpalignr $8,%xmm3,%xmm4,%xmm5
vmovdqu %xmm5,-16(%rdi)
@@ -262,23 +266,21 @@ gcm_init_htab_avx:
vmovdqu %xmm5,-16(%rdi)
vzeroupper
- .byte 0xf3,0xc3
+ RET
.cfi_endproc
-.size gcm_init_htab_avx,.-gcm_init_htab_avx
+SET_SIZE(gcm_init_htab_avx)
-.globl gcm_gmult_avx
-.type gcm_gmult_avx,@function
-.align 32
-gcm_gmult_avx:
+#if !defined (_WIN32) || defined (_KERNEL)
+ENTRY_ALIGN(gcm_gmult_avx, 32)
.cfi_startproc
+ ENDBR
jmp .L_gmult_clmul
.cfi_endproc
-.size gcm_gmult_avx,.-gcm_gmult_avx
-.globl gcm_ghash_avx
-.type gcm_ghash_avx,@function
-.align 32
-gcm_ghash_avx:
+SET_SIZE(gcm_gmult_avx)
+
+ENTRY_ALIGN(gcm_ghash_avx, 32)
.cfi_startproc
+ ENDBR
vzeroupper
vmovdqu (%rdi),%xmm10
@@ -384,7 +386,7 @@ gcm_ghash_avx:
subq $0x80,%rcx
jmp .Loop8x_avx
-.align 32
+.balign 32
.Loop8x_avx:
vpunpckhqdq %xmm15,%xmm15,%xmm8
vmovdqu 112(%rdx),%xmm14
@@ -504,7 +506,7 @@ gcm_ghash_avx:
addq $0x80,%rcx
jmp .Ltail_no_xor_avx
-.align 32
+.balign 32
.Lshort_avx:
vmovdqu -16(%rdx,%rcx,1),%xmm14
leaq (%rdx,%rcx,1),%rdx
@@ -608,7 +610,7 @@ gcm_ghash_avx:
subq $0x10,%rcx
jmp .Ltail_avx
-.align 32
+.balign 32
.Ltail_avx:
vpxor %xmm10,%xmm15,%xmm15
.Ltail_no_xor_avx:
@@ -649,10 +651,14 @@ gcm_ghash_avx:
vpshufb %xmm13,%xmm10,%xmm10
vmovdqu %xmm10,(%rdi)
vzeroupper
- .byte 0xf3,0xc3
+ RET
.cfi_endproc
-.size gcm_ghash_avx,.-gcm_ghash_avx
-.align 64
+SET_SIZE(gcm_ghash_avx)
+
+#endif /* !_WIN32 || _KERNEL */
+
+SECTION_STATIC
+.balign 64
.Lbswap_mask:
.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
.L0x1c2_polynomial:
@@ -661,14 +667,14 @@ gcm_ghash_avx:
.long 7,0,7,0
.L7_mask_poly:
.long 7,0,450,0
-.align 64
-.type .Lrem_4bit,@object
+.balign 64
+SET_OBJ(.Lrem_4bit)
.Lrem_4bit:
.long 0,0,0,471859200,0,943718400,0,610271232
.long 0,1887436800,0,1822425088,0,1220542464,0,1423966208
.long 0,3774873600,0,4246732800,0,3644850176,0,3311403008
.long 0,2441084928,0,2376073216,0,2847932416,0,3051356160
-.type .Lrem_8bit,@object
+SET_OBJ(.Lrem_8bit)
.Lrem_8bit:
.value 0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E
.value 0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E
@@ -704,7 +710,7 @@ gcm_ghash_avx:
.value 0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE
.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
+.balign 64
/* Mark the stack non-executable. */
#if defined(__linux__) && defined(__ELF__)
diff --git a/module/icp/asm-x86_64/sha2/sha256-x86_64.S b/module/icp/asm-x86_64/sha2/sha256-x86_64.S
new file mode 100644
index 000000000000..d3e5e3f0d080
--- /dev/null
+++ b/module/icp/asm-x86_64/sha2/sha256-x86_64.S
@@ -0,0 +1,5104 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__x86_64)
+
+#define _ASM
+#include <sys/asm_linkage.h>
+
+SECTION_STATIC
+
+.balign 64
+SET_OBJ(K256)
+K256:
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+
+ENTRY_ALIGN(zfs_sha256_transform_x64, 16)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ shlq $4,%rdx
+ subq $64+32,%rsp
+ leaq (%rsi,%rdx,4),%rdx
+ andq $-64,%rsp
+ movq %rdi,64+0(%rsp)
+ movq %rsi,64+8(%rsp)
+ movq %rdx,64+16(%rsp)
+ movq %rax,88(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08
+.Lprologue:
+ movl 0(%rdi),%eax
+ movl 4(%rdi),%ebx
+ movl 8(%rdi),%ecx
+ movl 12(%rdi),%edx
+ movl 16(%rdi),%r8d
+ movl 20(%rdi),%r9d
+ movl 24(%rdi),%r10d
+ movl 28(%rdi),%r11d
+ jmp .Lloop
+.balign 16
+.Lloop:
+ movl %ebx,%edi
+ leaq K256(%rip),%rbp
+ xorl %ecx,%edi
+ movl 0(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 4(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 8(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 12(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 16(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 20(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 24(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 28(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+ leaq 20(%rbp),%rbp
+ addl %r14d,%eax
+ movl 32(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 36(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 40(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 44(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 48(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 52(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 56(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 60(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+ leaq 20(%rbp),%rbp
+ jmp .Lrounds_16_xx
+.balign 16
+.Lrounds_16_xx:
+ movl 4(%rsp),%r13d
+ movl 56(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 36(%rsp),%r12d
+ addl 0(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+ leaq 4(%rbp),%rbp
+ movl 8(%rsp),%r13d
+ movl 60(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 40(%rsp),%r12d
+ addl 4(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+ leaq 4(%rbp),%rbp
+ movl 12(%rsp),%r13d
+ movl 0(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 44(%rsp),%r12d
+ addl 8(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+ leaq 4(%rbp),%rbp
+ movl 16(%rsp),%r13d
+ movl 4(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 48(%rsp),%r12d
+ addl 12(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+ leaq 20(%rbp),%rbp
+ movl 20(%rsp),%r13d
+ movl 8(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 52(%rsp),%r12d
+ addl 16(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+ leaq 4(%rbp),%rbp
+ movl 24(%rsp),%r13d
+ movl 12(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 56(%rsp),%r12d
+ addl 20(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+ leaq 4(%rbp),%rbp
+ movl 28(%rsp),%r13d
+ movl 16(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 60(%rsp),%r12d
+ addl 24(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+ leaq 4(%rbp),%rbp
+ movl 32(%rsp),%r13d
+ movl 20(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 0(%rsp),%r12d
+ addl 28(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+ leaq 20(%rbp),%rbp
+ movl 36(%rsp),%r13d
+ movl 24(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 4(%rsp),%r12d
+ addl 32(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+ leaq 4(%rbp),%rbp
+ movl 40(%rsp),%r13d
+ movl 28(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 8(%rsp),%r12d
+ addl 36(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+ leaq 4(%rbp),%rbp
+ movl 44(%rsp),%r13d
+ movl 32(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 12(%rsp),%r12d
+ addl 40(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+ leaq 4(%rbp),%rbp
+ movl 48(%rsp),%r13d
+ movl 36(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 16(%rsp),%r12d
+ addl 44(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+ leaq 20(%rbp),%rbp
+ movl 52(%rsp),%r13d
+ movl 40(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 20(%rsp),%r12d
+ addl 48(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+ leaq 4(%rbp),%rbp
+ movl 56(%rsp),%r13d
+ movl 44(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 24(%rsp),%r12d
+ addl 52(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+ leaq 4(%rbp),%rbp
+ movl 60(%rsp),%r13d
+ movl 48(%rsp),%r15d
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 28(%rsp),%r12d
+ addl 56(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+ leaq 4(%rbp),%rbp
+ movl 0(%rsp),%r13d
+ movl 52(%rsp),%edi
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 32(%rsp),%r12d
+ addl 60(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+ leaq 20(%rbp),%rbp
+ cmpb $0,3(%rbp)
+ jnz .Lrounds_16_xx
+ movq 64+0(%rsp),%rdi
+ addl %r14d,%eax
+ leaq 64(%rsi),%rsi
+ addl 0(%rdi),%eax
+ addl 4(%rdi),%ebx
+ addl 8(%rdi),%ecx
+ addl 12(%rdi),%edx
+ addl 16(%rdi),%r8d
+ addl 20(%rdi),%r9d
+ addl 24(%rdi),%r10d
+ addl 28(%rdi),%r11d
+ cmpq 64+16(%rsp),%rsi
+ movl %eax,0(%rdi)
+ movl %ebx,4(%rdi)
+ movl %ecx,8(%rdi)
+ movl %edx,12(%rdi)
+ movl %r8d,16(%rdi)
+ movl %r9d,20(%rdi)
+ movl %r10d,24(%rdi)
+ movl %r11d,28(%rdi)
+ jb .Lloop
+ movq 88(%rsp),%rsi
+.cfi_def_cfa %rsi,8
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha256_transform_x64)
+
+ENTRY_ALIGN(zfs_sha256_transform_shani, 64)
+.cfi_startproc
+ ENDBR
+ leaq K256+128(%rip),%rcx
+ movdqu (%rdi),%xmm1
+ movdqu 16(%rdi),%xmm2
+ movdqa 512-128(%rcx),%xmm7
+
+ pshufd $0x1b,%xmm1,%xmm0
+ pshufd $0xb1,%xmm1,%xmm1
+ pshufd $0x1b,%xmm2,%xmm2
+ movdqa %xmm7,%xmm8
+.byte 102,15,58,15,202,8
+ punpcklqdq %xmm0,%xmm2
+ jmp .Loop_shani
+
+.balign 16
+.Loop_shani:
+ movdqu (%rsi),%xmm3
+ movdqu 16(%rsi),%xmm4
+ movdqu 32(%rsi),%xmm5
+.byte 102,15,56,0,223
+ movdqu 48(%rsi),%xmm6
+
+ movdqa 0-128(%rcx),%xmm0
+ paddd %xmm3,%xmm0
+.byte 102,15,56,0,231
+ movdqa %xmm2,%xmm10
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ nop
+ movdqa %xmm1,%xmm9
+.byte 15,56,203,202
+
+ movdqa 32-128(%rcx),%xmm0
+ paddd %xmm4,%xmm0
+.byte 102,15,56,0,239
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ leaq 64(%rsi),%rsi
+.byte 15,56,204,220
+.byte 15,56,203,202
+
+ movdqa 64-128(%rcx),%xmm0
+ paddd %xmm5,%xmm0
+.byte 102,15,56,0,247
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm6,%xmm7
+.byte 102,15,58,15,253,4
+ nop
+ paddd %xmm7,%xmm3
+.byte 15,56,204,229
+.byte 15,56,203,202
+
+ movdqa 96-128(%rcx),%xmm0
+ paddd %xmm6,%xmm0
+.byte 15,56,205,222
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm3,%xmm7
+.byte 102,15,58,15,254,4
+ nop
+ paddd %xmm7,%xmm4
+.byte 15,56,204,238
+.byte 15,56,203,202
+ movdqa 128-128(%rcx),%xmm0
+ paddd %xmm3,%xmm0
+.byte 15,56,205,227
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm4,%xmm7
+.byte 102,15,58,15,251,4
+ nop
+ paddd %xmm7,%xmm5
+.byte 15,56,204,243
+.byte 15,56,203,202
+ movdqa 160-128(%rcx),%xmm0
+ paddd %xmm4,%xmm0
+.byte 15,56,205,236
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm5,%xmm7
+.byte 102,15,58,15,252,4
+ nop
+ paddd %xmm7,%xmm6
+.byte 15,56,204,220
+.byte 15,56,203,202
+ movdqa 192-128(%rcx),%xmm0
+ paddd %xmm5,%xmm0
+.byte 15,56,205,245
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm6,%xmm7
+.byte 102,15,58,15,253,4
+ nop
+ paddd %xmm7,%xmm3
+.byte 15,56,204,229
+.byte 15,56,203,202
+ movdqa 224-128(%rcx),%xmm0
+ paddd %xmm6,%xmm0
+.byte 15,56,205,222
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm3,%xmm7
+.byte 102,15,58,15,254,4
+ nop
+ paddd %xmm7,%xmm4
+.byte 15,56,204,238
+.byte 15,56,203,202
+ movdqa 256-128(%rcx),%xmm0
+ paddd %xmm3,%xmm0
+.byte 15,56,205,227
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm4,%xmm7
+.byte 102,15,58,15,251,4
+ nop
+ paddd %xmm7,%xmm5
+.byte 15,56,204,243
+.byte 15,56,203,202
+ movdqa 288-128(%rcx),%xmm0
+ paddd %xmm4,%xmm0
+.byte 15,56,205,236
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm5,%xmm7
+.byte 102,15,58,15,252,4
+ nop
+ paddd %xmm7,%xmm6
+.byte 15,56,204,220
+.byte 15,56,203,202
+ movdqa 320-128(%rcx),%xmm0
+ paddd %xmm5,%xmm0
+.byte 15,56,205,245
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm6,%xmm7
+.byte 102,15,58,15,253,4
+ nop
+ paddd %xmm7,%xmm3
+.byte 15,56,204,229
+.byte 15,56,203,202
+ movdqa 352-128(%rcx),%xmm0
+ paddd %xmm6,%xmm0
+.byte 15,56,205,222
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm3,%xmm7
+.byte 102,15,58,15,254,4
+ nop
+ paddd %xmm7,%xmm4
+.byte 15,56,204,238
+.byte 15,56,203,202
+ movdqa 384-128(%rcx),%xmm0
+ paddd %xmm3,%xmm0
+.byte 15,56,205,227
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm4,%xmm7
+.byte 102,15,58,15,251,4
+ nop
+ paddd %xmm7,%xmm5
+.byte 15,56,204,243
+.byte 15,56,203,202
+ movdqa 416-128(%rcx),%xmm0
+ paddd %xmm4,%xmm0
+.byte 15,56,205,236
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ movdqa %xmm5,%xmm7
+.byte 102,15,58,15,252,4
+.byte 15,56,203,202
+ paddd %xmm7,%xmm6
+
+ movdqa 448-128(%rcx),%xmm0
+ paddd %xmm5,%xmm0
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+.byte 15,56,205,245
+ movdqa %xmm8,%xmm7
+.byte 15,56,203,202
+
+ movdqa 480-128(%rcx),%xmm0
+ paddd %xmm6,%xmm0
+ nop
+.byte 15,56,203,209
+ pshufd $0x0e,%xmm0,%xmm0
+ decq %rdx
+ nop
+.byte 15,56,203,202
+
+ paddd %xmm10,%xmm2
+ paddd %xmm9,%xmm1
+ jnz .Loop_shani
+
+ pshufd $0xb1,%xmm2,%xmm2
+ pshufd $0x1b,%xmm1,%xmm7
+ pshufd $0xb1,%xmm1,%xmm1
+ punpckhqdq %xmm2,%xmm1
+.byte 102,15,58,15,215,8
+
+ movdqu %xmm1,(%rdi)
+ movdqu %xmm2,16(%rdi)
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha256_transform_shani)
+
+ENTRY_ALIGN(zfs_sha256_transform_ssse3, 64)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ shlq $4,%rdx
+ subq $96,%rsp
+ leaq (%rsi,%rdx,4),%rdx
+ andq $-64,%rsp
+ movq %rdi,64+0(%rsp)
+ movq %rsi,64+8(%rsp)
+ movq %rdx,64+16(%rsp)
+ movq %rax,88(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08
+.Lprologue_ssse3:
+
+ movl 0(%rdi),%eax
+ movl 4(%rdi),%ebx
+ movl 8(%rdi),%ecx
+ movl 12(%rdi),%edx
+ movl 16(%rdi),%r8d
+ movl 20(%rdi),%r9d
+ movl 24(%rdi),%r10d
+ movl 28(%rdi),%r11d
+
+ jmp .Lloop_ssse3
+.balign 16
+.Lloop_ssse3:
+ movdqa K256+512(%rip),%xmm7
+ movdqu 0(%rsi),%xmm0
+ movdqu 16(%rsi),%xmm1
+ movdqu 32(%rsi),%xmm2
+.byte 102,15,56,0,199
+ movdqu 48(%rsi),%xmm3
+ leaq K256(%rip),%rbp
+.byte 102,15,56,0,207
+ movdqa 0(%rbp),%xmm4
+ movdqa 32(%rbp),%xmm5
+.byte 102,15,56,0,215
+ paddd %xmm0,%xmm4
+ movdqa 64(%rbp),%xmm6
+.byte 102,15,56,0,223
+ movdqa 96(%rbp),%xmm7
+ paddd %xmm1,%xmm5
+ paddd %xmm2,%xmm6
+ paddd %xmm3,%xmm7
+ movdqa %xmm4,0(%rsp)
+ movl %eax,%r14d
+ movdqa %xmm5,16(%rsp)
+ movl %ebx,%edi
+ movdqa %xmm6,32(%rsp)
+ xorl %ecx,%edi
+ movdqa %xmm7,48(%rsp)
+ movl %r8d,%r13d
+ jmp .Lssse3_00_47
+
+.balign 16
+.Lssse3_00_47:
+ subq $-128,%rbp
+ rorl $14,%r13d
+ movdqa %xmm1,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm3,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,224,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,250,4
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm3,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm0
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm0
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm0,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 0(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm0,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,0(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm2,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm0,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,225,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,251,4
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm0,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm1
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm1
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm1,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 32(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm1,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,16(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm3,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm1,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,226,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,248,4
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm1,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm2
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm2
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm2,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 64(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm2,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,32(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm0,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm2,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,227,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,249,4
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm2,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm3
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm3
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm3,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 96(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm3,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,48(%rsp)
+ cmpb $0,131(%rbp)
+ jne .Lssse3_00_47
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movq 64+0(%rsp),%rdi
+ movl %r14d,%eax
+
+ addl 0(%rdi),%eax
+ leaq 64(%rsi),%rsi
+ addl 4(%rdi),%ebx
+ addl 8(%rdi),%ecx
+ addl 12(%rdi),%edx
+ addl 16(%rdi),%r8d
+ addl 20(%rdi),%r9d
+ addl 24(%rdi),%r10d
+ addl 28(%rdi),%r11d
+
+ cmpq 64+16(%rsp),%rsi
+
+ movl %eax,0(%rdi)
+ movl %ebx,4(%rdi)
+ movl %ecx,8(%rdi)
+ movl %edx,12(%rdi)
+ movl %r8d,16(%rdi)
+ movl %r9d,20(%rdi)
+ movl %r10d,24(%rdi)
+ movl %r11d,28(%rdi)
+ jb .Lloop_ssse3
+
+ movq 88(%rsp),%rsi
+.cfi_def_cfa %rsi,8
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue_ssse3:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha256_transform_ssse3)
+
+ENTRY_ALIGN(zfs_sha256_transform_avx, 64)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ shlq $4,%rdx
+ subq $96,%rsp
+ leaq (%rsi,%rdx,4),%rdx
+ andq $-64,%rsp
+ movq %rdi,64+0(%rsp)
+ movq %rsi,64+8(%rsp)
+ movq %rdx,64+16(%rsp)
+ movq %rax,88(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08
+.Lprologue_avx:
+
+ vzeroupper
+ movl 0(%rdi),%eax
+ movl 4(%rdi),%ebx
+ movl 8(%rdi),%ecx
+ movl 12(%rdi),%edx
+ movl 16(%rdi),%r8d
+ movl 20(%rdi),%r9d
+ movl 24(%rdi),%r10d
+ movl 28(%rdi),%r11d
+ vmovdqa K256+512+32(%rip),%xmm8
+ vmovdqa K256+512+64(%rip),%xmm9
+ jmp .Lloop_avx
+.balign 16
+.Lloop_avx:
+ vmovdqa K256+512(%rip),%xmm7
+ vmovdqu 0(%rsi),%xmm0
+ vmovdqu 16(%rsi),%xmm1
+ vmovdqu 32(%rsi),%xmm2
+ vmovdqu 48(%rsi),%xmm3
+ vpshufb %xmm7,%xmm0,%xmm0
+ leaq K256(%rip),%rbp
+ vpshufb %xmm7,%xmm1,%xmm1
+ vpshufb %xmm7,%xmm2,%xmm2
+ vpaddd 0(%rbp),%xmm0,%xmm4
+ vpshufb %xmm7,%xmm3,%xmm3
+ vpaddd 32(%rbp),%xmm1,%xmm5
+ vpaddd 64(%rbp),%xmm2,%xmm6
+ vpaddd 96(%rbp),%xmm3,%xmm7
+ vmovdqa %xmm4,0(%rsp)
+ movl %eax,%r14d
+ vmovdqa %xmm5,16(%rsp)
+ movl %ebx,%edi
+ vmovdqa %xmm6,32(%rsp)
+ xorl %ecx,%edi
+ vmovdqa %xmm7,48(%rsp)
+ movl %r8d,%r13d
+ jmp .Lavx_00_47
+
+.balign 16
+.Lavx_00_47:
+ subq $-128,%rbp
+ vpalignr $4,%xmm0,%xmm1,%xmm4
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ vpalignr $4,%xmm2,%xmm3,%xmm7
+ shrdl $9,%r14d,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ vpsrld $7,%xmm4,%xmm6
+ shrdl $5,%r13d,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ vpaddd %xmm7,%xmm0,%xmm0
+ xorl %r8d,%r13d
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ vpsrld $3,%xmm4,%xmm7
+ xorl %r10d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ebx,%r15d
+ vpslld $14,%xmm4,%xmm5
+ addl %r12d,%r11d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ vpxor %xmm6,%xmm7,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ vpshufd $250,%xmm3,%xmm7
+ shrdl $2,%r14d,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ vpsrld $11,%xmm6,%xmm6
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ shrdl $14,%r13d,%r13d
+ vpxor %xmm5,%xmm4,%xmm4
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ shrdl $9,%r14d,%r14d
+ vpslld $11,%xmm5,%xmm5
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ shrdl $5,%r13d,%r13d
+ vpxor %xmm6,%xmm4,%xmm4
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ vpsrld $10,%xmm7,%xmm6
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ vpxor %xmm5,%xmm4,%xmm4
+ shrdl $11,%r14d,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ vpsrlq $17,%xmm7,%xmm7
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ vpaddd %xmm4,%xmm0,%xmm0
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ shrdl $2,%r14d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %r10d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r10d
+ vpxor %xmm7,%xmm6,%xmm6
+ movl %edx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ecx,%r13d
+ vpshufb %xmm8,%xmm6,%xmm6
+ xorl %r8d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r10d,%r14d
+ vpaddd %xmm6,%xmm0,%xmm0
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ vpshufd $80,%xmm0,%xmm7
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ shrdl $11,%r14d,%r14d
+ vpsrld $10,%xmm7,%xmm6
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ shrdl $6,%r13d,%r13d
+ vpsrlq $17,%xmm7,%xmm7
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ vpxor %xmm7,%xmm6,%xmm6
+ xorl %r11d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r9d,%ebx
+ vpsrlq $2,%xmm7,%xmm7
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ vpshufb %xmm9,%xmm6,%xmm6
+ shrdl $9,%r14d,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ vpaddd %xmm6,%xmm0,%xmm0
+ shrdl $5,%r13d,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ vpaddd 0(%rbp),%xmm0,%xmm6
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ vmovdqa %xmm6,0(%rsp)
+ vpalignr $4,%xmm1,%xmm2,%xmm4
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ vpalignr $4,%xmm3,%xmm0,%xmm7
+ shrdl $9,%r14d,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ vpsrld $7,%xmm4,%xmm6
+ shrdl $5,%r13d,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ vpaddd %xmm7,%xmm1,%xmm1
+ xorl %eax,%r13d
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ vpsrld $3,%xmm4,%xmm7
+ xorl %ecx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r9d,%r15d
+ vpslld $14,%xmm4,%xmm5
+ addl %r12d,%edx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ vpxor %xmm6,%xmm7,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ vpshufd $250,%xmm0,%xmm7
+ shrdl $2,%r14d,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ vpsrld $11,%xmm6,%xmm6
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ shrdl $14,%r13d,%r13d
+ vpxor %xmm5,%xmm4,%xmm4
+ movl %r14d,%edx
+ movl %eax,%r12d
+ shrdl $9,%r14d,%r14d
+ vpslld $11,%xmm5,%xmm5
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ shrdl $5,%r13d,%r13d
+ vpxor %xmm6,%xmm4,%xmm4
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ vpsrld $10,%xmm7,%xmm6
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ vpxor %xmm5,%xmm4,%xmm4
+ shrdl $11,%r14d,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ vpsrlq $17,%xmm7,%xmm7
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ vpaddd %xmm4,%xmm1,%xmm1
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ shrdl $2,%r14d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %ecx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ecx
+ vpxor %xmm7,%xmm6,%xmm6
+ movl %r11d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r10d,%r13d
+ vpshufb %xmm8,%xmm6,%xmm6
+ xorl %eax,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ecx,%r14d
+ vpaddd %xmm6,%xmm1,%xmm1
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ vpshufd $80,%xmm1,%xmm7
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ shrdl $11,%r14d,%r14d
+ vpsrld $10,%xmm7,%xmm6
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ shrdl $6,%r13d,%r13d
+ vpsrlq $17,%xmm7,%xmm7
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ vpxor %xmm7,%xmm6,%xmm6
+ xorl %edx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %ebx,%r9d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ vpshufb %xmm9,%xmm6,%xmm6
+ shrdl $9,%r14d,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ vpaddd %xmm6,%xmm1,%xmm1
+ shrdl $5,%r13d,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ vpaddd 32(%rbp),%xmm1,%xmm6
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ vmovdqa %xmm6,16(%rsp)
+ vpalignr $4,%xmm2,%xmm3,%xmm4
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ vpalignr $4,%xmm0,%xmm1,%xmm7
+ shrdl $9,%r14d,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ vpsrld $7,%xmm4,%xmm6
+ shrdl $5,%r13d,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ vpaddd %xmm7,%xmm2,%xmm2
+ xorl %r8d,%r13d
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ vpsrld $3,%xmm4,%xmm7
+ xorl %r10d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ebx,%r15d
+ vpslld $14,%xmm4,%xmm5
+ addl %r12d,%r11d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ vpxor %xmm6,%xmm7,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ vpshufd $250,%xmm1,%xmm7
+ shrdl $2,%r14d,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ vpsrld $11,%xmm6,%xmm6
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ shrdl $14,%r13d,%r13d
+ vpxor %xmm5,%xmm4,%xmm4
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ shrdl $9,%r14d,%r14d
+ vpslld $11,%xmm5,%xmm5
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ shrdl $5,%r13d,%r13d
+ vpxor %xmm6,%xmm4,%xmm4
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ vpsrld $10,%xmm7,%xmm6
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ vpxor %xmm5,%xmm4,%xmm4
+ shrdl $11,%r14d,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ vpsrlq $17,%xmm7,%xmm7
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ vpaddd %xmm4,%xmm2,%xmm2
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ shrdl $2,%r14d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %r10d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r10d
+ vpxor %xmm7,%xmm6,%xmm6
+ movl %edx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ecx,%r13d
+ vpshufb %xmm8,%xmm6,%xmm6
+ xorl %r8d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r10d,%r14d
+ vpaddd %xmm6,%xmm2,%xmm2
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ vpshufd $80,%xmm2,%xmm7
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ shrdl $11,%r14d,%r14d
+ vpsrld $10,%xmm7,%xmm6
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ shrdl $6,%r13d,%r13d
+ vpsrlq $17,%xmm7,%xmm7
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ vpxor %xmm7,%xmm6,%xmm6
+ xorl %r11d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r9d,%ebx
+ vpsrlq $2,%xmm7,%xmm7
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ vpshufb %xmm9,%xmm6,%xmm6
+ shrdl $9,%r14d,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ vpaddd %xmm6,%xmm2,%xmm2
+ shrdl $5,%r13d,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ vpaddd 64(%rbp),%xmm2,%xmm6
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ vmovdqa %xmm6,32(%rsp)
+ vpalignr $4,%xmm3,%xmm0,%xmm4
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ vpalignr $4,%xmm1,%xmm2,%xmm7
+ shrdl $9,%r14d,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ vpsrld $7,%xmm4,%xmm6
+ shrdl $5,%r13d,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ vpaddd %xmm7,%xmm3,%xmm3
+ xorl %eax,%r13d
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ vpsrld $3,%xmm4,%xmm7
+ xorl %ecx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r9d,%r15d
+ vpslld $14,%xmm4,%xmm5
+ addl %r12d,%edx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ vpxor %xmm6,%xmm7,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ vpshufd $250,%xmm2,%xmm7
+ shrdl $2,%r14d,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ vpsrld $11,%xmm6,%xmm6
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ shrdl $14,%r13d,%r13d
+ vpxor %xmm5,%xmm4,%xmm4
+ movl %r14d,%edx
+ movl %eax,%r12d
+ shrdl $9,%r14d,%r14d
+ vpslld $11,%xmm5,%xmm5
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ shrdl $5,%r13d,%r13d
+ vpxor %xmm6,%xmm4,%xmm4
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ vpsrld $10,%xmm7,%xmm6
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ vpxor %xmm5,%xmm4,%xmm4
+ shrdl $11,%r14d,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ vpsrlq $17,%xmm7,%xmm7
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ vpaddd %xmm4,%xmm3,%xmm3
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ shrdl $2,%r14d,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %ecx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ecx
+ vpxor %xmm7,%xmm6,%xmm6
+ movl %r11d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r10d,%r13d
+ vpshufb %xmm8,%xmm6,%xmm6
+ xorl %eax,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ecx,%r14d
+ vpaddd %xmm6,%xmm3,%xmm3
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ vpshufd $80,%xmm3,%xmm7
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ shrdl $11,%r14d,%r14d
+ vpsrld $10,%xmm7,%xmm6
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ shrdl $6,%r13d,%r13d
+ vpsrlq $17,%xmm7,%xmm7
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ vpxor %xmm7,%xmm6,%xmm6
+ xorl %edx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %ebx,%r9d
+ vpsrlq $2,%xmm7,%xmm7
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ vpxor %xmm7,%xmm6,%xmm6
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ vpshufb %xmm9,%xmm6,%xmm6
+ shrdl $9,%r14d,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ vpaddd %xmm6,%xmm3,%xmm3
+ shrdl $5,%r13d,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ vpaddd 96(%rbp),%xmm3,%xmm6
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ vmovdqa %xmm6,48(%rsp)
+ cmpb $0,131(%rbp)
+ jne .Lavx_00_47
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ shrdl $2,%r14d,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ shrdl $6,%r13d,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ shrdl $2,%r14d,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ shrdl $14,%r13d,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ shrdl $9,%r14d,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ shrdl $5,%r13d,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ shrdl $11,%r14d,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ shrdl $6,%r13d,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ shrdl $2,%r14d,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movq 64+0(%rsp),%rdi
+ movl %r14d,%eax
+
+ addl 0(%rdi),%eax
+ leaq 64(%rsi),%rsi
+ addl 4(%rdi),%ebx
+ addl 8(%rdi),%ecx
+ addl 12(%rdi),%edx
+ addl 16(%rdi),%r8d
+ addl 20(%rdi),%r9d
+ addl 24(%rdi),%r10d
+ addl 28(%rdi),%r11d
+
+ cmpq 64+16(%rsp),%rsi
+
+ movl %eax,0(%rdi)
+ movl %ebx,4(%rdi)
+ movl %ecx,8(%rdi)
+ movl %edx,12(%rdi)
+ movl %r8d,16(%rdi)
+ movl %r9d,20(%rdi)
+ movl %r10d,24(%rdi)
+ movl %r11d,28(%rdi)
+ jb .Lloop_avx
+
+ movq 88(%rsp),%rsi
+.cfi_def_cfa %rsi,8
+ vzeroupper
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue_avx:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha256_transform_avx)
+
+ENTRY_ALIGN(zfs_sha256_transform_avx2, 64)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ subq $544,%rsp
+ shlq $4,%rdx
+ andq $-1024,%rsp
+ leaq (%rsi,%rdx,4),%rdx
+ addq $448,%rsp
+ movq %rdi,64+0(%rsp)
+ movq %rsi,64+8(%rsp)
+ movq %rdx,64+16(%rsp)
+ movq %rax,88(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08
+.Lprologue_avx2:
+
+ vzeroupper
+ subq $-64,%rsi
+ movl 0(%rdi),%eax
+ movq %rsi,%r12
+ movl 4(%rdi),%ebx
+ cmpq %rdx,%rsi
+ movl 8(%rdi),%ecx
+ cmoveq %rsp,%r12
+ movl 12(%rdi),%edx
+ movl 16(%rdi),%r8d
+ movl 20(%rdi),%r9d
+ movl 24(%rdi),%r10d
+ movl 28(%rdi),%r11d
+ vmovdqa K256+512+32(%rip),%ymm8
+ vmovdqa K256+512+64(%rip),%ymm9
+ jmp .Loop_avx2
+.balign 16
+.Loop_avx2:
+ vmovdqa K256+512(%rip),%ymm7
+ vmovdqu -64+0(%rsi),%xmm0
+ vmovdqu -64+16(%rsi),%xmm1
+ vmovdqu -64+32(%rsi),%xmm2
+ vmovdqu -64+48(%rsi),%xmm3
+
+ vinserti128 $1,(%r12),%ymm0,%ymm0
+ vinserti128 $1,16(%r12),%ymm1,%ymm1
+ vpshufb %ymm7,%ymm0,%ymm0
+ vinserti128 $1,32(%r12),%ymm2,%ymm2
+ vpshufb %ymm7,%ymm1,%ymm1
+ vinserti128 $1,48(%r12),%ymm3,%ymm3
+
+ leaq K256(%rip),%rbp
+ vpshufb %ymm7,%ymm2,%ymm2
+ vpaddd 0(%rbp),%ymm0,%ymm4
+ vpshufb %ymm7,%ymm3,%ymm3
+ vpaddd 32(%rbp),%ymm1,%ymm5
+ vpaddd 64(%rbp),%ymm2,%ymm6
+ vpaddd 96(%rbp),%ymm3,%ymm7
+ vmovdqa %ymm4,0(%rsp)
+ xorl %r14d,%r14d
+ vmovdqa %ymm5,32(%rsp)
+
+ movq 88(%rsp),%rdi
+.cfi_def_cfa %rdi,8
+ leaq -64(%rsp),%rsp
+
+
+
+ movq %rdi,-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ movl %ebx,%edi
+ vmovdqa %ymm6,0(%rsp)
+ xorl %ecx,%edi
+ vmovdqa %ymm7,32(%rsp)
+ movl %r9d,%r12d
+ subq $-32*4,%rbp
+ jmp .Lavx2_00_47
+
+.balign 16
+.Lavx2_00_47:
+ leaq -64(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x38,0x06,0x23,0x08
+
+ pushq 64-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08
+ leaq 8(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ vpalignr $4,%ymm0,%ymm1,%ymm4
+ addl 0+128(%rsp),%r11d
+ andl %r8d,%r12d
+ rorxl $25,%r8d,%r13d
+ vpalignr $4,%ymm2,%ymm3,%ymm7
+ rorxl $11,%r8d,%r15d
+ leal (%rax,%r14,1),%eax
+ leal (%r11,%r12,1),%r11d
+ vpsrld $7,%ymm4,%ymm6
+ andnl %r10d,%r8d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r8d,%r14d
+ vpaddd %ymm7,%ymm0,%ymm0
+ leal (%r11,%r12,1),%r11d
+ xorl %r14d,%r13d
+ movl %eax,%r15d
+ vpsrld $3,%ymm4,%ymm7
+ rorxl $22,%eax,%r12d
+ leal (%r11,%r13,1),%r11d
+ xorl %ebx,%r15d
+ vpslld $14,%ymm4,%ymm5
+ rorxl $13,%eax,%r14d
+ rorxl $2,%eax,%r13d
+ leal (%rdx,%r11,1),%edx
+ vpxor %ymm6,%ymm7,%ymm4
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %ebx,%edi
+ vpshufd $250,%ymm3,%ymm7
+ xorl %r13d,%r14d
+ leal (%r11,%rdi,1),%r11d
+ movl %r8d,%r12d
+ vpsrld $11,%ymm6,%ymm6
+ addl 4+128(%rsp),%r10d
+ andl %edx,%r12d
+ rorxl $25,%edx,%r13d
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $11,%edx,%edi
+ leal (%r11,%r14,1),%r11d
+ leal (%r10,%r12,1),%r10d
+ vpslld $11,%ymm5,%ymm5
+ andnl %r9d,%edx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%edx,%r14d
+ vpxor %ymm6,%ymm4,%ymm4
+ leal (%r10,%r12,1),%r10d
+ xorl %r14d,%r13d
+ movl %r11d,%edi
+ vpsrld $10,%ymm7,%ymm6
+ rorxl $22,%r11d,%r12d
+ leal (%r10,%r13,1),%r10d
+ xorl %eax,%edi
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $13,%r11d,%r14d
+ rorxl $2,%r11d,%r13d
+ leal (%rcx,%r10,1),%ecx
+ vpsrlq $17,%ymm7,%ymm7
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %eax,%r15d
+ vpaddd %ymm4,%ymm0,%ymm0
+ xorl %r13d,%r14d
+ leal (%r10,%r15,1),%r10d
+ movl %edx,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 8+128(%rsp),%r9d
+ andl %ecx,%r12d
+ rorxl $25,%ecx,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%ecx,%r15d
+ leal (%r10,%r14,1),%r10d
+ leal (%r9,%r12,1),%r9d
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %r8d,%ecx,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%ecx,%r14d
+ vpshufb %ymm8,%ymm6,%ymm6
+ leal (%r9,%r12,1),%r9d
+ xorl %r14d,%r13d
+ movl %r10d,%r15d
+ vpaddd %ymm6,%ymm0,%ymm0
+ rorxl $22,%r10d,%r12d
+ leal (%r9,%r13,1),%r9d
+ xorl %r11d,%r15d
+ vpshufd $80,%ymm0,%ymm7
+ rorxl $13,%r10d,%r14d
+ rorxl $2,%r10d,%r13d
+ leal (%rbx,%r9,1),%ebx
+ vpsrld $10,%ymm7,%ymm6
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r11d,%edi
+ vpsrlq $17,%ymm7,%ymm7
+ xorl %r13d,%r14d
+ leal (%r9,%rdi,1),%r9d
+ movl %ecx,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 12+128(%rsp),%r8d
+ andl %ebx,%r12d
+ rorxl $25,%ebx,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%ebx,%edi
+ leal (%r9,%r14,1),%r9d
+ leal (%r8,%r12,1),%r8d
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %edx,%ebx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%ebx,%r14d
+ vpshufb %ymm9,%ymm6,%ymm6
+ leal (%r8,%r12,1),%r8d
+ xorl %r14d,%r13d
+ movl %r9d,%edi
+ vpaddd %ymm6,%ymm0,%ymm0
+ rorxl $22,%r9d,%r12d
+ leal (%r8,%r13,1),%r8d
+ xorl %r10d,%edi
+ vpaddd 0(%rbp),%ymm0,%ymm6
+ rorxl $13,%r9d,%r14d
+ rorxl $2,%r9d,%r13d
+ leal (%rax,%r8,1),%eax
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r10d,%r15d
+ xorl %r13d,%r14d
+ leal (%r8,%r15,1),%r8d
+ movl %ebx,%r12d
+ vmovdqa %ymm6,0(%rsp)
+ vpalignr $4,%ymm1,%ymm2,%ymm4
+ addl 32+128(%rsp),%edx
+ andl %eax,%r12d
+ rorxl $25,%eax,%r13d
+ vpalignr $4,%ymm3,%ymm0,%ymm7
+ rorxl $11,%eax,%r15d
+ leal (%r8,%r14,1),%r8d
+ leal (%rdx,%r12,1),%edx
+ vpsrld $7,%ymm4,%ymm6
+ andnl %ecx,%eax,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%eax,%r14d
+ vpaddd %ymm7,%ymm1,%ymm1
+ leal (%rdx,%r12,1),%edx
+ xorl %r14d,%r13d
+ movl %r8d,%r15d
+ vpsrld $3,%ymm4,%ymm7
+ rorxl $22,%r8d,%r12d
+ leal (%rdx,%r13,1),%edx
+ xorl %r9d,%r15d
+ vpslld $14,%ymm4,%ymm5
+ rorxl $13,%r8d,%r14d
+ rorxl $2,%r8d,%r13d
+ leal (%r11,%rdx,1),%r11d
+ vpxor %ymm6,%ymm7,%ymm4
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r9d,%edi
+ vpshufd $250,%ymm0,%ymm7
+ xorl %r13d,%r14d
+ leal (%rdx,%rdi,1),%edx
+ movl %eax,%r12d
+ vpsrld $11,%ymm6,%ymm6
+ addl 36+128(%rsp),%ecx
+ andl %r11d,%r12d
+ rorxl $25,%r11d,%r13d
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $11,%r11d,%edi
+ leal (%rdx,%r14,1),%edx
+ leal (%rcx,%r12,1),%ecx
+ vpslld $11,%ymm5,%ymm5
+ andnl %ebx,%r11d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r11d,%r14d
+ vpxor %ymm6,%ymm4,%ymm4
+ leal (%rcx,%r12,1),%ecx
+ xorl %r14d,%r13d
+ movl %edx,%edi
+ vpsrld $10,%ymm7,%ymm6
+ rorxl $22,%edx,%r12d
+ leal (%rcx,%r13,1),%ecx
+ xorl %r8d,%edi
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $13,%edx,%r14d
+ rorxl $2,%edx,%r13d
+ leal (%r10,%rcx,1),%r10d
+ vpsrlq $17,%ymm7,%ymm7
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r8d,%r15d
+ vpaddd %ymm4,%ymm1,%ymm1
+ xorl %r13d,%r14d
+ leal (%rcx,%r15,1),%ecx
+ movl %r11d,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 40+128(%rsp),%ebx
+ andl %r10d,%r12d
+ rorxl $25,%r10d,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%r10d,%r15d
+ leal (%rcx,%r14,1),%ecx
+ leal (%rbx,%r12,1),%ebx
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %eax,%r10d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r10d,%r14d
+ vpshufb %ymm8,%ymm6,%ymm6
+ leal (%rbx,%r12,1),%ebx
+ xorl %r14d,%r13d
+ movl %ecx,%r15d
+ vpaddd %ymm6,%ymm1,%ymm1
+ rorxl $22,%ecx,%r12d
+ leal (%rbx,%r13,1),%ebx
+ xorl %edx,%r15d
+ vpshufd $80,%ymm1,%ymm7
+ rorxl $13,%ecx,%r14d
+ rorxl $2,%ecx,%r13d
+ leal (%r9,%rbx,1),%r9d
+ vpsrld $10,%ymm7,%ymm6
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %edx,%edi
+ vpsrlq $17,%ymm7,%ymm7
+ xorl %r13d,%r14d
+ leal (%rbx,%rdi,1),%ebx
+ movl %r10d,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 44+128(%rsp),%eax
+ andl %r9d,%r12d
+ rorxl $25,%r9d,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%r9d,%edi
+ leal (%rbx,%r14,1),%ebx
+ leal (%rax,%r12,1),%eax
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %r11d,%r9d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r9d,%r14d
+ vpshufb %ymm9,%ymm6,%ymm6
+ leal (%rax,%r12,1),%eax
+ xorl %r14d,%r13d
+ movl %ebx,%edi
+ vpaddd %ymm6,%ymm1,%ymm1
+ rorxl $22,%ebx,%r12d
+ leal (%rax,%r13,1),%eax
+ xorl %ecx,%edi
+ vpaddd 32(%rbp),%ymm1,%ymm6
+ rorxl $13,%ebx,%r14d
+ rorxl $2,%ebx,%r13d
+ leal (%r8,%rax,1),%r8d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %ecx,%r15d
+ xorl %r13d,%r14d
+ leal (%rax,%r15,1),%eax
+ movl %r9d,%r12d
+ vmovdqa %ymm6,32(%rsp)
+ leaq -64(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x38,0x06,0x23,0x08
+
+ pushq 64-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08
+ leaq 8(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ vpalignr $4,%ymm2,%ymm3,%ymm4
+ addl 0+128(%rsp),%r11d
+ andl %r8d,%r12d
+ rorxl $25,%r8d,%r13d
+ vpalignr $4,%ymm0,%ymm1,%ymm7
+ rorxl $11,%r8d,%r15d
+ leal (%rax,%r14,1),%eax
+ leal (%r11,%r12,1),%r11d
+ vpsrld $7,%ymm4,%ymm6
+ andnl %r10d,%r8d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r8d,%r14d
+ vpaddd %ymm7,%ymm2,%ymm2
+ leal (%r11,%r12,1),%r11d
+ xorl %r14d,%r13d
+ movl %eax,%r15d
+ vpsrld $3,%ymm4,%ymm7
+ rorxl $22,%eax,%r12d
+ leal (%r11,%r13,1),%r11d
+ xorl %ebx,%r15d
+ vpslld $14,%ymm4,%ymm5
+ rorxl $13,%eax,%r14d
+ rorxl $2,%eax,%r13d
+ leal (%rdx,%r11,1),%edx
+ vpxor %ymm6,%ymm7,%ymm4
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %ebx,%edi
+ vpshufd $250,%ymm1,%ymm7
+ xorl %r13d,%r14d
+ leal (%r11,%rdi,1),%r11d
+ movl %r8d,%r12d
+ vpsrld $11,%ymm6,%ymm6
+ addl 4+128(%rsp),%r10d
+ andl %edx,%r12d
+ rorxl $25,%edx,%r13d
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $11,%edx,%edi
+ leal (%r11,%r14,1),%r11d
+ leal (%r10,%r12,1),%r10d
+ vpslld $11,%ymm5,%ymm5
+ andnl %r9d,%edx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%edx,%r14d
+ vpxor %ymm6,%ymm4,%ymm4
+ leal (%r10,%r12,1),%r10d
+ xorl %r14d,%r13d
+ movl %r11d,%edi
+ vpsrld $10,%ymm7,%ymm6
+ rorxl $22,%r11d,%r12d
+ leal (%r10,%r13,1),%r10d
+ xorl %eax,%edi
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $13,%r11d,%r14d
+ rorxl $2,%r11d,%r13d
+ leal (%rcx,%r10,1),%ecx
+ vpsrlq $17,%ymm7,%ymm7
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %eax,%r15d
+ vpaddd %ymm4,%ymm2,%ymm2
+ xorl %r13d,%r14d
+ leal (%r10,%r15,1),%r10d
+ movl %edx,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 8+128(%rsp),%r9d
+ andl %ecx,%r12d
+ rorxl $25,%ecx,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%ecx,%r15d
+ leal (%r10,%r14,1),%r10d
+ leal (%r9,%r12,1),%r9d
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %r8d,%ecx,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%ecx,%r14d
+ vpshufb %ymm8,%ymm6,%ymm6
+ leal (%r9,%r12,1),%r9d
+ xorl %r14d,%r13d
+ movl %r10d,%r15d
+ vpaddd %ymm6,%ymm2,%ymm2
+ rorxl $22,%r10d,%r12d
+ leal (%r9,%r13,1),%r9d
+ xorl %r11d,%r15d
+ vpshufd $80,%ymm2,%ymm7
+ rorxl $13,%r10d,%r14d
+ rorxl $2,%r10d,%r13d
+ leal (%rbx,%r9,1),%ebx
+ vpsrld $10,%ymm7,%ymm6
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r11d,%edi
+ vpsrlq $17,%ymm7,%ymm7
+ xorl %r13d,%r14d
+ leal (%r9,%rdi,1),%r9d
+ movl %ecx,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 12+128(%rsp),%r8d
+ andl %ebx,%r12d
+ rorxl $25,%ebx,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%ebx,%edi
+ leal (%r9,%r14,1),%r9d
+ leal (%r8,%r12,1),%r8d
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %edx,%ebx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%ebx,%r14d
+ vpshufb %ymm9,%ymm6,%ymm6
+ leal (%r8,%r12,1),%r8d
+ xorl %r14d,%r13d
+ movl %r9d,%edi
+ vpaddd %ymm6,%ymm2,%ymm2
+ rorxl $22,%r9d,%r12d
+ leal (%r8,%r13,1),%r8d
+ xorl %r10d,%edi
+ vpaddd 64(%rbp),%ymm2,%ymm6
+ rorxl $13,%r9d,%r14d
+ rorxl $2,%r9d,%r13d
+ leal (%rax,%r8,1),%eax
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r10d,%r15d
+ xorl %r13d,%r14d
+ leal (%r8,%r15,1),%r8d
+ movl %ebx,%r12d
+ vmovdqa %ymm6,0(%rsp)
+ vpalignr $4,%ymm3,%ymm0,%ymm4
+ addl 32+128(%rsp),%edx
+ andl %eax,%r12d
+ rorxl $25,%eax,%r13d
+ vpalignr $4,%ymm1,%ymm2,%ymm7
+ rorxl $11,%eax,%r15d
+ leal (%r8,%r14,1),%r8d
+ leal (%rdx,%r12,1),%edx
+ vpsrld $7,%ymm4,%ymm6
+ andnl %ecx,%eax,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%eax,%r14d
+ vpaddd %ymm7,%ymm3,%ymm3
+ leal (%rdx,%r12,1),%edx
+ xorl %r14d,%r13d
+ movl %r8d,%r15d
+ vpsrld $3,%ymm4,%ymm7
+ rorxl $22,%r8d,%r12d
+ leal (%rdx,%r13,1),%edx
+ xorl %r9d,%r15d
+ vpslld $14,%ymm4,%ymm5
+ rorxl $13,%r8d,%r14d
+ rorxl $2,%r8d,%r13d
+ leal (%r11,%rdx,1),%r11d
+ vpxor %ymm6,%ymm7,%ymm4
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r9d,%edi
+ vpshufd $250,%ymm2,%ymm7
+ xorl %r13d,%r14d
+ leal (%rdx,%rdi,1),%edx
+ movl %eax,%r12d
+ vpsrld $11,%ymm6,%ymm6
+ addl 36+128(%rsp),%ecx
+ andl %r11d,%r12d
+ rorxl $25,%r11d,%r13d
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $11,%r11d,%edi
+ leal (%rdx,%r14,1),%edx
+ leal (%rcx,%r12,1),%ecx
+ vpslld $11,%ymm5,%ymm5
+ andnl %ebx,%r11d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r11d,%r14d
+ vpxor %ymm6,%ymm4,%ymm4
+ leal (%rcx,%r12,1),%ecx
+ xorl %r14d,%r13d
+ movl %edx,%edi
+ vpsrld $10,%ymm7,%ymm6
+ rorxl $22,%edx,%r12d
+ leal (%rcx,%r13,1),%ecx
+ xorl %r8d,%edi
+ vpxor %ymm5,%ymm4,%ymm4
+ rorxl $13,%edx,%r14d
+ rorxl $2,%edx,%r13d
+ leal (%r10,%rcx,1),%r10d
+ vpsrlq $17,%ymm7,%ymm7
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r8d,%r15d
+ vpaddd %ymm4,%ymm3,%ymm3
+ xorl %r13d,%r14d
+ leal (%rcx,%r15,1),%ecx
+ movl %r11d,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 40+128(%rsp),%ebx
+ andl %r10d,%r12d
+ rorxl $25,%r10d,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%r10d,%r15d
+ leal (%rcx,%r14,1),%ecx
+ leal (%rbx,%r12,1),%ebx
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %eax,%r10d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r10d,%r14d
+ vpshufb %ymm8,%ymm6,%ymm6
+ leal (%rbx,%r12,1),%ebx
+ xorl %r14d,%r13d
+ movl %ecx,%r15d
+ vpaddd %ymm6,%ymm3,%ymm3
+ rorxl $22,%ecx,%r12d
+ leal (%rbx,%r13,1),%ebx
+ xorl %edx,%r15d
+ vpshufd $80,%ymm3,%ymm7
+ rorxl $13,%ecx,%r14d
+ rorxl $2,%ecx,%r13d
+ leal (%r9,%rbx,1),%r9d
+ vpsrld $10,%ymm7,%ymm6
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %edx,%edi
+ vpsrlq $17,%ymm7,%ymm7
+ xorl %r13d,%r14d
+ leal (%rbx,%rdi,1),%ebx
+ movl %r10d,%r12d
+ vpxor %ymm7,%ymm6,%ymm6
+ addl 44+128(%rsp),%eax
+ andl %r9d,%r12d
+ rorxl $25,%r9d,%r13d
+ vpsrlq $2,%ymm7,%ymm7
+ rorxl $11,%r9d,%edi
+ leal (%rbx,%r14,1),%ebx
+ leal (%rax,%r12,1),%eax
+ vpxor %ymm7,%ymm6,%ymm6
+ andnl %r11d,%r9d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r9d,%r14d
+ vpshufb %ymm9,%ymm6,%ymm6
+ leal (%rax,%r12,1),%eax
+ xorl %r14d,%r13d
+ movl %ebx,%edi
+ vpaddd %ymm6,%ymm3,%ymm3
+ rorxl $22,%ebx,%r12d
+ leal (%rax,%r13,1),%eax
+ xorl %ecx,%edi
+ vpaddd 96(%rbp),%ymm3,%ymm6
+ rorxl $13,%ebx,%r14d
+ rorxl $2,%ebx,%r13d
+ leal (%r8,%rax,1),%r8d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %ecx,%r15d
+ xorl %r13d,%r14d
+ leal (%rax,%r15,1),%eax
+ movl %r9d,%r12d
+ vmovdqa %ymm6,32(%rsp)
+ leaq 128(%rbp),%rbp
+ cmpb $0,3(%rbp)
+ jne .Lavx2_00_47
+ addl 0+64(%rsp),%r11d
+ andl %r8d,%r12d
+ rorxl $25,%r8d,%r13d
+ rorxl $11,%r8d,%r15d
+ leal (%rax,%r14,1),%eax
+ leal (%r11,%r12,1),%r11d
+ andnl %r10d,%r8d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r8d,%r14d
+ leal (%r11,%r12,1),%r11d
+ xorl %r14d,%r13d
+ movl %eax,%r15d
+ rorxl $22,%eax,%r12d
+ leal (%r11,%r13,1),%r11d
+ xorl %ebx,%r15d
+ rorxl $13,%eax,%r14d
+ rorxl $2,%eax,%r13d
+ leal (%rdx,%r11,1),%edx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %ebx,%edi
+ xorl %r13d,%r14d
+ leal (%r11,%rdi,1),%r11d
+ movl %r8d,%r12d
+ addl 4+64(%rsp),%r10d
+ andl %edx,%r12d
+ rorxl $25,%edx,%r13d
+ rorxl $11,%edx,%edi
+ leal (%r11,%r14,1),%r11d
+ leal (%r10,%r12,1),%r10d
+ andnl %r9d,%edx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%edx,%r14d
+ leal (%r10,%r12,1),%r10d
+ xorl %r14d,%r13d
+ movl %r11d,%edi
+ rorxl $22,%r11d,%r12d
+ leal (%r10,%r13,1),%r10d
+ xorl %eax,%edi
+ rorxl $13,%r11d,%r14d
+ rorxl $2,%r11d,%r13d
+ leal (%rcx,%r10,1),%ecx
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %eax,%r15d
+ xorl %r13d,%r14d
+ leal (%r10,%r15,1),%r10d
+ movl %edx,%r12d
+ addl 8+64(%rsp),%r9d
+ andl %ecx,%r12d
+ rorxl $25,%ecx,%r13d
+ rorxl $11,%ecx,%r15d
+ leal (%r10,%r14,1),%r10d
+ leal (%r9,%r12,1),%r9d
+ andnl %r8d,%ecx,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%ecx,%r14d
+ leal (%r9,%r12,1),%r9d
+ xorl %r14d,%r13d
+ movl %r10d,%r15d
+ rorxl $22,%r10d,%r12d
+ leal (%r9,%r13,1),%r9d
+ xorl %r11d,%r15d
+ rorxl $13,%r10d,%r14d
+ rorxl $2,%r10d,%r13d
+ leal (%rbx,%r9,1),%ebx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r11d,%edi
+ xorl %r13d,%r14d
+ leal (%r9,%rdi,1),%r9d
+ movl %ecx,%r12d
+ addl 12+64(%rsp),%r8d
+ andl %ebx,%r12d
+ rorxl $25,%ebx,%r13d
+ rorxl $11,%ebx,%edi
+ leal (%r9,%r14,1),%r9d
+ leal (%r8,%r12,1),%r8d
+ andnl %edx,%ebx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%ebx,%r14d
+ leal (%r8,%r12,1),%r8d
+ xorl %r14d,%r13d
+ movl %r9d,%edi
+ rorxl $22,%r9d,%r12d
+ leal (%r8,%r13,1),%r8d
+ xorl %r10d,%edi
+ rorxl $13,%r9d,%r14d
+ rorxl $2,%r9d,%r13d
+ leal (%rax,%r8,1),%eax
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r10d,%r15d
+ xorl %r13d,%r14d
+ leal (%r8,%r15,1),%r8d
+ movl %ebx,%r12d
+ addl 32+64(%rsp),%edx
+ andl %eax,%r12d
+ rorxl $25,%eax,%r13d
+ rorxl $11,%eax,%r15d
+ leal (%r8,%r14,1),%r8d
+ leal (%rdx,%r12,1),%edx
+ andnl %ecx,%eax,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%eax,%r14d
+ leal (%rdx,%r12,1),%edx
+ xorl %r14d,%r13d
+ movl %r8d,%r15d
+ rorxl $22,%r8d,%r12d
+ leal (%rdx,%r13,1),%edx
+ xorl %r9d,%r15d
+ rorxl $13,%r8d,%r14d
+ rorxl $2,%r8d,%r13d
+ leal (%r11,%rdx,1),%r11d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r9d,%edi
+ xorl %r13d,%r14d
+ leal (%rdx,%rdi,1),%edx
+ movl %eax,%r12d
+ addl 36+64(%rsp),%ecx
+ andl %r11d,%r12d
+ rorxl $25,%r11d,%r13d
+ rorxl $11,%r11d,%edi
+ leal (%rdx,%r14,1),%edx
+ leal (%rcx,%r12,1),%ecx
+ andnl %ebx,%r11d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r11d,%r14d
+ leal (%rcx,%r12,1),%ecx
+ xorl %r14d,%r13d
+ movl %edx,%edi
+ rorxl $22,%edx,%r12d
+ leal (%rcx,%r13,1),%ecx
+ xorl %r8d,%edi
+ rorxl $13,%edx,%r14d
+ rorxl $2,%edx,%r13d
+ leal (%r10,%rcx,1),%r10d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r8d,%r15d
+ xorl %r13d,%r14d
+ leal (%rcx,%r15,1),%ecx
+ movl %r11d,%r12d
+ addl 40+64(%rsp),%ebx
+ andl %r10d,%r12d
+ rorxl $25,%r10d,%r13d
+ rorxl $11,%r10d,%r15d
+ leal (%rcx,%r14,1),%ecx
+ leal (%rbx,%r12,1),%ebx
+ andnl %eax,%r10d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r10d,%r14d
+ leal (%rbx,%r12,1),%ebx
+ xorl %r14d,%r13d
+ movl %ecx,%r15d
+ rorxl $22,%ecx,%r12d
+ leal (%rbx,%r13,1),%ebx
+ xorl %edx,%r15d
+ rorxl $13,%ecx,%r14d
+ rorxl $2,%ecx,%r13d
+ leal (%r9,%rbx,1),%r9d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %edx,%edi
+ xorl %r13d,%r14d
+ leal (%rbx,%rdi,1),%ebx
+ movl %r10d,%r12d
+ addl 44+64(%rsp),%eax
+ andl %r9d,%r12d
+ rorxl $25,%r9d,%r13d
+ rorxl $11,%r9d,%edi
+ leal (%rbx,%r14,1),%ebx
+ leal (%rax,%r12,1),%eax
+ andnl %r11d,%r9d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r9d,%r14d
+ leal (%rax,%r12,1),%eax
+ xorl %r14d,%r13d
+ movl %ebx,%edi
+ rorxl $22,%ebx,%r12d
+ leal (%rax,%r13,1),%eax
+ xorl %ecx,%edi
+ rorxl $13,%ebx,%r14d
+ rorxl $2,%ebx,%r13d
+ leal (%r8,%rax,1),%r8d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %ecx,%r15d
+ xorl %r13d,%r14d
+ leal (%rax,%r15,1),%eax
+ movl %r9d,%r12d
+ addl 0(%rsp),%r11d
+ andl %r8d,%r12d
+ rorxl $25,%r8d,%r13d
+ rorxl $11,%r8d,%r15d
+ leal (%rax,%r14,1),%eax
+ leal (%r11,%r12,1),%r11d
+ andnl %r10d,%r8d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r8d,%r14d
+ leal (%r11,%r12,1),%r11d
+ xorl %r14d,%r13d
+ movl %eax,%r15d
+ rorxl $22,%eax,%r12d
+ leal (%r11,%r13,1),%r11d
+ xorl %ebx,%r15d
+ rorxl $13,%eax,%r14d
+ rorxl $2,%eax,%r13d
+ leal (%rdx,%r11,1),%edx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %ebx,%edi
+ xorl %r13d,%r14d
+ leal (%r11,%rdi,1),%r11d
+ movl %r8d,%r12d
+ addl 4(%rsp),%r10d
+ andl %edx,%r12d
+ rorxl $25,%edx,%r13d
+ rorxl $11,%edx,%edi
+ leal (%r11,%r14,1),%r11d
+ leal (%r10,%r12,1),%r10d
+ andnl %r9d,%edx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%edx,%r14d
+ leal (%r10,%r12,1),%r10d
+ xorl %r14d,%r13d
+ movl %r11d,%edi
+ rorxl $22,%r11d,%r12d
+ leal (%r10,%r13,1),%r10d
+ xorl %eax,%edi
+ rorxl $13,%r11d,%r14d
+ rorxl $2,%r11d,%r13d
+ leal (%rcx,%r10,1),%ecx
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %eax,%r15d
+ xorl %r13d,%r14d
+ leal (%r10,%r15,1),%r10d
+ movl %edx,%r12d
+ addl 8(%rsp),%r9d
+ andl %ecx,%r12d
+ rorxl $25,%ecx,%r13d
+ rorxl $11,%ecx,%r15d
+ leal (%r10,%r14,1),%r10d
+ leal (%r9,%r12,1),%r9d
+ andnl %r8d,%ecx,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%ecx,%r14d
+ leal (%r9,%r12,1),%r9d
+ xorl %r14d,%r13d
+ movl %r10d,%r15d
+ rorxl $22,%r10d,%r12d
+ leal (%r9,%r13,1),%r9d
+ xorl %r11d,%r15d
+ rorxl $13,%r10d,%r14d
+ rorxl $2,%r10d,%r13d
+ leal (%rbx,%r9,1),%ebx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r11d,%edi
+ xorl %r13d,%r14d
+ leal (%r9,%rdi,1),%r9d
+ movl %ecx,%r12d
+ addl 12(%rsp),%r8d
+ andl %ebx,%r12d
+ rorxl $25,%ebx,%r13d
+ rorxl $11,%ebx,%edi
+ leal (%r9,%r14,1),%r9d
+ leal (%r8,%r12,1),%r8d
+ andnl %edx,%ebx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%ebx,%r14d
+ leal (%r8,%r12,1),%r8d
+ xorl %r14d,%r13d
+ movl %r9d,%edi
+ rorxl $22,%r9d,%r12d
+ leal (%r8,%r13,1),%r8d
+ xorl %r10d,%edi
+ rorxl $13,%r9d,%r14d
+ rorxl $2,%r9d,%r13d
+ leal (%rax,%r8,1),%eax
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r10d,%r15d
+ xorl %r13d,%r14d
+ leal (%r8,%r15,1),%r8d
+ movl %ebx,%r12d
+ addl 32(%rsp),%edx
+ andl %eax,%r12d
+ rorxl $25,%eax,%r13d
+ rorxl $11,%eax,%r15d
+ leal (%r8,%r14,1),%r8d
+ leal (%rdx,%r12,1),%edx
+ andnl %ecx,%eax,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%eax,%r14d
+ leal (%rdx,%r12,1),%edx
+ xorl %r14d,%r13d
+ movl %r8d,%r15d
+ rorxl $22,%r8d,%r12d
+ leal (%rdx,%r13,1),%edx
+ xorl %r9d,%r15d
+ rorxl $13,%r8d,%r14d
+ rorxl $2,%r8d,%r13d
+ leal (%r11,%rdx,1),%r11d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r9d,%edi
+ xorl %r13d,%r14d
+ leal (%rdx,%rdi,1),%edx
+ movl %eax,%r12d
+ addl 36(%rsp),%ecx
+ andl %r11d,%r12d
+ rorxl $25,%r11d,%r13d
+ rorxl $11,%r11d,%edi
+ leal (%rdx,%r14,1),%edx
+ leal (%rcx,%r12,1),%ecx
+ andnl %ebx,%r11d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r11d,%r14d
+ leal (%rcx,%r12,1),%ecx
+ xorl %r14d,%r13d
+ movl %edx,%edi
+ rorxl $22,%edx,%r12d
+ leal (%rcx,%r13,1),%ecx
+ xorl %r8d,%edi
+ rorxl $13,%edx,%r14d
+ rorxl $2,%edx,%r13d
+ leal (%r10,%rcx,1),%r10d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r8d,%r15d
+ xorl %r13d,%r14d
+ leal (%rcx,%r15,1),%ecx
+ movl %r11d,%r12d
+ addl 40(%rsp),%ebx
+ andl %r10d,%r12d
+ rorxl $25,%r10d,%r13d
+ rorxl $11,%r10d,%r15d
+ leal (%rcx,%r14,1),%ecx
+ leal (%rbx,%r12,1),%ebx
+ andnl %eax,%r10d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r10d,%r14d
+ leal (%rbx,%r12,1),%ebx
+ xorl %r14d,%r13d
+ movl %ecx,%r15d
+ rorxl $22,%ecx,%r12d
+ leal (%rbx,%r13,1),%ebx
+ xorl %edx,%r15d
+ rorxl $13,%ecx,%r14d
+ rorxl $2,%ecx,%r13d
+ leal (%r9,%rbx,1),%r9d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %edx,%edi
+ xorl %r13d,%r14d
+ leal (%rbx,%rdi,1),%ebx
+ movl %r10d,%r12d
+ addl 44(%rsp),%eax
+ andl %r9d,%r12d
+ rorxl $25,%r9d,%r13d
+ rorxl $11,%r9d,%edi
+ leal (%rbx,%r14,1),%ebx
+ leal (%rax,%r12,1),%eax
+ andnl %r11d,%r9d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r9d,%r14d
+ leal (%rax,%r12,1),%eax
+ xorl %r14d,%r13d
+ movl %ebx,%edi
+ rorxl $22,%ebx,%r12d
+ leal (%rax,%r13,1),%eax
+ xorl %ecx,%edi
+ rorxl $13,%ebx,%r14d
+ rorxl $2,%ebx,%r13d
+ leal (%r8,%rax,1),%r8d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %ecx,%r15d
+ xorl %r13d,%r14d
+ leal (%rax,%r15,1),%eax
+ movl %r9d,%r12d
+ movq 512(%rsp),%rdi
+ addl %r14d,%eax
+
+ leaq 448(%rsp),%rbp
+
+ addl 0(%rdi),%eax
+ addl 4(%rdi),%ebx
+ addl 8(%rdi),%ecx
+ addl 12(%rdi),%edx
+ addl 16(%rdi),%r8d
+ addl 20(%rdi),%r9d
+ addl 24(%rdi),%r10d
+ addl 28(%rdi),%r11d
+
+ movl %eax,0(%rdi)
+ movl %ebx,4(%rdi)
+ movl %ecx,8(%rdi)
+ movl %edx,12(%rdi)
+ movl %r8d,16(%rdi)
+ movl %r9d,20(%rdi)
+ movl %r10d,24(%rdi)
+ movl %r11d,28(%rdi)
+
+ cmpq 80(%rbp),%rsi
+ je .Ldone_avx2
+
+ xorl %r14d,%r14d
+ movl %ebx,%edi
+ xorl %ecx,%edi
+ movl %r9d,%r12d
+ jmp .Lower_avx2
+.balign 16
+.Lower_avx2:
+ addl 0+16(%rbp),%r11d
+ andl %r8d,%r12d
+ rorxl $25,%r8d,%r13d
+ rorxl $11,%r8d,%r15d
+ leal (%rax,%r14,1),%eax
+ leal (%r11,%r12,1),%r11d
+ andnl %r10d,%r8d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r8d,%r14d
+ leal (%r11,%r12,1),%r11d
+ xorl %r14d,%r13d
+ movl %eax,%r15d
+ rorxl $22,%eax,%r12d
+ leal (%r11,%r13,1),%r11d
+ xorl %ebx,%r15d
+ rorxl $13,%eax,%r14d
+ rorxl $2,%eax,%r13d
+ leal (%rdx,%r11,1),%edx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %ebx,%edi
+ xorl %r13d,%r14d
+ leal (%r11,%rdi,1),%r11d
+ movl %r8d,%r12d
+ addl 4+16(%rbp),%r10d
+ andl %edx,%r12d
+ rorxl $25,%edx,%r13d
+ rorxl $11,%edx,%edi
+ leal (%r11,%r14,1),%r11d
+ leal (%r10,%r12,1),%r10d
+ andnl %r9d,%edx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%edx,%r14d
+ leal (%r10,%r12,1),%r10d
+ xorl %r14d,%r13d
+ movl %r11d,%edi
+ rorxl $22,%r11d,%r12d
+ leal (%r10,%r13,1),%r10d
+ xorl %eax,%edi
+ rorxl $13,%r11d,%r14d
+ rorxl $2,%r11d,%r13d
+ leal (%rcx,%r10,1),%ecx
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %eax,%r15d
+ xorl %r13d,%r14d
+ leal (%r10,%r15,1),%r10d
+ movl %edx,%r12d
+ addl 8+16(%rbp),%r9d
+ andl %ecx,%r12d
+ rorxl $25,%ecx,%r13d
+ rorxl $11,%ecx,%r15d
+ leal (%r10,%r14,1),%r10d
+ leal (%r9,%r12,1),%r9d
+ andnl %r8d,%ecx,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%ecx,%r14d
+ leal (%r9,%r12,1),%r9d
+ xorl %r14d,%r13d
+ movl %r10d,%r15d
+ rorxl $22,%r10d,%r12d
+ leal (%r9,%r13,1),%r9d
+ xorl %r11d,%r15d
+ rorxl $13,%r10d,%r14d
+ rorxl $2,%r10d,%r13d
+ leal (%rbx,%r9,1),%ebx
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r11d,%edi
+ xorl %r13d,%r14d
+ leal (%r9,%rdi,1),%r9d
+ movl %ecx,%r12d
+ addl 12+16(%rbp),%r8d
+ andl %ebx,%r12d
+ rorxl $25,%ebx,%r13d
+ rorxl $11,%ebx,%edi
+ leal (%r9,%r14,1),%r9d
+ leal (%r8,%r12,1),%r8d
+ andnl %edx,%ebx,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%ebx,%r14d
+ leal (%r8,%r12,1),%r8d
+ xorl %r14d,%r13d
+ movl %r9d,%edi
+ rorxl $22,%r9d,%r12d
+ leal (%r8,%r13,1),%r8d
+ xorl %r10d,%edi
+ rorxl $13,%r9d,%r14d
+ rorxl $2,%r9d,%r13d
+ leal (%rax,%r8,1),%eax
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r10d,%r15d
+ xorl %r13d,%r14d
+ leal (%r8,%r15,1),%r8d
+ movl %ebx,%r12d
+ addl 32+16(%rbp),%edx
+ andl %eax,%r12d
+ rorxl $25,%eax,%r13d
+ rorxl $11,%eax,%r15d
+ leal (%r8,%r14,1),%r8d
+ leal (%rdx,%r12,1),%edx
+ andnl %ecx,%eax,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%eax,%r14d
+ leal (%rdx,%r12,1),%edx
+ xorl %r14d,%r13d
+ movl %r8d,%r15d
+ rorxl $22,%r8d,%r12d
+ leal (%rdx,%r13,1),%edx
+ xorl %r9d,%r15d
+ rorxl $13,%r8d,%r14d
+ rorxl $2,%r8d,%r13d
+ leal (%r11,%rdx,1),%r11d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %r9d,%edi
+ xorl %r13d,%r14d
+ leal (%rdx,%rdi,1),%edx
+ movl %eax,%r12d
+ addl 36+16(%rbp),%ecx
+ andl %r11d,%r12d
+ rorxl $25,%r11d,%r13d
+ rorxl $11,%r11d,%edi
+ leal (%rdx,%r14,1),%edx
+ leal (%rcx,%r12,1),%ecx
+ andnl %ebx,%r11d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r11d,%r14d
+ leal (%rcx,%r12,1),%ecx
+ xorl %r14d,%r13d
+ movl %edx,%edi
+ rorxl $22,%edx,%r12d
+ leal (%rcx,%r13,1),%ecx
+ xorl %r8d,%edi
+ rorxl $13,%edx,%r14d
+ rorxl $2,%edx,%r13d
+ leal (%r10,%rcx,1),%r10d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %r8d,%r15d
+ xorl %r13d,%r14d
+ leal (%rcx,%r15,1),%ecx
+ movl %r11d,%r12d
+ addl 40+16(%rbp),%ebx
+ andl %r10d,%r12d
+ rorxl $25,%r10d,%r13d
+ rorxl $11,%r10d,%r15d
+ leal (%rcx,%r14,1),%ecx
+ leal (%rbx,%r12,1),%ebx
+ andnl %eax,%r10d,%r12d
+ xorl %r15d,%r13d
+ rorxl $6,%r10d,%r14d
+ leal (%rbx,%r12,1),%ebx
+ xorl %r14d,%r13d
+ movl %ecx,%r15d
+ rorxl $22,%ecx,%r12d
+ leal (%rbx,%r13,1),%ebx
+ xorl %edx,%r15d
+ rorxl $13,%ecx,%r14d
+ rorxl $2,%ecx,%r13d
+ leal (%r9,%rbx,1),%r9d
+ andl %r15d,%edi
+ xorl %r12d,%r14d
+ xorl %edx,%edi
+ xorl %r13d,%r14d
+ leal (%rbx,%rdi,1),%ebx
+ movl %r10d,%r12d
+ addl 44+16(%rbp),%eax
+ andl %r9d,%r12d
+ rorxl $25,%r9d,%r13d
+ rorxl $11,%r9d,%edi
+ leal (%rbx,%r14,1),%ebx
+ leal (%rax,%r12,1),%eax
+ andnl %r11d,%r9d,%r12d
+ xorl %edi,%r13d
+ rorxl $6,%r9d,%r14d
+ leal (%rax,%r12,1),%eax
+ xorl %r14d,%r13d
+ movl %ebx,%edi
+ rorxl $22,%ebx,%r12d
+ leal (%rax,%r13,1),%eax
+ xorl %ecx,%edi
+ rorxl $13,%ebx,%r14d
+ rorxl $2,%ebx,%r13d
+ leal (%r8,%rax,1),%r8d
+ andl %edi,%r15d
+ xorl %r12d,%r14d
+ xorl %ecx,%r15d
+ xorl %r13d,%r14d
+ leal (%rax,%r15,1),%eax
+ movl %r9d,%r12d
+ leaq -64(%rbp),%rbp
+ cmpq %rsp,%rbp
+ jae .Lower_avx2
+
+ movq 512(%rsp),%rdi
+ addl %r14d,%eax
+
+ leaq 448(%rsp),%rsp
+
+.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08
+
+ addl 0(%rdi),%eax
+ addl 4(%rdi),%ebx
+ addl 8(%rdi),%ecx
+ addl 12(%rdi),%edx
+ addl 16(%rdi),%r8d
+ addl 20(%rdi),%r9d
+ leaq 128(%rsi),%rsi
+ addl 24(%rdi),%r10d
+ movq %rsi,%r12
+ addl 28(%rdi),%r11d
+ cmpq 64+16(%rsp),%rsi
+
+ movl %eax,0(%rdi)
+ cmoveq %rsp,%r12
+ movl %ebx,4(%rdi)
+ movl %ecx,8(%rdi)
+ movl %edx,12(%rdi)
+ movl %r8d,16(%rdi)
+ movl %r9d,20(%rdi)
+ movl %r10d,24(%rdi)
+ movl %r11d,28(%rdi)
+
+ jbe .Loop_avx2
+ leaq (%rsp),%rbp
+
+
+.cfi_escape 0x0f,0x06,0x76,0xd8,0x00,0x06,0x23,0x08
+
+.Ldone_avx2:
+ movq 88(%rbp),%rsi
+.cfi_def_cfa %rsi,8
+ vzeroupper
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue_avx2:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha256_transform_avx2)
+
+#if defined(__ELF__)
+ .section .note.GNU-stack,"",%progbits
+#endif
+#endif
diff --git a/module/icp/asm-x86_64/sha2/sha256_impl.S b/module/icp/asm-x86_64/sha2/sha256_impl.S
deleted file mode 100644
index 1391bd59a017..000000000000
--- a/module/icp/asm-x86_64/sha2/sha256_impl.S
+++ /dev/null
@@ -1,2089 +0,0 @@
-/*
- * ====================================================================
- * Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
- * project. Rights for redistribution and usage in source and binary
- * forms are granted according to the OpenSSL license.
- * ====================================================================
- *
- * sha256/512_block procedure for x86_64.
- *
- * 40% improvement over compiler-generated code on Opteron. On EM64T
- * sha256 was observed to run >80% faster and sha512 - >40%. No magical
- * tricks, just straight implementation... I really wonder why gcc
- * [being armed with inline assembler] fails to generate as fast code.
- * The only thing which is cool about this module is that it's very
- * same instruction sequence used for both SHA-256 and SHA-512. In
- * former case the instructions operate on 32-bit operands, while in
- * latter - on 64-bit ones. All I had to do is to get one flavor right,
- * the other one passed the test right away:-)
- *
- * sha256_block runs in ~1005 cycles on Opteron, which gives you
- * asymptotic performance of 64*1000/1005=63.7MBps times CPU clock
- * frequency in GHz. sha512_block runs in ~1275 cycles, which results
- * in 128*1000/1275=100MBps per GHz. Is there room for improvement?
- * Well, if you compare it to IA-64 implementation, which maintains
- * X[16] in register bank[!], tends to 4 instructions per CPU clock
- * cycle and runs in 1003 cycles, 1275 is very good result for 3-way
- * issue Opteron pipeline and X[16] maintained in memory. So that *if*
- * there is a way to improve it, *then* the only way would be to try to
- * offload X[16] updates to SSE unit, but that would require "deeper"
- * loop unroll, which in turn would naturally cause size blow-up, not
- * to mention increased complexity! And once again, only *if* it's
- * actually possible to noticeably improve overall ILP, instruction
- * level parallelism, on a given CPU implementation in this case.
- *
- * Special note on Intel EM64T. While Opteron CPU exhibits perfect
- * performance ratio of 1.5 between 64- and 32-bit flavors [see above],
- * [currently available] EM64T CPUs apparently are far from it. On the
- * contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit
- * sha256_block:-( This is presumably because 64-bit shifts/rotates
- * apparently are not atomic instructions, but implemented in microcode.
- */
-
-/*
- * OpenSolaris OS modifications
- *
- * Sun elects to use this software under the BSD license.
- *
- * This source originates from OpenSSL file sha512-x86_64.pl at
- * ftp://ftp.openssl.org/snapshot/openssl-0.9.8-stable-SNAP-20080131.tar.gz
- * (presumably for future OpenSSL release 0.9.8h), with these changes:
- *
- * 1. Added perl "use strict" and declared variables.
- *
- * 2. Added OpenSolaris ENTRY_NP/SET_SIZE macros from
- * /usr/include/sys/asm_linkage.h, .ident keywords, and lint(1B) guards.
- *
- * 3. Removed x86_64-xlate.pl script (not needed for as(1) or gas(1)
- * assemblers). Replaced the .picmeup macro with assembler code.
- *
- * 4. Added 8 to $ctx, as OpenSolaris OS has an extra 4-byte field, "algotype",
- * at the beginning of SHA2_CTX (the next field is 8-byte aligned).
- */
-
-/*
- * This file was generated by a perl script (sha512-x86_64.pl) that were
- * used to generate sha256 and sha512 variants from the same code base.
- * The comments from the original file have been pasted above.
- */
-
-#if defined(lint) || defined(__lint)
-#include <sys/stdint.h>
-#include <sha2/sha2.h>
-
-void
-SHA256TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num)
-{
- (void) ctx, (void) in, (void) num;
-}
-
-
-#else
-#define _ASM
-#include <sys/asm_linkage.h>
-
-ENTRY_NP(SHA256TransformBlocks)
-.cfi_startproc
- movq %rsp, %rax
-.cfi_def_cfa_register %rax
- push %rbx
-.cfi_offset %rbx,-16
- push %rbp
-.cfi_offset %rbp,-24
- push %r12
-.cfi_offset %r12,-32
- push %r13
-.cfi_offset %r13,-40
- push %r14
-.cfi_offset %r14,-48
- push %r15
-.cfi_offset %r15,-56
- mov %rsp,%rbp # copy %rsp
- shl $4,%rdx # num*16
- sub $16*4+4*8,%rsp
- lea (%rsi,%rdx,4),%rdx # inp+num*16*4
- and $-64,%rsp # align stack frame
- add $8,%rdi # Skip OpenSolaris field, "algotype"
- mov %rdi,16*4+0*8(%rsp) # save ctx, 1st arg
- mov %rsi,16*4+1*8(%rsp) # save inp, 2nd arg
- mov %rdx,16*4+2*8(%rsp) # save end pointer, "3rd" arg
- mov %rbp,16*4+3*8(%rsp) # save copy of %rsp
-# echo ".cfi_cfa_expression %rsp+88,deref,+56" |
-# openssl/crypto/perlasm/x86_64-xlate.pl
-.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x38
-
- #.picmeup %rbp
- # The .picmeup pseudo-directive, from perlasm/x86_64_xlate.pl, puts
- # the address of the "next" instruction into the target register
- # (%rbp). This generates these 2 instructions:
- lea .Llea(%rip),%rbp
- #nop # .picmeup generates a nop for mod 8 alignment--not needed here
-
-.Llea:
- lea K256-.(%rbp),%rbp
-
- mov 4*0(%rdi),%eax
- mov 4*1(%rdi),%ebx
- mov 4*2(%rdi),%ecx
- mov 4*3(%rdi),%edx
- mov 4*4(%rdi),%r8d
- mov 4*5(%rdi),%r9d
- mov 4*6(%rdi),%r10d
- mov 4*7(%rdi),%r11d
- jmp .Lloop
-
-.align 16
-.Lloop:
- xor %rdi,%rdi
- mov 4*0(%rsi),%r12d
- bswap %r12d
- mov %r8d,%r13d
- mov %r8d,%r14d
- mov %r9d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r10d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r8d,%r15d # (f^g)&e
- mov %r12d,0(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r10d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r11d,%r12d # T1+=h
-
- mov %eax,%r11d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %eax,%r13d
- mov %eax,%r14d
-
- ror $2,%r11d
- ror $13,%r13d
- mov %eax,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r11d
- ror $9,%r13d
- or %ecx,%r14d # a|c
-
- xor %r13d,%r11d # h=Sigma0(a)
- and %ecx,%r15d # a&c
- add %r12d,%edx # d+=T1
-
- and %ebx,%r14d # (a|c)&b
- add %r12d,%r11d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r11d # h+=Maj(a,b,c)
- mov 4*1(%rsi),%r12d
- bswap %r12d
- mov %edx,%r13d
- mov %edx,%r14d
- mov %r8d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r9d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %edx,%r15d # (f^g)&e
- mov %r12d,4(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r9d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r10d,%r12d # T1+=h
-
- mov %r11d,%r10d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r11d,%r13d
- mov %r11d,%r14d
-
- ror $2,%r10d
- ror $13,%r13d
- mov %r11d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r10d
- ror $9,%r13d
- or %ebx,%r14d # a|c
-
- xor %r13d,%r10d # h=Sigma0(a)
- and %ebx,%r15d # a&c
- add %r12d,%ecx # d+=T1
-
- and %eax,%r14d # (a|c)&b
- add %r12d,%r10d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r10d # h+=Maj(a,b,c)
- mov 4*2(%rsi),%r12d
- bswap %r12d
- mov %ecx,%r13d
- mov %ecx,%r14d
- mov %edx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r8d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ecx,%r15d # (f^g)&e
- mov %r12d,8(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r8d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r9d,%r12d # T1+=h
-
- mov %r10d,%r9d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r10d,%r13d
- mov %r10d,%r14d
-
- ror $2,%r9d
- ror $13,%r13d
- mov %r10d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r9d
- ror $9,%r13d
- or %eax,%r14d # a|c
-
- xor %r13d,%r9d # h=Sigma0(a)
- and %eax,%r15d # a&c
- add %r12d,%ebx # d+=T1
-
- and %r11d,%r14d # (a|c)&b
- add %r12d,%r9d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r9d # h+=Maj(a,b,c)
- mov 4*3(%rsi),%r12d
- bswap %r12d
- mov %ebx,%r13d
- mov %ebx,%r14d
- mov %ecx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %edx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ebx,%r15d # (f^g)&e
- mov %r12d,12(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %edx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r8d,%r12d # T1+=h
-
- mov %r9d,%r8d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r9d,%r13d
- mov %r9d,%r14d
-
- ror $2,%r8d
- ror $13,%r13d
- mov %r9d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r8d
- ror $9,%r13d
- or %r11d,%r14d # a|c
-
- xor %r13d,%r8d # h=Sigma0(a)
- and %r11d,%r15d # a&c
- add %r12d,%eax # d+=T1
-
- and %r10d,%r14d # (a|c)&b
- add %r12d,%r8d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r8d # h+=Maj(a,b,c)
- mov 4*4(%rsi),%r12d
- bswap %r12d
- mov %eax,%r13d
- mov %eax,%r14d
- mov %ebx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ecx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %eax,%r15d # (f^g)&e
- mov %r12d,16(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ecx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %edx,%r12d # T1+=h
-
- mov %r8d,%edx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r8d,%r13d
- mov %r8d,%r14d
-
- ror $2,%edx
- ror $13,%r13d
- mov %r8d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%edx
- ror $9,%r13d
- or %r10d,%r14d # a|c
-
- xor %r13d,%edx # h=Sigma0(a)
- and %r10d,%r15d # a&c
- add %r12d,%r11d # d+=T1
-
- and %r9d,%r14d # (a|c)&b
- add %r12d,%edx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%edx # h+=Maj(a,b,c)
- mov 4*5(%rsi),%r12d
- bswap %r12d
- mov %r11d,%r13d
- mov %r11d,%r14d
- mov %eax,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ebx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r11d,%r15d # (f^g)&e
- mov %r12d,20(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ebx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ecx,%r12d # T1+=h
-
- mov %edx,%ecx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %edx,%r13d
- mov %edx,%r14d
-
- ror $2,%ecx
- ror $13,%r13d
- mov %edx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ecx
- ror $9,%r13d
- or %r9d,%r14d # a|c
-
- xor %r13d,%ecx # h=Sigma0(a)
- and %r9d,%r15d # a&c
- add %r12d,%r10d # d+=T1
-
- and %r8d,%r14d # (a|c)&b
- add %r12d,%ecx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ecx # h+=Maj(a,b,c)
- mov 4*6(%rsi),%r12d
- bswap %r12d
- mov %r10d,%r13d
- mov %r10d,%r14d
- mov %r11d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %eax,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r10d,%r15d # (f^g)&e
- mov %r12d,24(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %eax,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ebx,%r12d # T1+=h
-
- mov %ecx,%ebx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ecx,%r13d
- mov %ecx,%r14d
-
- ror $2,%ebx
- ror $13,%r13d
- mov %ecx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ebx
- ror $9,%r13d
- or %r8d,%r14d # a|c
-
- xor %r13d,%ebx # h=Sigma0(a)
- and %r8d,%r15d # a&c
- add %r12d,%r9d # d+=T1
-
- and %edx,%r14d # (a|c)&b
- add %r12d,%ebx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ebx # h+=Maj(a,b,c)
- mov 4*7(%rsi),%r12d
- bswap %r12d
- mov %r9d,%r13d
- mov %r9d,%r14d
- mov %r10d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r11d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r9d,%r15d # (f^g)&e
- mov %r12d,28(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r11d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %eax,%r12d # T1+=h
-
- mov %ebx,%eax
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ebx,%r13d
- mov %ebx,%r14d
-
- ror $2,%eax
- ror $13,%r13d
- mov %ebx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%eax
- ror $9,%r13d
- or %edx,%r14d # a|c
-
- xor %r13d,%eax # h=Sigma0(a)
- and %edx,%r15d # a&c
- add %r12d,%r8d # d+=T1
-
- and %ecx,%r14d # (a|c)&b
- add %r12d,%eax # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%eax # h+=Maj(a,b,c)
- mov 4*8(%rsi),%r12d
- bswap %r12d
- mov %r8d,%r13d
- mov %r8d,%r14d
- mov %r9d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r10d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r8d,%r15d # (f^g)&e
- mov %r12d,32(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r10d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r11d,%r12d # T1+=h
-
- mov %eax,%r11d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %eax,%r13d
- mov %eax,%r14d
-
- ror $2,%r11d
- ror $13,%r13d
- mov %eax,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r11d
- ror $9,%r13d
- or %ecx,%r14d # a|c
-
- xor %r13d,%r11d # h=Sigma0(a)
- and %ecx,%r15d # a&c
- add %r12d,%edx # d+=T1
-
- and %ebx,%r14d # (a|c)&b
- add %r12d,%r11d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r11d # h+=Maj(a,b,c)
- mov 4*9(%rsi),%r12d
- bswap %r12d
- mov %edx,%r13d
- mov %edx,%r14d
- mov %r8d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r9d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %edx,%r15d # (f^g)&e
- mov %r12d,36(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r9d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r10d,%r12d # T1+=h
-
- mov %r11d,%r10d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r11d,%r13d
- mov %r11d,%r14d
-
- ror $2,%r10d
- ror $13,%r13d
- mov %r11d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r10d
- ror $9,%r13d
- or %ebx,%r14d # a|c
-
- xor %r13d,%r10d # h=Sigma0(a)
- and %ebx,%r15d # a&c
- add %r12d,%ecx # d+=T1
-
- and %eax,%r14d # (a|c)&b
- add %r12d,%r10d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r10d # h+=Maj(a,b,c)
- mov 4*10(%rsi),%r12d
- bswap %r12d
- mov %ecx,%r13d
- mov %ecx,%r14d
- mov %edx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r8d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ecx,%r15d # (f^g)&e
- mov %r12d,40(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r8d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r9d,%r12d # T1+=h
-
- mov %r10d,%r9d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r10d,%r13d
- mov %r10d,%r14d
-
- ror $2,%r9d
- ror $13,%r13d
- mov %r10d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r9d
- ror $9,%r13d
- or %eax,%r14d # a|c
-
- xor %r13d,%r9d # h=Sigma0(a)
- and %eax,%r15d # a&c
- add %r12d,%ebx # d+=T1
-
- and %r11d,%r14d # (a|c)&b
- add %r12d,%r9d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r9d # h+=Maj(a,b,c)
- mov 4*11(%rsi),%r12d
- bswap %r12d
- mov %ebx,%r13d
- mov %ebx,%r14d
- mov %ecx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %edx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ebx,%r15d # (f^g)&e
- mov %r12d,44(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %edx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r8d,%r12d # T1+=h
-
- mov %r9d,%r8d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r9d,%r13d
- mov %r9d,%r14d
-
- ror $2,%r8d
- ror $13,%r13d
- mov %r9d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r8d
- ror $9,%r13d
- or %r11d,%r14d # a|c
-
- xor %r13d,%r8d # h=Sigma0(a)
- and %r11d,%r15d # a&c
- add %r12d,%eax # d+=T1
-
- and %r10d,%r14d # (a|c)&b
- add %r12d,%r8d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r8d # h+=Maj(a,b,c)
- mov 4*12(%rsi),%r12d
- bswap %r12d
- mov %eax,%r13d
- mov %eax,%r14d
- mov %ebx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ecx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %eax,%r15d # (f^g)&e
- mov %r12d,48(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ecx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %edx,%r12d # T1+=h
-
- mov %r8d,%edx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r8d,%r13d
- mov %r8d,%r14d
-
- ror $2,%edx
- ror $13,%r13d
- mov %r8d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%edx
- ror $9,%r13d
- or %r10d,%r14d # a|c
-
- xor %r13d,%edx # h=Sigma0(a)
- and %r10d,%r15d # a&c
- add %r12d,%r11d # d+=T1
-
- and %r9d,%r14d # (a|c)&b
- add %r12d,%edx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%edx # h+=Maj(a,b,c)
- mov 4*13(%rsi),%r12d
- bswap %r12d
- mov %r11d,%r13d
- mov %r11d,%r14d
- mov %eax,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ebx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r11d,%r15d # (f^g)&e
- mov %r12d,52(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ebx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ecx,%r12d # T1+=h
-
- mov %edx,%ecx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %edx,%r13d
- mov %edx,%r14d
-
- ror $2,%ecx
- ror $13,%r13d
- mov %edx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ecx
- ror $9,%r13d
- or %r9d,%r14d # a|c
-
- xor %r13d,%ecx # h=Sigma0(a)
- and %r9d,%r15d # a&c
- add %r12d,%r10d # d+=T1
-
- and %r8d,%r14d # (a|c)&b
- add %r12d,%ecx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ecx # h+=Maj(a,b,c)
- mov 4*14(%rsi),%r12d
- bswap %r12d
- mov %r10d,%r13d
- mov %r10d,%r14d
- mov %r11d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %eax,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r10d,%r15d # (f^g)&e
- mov %r12d,56(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %eax,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ebx,%r12d # T1+=h
-
- mov %ecx,%ebx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ecx,%r13d
- mov %ecx,%r14d
-
- ror $2,%ebx
- ror $13,%r13d
- mov %ecx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ebx
- ror $9,%r13d
- or %r8d,%r14d # a|c
-
- xor %r13d,%ebx # h=Sigma0(a)
- and %r8d,%r15d # a&c
- add %r12d,%r9d # d+=T1
-
- and %edx,%r14d # (a|c)&b
- add %r12d,%ebx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ebx # h+=Maj(a,b,c)
- mov 4*15(%rsi),%r12d
- bswap %r12d
- mov %r9d,%r13d
- mov %r9d,%r14d
- mov %r10d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r11d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r9d,%r15d # (f^g)&e
- mov %r12d,60(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r11d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %eax,%r12d # T1+=h
-
- mov %ebx,%eax
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ebx,%r13d
- mov %ebx,%r14d
-
- ror $2,%eax
- ror $13,%r13d
- mov %ebx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%eax
- ror $9,%r13d
- or %edx,%r14d # a|c
-
- xor %r13d,%eax # h=Sigma0(a)
- and %edx,%r15d # a&c
- add %r12d,%r8d # d+=T1
-
- and %ecx,%r14d # (a|c)&b
- add %r12d,%eax # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%eax # h+=Maj(a,b,c)
- jmp .Lrounds_16_xx
-.align 16
-.Lrounds_16_xx:
- mov 4(%rsp),%r13d
- mov 56(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 36(%rsp),%r12d
-
- add 0(%rsp),%r12d
- mov %r8d,%r13d
- mov %r8d,%r14d
- mov %r9d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r10d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r8d,%r15d # (f^g)&e
- mov %r12d,0(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r10d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r11d,%r12d # T1+=h
-
- mov %eax,%r11d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %eax,%r13d
- mov %eax,%r14d
-
- ror $2,%r11d
- ror $13,%r13d
- mov %eax,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r11d
- ror $9,%r13d
- or %ecx,%r14d # a|c
-
- xor %r13d,%r11d # h=Sigma0(a)
- and %ecx,%r15d # a&c
- add %r12d,%edx # d+=T1
-
- and %ebx,%r14d # (a|c)&b
- add %r12d,%r11d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r11d # h+=Maj(a,b,c)
- mov 8(%rsp),%r13d
- mov 60(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 40(%rsp),%r12d
-
- add 4(%rsp),%r12d
- mov %edx,%r13d
- mov %edx,%r14d
- mov %r8d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r9d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %edx,%r15d # (f^g)&e
- mov %r12d,4(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r9d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r10d,%r12d # T1+=h
-
- mov %r11d,%r10d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r11d,%r13d
- mov %r11d,%r14d
-
- ror $2,%r10d
- ror $13,%r13d
- mov %r11d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r10d
- ror $9,%r13d
- or %ebx,%r14d # a|c
-
- xor %r13d,%r10d # h=Sigma0(a)
- and %ebx,%r15d # a&c
- add %r12d,%ecx # d+=T1
-
- and %eax,%r14d # (a|c)&b
- add %r12d,%r10d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r10d # h+=Maj(a,b,c)
- mov 12(%rsp),%r13d
- mov 0(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 44(%rsp),%r12d
-
- add 8(%rsp),%r12d
- mov %ecx,%r13d
- mov %ecx,%r14d
- mov %edx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r8d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ecx,%r15d # (f^g)&e
- mov %r12d,8(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r8d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r9d,%r12d # T1+=h
-
- mov %r10d,%r9d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r10d,%r13d
- mov %r10d,%r14d
-
- ror $2,%r9d
- ror $13,%r13d
- mov %r10d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r9d
- ror $9,%r13d
- or %eax,%r14d # a|c
-
- xor %r13d,%r9d # h=Sigma0(a)
- and %eax,%r15d # a&c
- add %r12d,%ebx # d+=T1
-
- and %r11d,%r14d # (a|c)&b
- add %r12d,%r9d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r9d # h+=Maj(a,b,c)
- mov 16(%rsp),%r13d
- mov 4(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 48(%rsp),%r12d
-
- add 12(%rsp),%r12d
- mov %ebx,%r13d
- mov %ebx,%r14d
- mov %ecx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %edx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ebx,%r15d # (f^g)&e
- mov %r12d,12(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %edx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r8d,%r12d # T1+=h
-
- mov %r9d,%r8d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r9d,%r13d
- mov %r9d,%r14d
-
- ror $2,%r8d
- ror $13,%r13d
- mov %r9d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r8d
- ror $9,%r13d
- or %r11d,%r14d # a|c
-
- xor %r13d,%r8d # h=Sigma0(a)
- and %r11d,%r15d # a&c
- add %r12d,%eax # d+=T1
-
- and %r10d,%r14d # (a|c)&b
- add %r12d,%r8d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r8d # h+=Maj(a,b,c)
- mov 20(%rsp),%r13d
- mov 8(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 52(%rsp),%r12d
-
- add 16(%rsp),%r12d
- mov %eax,%r13d
- mov %eax,%r14d
- mov %ebx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ecx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %eax,%r15d # (f^g)&e
- mov %r12d,16(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ecx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %edx,%r12d # T1+=h
-
- mov %r8d,%edx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r8d,%r13d
- mov %r8d,%r14d
-
- ror $2,%edx
- ror $13,%r13d
- mov %r8d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%edx
- ror $9,%r13d
- or %r10d,%r14d # a|c
-
- xor %r13d,%edx # h=Sigma0(a)
- and %r10d,%r15d # a&c
- add %r12d,%r11d # d+=T1
-
- and %r9d,%r14d # (a|c)&b
- add %r12d,%edx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%edx # h+=Maj(a,b,c)
- mov 24(%rsp),%r13d
- mov 12(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 56(%rsp),%r12d
-
- add 20(%rsp),%r12d
- mov %r11d,%r13d
- mov %r11d,%r14d
- mov %eax,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ebx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r11d,%r15d # (f^g)&e
- mov %r12d,20(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ebx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ecx,%r12d # T1+=h
-
- mov %edx,%ecx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %edx,%r13d
- mov %edx,%r14d
-
- ror $2,%ecx
- ror $13,%r13d
- mov %edx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ecx
- ror $9,%r13d
- or %r9d,%r14d # a|c
-
- xor %r13d,%ecx # h=Sigma0(a)
- and %r9d,%r15d # a&c
- add %r12d,%r10d # d+=T1
-
- and %r8d,%r14d # (a|c)&b
- add %r12d,%ecx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ecx # h+=Maj(a,b,c)
- mov 28(%rsp),%r13d
- mov 16(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 60(%rsp),%r12d
-
- add 24(%rsp),%r12d
- mov %r10d,%r13d
- mov %r10d,%r14d
- mov %r11d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %eax,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r10d,%r15d # (f^g)&e
- mov %r12d,24(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %eax,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ebx,%r12d # T1+=h
-
- mov %ecx,%ebx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ecx,%r13d
- mov %ecx,%r14d
-
- ror $2,%ebx
- ror $13,%r13d
- mov %ecx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ebx
- ror $9,%r13d
- or %r8d,%r14d # a|c
-
- xor %r13d,%ebx # h=Sigma0(a)
- and %r8d,%r15d # a&c
- add %r12d,%r9d # d+=T1
-
- and %edx,%r14d # (a|c)&b
- add %r12d,%ebx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ebx # h+=Maj(a,b,c)
- mov 32(%rsp),%r13d
- mov 20(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 0(%rsp),%r12d
-
- add 28(%rsp),%r12d
- mov %r9d,%r13d
- mov %r9d,%r14d
- mov %r10d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r11d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r9d,%r15d # (f^g)&e
- mov %r12d,28(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r11d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %eax,%r12d # T1+=h
-
- mov %ebx,%eax
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ebx,%r13d
- mov %ebx,%r14d
-
- ror $2,%eax
- ror $13,%r13d
- mov %ebx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%eax
- ror $9,%r13d
- or %edx,%r14d # a|c
-
- xor %r13d,%eax # h=Sigma0(a)
- and %edx,%r15d # a&c
- add %r12d,%r8d # d+=T1
-
- and %ecx,%r14d # (a|c)&b
- add %r12d,%eax # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%eax # h+=Maj(a,b,c)
- mov 36(%rsp),%r13d
- mov 24(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 4(%rsp),%r12d
-
- add 32(%rsp),%r12d
- mov %r8d,%r13d
- mov %r8d,%r14d
- mov %r9d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r10d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r8d,%r15d # (f^g)&e
- mov %r12d,32(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r10d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r11d,%r12d # T1+=h
-
- mov %eax,%r11d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %eax,%r13d
- mov %eax,%r14d
-
- ror $2,%r11d
- ror $13,%r13d
- mov %eax,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r11d
- ror $9,%r13d
- or %ecx,%r14d # a|c
-
- xor %r13d,%r11d # h=Sigma0(a)
- and %ecx,%r15d # a&c
- add %r12d,%edx # d+=T1
-
- and %ebx,%r14d # (a|c)&b
- add %r12d,%r11d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r11d # h+=Maj(a,b,c)
- mov 40(%rsp),%r13d
- mov 28(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 8(%rsp),%r12d
-
- add 36(%rsp),%r12d
- mov %edx,%r13d
- mov %edx,%r14d
- mov %r8d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r9d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %edx,%r15d # (f^g)&e
- mov %r12d,36(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r9d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r10d,%r12d # T1+=h
-
- mov %r11d,%r10d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r11d,%r13d
- mov %r11d,%r14d
-
- ror $2,%r10d
- ror $13,%r13d
- mov %r11d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r10d
- ror $9,%r13d
- or %ebx,%r14d # a|c
-
- xor %r13d,%r10d # h=Sigma0(a)
- and %ebx,%r15d # a&c
- add %r12d,%ecx # d+=T1
-
- and %eax,%r14d # (a|c)&b
- add %r12d,%r10d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r10d # h+=Maj(a,b,c)
- mov 44(%rsp),%r13d
- mov 32(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 12(%rsp),%r12d
-
- add 40(%rsp),%r12d
- mov %ecx,%r13d
- mov %ecx,%r14d
- mov %edx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r8d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ecx,%r15d # (f^g)&e
- mov %r12d,40(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r8d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r9d,%r12d # T1+=h
-
- mov %r10d,%r9d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r10d,%r13d
- mov %r10d,%r14d
-
- ror $2,%r9d
- ror $13,%r13d
- mov %r10d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r9d
- ror $9,%r13d
- or %eax,%r14d # a|c
-
- xor %r13d,%r9d # h=Sigma0(a)
- and %eax,%r15d # a&c
- add %r12d,%ebx # d+=T1
-
- and %r11d,%r14d # (a|c)&b
- add %r12d,%r9d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r9d # h+=Maj(a,b,c)
- mov 48(%rsp),%r13d
- mov 36(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 16(%rsp),%r12d
-
- add 44(%rsp),%r12d
- mov %ebx,%r13d
- mov %ebx,%r14d
- mov %ecx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %edx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %ebx,%r15d # (f^g)&e
- mov %r12d,44(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %edx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %r8d,%r12d # T1+=h
-
- mov %r9d,%r8d
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r9d,%r13d
- mov %r9d,%r14d
-
- ror $2,%r8d
- ror $13,%r13d
- mov %r9d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%r8d
- ror $9,%r13d
- or %r11d,%r14d # a|c
-
- xor %r13d,%r8d # h=Sigma0(a)
- and %r11d,%r15d # a&c
- add %r12d,%eax # d+=T1
-
- and %r10d,%r14d # (a|c)&b
- add %r12d,%r8d # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%r8d # h+=Maj(a,b,c)
- mov 52(%rsp),%r13d
- mov 40(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 20(%rsp),%r12d
-
- add 48(%rsp),%r12d
- mov %eax,%r13d
- mov %eax,%r14d
- mov %ebx,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ecx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %eax,%r15d # (f^g)&e
- mov %r12d,48(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ecx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %edx,%r12d # T1+=h
-
- mov %r8d,%edx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %r8d,%r13d
- mov %r8d,%r14d
-
- ror $2,%edx
- ror $13,%r13d
- mov %r8d,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%edx
- ror $9,%r13d
- or %r10d,%r14d # a|c
-
- xor %r13d,%edx # h=Sigma0(a)
- and %r10d,%r15d # a&c
- add %r12d,%r11d # d+=T1
-
- and %r9d,%r14d # (a|c)&b
- add %r12d,%edx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%edx # h+=Maj(a,b,c)
- mov 56(%rsp),%r13d
- mov 44(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 24(%rsp),%r12d
-
- add 52(%rsp),%r12d
- mov %r11d,%r13d
- mov %r11d,%r14d
- mov %eax,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %ebx,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r11d,%r15d # (f^g)&e
- mov %r12d,52(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %ebx,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ecx,%r12d # T1+=h
-
- mov %edx,%ecx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %edx,%r13d
- mov %edx,%r14d
-
- ror $2,%ecx
- ror $13,%r13d
- mov %edx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ecx
- ror $9,%r13d
- or %r9d,%r14d # a|c
-
- xor %r13d,%ecx # h=Sigma0(a)
- and %r9d,%r15d # a&c
- add %r12d,%r10d # d+=T1
-
- and %r8d,%r14d # (a|c)&b
- add %r12d,%ecx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ecx # h+=Maj(a,b,c)
- mov 60(%rsp),%r13d
- mov 48(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 28(%rsp),%r12d
-
- add 56(%rsp),%r12d
- mov %r10d,%r13d
- mov %r10d,%r14d
- mov %r11d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %eax,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r10d,%r15d # (f^g)&e
- mov %r12d,56(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %eax,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %ebx,%r12d # T1+=h
-
- mov %ecx,%ebx
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ecx,%r13d
- mov %ecx,%r14d
-
- ror $2,%ebx
- ror $13,%r13d
- mov %ecx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%ebx
- ror $9,%r13d
- or %r8d,%r14d # a|c
-
- xor %r13d,%ebx # h=Sigma0(a)
- and %r8d,%r15d # a&c
- add %r12d,%r9d # d+=T1
-
- and %edx,%r14d # (a|c)&b
- add %r12d,%ebx # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%ebx # h+=Maj(a,b,c)
- mov 0(%rsp),%r13d
- mov 52(%rsp),%r12d
-
- mov %r13d,%r15d
-
- shr $3,%r13d
- ror $7,%r15d
-
- xor %r15d,%r13d
- ror $11,%r15d
-
- xor %r15d,%r13d # sigma0(X[(i+1)&0xf])
- mov %r12d,%r14d
-
- shr $10,%r12d
- ror $17,%r14d
-
- xor %r14d,%r12d
- ror $2,%r14d
-
- xor %r14d,%r12d # sigma1(X[(i+14)&0xf])
-
- add %r13d,%r12d
-
- add 32(%rsp),%r12d
-
- add 60(%rsp),%r12d
- mov %r9d,%r13d
- mov %r9d,%r14d
- mov %r10d,%r15d
-
- ror $6,%r13d
- ror $11,%r14d
- xor %r11d,%r15d # f^g
-
- xor %r14d,%r13d
- ror $14,%r14d
- and %r9d,%r15d # (f^g)&e
- mov %r12d,60(%rsp)
-
- xor %r14d,%r13d # Sigma1(e)
- xor %r11d,%r15d # Ch(e,f,g)=((f^g)&e)^g
- add %eax,%r12d # T1+=h
-
- mov %ebx,%eax
- add %r13d,%r12d # T1+=Sigma1(e)
-
- add %r15d,%r12d # T1+=Ch(e,f,g)
- mov %ebx,%r13d
- mov %ebx,%r14d
-
- ror $2,%eax
- ror $13,%r13d
- mov %ebx,%r15d
- add (%rbp,%rdi,4),%r12d # T1+=K[round]
-
- xor %r13d,%eax
- ror $9,%r13d
- or %edx,%r14d # a|c
-
- xor %r13d,%eax # h=Sigma0(a)
- and %edx,%r15d # a&c
- add %r12d,%r8d # d+=T1
-
- and %ecx,%r14d # (a|c)&b
- add %r12d,%eax # h+=T1
-
- or %r15d,%r14d # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14d,%eax # h+=Maj(a,b,c)
- cmp $64,%rdi
- jb .Lrounds_16_xx
-
- mov 16*4+0*8(%rsp),%rdi
- lea 16*4(%rsi),%rsi
-
- add 4*0(%rdi),%eax
- add 4*1(%rdi),%ebx
- add 4*2(%rdi),%ecx
- add 4*3(%rdi),%edx
- add 4*4(%rdi),%r8d
- add 4*5(%rdi),%r9d
- add 4*6(%rdi),%r10d
- add 4*7(%rdi),%r11d
-
- cmp 16*4+2*8(%rsp),%rsi
-
- mov %eax,4*0(%rdi)
- mov %ebx,4*1(%rdi)
- mov %ecx,4*2(%rdi)
- mov %edx,4*3(%rdi)
- mov %r8d,4*4(%rdi)
- mov %r9d,4*5(%rdi)
- mov %r10d,4*6(%rdi)
- mov %r11d,4*7(%rdi)
- jb .Lloop
-
- mov 16*4+3*8(%rsp),%rsp
-.cfi_def_cfa %rsp,56
- pop %r15
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r15
- pop %r14
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r14
- pop %r13
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r13
- pop %r12
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r12
- pop %rbp
-.cfi_adjust_cfa_offset -8
-.cfi_restore %rbp
- pop %rbx
-.cfi_adjust_cfa_offset -8
-.cfi_restore %rbx
-
- RET
-.cfi_endproc
-SET_SIZE(SHA256TransformBlocks)
-
-.section .rodata
-.align 64
-.type K256,@object
-K256:
- .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
- .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
- .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
- .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
- .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
- .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
- .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
- .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
- .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
- .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
- .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
- .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
- .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
- .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
- .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
- .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
-#endif /* !lint && !__lint */
-
-#ifdef __ELF__
-.section .note.GNU-stack,"",%progbits
-#endif
diff --git a/module/icp/asm-x86_64/sha2/sha512-x86_64.S b/module/icp/asm-x86_64/sha2/sha512-x86_64.S
new file mode 100644
index 000000000000..fbbcca650d10
--- /dev/null
+++ b/module/icp/asm-x86_64/sha2/sha512-x86_64.S
@@ -0,0 +1,4011 @@
+/*
+ * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Portions Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ * - modified assembly to fit into OpenZFS
+ */
+
+#if defined(__x86_64)
+
+#define _ASM
+#include <sys/asm_linkage.h>
+
+SECTION_STATIC
+
+.balign 64
+SET_OBJ(K512)
+K512:
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+
+ENTRY_ALIGN(zfs_sha512_transform_x64, 16)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ shlq $4,%rdx
+ subq $128+32,%rsp
+ leaq (%rsi,%rdx,8),%rdx
+ andq $-64,%rsp
+ movq %rdi,128+0(%rsp)
+ movq %rsi,128+8(%rsp)
+ movq %rdx,128+16(%rsp)
+ movq %rax,152(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08
+.Lprologue:
+ movq 0(%rdi),%rax
+ movq 8(%rdi),%rbx
+ movq 16(%rdi),%rcx
+ movq 24(%rdi),%rdx
+ movq 32(%rdi),%r8
+ movq 40(%rdi),%r9
+ movq 48(%rdi),%r10
+ movq 56(%rdi),%r11
+ jmp .Lloop
+.balign 16
+.Lloop:
+ movq %rbx,%rdi
+ leaq K512(%rip),%rbp
+ xorq %rcx,%rdi
+ movq 0(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 8(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 16(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 24(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 32(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 40(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 48(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 56(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+ leaq 24(%rbp),%rbp
+ addq %r14,%rax
+ movq 64(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 72(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 80(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 88(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 96(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 104(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 112(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 120(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+ leaq 24(%rbp),%rbp
+ jmp .Lrounds_16_xx
+.balign 16
+.Lrounds_16_xx:
+ movq 8(%rsp),%r13
+ movq 112(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 72(%rsp),%r12
+ addq 0(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+ leaq 8(%rbp),%rbp
+ movq 16(%rsp),%r13
+ movq 120(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 80(%rsp),%r12
+ addq 8(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+ leaq 24(%rbp),%rbp
+ movq 24(%rsp),%r13
+ movq 0(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 88(%rsp),%r12
+ addq 16(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+ leaq 8(%rbp),%rbp
+ movq 32(%rsp),%r13
+ movq 8(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 96(%rsp),%r12
+ addq 24(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+ leaq 24(%rbp),%rbp
+ movq 40(%rsp),%r13
+ movq 16(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 104(%rsp),%r12
+ addq 32(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+ leaq 8(%rbp),%rbp
+ movq 48(%rsp),%r13
+ movq 24(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 112(%rsp),%r12
+ addq 40(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+ leaq 24(%rbp),%rbp
+ movq 56(%rsp),%r13
+ movq 32(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 120(%rsp),%r12
+ addq 48(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+ leaq 8(%rbp),%rbp
+ movq 64(%rsp),%r13
+ movq 40(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 0(%rsp),%r12
+ addq 56(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+ leaq 24(%rbp),%rbp
+ movq 72(%rsp),%r13
+ movq 48(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 8(%rsp),%r12
+ addq 64(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+ leaq 8(%rbp),%rbp
+ movq 80(%rsp),%r13
+ movq 56(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 16(%rsp),%r12
+ addq 72(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+ leaq 24(%rbp),%rbp
+ movq 88(%rsp),%r13
+ movq 64(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 24(%rsp),%r12
+ addq 80(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+ leaq 8(%rbp),%rbp
+ movq 96(%rsp),%r13
+ movq 72(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 32(%rsp),%r12
+ addq 88(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+ leaq 24(%rbp),%rbp
+ movq 104(%rsp),%r13
+ movq 80(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 40(%rsp),%r12
+ addq 96(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+ leaq 8(%rbp),%rbp
+ movq 112(%rsp),%r13
+ movq 88(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 48(%rsp),%r12
+ addq 104(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+ leaq 24(%rbp),%rbp
+ movq 120(%rsp),%r13
+ movq 96(%rsp),%r15
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 56(%rsp),%r12
+ addq 112(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+ leaq 8(%rbp),%rbp
+ movq 0(%rsp),%r13
+ movq 104(%rsp),%rdi
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 64(%rsp),%r12
+ addq 120(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+ leaq 24(%rbp),%rbp
+ cmpb $0,7(%rbp)
+ jnz .Lrounds_16_xx
+ movq 128+0(%rsp),%rdi
+ addq %r14,%rax
+ leaq 128(%rsi),%rsi
+ addq 0(%rdi),%rax
+ addq 8(%rdi),%rbx
+ addq 16(%rdi),%rcx
+ addq 24(%rdi),%rdx
+ addq 32(%rdi),%r8
+ addq 40(%rdi),%r9
+ addq 48(%rdi),%r10
+ addq 56(%rdi),%r11
+ cmpq 128+16(%rsp),%rsi
+ movq %rax,0(%rdi)
+ movq %rbx,8(%rdi)
+ movq %rcx,16(%rdi)
+ movq %rdx,24(%rdi)
+ movq %r8,32(%rdi)
+ movq %r9,40(%rdi)
+ movq %r10,48(%rdi)
+ movq %r11,56(%rdi)
+ jb .Lloop
+ movq 152(%rsp),%rsi
+.cfi_def_cfa %rsi,8
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha512_transform_x64)
+
+ENTRY_ALIGN(zfs_sha512_transform_avx, 64)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ shlq $4,%rdx
+ subq $160,%rsp
+ leaq (%rsi,%rdx,8),%rdx
+ andq $-64,%rsp
+ movq %rdi,128+0(%rsp)
+ movq %rsi,128+8(%rsp)
+ movq %rdx,128+16(%rsp)
+ movq %rax,152(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08
+.Lprologue_avx:
+
+ vzeroupper
+ movq 0(%rdi),%rax
+ movq 8(%rdi),%rbx
+ movq 16(%rdi),%rcx
+ movq 24(%rdi),%rdx
+ movq 32(%rdi),%r8
+ movq 40(%rdi),%r9
+ movq 48(%rdi),%r10
+ movq 56(%rdi),%r11
+ jmp .Lloop_avx
+.balign 16
+.Lloop_avx:
+ vmovdqa K512+1280(%rip),%xmm11
+ vmovdqu 0(%rsi),%xmm0
+ leaq K512+128(%rip),%rbp
+ vmovdqu 16(%rsi),%xmm1
+ vmovdqu 32(%rsi),%xmm2
+ vpshufb %xmm11,%xmm0,%xmm0
+ vmovdqu 48(%rsi),%xmm3
+ vpshufb %xmm11,%xmm1,%xmm1
+ vmovdqu 64(%rsi),%xmm4
+ vpshufb %xmm11,%xmm2,%xmm2
+ vmovdqu 80(%rsi),%xmm5
+ vpshufb %xmm11,%xmm3,%xmm3
+ vmovdqu 96(%rsi),%xmm6
+ vpshufb %xmm11,%xmm4,%xmm4
+ vmovdqu 112(%rsi),%xmm7
+ vpshufb %xmm11,%xmm5,%xmm5
+ vpaddq -128(%rbp),%xmm0,%xmm8
+ vpshufb %xmm11,%xmm6,%xmm6
+ vpaddq -96(%rbp),%xmm1,%xmm9
+ vpshufb %xmm11,%xmm7,%xmm7
+ vpaddq -64(%rbp),%xmm2,%xmm10
+ vpaddq -32(%rbp),%xmm3,%xmm11
+ vmovdqa %xmm8,0(%rsp)
+ vpaddq 0(%rbp),%xmm4,%xmm8
+ vmovdqa %xmm9,16(%rsp)
+ vpaddq 32(%rbp),%xmm5,%xmm9
+ vmovdqa %xmm10,32(%rsp)
+ vpaddq 64(%rbp),%xmm6,%xmm10
+ vmovdqa %xmm11,48(%rsp)
+ vpaddq 96(%rbp),%xmm7,%xmm11
+ vmovdqa %xmm8,64(%rsp)
+ movq %rax,%r14
+ vmovdqa %xmm9,80(%rsp)
+ movq %rbx,%rdi
+ vmovdqa %xmm10,96(%rsp)
+ xorq %rcx,%rdi
+ vmovdqa %xmm11,112(%rsp)
+ movq %r8,%r13
+ jmp .Lavx_00_47
+
+.balign 16
+.Lavx_00_47:
+ addq $256,%rbp
+ vpalignr $8,%xmm0,%xmm1,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%rax
+ vpalignr $8,%xmm4,%xmm5,%xmm11
+ movq %r9,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %r8,%r13
+ xorq %r10,%r12
+ vpaddq %xmm11,%xmm0,%xmm0
+ shrdq $4,%r13,%r13
+ xorq %rax,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %r8,%r12
+ xorq %r8,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 0(%rsp),%r11
+ movq %rax,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %r10,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %rbx,%r15
+ addq %r12,%r11
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %rax,%r14
+ addq %r13,%r11
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %rbx,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm7,%xmm11
+ addq %r11,%rdx
+ addq %rdi,%r11
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %rdx,%r13
+ addq %r11,%r14
+ vpsllq $3,%xmm7,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%r11
+ vpaddq %xmm8,%xmm0,%xmm0
+ movq %r8,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm7,%xmm9
+ xorq %rdx,%r13
+ xorq %r9,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %r11,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %rdx,%r12
+ xorq %rdx,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 8(%rsp),%r10
+ movq %r11,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %r9,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %rax,%rdi
+ addq %r12,%r10
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm0,%xmm0
+ xorq %r11,%r14
+ addq %r13,%r10
+ vpaddq -128(%rbp),%xmm0,%xmm10
+ xorq %rax,%r15
+ shrdq $28,%r14,%r14
+ addq %r10,%rcx
+ addq %r15,%r10
+ movq %rcx,%r13
+ addq %r10,%r14
+ vmovdqa %xmm10,0(%rsp)
+ vpalignr $8,%xmm1,%xmm2,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%r10
+ vpalignr $8,%xmm5,%xmm6,%xmm11
+ movq %rdx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %rcx,%r13
+ xorq %r8,%r12
+ vpaddq %xmm11,%xmm1,%xmm1
+ shrdq $4,%r13,%r13
+ xorq %r10,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %rcx,%r12
+ xorq %rcx,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 16(%rsp),%r9
+ movq %r10,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %r8,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %r11,%r15
+ addq %r12,%r9
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %r10,%r14
+ addq %r13,%r9
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %r11,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm0,%xmm11
+ addq %r9,%rbx
+ addq %rdi,%r9
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %rbx,%r13
+ addq %r9,%r14
+ vpsllq $3,%xmm0,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%r9
+ vpaddq %xmm8,%xmm1,%xmm1
+ movq %rcx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm0,%xmm9
+ xorq %rbx,%r13
+ xorq %rdx,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %r9,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %rbx,%r12
+ xorq %rbx,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 24(%rsp),%r8
+ movq %r9,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %rdx,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %r10,%rdi
+ addq %r12,%r8
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm1,%xmm1
+ xorq %r9,%r14
+ addq %r13,%r8
+ vpaddq -96(%rbp),%xmm1,%xmm10
+ xorq %r10,%r15
+ shrdq $28,%r14,%r14
+ addq %r8,%rax
+ addq %r15,%r8
+ movq %rax,%r13
+ addq %r8,%r14
+ vmovdqa %xmm10,16(%rsp)
+ vpalignr $8,%xmm2,%xmm3,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%r8
+ vpalignr $8,%xmm6,%xmm7,%xmm11
+ movq %rbx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %rax,%r13
+ xorq %rcx,%r12
+ vpaddq %xmm11,%xmm2,%xmm2
+ shrdq $4,%r13,%r13
+ xorq %r8,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %rax,%r12
+ xorq %rax,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 32(%rsp),%rdx
+ movq %r8,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %rcx,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %r9,%r15
+ addq %r12,%rdx
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %r8,%r14
+ addq %r13,%rdx
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %r9,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm1,%xmm11
+ addq %rdx,%r11
+ addq %rdi,%rdx
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %r11,%r13
+ addq %rdx,%r14
+ vpsllq $3,%xmm1,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%rdx
+ vpaddq %xmm8,%xmm2,%xmm2
+ movq %rax,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm1,%xmm9
+ xorq %r11,%r13
+ xorq %rbx,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %rdx,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %r11,%r12
+ xorq %r11,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 40(%rsp),%rcx
+ movq %rdx,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %rbx,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %r8,%rdi
+ addq %r12,%rcx
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm2,%xmm2
+ xorq %rdx,%r14
+ addq %r13,%rcx
+ vpaddq -64(%rbp),%xmm2,%xmm10
+ xorq %r8,%r15
+ shrdq $28,%r14,%r14
+ addq %rcx,%r10
+ addq %r15,%rcx
+ movq %r10,%r13
+ addq %rcx,%r14
+ vmovdqa %xmm10,32(%rsp)
+ vpalignr $8,%xmm3,%xmm4,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%rcx
+ vpalignr $8,%xmm7,%xmm0,%xmm11
+ movq %r11,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %r10,%r13
+ xorq %rax,%r12
+ vpaddq %xmm11,%xmm3,%xmm3
+ shrdq $4,%r13,%r13
+ xorq %rcx,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %r10,%r12
+ xorq %r10,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 48(%rsp),%rbx
+ movq %rcx,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %rax,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %rdx,%r15
+ addq %r12,%rbx
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %rcx,%r14
+ addq %r13,%rbx
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %rdx,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm2,%xmm11
+ addq %rbx,%r9
+ addq %rdi,%rbx
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %r9,%r13
+ addq %rbx,%r14
+ vpsllq $3,%xmm2,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%rbx
+ vpaddq %xmm8,%xmm3,%xmm3
+ movq %r10,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm2,%xmm9
+ xorq %r9,%r13
+ xorq %r11,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %rbx,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %r9,%r12
+ xorq %r9,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 56(%rsp),%rax
+ movq %rbx,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %r11,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %rcx,%rdi
+ addq %r12,%rax
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm3,%xmm3
+ xorq %rbx,%r14
+ addq %r13,%rax
+ vpaddq -32(%rbp),%xmm3,%xmm10
+ xorq %rcx,%r15
+ shrdq $28,%r14,%r14
+ addq %rax,%r8
+ addq %r15,%rax
+ movq %r8,%r13
+ addq %rax,%r14
+ vmovdqa %xmm10,48(%rsp)
+ vpalignr $8,%xmm4,%xmm5,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%rax
+ vpalignr $8,%xmm0,%xmm1,%xmm11
+ movq %r9,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %r8,%r13
+ xorq %r10,%r12
+ vpaddq %xmm11,%xmm4,%xmm4
+ shrdq $4,%r13,%r13
+ xorq %rax,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %r8,%r12
+ xorq %r8,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 64(%rsp),%r11
+ movq %rax,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %r10,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %rbx,%r15
+ addq %r12,%r11
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %rax,%r14
+ addq %r13,%r11
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %rbx,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm3,%xmm11
+ addq %r11,%rdx
+ addq %rdi,%r11
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %rdx,%r13
+ addq %r11,%r14
+ vpsllq $3,%xmm3,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%r11
+ vpaddq %xmm8,%xmm4,%xmm4
+ movq %r8,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm3,%xmm9
+ xorq %rdx,%r13
+ xorq %r9,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %r11,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %rdx,%r12
+ xorq %rdx,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 72(%rsp),%r10
+ movq %r11,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %r9,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %rax,%rdi
+ addq %r12,%r10
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm4,%xmm4
+ xorq %r11,%r14
+ addq %r13,%r10
+ vpaddq 0(%rbp),%xmm4,%xmm10
+ xorq %rax,%r15
+ shrdq $28,%r14,%r14
+ addq %r10,%rcx
+ addq %r15,%r10
+ movq %rcx,%r13
+ addq %r10,%r14
+ vmovdqa %xmm10,64(%rsp)
+ vpalignr $8,%xmm5,%xmm6,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%r10
+ vpalignr $8,%xmm1,%xmm2,%xmm11
+ movq %rdx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %rcx,%r13
+ xorq %r8,%r12
+ vpaddq %xmm11,%xmm5,%xmm5
+ shrdq $4,%r13,%r13
+ xorq %r10,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %rcx,%r12
+ xorq %rcx,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 80(%rsp),%r9
+ movq %r10,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %r8,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %r11,%r15
+ addq %r12,%r9
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %r10,%r14
+ addq %r13,%r9
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %r11,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm4,%xmm11
+ addq %r9,%rbx
+ addq %rdi,%r9
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %rbx,%r13
+ addq %r9,%r14
+ vpsllq $3,%xmm4,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%r9
+ vpaddq %xmm8,%xmm5,%xmm5
+ movq %rcx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm4,%xmm9
+ xorq %rbx,%r13
+ xorq %rdx,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %r9,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %rbx,%r12
+ xorq %rbx,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 88(%rsp),%r8
+ movq %r9,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %rdx,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %r10,%rdi
+ addq %r12,%r8
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm5,%xmm5
+ xorq %r9,%r14
+ addq %r13,%r8
+ vpaddq 32(%rbp),%xmm5,%xmm10
+ xorq %r10,%r15
+ shrdq $28,%r14,%r14
+ addq %r8,%rax
+ addq %r15,%r8
+ movq %rax,%r13
+ addq %r8,%r14
+ vmovdqa %xmm10,80(%rsp)
+ vpalignr $8,%xmm6,%xmm7,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%r8
+ vpalignr $8,%xmm2,%xmm3,%xmm11
+ movq %rbx,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %rax,%r13
+ xorq %rcx,%r12
+ vpaddq %xmm11,%xmm6,%xmm6
+ shrdq $4,%r13,%r13
+ xorq %r8,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %rax,%r12
+ xorq %rax,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 96(%rsp),%rdx
+ movq %r8,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %rcx,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %r9,%r15
+ addq %r12,%rdx
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %r8,%r14
+ addq %r13,%rdx
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %r9,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm5,%xmm11
+ addq %rdx,%r11
+ addq %rdi,%rdx
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %r11,%r13
+ addq %rdx,%r14
+ vpsllq $3,%xmm5,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%rdx
+ vpaddq %xmm8,%xmm6,%xmm6
+ movq %rax,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm5,%xmm9
+ xorq %r11,%r13
+ xorq %rbx,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %rdx,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %r11,%r12
+ xorq %r11,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 104(%rsp),%rcx
+ movq %rdx,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %rbx,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %r8,%rdi
+ addq %r12,%rcx
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm6,%xmm6
+ xorq %rdx,%r14
+ addq %r13,%rcx
+ vpaddq 64(%rbp),%xmm6,%xmm10
+ xorq %r8,%r15
+ shrdq $28,%r14,%r14
+ addq %rcx,%r10
+ addq %r15,%rcx
+ movq %r10,%r13
+ addq %rcx,%r14
+ vmovdqa %xmm10,96(%rsp)
+ vpalignr $8,%xmm7,%xmm0,%xmm8
+ shrdq $23,%r13,%r13
+ movq %r14,%rcx
+ vpalignr $8,%xmm3,%xmm4,%xmm11
+ movq %r11,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $1,%xmm8,%xmm10
+ xorq %r10,%r13
+ xorq %rax,%r12
+ vpaddq %xmm11,%xmm7,%xmm7
+ shrdq $4,%r13,%r13
+ xorq %rcx,%r14
+ vpsrlq $7,%xmm8,%xmm11
+ andq %r10,%r12
+ xorq %r10,%r13
+ vpsllq $56,%xmm8,%xmm9
+ addq 112(%rsp),%rbx
+ movq %rcx,%r15
+ vpxor %xmm10,%xmm11,%xmm8
+ xorq %rax,%r12
+ shrdq $6,%r14,%r14
+ vpsrlq $7,%xmm10,%xmm10
+ xorq %rdx,%r15
+ addq %r12,%rbx
+ vpxor %xmm9,%xmm8,%xmm8
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ vpsllq $7,%xmm9,%xmm9
+ xorq %rcx,%r14
+ addq %r13,%rbx
+ vpxor %xmm10,%xmm8,%xmm8
+ xorq %rdx,%rdi
+ shrdq $28,%r14,%r14
+ vpsrlq $6,%xmm6,%xmm11
+ addq %rbx,%r9
+ addq %rdi,%rbx
+ vpxor %xmm9,%xmm8,%xmm8
+ movq %r9,%r13
+ addq %rbx,%r14
+ vpsllq $3,%xmm6,%xmm10
+ shrdq $23,%r13,%r13
+ movq %r14,%rbx
+ vpaddq %xmm8,%xmm7,%xmm7
+ movq %r10,%r12
+ shrdq $5,%r14,%r14
+ vpsrlq $19,%xmm6,%xmm9
+ xorq %r9,%r13
+ xorq %r11,%r12
+ vpxor %xmm10,%xmm11,%xmm11
+ shrdq $4,%r13,%r13
+ xorq %rbx,%r14
+ vpsllq $42,%xmm10,%xmm10
+ andq %r9,%r12
+ xorq %r9,%r13
+ vpxor %xmm9,%xmm11,%xmm11
+ addq 120(%rsp),%rax
+ movq %rbx,%rdi
+ vpsrlq $42,%xmm9,%xmm9
+ xorq %r11,%r12
+ shrdq $6,%r14,%r14
+ vpxor %xmm10,%xmm11,%xmm11
+ xorq %rcx,%rdi
+ addq %r12,%rax
+ vpxor %xmm9,%xmm11,%xmm11
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ vpaddq %xmm11,%xmm7,%xmm7
+ xorq %rbx,%r14
+ addq %r13,%rax
+ vpaddq 96(%rbp),%xmm7,%xmm10
+ xorq %rcx,%r15
+ shrdq $28,%r14,%r14
+ addq %rax,%r8
+ addq %r15,%rax
+ movq %r8,%r13
+ addq %rax,%r14
+ vmovdqa %xmm10,112(%rsp)
+ cmpb $0,135(%rbp)
+ jne .Lavx_00_47
+ shrdq $23,%r13,%r13
+ movq %r14,%rax
+ movq %r9,%r12
+ shrdq $5,%r14,%r14
+ xorq %r8,%r13
+ xorq %r10,%r12
+ shrdq $4,%r13,%r13
+ xorq %rax,%r14
+ andq %r8,%r12
+ xorq %r8,%r13
+ addq 0(%rsp),%r11
+ movq %rax,%r15
+ xorq %r10,%r12
+ shrdq $6,%r14,%r14
+ xorq %rbx,%r15
+ addq %r12,%r11
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %rax,%r14
+ addq %r13,%r11
+ xorq %rbx,%rdi
+ shrdq $28,%r14,%r14
+ addq %r11,%rdx
+ addq %rdi,%r11
+ movq %rdx,%r13
+ addq %r11,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r11
+ movq %r8,%r12
+ shrdq $5,%r14,%r14
+ xorq %rdx,%r13
+ xorq %r9,%r12
+ shrdq $4,%r13,%r13
+ xorq %r11,%r14
+ andq %rdx,%r12
+ xorq %rdx,%r13
+ addq 8(%rsp),%r10
+ movq %r11,%rdi
+ xorq %r9,%r12
+ shrdq $6,%r14,%r14
+ xorq %rax,%rdi
+ addq %r12,%r10
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %r11,%r14
+ addq %r13,%r10
+ xorq %rax,%r15
+ shrdq $28,%r14,%r14
+ addq %r10,%rcx
+ addq %r15,%r10
+ movq %rcx,%r13
+ addq %r10,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r10
+ movq %rdx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rcx,%r13
+ xorq %r8,%r12
+ shrdq $4,%r13,%r13
+ xorq %r10,%r14
+ andq %rcx,%r12
+ xorq %rcx,%r13
+ addq 16(%rsp),%r9
+ movq %r10,%r15
+ xorq %r8,%r12
+ shrdq $6,%r14,%r14
+ xorq %r11,%r15
+ addq %r12,%r9
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %r10,%r14
+ addq %r13,%r9
+ xorq %r11,%rdi
+ shrdq $28,%r14,%r14
+ addq %r9,%rbx
+ addq %rdi,%r9
+ movq %rbx,%r13
+ addq %r9,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r9
+ movq %rcx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rbx,%r13
+ xorq %rdx,%r12
+ shrdq $4,%r13,%r13
+ xorq %r9,%r14
+ andq %rbx,%r12
+ xorq %rbx,%r13
+ addq 24(%rsp),%r8
+ movq %r9,%rdi
+ xorq %rdx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r10,%rdi
+ addq %r12,%r8
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %r9,%r14
+ addq %r13,%r8
+ xorq %r10,%r15
+ shrdq $28,%r14,%r14
+ addq %r8,%rax
+ addq %r15,%r8
+ movq %rax,%r13
+ addq %r8,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r8
+ movq %rbx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rax,%r13
+ xorq %rcx,%r12
+ shrdq $4,%r13,%r13
+ xorq %r8,%r14
+ andq %rax,%r12
+ xorq %rax,%r13
+ addq 32(%rsp),%rdx
+ movq %r8,%r15
+ xorq %rcx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r9,%r15
+ addq %r12,%rdx
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %r8,%r14
+ addq %r13,%rdx
+ xorq %r9,%rdi
+ shrdq $28,%r14,%r14
+ addq %rdx,%r11
+ addq %rdi,%rdx
+ movq %r11,%r13
+ addq %rdx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rdx
+ movq %rax,%r12
+ shrdq $5,%r14,%r14
+ xorq %r11,%r13
+ xorq %rbx,%r12
+ shrdq $4,%r13,%r13
+ xorq %rdx,%r14
+ andq %r11,%r12
+ xorq %r11,%r13
+ addq 40(%rsp),%rcx
+ movq %rdx,%rdi
+ xorq %rbx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r8,%rdi
+ addq %r12,%rcx
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %rdx,%r14
+ addq %r13,%rcx
+ xorq %r8,%r15
+ shrdq $28,%r14,%r14
+ addq %rcx,%r10
+ addq %r15,%rcx
+ movq %r10,%r13
+ addq %rcx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rcx
+ movq %r11,%r12
+ shrdq $5,%r14,%r14
+ xorq %r10,%r13
+ xorq %rax,%r12
+ shrdq $4,%r13,%r13
+ xorq %rcx,%r14
+ andq %r10,%r12
+ xorq %r10,%r13
+ addq 48(%rsp),%rbx
+ movq %rcx,%r15
+ xorq %rax,%r12
+ shrdq $6,%r14,%r14
+ xorq %rdx,%r15
+ addq %r12,%rbx
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %rcx,%r14
+ addq %r13,%rbx
+ xorq %rdx,%rdi
+ shrdq $28,%r14,%r14
+ addq %rbx,%r9
+ addq %rdi,%rbx
+ movq %r9,%r13
+ addq %rbx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rbx
+ movq %r10,%r12
+ shrdq $5,%r14,%r14
+ xorq %r9,%r13
+ xorq %r11,%r12
+ shrdq $4,%r13,%r13
+ xorq %rbx,%r14
+ andq %r9,%r12
+ xorq %r9,%r13
+ addq 56(%rsp),%rax
+ movq %rbx,%rdi
+ xorq %r11,%r12
+ shrdq $6,%r14,%r14
+ xorq %rcx,%rdi
+ addq %r12,%rax
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %rbx,%r14
+ addq %r13,%rax
+ xorq %rcx,%r15
+ shrdq $28,%r14,%r14
+ addq %rax,%r8
+ addq %r15,%rax
+ movq %r8,%r13
+ addq %rax,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rax
+ movq %r9,%r12
+ shrdq $5,%r14,%r14
+ xorq %r8,%r13
+ xorq %r10,%r12
+ shrdq $4,%r13,%r13
+ xorq %rax,%r14
+ andq %r8,%r12
+ xorq %r8,%r13
+ addq 64(%rsp),%r11
+ movq %rax,%r15
+ xorq %r10,%r12
+ shrdq $6,%r14,%r14
+ xorq %rbx,%r15
+ addq %r12,%r11
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %rax,%r14
+ addq %r13,%r11
+ xorq %rbx,%rdi
+ shrdq $28,%r14,%r14
+ addq %r11,%rdx
+ addq %rdi,%r11
+ movq %rdx,%r13
+ addq %r11,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r11
+ movq %r8,%r12
+ shrdq $5,%r14,%r14
+ xorq %rdx,%r13
+ xorq %r9,%r12
+ shrdq $4,%r13,%r13
+ xorq %r11,%r14
+ andq %rdx,%r12
+ xorq %rdx,%r13
+ addq 72(%rsp),%r10
+ movq %r11,%rdi
+ xorq %r9,%r12
+ shrdq $6,%r14,%r14
+ xorq %rax,%rdi
+ addq %r12,%r10
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %r11,%r14
+ addq %r13,%r10
+ xorq %rax,%r15
+ shrdq $28,%r14,%r14
+ addq %r10,%rcx
+ addq %r15,%r10
+ movq %rcx,%r13
+ addq %r10,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r10
+ movq %rdx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rcx,%r13
+ xorq %r8,%r12
+ shrdq $4,%r13,%r13
+ xorq %r10,%r14
+ andq %rcx,%r12
+ xorq %rcx,%r13
+ addq 80(%rsp),%r9
+ movq %r10,%r15
+ xorq %r8,%r12
+ shrdq $6,%r14,%r14
+ xorq %r11,%r15
+ addq %r12,%r9
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %r10,%r14
+ addq %r13,%r9
+ xorq %r11,%rdi
+ shrdq $28,%r14,%r14
+ addq %r9,%rbx
+ addq %rdi,%r9
+ movq %rbx,%r13
+ addq %r9,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r9
+ movq %rcx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rbx,%r13
+ xorq %rdx,%r12
+ shrdq $4,%r13,%r13
+ xorq %r9,%r14
+ andq %rbx,%r12
+ xorq %rbx,%r13
+ addq 88(%rsp),%r8
+ movq %r9,%rdi
+ xorq %rdx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r10,%rdi
+ addq %r12,%r8
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %r9,%r14
+ addq %r13,%r8
+ xorq %r10,%r15
+ shrdq $28,%r14,%r14
+ addq %r8,%rax
+ addq %r15,%r8
+ movq %rax,%r13
+ addq %r8,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%r8
+ movq %rbx,%r12
+ shrdq $5,%r14,%r14
+ xorq %rax,%r13
+ xorq %rcx,%r12
+ shrdq $4,%r13,%r13
+ xorq %r8,%r14
+ andq %rax,%r12
+ xorq %rax,%r13
+ addq 96(%rsp),%rdx
+ movq %r8,%r15
+ xorq %rcx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r9,%r15
+ addq %r12,%rdx
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %r8,%r14
+ addq %r13,%rdx
+ xorq %r9,%rdi
+ shrdq $28,%r14,%r14
+ addq %rdx,%r11
+ addq %rdi,%rdx
+ movq %r11,%r13
+ addq %rdx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rdx
+ movq %rax,%r12
+ shrdq $5,%r14,%r14
+ xorq %r11,%r13
+ xorq %rbx,%r12
+ shrdq $4,%r13,%r13
+ xorq %rdx,%r14
+ andq %r11,%r12
+ xorq %r11,%r13
+ addq 104(%rsp),%rcx
+ movq %rdx,%rdi
+ xorq %rbx,%r12
+ shrdq $6,%r14,%r14
+ xorq %r8,%rdi
+ addq %r12,%rcx
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %rdx,%r14
+ addq %r13,%rcx
+ xorq %r8,%r15
+ shrdq $28,%r14,%r14
+ addq %rcx,%r10
+ addq %r15,%rcx
+ movq %r10,%r13
+ addq %rcx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rcx
+ movq %r11,%r12
+ shrdq $5,%r14,%r14
+ xorq %r10,%r13
+ xorq %rax,%r12
+ shrdq $4,%r13,%r13
+ xorq %rcx,%r14
+ andq %r10,%r12
+ xorq %r10,%r13
+ addq 112(%rsp),%rbx
+ movq %rcx,%r15
+ xorq %rax,%r12
+ shrdq $6,%r14,%r14
+ xorq %rdx,%r15
+ addq %r12,%rbx
+ shrdq $14,%r13,%r13
+ andq %r15,%rdi
+ xorq %rcx,%r14
+ addq %r13,%rbx
+ xorq %rdx,%rdi
+ shrdq $28,%r14,%r14
+ addq %rbx,%r9
+ addq %rdi,%rbx
+ movq %r9,%r13
+ addq %rbx,%r14
+ shrdq $23,%r13,%r13
+ movq %r14,%rbx
+ movq %r10,%r12
+ shrdq $5,%r14,%r14
+ xorq %r9,%r13
+ xorq %r11,%r12
+ shrdq $4,%r13,%r13
+ xorq %rbx,%r14
+ andq %r9,%r12
+ xorq %r9,%r13
+ addq 120(%rsp),%rax
+ movq %rbx,%rdi
+ xorq %r11,%r12
+ shrdq $6,%r14,%r14
+ xorq %rcx,%rdi
+ addq %r12,%rax
+ shrdq $14,%r13,%r13
+ andq %rdi,%r15
+ xorq %rbx,%r14
+ addq %r13,%rax
+ xorq %rcx,%r15
+ shrdq $28,%r14,%r14
+ addq %rax,%r8
+ addq %r15,%rax
+ movq %r8,%r13
+ addq %rax,%r14
+ movq 128+0(%rsp),%rdi
+ movq %r14,%rax
+
+ addq 0(%rdi),%rax
+ leaq 128(%rsi),%rsi
+ addq 8(%rdi),%rbx
+ addq 16(%rdi),%rcx
+ addq 24(%rdi),%rdx
+ addq 32(%rdi),%r8
+ addq 40(%rdi),%r9
+ addq 48(%rdi),%r10
+ addq 56(%rdi),%r11
+
+ cmpq 128+16(%rsp),%rsi
+
+ movq %rax,0(%rdi)
+ movq %rbx,8(%rdi)
+ movq %rcx,16(%rdi)
+ movq %rdx,24(%rdi)
+ movq %r8,32(%rdi)
+ movq %r9,40(%rdi)
+ movq %r10,48(%rdi)
+ movq %r11,56(%rdi)
+ jb .Lloop_avx
+
+ movq 152(%rsp),%rsi
+.cfi_def_cfa %rsi,8
+ vzeroupper
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue_avx:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha512_transform_avx)
+
+ENTRY_ALIGN(zfs_sha512_transform_avx2, 64)
+.cfi_startproc
+ ENDBR
+ movq %rsp,%rax
+.cfi_def_cfa_register %rax
+ pushq %rbx
+.cfi_offset %rbx,-16
+ pushq %rbp
+.cfi_offset %rbp,-24
+ pushq %r12
+.cfi_offset %r12,-32
+ pushq %r13
+.cfi_offset %r13,-40
+ pushq %r14
+.cfi_offset %r14,-48
+ pushq %r15
+.cfi_offset %r15,-56
+ subq $1312,%rsp
+ shlq $4,%rdx
+ andq $-2048,%rsp
+ leaq (%rsi,%rdx,8),%rdx
+ addq $1152,%rsp
+ movq %rdi,128+0(%rsp)
+ movq %rsi,128+8(%rsp)
+ movq %rdx,128+16(%rsp)
+ movq %rax,152(%rsp)
+.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08
+.Lprologue_avx2:
+
+ vzeroupper
+ subq $-128,%rsi
+ movq 0(%rdi),%rax
+ movq %rsi,%r12
+ movq 8(%rdi),%rbx
+ cmpq %rdx,%rsi
+ movq 16(%rdi),%rcx
+ cmoveq %rsp,%r12
+ movq 24(%rdi),%rdx
+ movq 32(%rdi),%r8
+ movq 40(%rdi),%r9
+ movq 48(%rdi),%r10
+ movq 56(%rdi),%r11
+ jmp .Loop_avx2
+.balign 16
+.Loop_avx2:
+ vmovdqu -128(%rsi),%xmm0
+ vmovdqu -128+16(%rsi),%xmm1
+ vmovdqu -128+32(%rsi),%xmm2
+ leaq K512+128(%rip),%rbp
+ vmovdqu -128+48(%rsi),%xmm3
+ vmovdqu -128+64(%rsi),%xmm4
+ vmovdqu -128+80(%rsi),%xmm5
+ vmovdqu -128+96(%rsi),%xmm6
+ vmovdqu -128+112(%rsi),%xmm7
+
+ vmovdqa 1152(%rbp),%ymm10
+ vinserti128 $1,(%r12),%ymm0,%ymm0
+ vinserti128 $1,16(%r12),%ymm1,%ymm1
+ vpshufb %ymm10,%ymm0,%ymm0
+ vinserti128 $1,32(%r12),%ymm2,%ymm2
+ vpshufb %ymm10,%ymm1,%ymm1
+ vinserti128 $1,48(%r12),%ymm3,%ymm3
+ vpshufb %ymm10,%ymm2,%ymm2
+ vinserti128 $1,64(%r12),%ymm4,%ymm4
+ vpshufb %ymm10,%ymm3,%ymm3
+ vinserti128 $1,80(%r12),%ymm5,%ymm5
+ vpshufb %ymm10,%ymm4,%ymm4
+ vinserti128 $1,96(%r12),%ymm6,%ymm6
+ vpshufb %ymm10,%ymm5,%ymm5
+ vinserti128 $1,112(%r12),%ymm7,%ymm7
+
+ vpaddq -128(%rbp),%ymm0,%ymm8
+ vpshufb %ymm10,%ymm6,%ymm6
+ vpaddq -96(%rbp),%ymm1,%ymm9
+ vpshufb %ymm10,%ymm7,%ymm7
+ vpaddq -64(%rbp),%ymm2,%ymm10
+ vpaddq -32(%rbp),%ymm3,%ymm11
+ vmovdqa %ymm8,0(%rsp)
+ vpaddq 0(%rbp),%ymm4,%ymm8
+ vmovdqa %ymm9,32(%rsp)
+ vpaddq 32(%rbp),%ymm5,%ymm9
+ vmovdqa %ymm10,64(%rsp)
+ vpaddq 64(%rbp),%ymm6,%ymm10
+ vmovdqa %ymm11,96(%rsp)
+
+ movq 152(%rsp),%rdi
+.cfi_def_cfa %rdi,8
+ leaq -128(%rsp),%rsp
+
+
+
+ movq %rdi,-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ vpaddq 96(%rbp),%ymm7,%ymm11
+ vmovdqa %ymm8,0(%rsp)
+ xorq %r14,%r14
+ vmovdqa %ymm9,32(%rsp)
+ movq %rbx,%rdi
+ vmovdqa %ymm10,64(%rsp)
+ xorq %rcx,%rdi
+ vmovdqa %ymm11,96(%rsp)
+ movq %r9,%r12
+ addq $32*8,%rbp
+ jmp .Lavx2_00_47
+
+.balign 16
+.Lavx2_00_47:
+ leaq -128(%rsp),%rsp
+.cfi_escape 0x0f,0x06,0x77,0xf8,0x00,0x06,0x23,0x08
+
+ pushq 128-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08
+ leaq 8(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ vpalignr $8,%ymm0,%ymm1,%ymm8
+ addq 0+256(%rsp),%r11
+ andq %r8,%r12
+ rorxq $41,%r8,%r13
+ vpalignr $8,%ymm4,%ymm5,%ymm11
+ rorxq $18,%r8,%r15
+ leaq (%rax,%r14,1),%rax
+ leaq (%r11,%r12,1),%r11
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %r10,%r8,%r12
+ xorq %r15,%r13
+ rorxq $14,%r8,%r14
+ vpaddq %ymm11,%ymm0,%ymm0
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%r11,%r12,1),%r11
+ xorq %r14,%r13
+ movq %rax,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%rax,%r12
+ leaq (%r11,%r13,1),%r11
+ xorq %rbx,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%rax,%r14
+ rorxq $28,%rax,%r13
+ leaq (%rdx,%r11,1),%rdx
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rbx,%rdi
+ vpsrlq $6,%ymm7,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%r11,%rdi,1),%r11
+ movq %r8,%r12
+ vpsllq $3,%ymm7,%ymm10
+ vpaddq %ymm8,%ymm0,%ymm0
+ addq 8+256(%rsp),%r10
+ andq %rdx,%r12
+ rorxq $41,%rdx,%r13
+ vpsrlq $19,%ymm7,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%rdx,%rdi
+ leaq (%r11,%r14,1),%r11
+ leaq (%r10,%r12,1),%r10
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %r9,%rdx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rdx,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%r10,%r12,1),%r10
+ xorq %r14,%r13
+ movq %r11,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%r11,%r12
+ leaq (%r10,%r13,1),%r10
+ xorq %rax,%rdi
+ vpaddq %ymm11,%ymm0,%ymm0
+ rorxq $34,%r11,%r14
+ rorxq $28,%r11,%r13
+ leaq (%rcx,%r10,1),%rcx
+ vpaddq -128(%rbp),%ymm0,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rax,%r15
+ xorq %r13,%r14
+ leaq (%r10,%r15,1),%r10
+ movq %rdx,%r12
+ vmovdqa %ymm10,0(%rsp)
+ vpalignr $8,%ymm1,%ymm2,%ymm8
+ addq 32+256(%rsp),%r9
+ andq %rcx,%r12
+ rorxq $41,%rcx,%r13
+ vpalignr $8,%ymm5,%ymm6,%ymm11
+ rorxq $18,%rcx,%r15
+ leaq (%r10,%r14,1),%r10
+ leaq (%r9,%r12,1),%r9
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %r8,%rcx,%r12
+ xorq %r15,%r13
+ rorxq $14,%rcx,%r14
+ vpaddq %ymm11,%ymm1,%ymm1
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%r9,%r12,1),%r9
+ xorq %r14,%r13
+ movq %r10,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%r10,%r12
+ leaq (%r9,%r13,1),%r9
+ xorq %r11,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%r10,%r14
+ rorxq $28,%r10,%r13
+ leaq (%rbx,%r9,1),%rbx
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r11,%rdi
+ vpsrlq $6,%ymm0,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%r9,%rdi,1),%r9
+ movq %rcx,%r12
+ vpsllq $3,%ymm0,%ymm10
+ vpaddq %ymm8,%ymm1,%ymm1
+ addq 40+256(%rsp),%r8
+ andq %rbx,%r12
+ rorxq $41,%rbx,%r13
+ vpsrlq $19,%ymm0,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%rbx,%rdi
+ leaq (%r9,%r14,1),%r9
+ leaq (%r8,%r12,1),%r8
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %rdx,%rbx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rbx,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%r8,%r12,1),%r8
+ xorq %r14,%r13
+ movq %r9,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%r9,%r12
+ leaq (%r8,%r13,1),%r8
+ xorq %r10,%rdi
+ vpaddq %ymm11,%ymm1,%ymm1
+ rorxq $34,%r9,%r14
+ rorxq $28,%r9,%r13
+ leaq (%rax,%r8,1),%rax
+ vpaddq -96(%rbp),%ymm1,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r10,%r15
+ xorq %r13,%r14
+ leaq (%r8,%r15,1),%r8
+ movq %rbx,%r12
+ vmovdqa %ymm10,32(%rsp)
+ vpalignr $8,%ymm2,%ymm3,%ymm8
+ addq 64+256(%rsp),%rdx
+ andq %rax,%r12
+ rorxq $41,%rax,%r13
+ vpalignr $8,%ymm6,%ymm7,%ymm11
+ rorxq $18,%rax,%r15
+ leaq (%r8,%r14,1),%r8
+ leaq (%rdx,%r12,1),%rdx
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %rcx,%rax,%r12
+ xorq %r15,%r13
+ rorxq $14,%rax,%r14
+ vpaddq %ymm11,%ymm2,%ymm2
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%rdx,%r12,1),%rdx
+ xorq %r14,%r13
+ movq %r8,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%r8,%r12
+ leaq (%rdx,%r13,1),%rdx
+ xorq %r9,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%r8,%r14
+ rorxq $28,%r8,%r13
+ leaq (%r11,%rdx,1),%r11
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r9,%rdi
+ vpsrlq $6,%ymm1,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%rdx,%rdi,1),%rdx
+ movq %rax,%r12
+ vpsllq $3,%ymm1,%ymm10
+ vpaddq %ymm8,%ymm2,%ymm2
+ addq 72+256(%rsp),%rcx
+ andq %r11,%r12
+ rorxq $41,%r11,%r13
+ vpsrlq $19,%ymm1,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%r11,%rdi
+ leaq (%rdx,%r14,1),%rdx
+ leaq (%rcx,%r12,1),%rcx
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %rbx,%r11,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r11,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%rcx,%r12,1),%rcx
+ xorq %r14,%r13
+ movq %rdx,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%rdx,%r12
+ leaq (%rcx,%r13,1),%rcx
+ xorq %r8,%rdi
+ vpaddq %ymm11,%ymm2,%ymm2
+ rorxq $34,%rdx,%r14
+ rorxq $28,%rdx,%r13
+ leaq (%r10,%rcx,1),%r10
+ vpaddq -64(%rbp),%ymm2,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r8,%r15
+ xorq %r13,%r14
+ leaq (%rcx,%r15,1),%rcx
+ movq %r11,%r12
+ vmovdqa %ymm10,64(%rsp)
+ vpalignr $8,%ymm3,%ymm4,%ymm8
+ addq 96+256(%rsp),%rbx
+ andq %r10,%r12
+ rorxq $41,%r10,%r13
+ vpalignr $8,%ymm7,%ymm0,%ymm11
+ rorxq $18,%r10,%r15
+ leaq (%rcx,%r14,1),%rcx
+ leaq (%rbx,%r12,1),%rbx
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %rax,%r10,%r12
+ xorq %r15,%r13
+ rorxq $14,%r10,%r14
+ vpaddq %ymm11,%ymm3,%ymm3
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%rbx,%r12,1),%rbx
+ xorq %r14,%r13
+ movq %rcx,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%rcx,%r12
+ leaq (%rbx,%r13,1),%rbx
+ xorq %rdx,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%rcx,%r14
+ rorxq $28,%rcx,%r13
+ leaq (%r9,%rbx,1),%r9
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rdx,%rdi
+ vpsrlq $6,%ymm2,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%rbx,%rdi,1),%rbx
+ movq %r10,%r12
+ vpsllq $3,%ymm2,%ymm10
+ vpaddq %ymm8,%ymm3,%ymm3
+ addq 104+256(%rsp),%rax
+ andq %r9,%r12
+ rorxq $41,%r9,%r13
+ vpsrlq $19,%ymm2,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%r9,%rdi
+ leaq (%rbx,%r14,1),%rbx
+ leaq (%rax,%r12,1),%rax
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %r11,%r9,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r9,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%rax,%r12,1),%rax
+ xorq %r14,%r13
+ movq %rbx,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%rbx,%r12
+ leaq (%rax,%r13,1),%rax
+ xorq %rcx,%rdi
+ vpaddq %ymm11,%ymm3,%ymm3
+ rorxq $34,%rbx,%r14
+ rorxq $28,%rbx,%r13
+ leaq (%r8,%rax,1),%r8
+ vpaddq -32(%rbp),%ymm3,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rcx,%r15
+ xorq %r13,%r14
+ leaq (%rax,%r15,1),%rax
+ movq %r9,%r12
+ vmovdqa %ymm10,96(%rsp)
+ leaq -128(%rsp),%rsp
+.cfi_escape 0x0f,0x06,0x77,0xf8,0x00,0x06,0x23,0x08
+
+ pushq 128-8(%rsp)
+.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08
+ leaq 8(%rsp),%rsp
+.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08
+ vpalignr $8,%ymm4,%ymm5,%ymm8
+ addq 0+256(%rsp),%r11
+ andq %r8,%r12
+ rorxq $41,%r8,%r13
+ vpalignr $8,%ymm0,%ymm1,%ymm11
+ rorxq $18,%r8,%r15
+ leaq (%rax,%r14,1),%rax
+ leaq (%r11,%r12,1),%r11
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %r10,%r8,%r12
+ xorq %r15,%r13
+ rorxq $14,%r8,%r14
+ vpaddq %ymm11,%ymm4,%ymm4
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%r11,%r12,1),%r11
+ xorq %r14,%r13
+ movq %rax,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%rax,%r12
+ leaq (%r11,%r13,1),%r11
+ xorq %rbx,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%rax,%r14
+ rorxq $28,%rax,%r13
+ leaq (%rdx,%r11,1),%rdx
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rbx,%rdi
+ vpsrlq $6,%ymm3,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%r11,%rdi,1),%r11
+ movq %r8,%r12
+ vpsllq $3,%ymm3,%ymm10
+ vpaddq %ymm8,%ymm4,%ymm4
+ addq 8+256(%rsp),%r10
+ andq %rdx,%r12
+ rorxq $41,%rdx,%r13
+ vpsrlq $19,%ymm3,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%rdx,%rdi
+ leaq (%r11,%r14,1),%r11
+ leaq (%r10,%r12,1),%r10
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %r9,%rdx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rdx,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%r10,%r12,1),%r10
+ xorq %r14,%r13
+ movq %r11,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%r11,%r12
+ leaq (%r10,%r13,1),%r10
+ xorq %rax,%rdi
+ vpaddq %ymm11,%ymm4,%ymm4
+ rorxq $34,%r11,%r14
+ rorxq $28,%r11,%r13
+ leaq (%rcx,%r10,1),%rcx
+ vpaddq 0(%rbp),%ymm4,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rax,%r15
+ xorq %r13,%r14
+ leaq (%r10,%r15,1),%r10
+ movq %rdx,%r12
+ vmovdqa %ymm10,0(%rsp)
+ vpalignr $8,%ymm5,%ymm6,%ymm8
+ addq 32+256(%rsp),%r9
+ andq %rcx,%r12
+ rorxq $41,%rcx,%r13
+ vpalignr $8,%ymm1,%ymm2,%ymm11
+ rorxq $18,%rcx,%r15
+ leaq (%r10,%r14,1),%r10
+ leaq (%r9,%r12,1),%r9
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %r8,%rcx,%r12
+ xorq %r15,%r13
+ rorxq $14,%rcx,%r14
+ vpaddq %ymm11,%ymm5,%ymm5
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%r9,%r12,1),%r9
+ xorq %r14,%r13
+ movq %r10,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%r10,%r12
+ leaq (%r9,%r13,1),%r9
+ xorq %r11,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%r10,%r14
+ rorxq $28,%r10,%r13
+ leaq (%rbx,%r9,1),%rbx
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r11,%rdi
+ vpsrlq $6,%ymm4,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%r9,%rdi,1),%r9
+ movq %rcx,%r12
+ vpsllq $3,%ymm4,%ymm10
+ vpaddq %ymm8,%ymm5,%ymm5
+ addq 40+256(%rsp),%r8
+ andq %rbx,%r12
+ rorxq $41,%rbx,%r13
+ vpsrlq $19,%ymm4,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%rbx,%rdi
+ leaq (%r9,%r14,1),%r9
+ leaq (%r8,%r12,1),%r8
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %rdx,%rbx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rbx,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%r8,%r12,1),%r8
+ xorq %r14,%r13
+ movq %r9,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%r9,%r12
+ leaq (%r8,%r13,1),%r8
+ xorq %r10,%rdi
+ vpaddq %ymm11,%ymm5,%ymm5
+ rorxq $34,%r9,%r14
+ rorxq $28,%r9,%r13
+ leaq (%rax,%r8,1),%rax
+ vpaddq 32(%rbp),%ymm5,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r10,%r15
+ xorq %r13,%r14
+ leaq (%r8,%r15,1),%r8
+ movq %rbx,%r12
+ vmovdqa %ymm10,32(%rsp)
+ vpalignr $8,%ymm6,%ymm7,%ymm8
+ addq 64+256(%rsp),%rdx
+ andq %rax,%r12
+ rorxq $41,%rax,%r13
+ vpalignr $8,%ymm2,%ymm3,%ymm11
+ rorxq $18,%rax,%r15
+ leaq (%r8,%r14,1),%r8
+ leaq (%rdx,%r12,1),%rdx
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %rcx,%rax,%r12
+ xorq %r15,%r13
+ rorxq $14,%rax,%r14
+ vpaddq %ymm11,%ymm6,%ymm6
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%rdx,%r12,1),%rdx
+ xorq %r14,%r13
+ movq %r8,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%r8,%r12
+ leaq (%rdx,%r13,1),%rdx
+ xorq %r9,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%r8,%r14
+ rorxq $28,%r8,%r13
+ leaq (%r11,%rdx,1),%r11
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r9,%rdi
+ vpsrlq $6,%ymm5,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%rdx,%rdi,1),%rdx
+ movq %rax,%r12
+ vpsllq $3,%ymm5,%ymm10
+ vpaddq %ymm8,%ymm6,%ymm6
+ addq 72+256(%rsp),%rcx
+ andq %r11,%r12
+ rorxq $41,%r11,%r13
+ vpsrlq $19,%ymm5,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%r11,%rdi
+ leaq (%rdx,%r14,1),%rdx
+ leaq (%rcx,%r12,1),%rcx
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %rbx,%r11,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r11,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%rcx,%r12,1),%rcx
+ xorq %r14,%r13
+ movq %rdx,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%rdx,%r12
+ leaq (%rcx,%r13,1),%rcx
+ xorq %r8,%rdi
+ vpaddq %ymm11,%ymm6,%ymm6
+ rorxq $34,%rdx,%r14
+ rorxq $28,%rdx,%r13
+ leaq (%r10,%rcx,1),%r10
+ vpaddq 64(%rbp),%ymm6,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r8,%r15
+ xorq %r13,%r14
+ leaq (%rcx,%r15,1),%rcx
+ movq %r11,%r12
+ vmovdqa %ymm10,64(%rsp)
+ vpalignr $8,%ymm7,%ymm0,%ymm8
+ addq 96+256(%rsp),%rbx
+ andq %r10,%r12
+ rorxq $41,%r10,%r13
+ vpalignr $8,%ymm3,%ymm4,%ymm11
+ rorxq $18,%r10,%r15
+ leaq (%rcx,%r14,1),%rcx
+ leaq (%rbx,%r12,1),%rbx
+ vpsrlq $1,%ymm8,%ymm10
+ andnq %rax,%r10,%r12
+ xorq %r15,%r13
+ rorxq $14,%r10,%r14
+ vpaddq %ymm11,%ymm7,%ymm7
+ vpsrlq $7,%ymm8,%ymm11
+ leaq (%rbx,%r12,1),%rbx
+ xorq %r14,%r13
+ movq %rcx,%r15
+ vpsllq $56,%ymm8,%ymm9
+ vpxor %ymm10,%ymm11,%ymm8
+ rorxq $39,%rcx,%r12
+ leaq (%rbx,%r13,1),%rbx
+ xorq %rdx,%r15
+ vpsrlq $7,%ymm10,%ymm10
+ vpxor %ymm9,%ymm8,%ymm8
+ rorxq $34,%rcx,%r14
+ rorxq $28,%rcx,%r13
+ leaq (%r9,%rbx,1),%r9
+ vpsllq $7,%ymm9,%ymm9
+ vpxor %ymm10,%ymm8,%ymm8
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rdx,%rdi
+ vpsrlq $6,%ymm6,%ymm11
+ vpxor %ymm9,%ymm8,%ymm8
+ xorq %r13,%r14
+ leaq (%rbx,%rdi,1),%rbx
+ movq %r10,%r12
+ vpsllq $3,%ymm6,%ymm10
+ vpaddq %ymm8,%ymm7,%ymm7
+ addq 104+256(%rsp),%rax
+ andq %r9,%r12
+ rorxq $41,%r9,%r13
+ vpsrlq $19,%ymm6,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ rorxq $18,%r9,%rdi
+ leaq (%rbx,%r14,1),%rbx
+ leaq (%rax,%r12,1),%rax
+ vpsllq $42,%ymm10,%ymm10
+ vpxor %ymm9,%ymm11,%ymm11
+ andnq %r11,%r9,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r9,%r14
+ vpsrlq $42,%ymm9,%ymm9
+ vpxor %ymm10,%ymm11,%ymm11
+ leaq (%rax,%r12,1),%rax
+ xorq %r14,%r13
+ movq %rbx,%rdi
+ vpxor %ymm9,%ymm11,%ymm11
+ rorxq $39,%rbx,%r12
+ leaq (%rax,%r13,1),%rax
+ xorq %rcx,%rdi
+ vpaddq %ymm11,%ymm7,%ymm7
+ rorxq $34,%rbx,%r14
+ rorxq $28,%rbx,%r13
+ leaq (%r8,%rax,1),%r8
+ vpaddq 96(%rbp),%ymm7,%ymm10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rcx,%r15
+ xorq %r13,%r14
+ leaq (%rax,%r15,1),%rax
+ movq %r9,%r12
+ vmovdqa %ymm10,96(%rsp)
+ leaq 256(%rbp),%rbp
+ cmpb $0,-121(%rbp)
+ jne .Lavx2_00_47
+ addq 0+128(%rsp),%r11
+ andq %r8,%r12
+ rorxq $41,%r8,%r13
+ rorxq $18,%r8,%r15
+ leaq (%rax,%r14,1),%rax
+ leaq (%r11,%r12,1),%r11
+ andnq %r10,%r8,%r12
+ xorq %r15,%r13
+ rorxq $14,%r8,%r14
+ leaq (%r11,%r12,1),%r11
+ xorq %r14,%r13
+ movq %rax,%r15
+ rorxq $39,%rax,%r12
+ leaq (%r11,%r13,1),%r11
+ xorq %rbx,%r15
+ rorxq $34,%rax,%r14
+ rorxq $28,%rax,%r13
+ leaq (%rdx,%r11,1),%rdx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rbx,%rdi
+ xorq %r13,%r14
+ leaq (%r11,%rdi,1),%r11
+ movq %r8,%r12
+ addq 8+128(%rsp),%r10
+ andq %rdx,%r12
+ rorxq $41,%rdx,%r13
+ rorxq $18,%rdx,%rdi
+ leaq (%r11,%r14,1),%r11
+ leaq (%r10,%r12,1),%r10
+ andnq %r9,%rdx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rdx,%r14
+ leaq (%r10,%r12,1),%r10
+ xorq %r14,%r13
+ movq %r11,%rdi
+ rorxq $39,%r11,%r12
+ leaq (%r10,%r13,1),%r10
+ xorq %rax,%rdi
+ rorxq $34,%r11,%r14
+ rorxq $28,%r11,%r13
+ leaq (%rcx,%r10,1),%rcx
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rax,%r15
+ xorq %r13,%r14
+ leaq (%r10,%r15,1),%r10
+ movq %rdx,%r12
+ addq 32+128(%rsp),%r9
+ andq %rcx,%r12
+ rorxq $41,%rcx,%r13
+ rorxq $18,%rcx,%r15
+ leaq (%r10,%r14,1),%r10
+ leaq (%r9,%r12,1),%r9
+ andnq %r8,%rcx,%r12
+ xorq %r15,%r13
+ rorxq $14,%rcx,%r14
+ leaq (%r9,%r12,1),%r9
+ xorq %r14,%r13
+ movq %r10,%r15
+ rorxq $39,%r10,%r12
+ leaq (%r9,%r13,1),%r9
+ xorq %r11,%r15
+ rorxq $34,%r10,%r14
+ rorxq $28,%r10,%r13
+ leaq (%rbx,%r9,1),%rbx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r11,%rdi
+ xorq %r13,%r14
+ leaq (%r9,%rdi,1),%r9
+ movq %rcx,%r12
+ addq 40+128(%rsp),%r8
+ andq %rbx,%r12
+ rorxq $41,%rbx,%r13
+ rorxq $18,%rbx,%rdi
+ leaq (%r9,%r14,1),%r9
+ leaq (%r8,%r12,1),%r8
+ andnq %rdx,%rbx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rbx,%r14
+ leaq (%r8,%r12,1),%r8
+ xorq %r14,%r13
+ movq %r9,%rdi
+ rorxq $39,%r9,%r12
+ leaq (%r8,%r13,1),%r8
+ xorq %r10,%rdi
+ rorxq $34,%r9,%r14
+ rorxq $28,%r9,%r13
+ leaq (%rax,%r8,1),%rax
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r10,%r15
+ xorq %r13,%r14
+ leaq (%r8,%r15,1),%r8
+ movq %rbx,%r12
+ addq 64+128(%rsp),%rdx
+ andq %rax,%r12
+ rorxq $41,%rax,%r13
+ rorxq $18,%rax,%r15
+ leaq (%r8,%r14,1),%r8
+ leaq (%rdx,%r12,1),%rdx
+ andnq %rcx,%rax,%r12
+ xorq %r15,%r13
+ rorxq $14,%rax,%r14
+ leaq (%rdx,%r12,1),%rdx
+ xorq %r14,%r13
+ movq %r8,%r15
+ rorxq $39,%r8,%r12
+ leaq (%rdx,%r13,1),%rdx
+ xorq %r9,%r15
+ rorxq $34,%r8,%r14
+ rorxq $28,%r8,%r13
+ leaq (%r11,%rdx,1),%r11
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r9,%rdi
+ xorq %r13,%r14
+ leaq (%rdx,%rdi,1),%rdx
+ movq %rax,%r12
+ addq 72+128(%rsp),%rcx
+ andq %r11,%r12
+ rorxq $41,%r11,%r13
+ rorxq $18,%r11,%rdi
+ leaq (%rdx,%r14,1),%rdx
+ leaq (%rcx,%r12,1),%rcx
+ andnq %rbx,%r11,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r11,%r14
+ leaq (%rcx,%r12,1),%rcx
+ xorq %r14,%r13
+ movq %rdx,%rdi
+ rorxq $39,%rdx,%r12
+ leaq (%rcx,%r13,1),%rcx
+ xorq %r8,%rdi
+ rorxq $34,%rdx,%r14
+ rorxq $28,%rdx,%r13
+ leaq (%r10,%rcx,1),%r10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r8,%r15
+ xorq %r13,%r14
+ leaq (%rcx,%r15,1),%rcx
+ movq %r11,%r12
+ addq 96+128(%rsp),%rbx
+ andq %r10,%r12
+ rorxq $41,%r10,%r13
+ rorxq $18,%r10,%r15
+ leaq (%rcx,%r14,1),%rcx
+ leaq (%rbx,%r12,1),%rbx
+ andnq %rax,%r10,%r12
+ xorq %r15,%r13
+ rorxq $14,%r10,%r14
+ leaq (%rbx,%r12,1),%rbx
+ xorq %r14,%r13
+ movq %rcx,%r15
+ rorxq $39,%rcx,%r12
+ leaq (%rbx,%r13,1),%rbx
+ xorq %rdx,%r15
+ rorxq $34,%rcx,%r14
+ rorxq $28,%rcx,%r13
+ leaq (%r9,%rbx,1),%r9
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rdx,%rdi
+ xorq %r13,%r14
+ leaq (%rbx,%rdi,1),%rbx
+ movq %r10,%r12
+ addq 104+128(%rsp),%rax
+ andq %r9,%r12
+ rorxq $41,%r9,%r13
+ rorxq $18,%r9,%rdi
+ leaq (%rbx,%r14,1),%rbx
+ leaq (%rax,%r12,1),%rax
+ andnq %r11,%r9,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r9,%r14
+ leaq (%rax,%r12,1),%rax
+ xorq %r14,%r13
+ movq %rbx,%rdi
+ rorxq $39,%rbx,%r12
+ leaq (%rax,%r13,1),%rax
+ xorq %rcx,%rdi
+ rorxq $34,%rbx,%r14
+ rorxq $28,%rbx,%r13
+ leaq (%r8,%rax,1),%r8
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rcx,%r15
+ xorq %r13,%r14
+ leaq (%rax,%r15,1),%rax
+ movq %r9,%r12
+ addq 0(%rsp),%r11
+ andq %r8,%r12
+ rorxq $41,%r8,%r13
+ rorxq $18,%r8,%r15
+ leaq (%rax,%r14,1),%rax
+ leaq (%r11,%r12,1),%r11
+ andnq %r10,%r8,%r12
+ xorq %r15,%r13
+ rorxq $14,%r8,%r14
+ leaq (%r11,%r12,1),%r11
+ xorq %r14,%r13
+ movq %rax,%r15
+ rorxq $39,%rax,%r12
+ leaq (%r11,%r13,1),%r11
+ xorq %rbx,%r15
+ rorxq $34,%rax,%r14
+ rorxq $28,%rax,%r13
+ leaq (%rdx,%r11,1),%rdx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rbx,%rdi
+ xorq %r13,%r14
+ leaq (%r11,%rdi,1),%r11
+ movq %r8,%r12
+ addq 8(%rsp),%r10
+ andq %rdx,%r12
+ rorxq $41,%rdx,%r13
+ rorxq $18,%rdx,%rdi
+ leaq (%r11,%r14,1),%r11
+ leaq (%r10,%r12,1),%r10
+ andnq %r9,%rdx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rdx,%r14
+ leaq (%r10,%r12,1),%r10
+ xorq %r14,%r13
+ movq %r11,%rdi
+ rorxq $39,%r11,%r12
+ leaq (%r10,%r13,1),%r10
+ xorq %rax,%rdi
+ rorxq $34,%r11,%r14
+ rorxq $28,%r11,%r13
+ leaq (%rcx,%r10,1),%rcx
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rax,%r15
+ xorq %r13,%r14
+ leaq (%r10,%r15,1),%r10
+ movq %rdx,%r12
+ addq 32(%rsp),%r9
+ andq %rcx,%r12
+ rorxq $41,%rcx,%r13
+ rorxq $18,%rcx,%r15
+ leaq (%r10,%r14,1),%r10
+ leaq (%r9,%r12,1),%r9
+ andnq %r8,%rcx,%r12
+ xorq %r15,%r13
+ rorxq $14,%rcx,%r14
+ leaq (%r9,%r12,1),%r9
+ xorq %r14,%r13
+ movq %r10,%r15
+ rorxq $39,%r10,%r12
+ leaq (%r9,%r13,1),%r9
+ xorq %r11,%r15
+ rorxq $34,%r10,%r14
+ rorxq $28,%r10,%r13
+ leaq (%rbx,%r9,1),%rbx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r11,%rdi
+ xorq %r13,%r14
+ leaq (%r9,%rdi,1),%r9
+ movq %rcx,%r12
+ addq 40(%rsp),%r8
+ andq %rbx,%r12
+ rorxq $41,%rbx,%r13
+ rorxq $18,%rbx,%rdi
+ leaq (%r9,%r14,1),%r9
+ leaq (%r8,%r12,1),%r8
+ andnq %rdx,%rbx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rbx,%r14
+ leaq (%r8,%r12,1),%r8
+ xorq %r14,%r13
+ movq %r9,%rdi
+ rorxq $39,%r9,%r12
+ leaq (%r8,%r13,1),%r8
+ xorq %r10,%rdi
+ rorxq $34,%r9,%r14
+ rorxq $28,%r9,%r13
+ leaq (%rax,%r8,1),%rax
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r10,%r15
+ xorq %r13,%r14
+ leaq (%r8,%r15,1),%r8
+ movq %rbx,%r12
+ addq 64(%rsp),%rdx
+ andq %rax,%r12
+ rorxq $41,%rax,%r13
+ rorxq $18,%rax,%r15
+ leaq (%r8,%r14,1),%r8
+ leaq (%rdx,%r12,1),%rdx
+ andnq %rcx,%rax,%r12
+ xorq %r15,%r13
+ rorxq $14,%rax,%r14
+ leaq (%rdx,%r12,1),%rdx
+ xorq %r14,%r13
+ movq %r8,%r15
+ rorxq $39,%r8,%r12
+ leaq (%rdx,%r13,1),%rdx
+ xorq %r9,%r15
+ rorxq $34,%r8,%r14
+ rorxq $28,%r8,%r13
+ leaq (%r11,%rdx,1),%r11
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r9,%rdi
+ xorq %r13,%r14
+ leaq (%rdx,%rdi,1),%rdx
+ movq %rax,%r12
+ addq 72(%rsp),%rcx
+ andq %r11,%r12
+ rorxq $41,%r11,%r13
+ rorxq $18,%r11,%rdi
+ leaq (%rdx,%r14,1),%rdx
+ leaq (%rcx,%r12,1),%rcx
+ andnq %rbx,%r11,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r11,%r14
+ leaq (%rcx,%r12,1),%rcx
+ xorq %r14,%r13
+ movq %rdx,%rdi
+ rorxq $39,%rdx,%r12
+ leaq (%rcx,%r13,1),%rcx
+ xorq %r8,%rdi
+ rorxq $34,%rdx,%r14
+ rorxq $28,%rdx,%r13
+ leaq (%r10,%rcx,1),%r10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r8,%r15
+ xorq %r13,%r14
+ leaq (%rcx,%r15,1),%rcx
+ movq %r11,%r12
+ addq 96(%rsp),%rbx
+ andq %r10,%r12
+ rorxq $41,%r10,%r13
+ rorxq $18,%r10,%r15
+ leaq (%rcx,%r14,1),%rcx
+ leaq (%rbx,%r12,1),%rbx
+ andnq %rax,%r10,%r12
+ xorq %r15,%r13
+ rorxq $14,%r10,%r14
+ leaq (%rbx,%r12,1),%rbx
+ xorq %r14,%r13
+ movq %rcx,%r15
+ rorxq $39,%rcx,%r12
+ leaq (%rbx,%r13,1),%rbx
+ xorq %rdx,%r15
+ rorxq $34,%rcx,%r14
+ rorxq $28,%rcx,%r13
+ leaq (%r9,%rbx,1),%r9
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rdx,%rdi
+ xorq %r13,%r14
+ leaq (%rbx,%rdi,1),%rbx
+ movq %r10,%r12
+ addq 104(%rsp),%rax
+ andq %r9,%r12
+ rorxq $41,%r9,%r13
+ rorxq $18,%r9,%rdi
+ leaq (%rbx,%r14,1),%rbx
+ leaq (%rax,%r12,1),%rax
+ andnq %r11,%r9,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r9,%r14
+ leaq (%rax,%r12,1),%rax
+ xorq %r14,%r13
+ movq %rbx,%rdi
+ rorxq $39,%rbx,%r12
+ leaq (%rax,%r13,1),%rax
+ xorq %rcx,%rdi
+ rorxq $34,%rbx,%r14
+ rorxq $28,%rbx,%r13
+ leaq (%r8,%rax,1),%r8
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rcx,%r15
+ xorq %r13,%r14
+ leaq (%rax,%r15,1),%rax
+ movq %r9,%r12
+ movq 1280(%rsp),%rdi
+ addq %r14,%rax
+
+ leaq 1152(%rsp),%rbp
+
+ addq 0(%rdi),%rax
+ addq 8(%rdi),%rbx
+ addq 16(%rdi),%rcx
+ addq 24(%rdi),%rdx
+ addq 32(%rdi),%r8
+ addq 40(%rdi),%r9
+ addq 48(%rdi),%r10
+ addq 56(%rdi),%r11
+
+ movq %rax,0(%rdi)
+ movq %rbx,8(%rdi)
+ movq %rcx,16(%rdi)
+ movq %rdx,24(%rdi)
+ movq %r8,32(%rdi)
+ movq %r9,40(%rdi)
+ movq %r10,48(%rdi)
+ movq %r11,56(%rdi)
+
+ cmpq 144(%rbp),%rsi
+ je .Ldone_avx2
+
+ xorq %r14,%r14
+ movq %rbx,%rdi
+ xorq %rcx,%rdi
+ movq %r9,%r12
+ jmp .Lower_avx2
+.balign 16
+.Lower_avx2:
+ addq 0+16(%rbp),%r11
+ andq %r8,%r12
+ rorxq $41,%r8,%r13
+ rorxq $18,%r8,%r15
+ leaq (%rax,%r14,1),%rax
+ leaq (%r11,%r12,1),%r11
+ andnq %r10,%r8,%r12
+ xorq %r15,%r13
+ rorxq $14,%r8,%r14
+ leaq (%r11,%r12,1),%r11
+ xorq %r14,%r13
+ movq %rax,%r15
+ rorxq $39,%rax,%r12
+ leaq (%r11,%r13,1),%r11
+ xorq %rbx,%r15
+ rorxq $34,%rax,%r14
+ rorxq $28,%rax,%r13
+ leaq (%rdx,%r11,1),%rdx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rbx,%rdi
+ xorq %r13,%r14
+ leaq (%r11,%rdi,1),%r11
+ movq %r8,%r12
+ addq 8+16(%rbp),%r10
+ andq %rdx,%r12
+ rorxq $41,%rdx,%r13
+ rorxq $18,%rdx,%rdi
+ leaq (%r11,%r14,1),%r11
+ leaq (%r10,%r12,1),%r10
+ andnq %r9,%rdx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rdx,%r14
+ leaq (%r10,%r12,1),%r10
+ xorq %r14,%r13
+ movq %r11,%rdi
+ rorxq $39,%r11,%r12
+ leaq (%r10,%r13,1),%r10
+ xorq %rax,%rdi
+ rorxq $34,%r11,%r14
+ rorxq $28,%r11,%r13
+ leaq (%rcx,%r10,1),%rcx
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rax,%r15
+ xorq %r13,%r14
+ leaq (%r10,%r15,1),%r10
+ movq %rdx,%r12
+ addq 32+16(%rbp),%r9
+ andq %rcx,%r12
+ rorxq $41,%rcx,%r13
+ rorxq $18,%rcx,%r15
+ leaq (%r10,%r14,1),%r10
+ leaq (%r9,%r12,1),%r9
+ andnq %r8,%rcx,%r12
+ xorq %r15,%r13
+ rorxq $14,%rcx,%r14
+ leaq (%r9,%r12,1),%r9
+ xorq %r14,%r13
+ movq %r10,%r15
+ rorxq $39,%r10,%r12
+ leaq (%r9,%r13,1),%r9
+ xorq %r11,%r15
+ rorxq $34,%r10,%r14
+ rorxq $28,%r10,%r13
+ leaq (%rbx,%r9,1),%rbx
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r11,%rdi
+ xorq %r13,%r14
+ leaq (%r9,%rdi,1),%r9
+ movq %rcx,%r12
+ addq 40+16(%rbp),%r8
+ andq %rbx,%r12
+ rorxq $41,%rbx,%r13
+ rorxq $18,%rbx,%rdi
+ leaq (%r9,%r14,1),%r9
+ leaq (%r8,%r12,1),%r8
+ andnq %rdx,%rbx,%r12
+ xorq %rdi,%r13
+ rorxq $14,%rbx,%r14
+ leaq (%r8,%r12,1),%r8
+ xorq %r14,%r13
+ movq %r9,%rdi
+ rorxq $39,%r9,%r12
+ leaq (%r8,%r13,1),%r8
+ xorq %r10,%rdi
+ rorxq $34,%r9,%r14
+ rorxq $28,%r9,%r13
+ leaq (%rax,%r8,1),%rax
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r10,%r15
+ xorq %r13,%r14
+ leaq (%r8,%r15,1),%r8
+ movq %rbx,%r12
+ addq 64+16(%rbp),%rdx
+ andq %rax,%r12
+ rorxq $41,%rax,%r13
+ rorxq $18,%rax,%r15
+ leaq (%r8,%r14,1),%r8
+ leaq (%rdx,%r12,1),%rdx
+ andnq %rcx,%rax,%r12
+ xorq %r15,%r13
+ rorxq $14,%rax,%r14
+ leaq (%rdx,%r12,1),%rdx
+ xorq %r14,%r13
+ movq %r8,%r15
+ rorxq $39,%r8,%r12
+ leaq (%rdx,%r13,1),%rdx
+ xorq %r9,%r15
+ rorxq $34,%r8,%r14
+ rorxq $28,%r8,%r13
+ leaq (%r11,%rdx,1),%r11
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %r9,%rdi
+ xorq %r13,%r14
+ leaq (%rdx,%rdi,1),%rdx
+ movq %rax,%r12
+ addq 72+16(%rbp),%rcx
+ andq %r11,%r12
+ rorxq $41,%r11,%r13
+ rorxq $18,%r11,%rdi
+ leaq (%rdx,%r14,1),%rdx
+ leaq (%rcx,%r12,1),%rcx
+ andnq %rbx,%r11,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r11,%r14
+ leaq (%rcx,%r12,1),%rcx
+ xorq %r14,%r13
+ movq %rdx,%rdi
+ rorxq $39,%rdx,%r12
+ leaq (%rcx,%r13,1),%rcx
+ xorq %r8,%rdi
+ rorxq $34,%rdx,%r14
+ rorxq $28,%rdx,%r13
+ leaq (%r10,%rcx,1),%r10
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %r8,%r15
+ xorq %r13,%r14
+ leaq (%rcx,%r15,1),%rcx
+ movq %r11,%r12
+ addq 96+16(%rbp),%rbx
+ andq %r10,%r12
+ rorxq $41,%r10,%r13
+ rorxq $18,%r10,%r15
+ leaq (%rcx,%r14,1),%rcx
+ leaq (%rbx,%r12,1),%rbx
+ andnq %rax,%r10,%r12
+ xorq %r15,%r13
+ rorxq $14,%r10,%r14
+ leaq (%rbx,%r12,1),%rbx
+ xorq %r14,%r13
+ movq %rcx,%r15
+ rorxq $39,%rcx,%r12
+ leaq (%rbx,%r13,1),%rbx
+ xorq %rdx,%r15
+ rorxq $34,%rcx,%r14
+ rorxq $28,%rcx,%r13
+ leaq (%r9,%rbx,1),%r9
+ andq %r15,%rdi
+ xorq %r12,%r14
+ xorq %rdx,%rdi
+ xorq %r13,%r14
+ leaq (%rbx,%rdi,1),%rbx
+ movq %r10,%r12
+ addq 104+16(%rbp),%rax
+ andq %r9,%r12
+ rorxq $41,%r9,%r13
+ rorxq $18,%r9,%rdi
+ leaq (%rbx,%r14,1),%rbx
+ leaq (%rax,%r12,1),%rax
+ andnq %r11,%r9,%r12
+ xorq %rdi,%r13
+ rorxq $14,%r9,%r14
+ leaq (%rax,%r12,1),%rax
+ xorq %r14,%r13
+ movq %rbx,%rdi
+ rorxq $39,%rbx,%r12
+ leaq (%rax,%r13,1),%rax
+ xorq %rcx,%rdi
+ rorxq $34,%rbx,%r14
+ rorxq $28,%rbx,%r13
+ leaq (%r8,%rax,1),%r8
+ andq %rdi,%r15
+ xorq %r12,%r14
+ xorq %rcx,%r15
+ xorq %r13,%r14
+ leaq (%rax,%r15,1),%rax
+ movq %r9,%r12
+ leaq -128(%rbp),%rbp
+ cmpq %rsp,%rbp
+ jae .Lower_avx2
+
+ movq 1280(%rsp),%rdi
+ addq %r14,%rax
+
+ leaq 1152(%rsp),%rsp
+
+.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08
+
+ addq 0(%rdi),%rax
+ addq 8(%rdi),%rbx
+ addq 16(%rdi),%rcx
+ addq 24(%rdi),%rdx
+ addq 32(%rdi),%r8
+ addq 40(%rdi),%r9
+ leaq 256(%rsi),%rsi
+ addq 48(%rdi),%r10
+ movq %rsi,%r12
+ addq 56(%rdi),%r11
+ cmpq 128+16(%rsp),%rsi
+
+ movq %rax,0(%rdi)
+ cmoveq %rsp,%r12
+ movq %rbx,8(%rdi)
+ movq %rcx,16(%rdi)
+ movq %rdx,24(%rdi)
+ movq %r8,32(%rdi)
+ movq %r9,40(%rdi)
+ movq %r10,48(%rdi)
+ movq %r11,56(%rdi)
+
+ jbe .Loop_avx2
+ leaq (%rsp),%rbp
+
+.cfi_escape 0x0f,0x06,0x76,0x98,0x01,0x06,0x23,0x08
+
+.Ldone_avx2:
+ movq 152(%rbp),%rsi
+.cfi_def_cfa %rsi,8
+ vzeroupper
+ movq -48(%rsi),%r15
+.cfi_restore %r15
+ movq -40(%rsi),%r14
+.cfi_restore %r14
+ movq -32(%rsi),%r13
+.cfi_restore %r13
+ movq -24(%rsi),%r12
+.cfi_restore %r12
+ movq -16(%rsi),%rbp
+.cfi_restore %rbp
+ movq -8(%rsi),%rbx
+.cfi_restore %rbx
+ leaq (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lepilogue_avx2:
+ RET
+.cfi_endproc
+SET_SIZE(zfs_sha512_transform_avx2)
+
+#if defined(__ELF__)
+ .section .note.GNU-stack,"",%progbits
+#endif
+#endif
diff --git a/module/icp/asm-x86_64/sha2/sha512_impl.S b/module/icp/asm-x86_64/sha2/sha512_impl.S
deleted file mode 100644
index e61e96957bc6..000000000000
--- a/module/icp/asm-x86_64/sha2/sha512_impl.S
+++ /dev/null
@@ -1,2114 +0,0 @@
-/*
- * ====================================================================
- * Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
- * project. Rights for redistribution and usage in source and binary
- * forms are granted according to the OpenSSL license.
- * ====================================================================
- *
- * sha256/512_block procedure for x86_64.
- *
- * 40% improvement over compiler-generated code on Opteron. On EM64T
- * sha256 was observed to run >80% faster and sha512 - >40%. No magical
- * tricks, just straight implementation... I really wonder why gcc
- * [being armed with inline assembler] fails to generate as fast code.
- * The only thing which is cool about this module is that it's very
- * same instruction sequence used for both SHA-256 and SHA-512. In
- * former case the instructions operate on 32-bit operands, while in
- * latter - on 64-bit ones. All I had to do is to get one flavor right,
- * the other one passed the test right away:-)
- *
- * sha256_block runs in ~1005 cycles on Opteron, which gives you
- * asymptotic performance of 64*1000/1005=63.7MBps times CPU clock
- * frequency in GHz. sha512_block runs in ~1275 cycles, which results
- * in 128*1000/1275=100MBps per GHz. Is there room for improvement?
- * Well, if you compare it to IA-64 implementation, which maintains
- * X[16] in register bank[!], tends to 4 instructions per CPU clock
- * cycle and runs in 1003 cycles, 1275 is very good result for 3-way
- * issue Opteron pipeline and X[16] maintained in memory. So that *if*
- * there is a way to improve it, *then* the only way would be to try to
- * offload X[16] updates to SSE unit, but that would require "deeper"
- * loop unroll, which in turn would naturally cause size blow-up, not
- * to mention increased complexity! And once again, only *if* it's
- * actually possible to noticeably improve overall ILP, instruction
- * level parallelism, on a given CPU implementation in this case.
- *
- * Special note on Intel EM64T. While Opteron CPU exhibits perfect
- * performance ratio of 1.5 between 64- and 32-bit flavors [see above],
- * [currently available] EM64T CPUs apparently are far from it. On the
- * contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit
- * sha256_block:-( This is presumably because 64-bit shifts/rotates
- * apparently are not atomic instructions, but implemented in microcode.
- */
-
-/*
- * OpenSolaris OS modifications
- *
- * Sun elects to use this software under the BSD license.
- *
- * This source originates from OpenSSL file sha512-x86_64.pl at
- * ftp://ftp.openssl.org/snapshot/openssl-0.9.8-stable-SNAP-20080131.tar.gz
- * (presumably for future OpenSSL release 0.9.8h), with these changes:
- *
- * 1. Added perl "use strict" and declared variables.
- *
- * 2. Added OpenSolaris ENTRY_NP/SET_SIZE macros from
- * /usr/include/sys/asm_linkage.h, .ident keywords, and lint(1B) guards.
- *
- * 3. Removed x86_64-xlate.pl script (not needed for as(1) or gas(1)
- * assemblers). Replaced the .picmeup macro with assembler code.
- *
- * 4. Added 8 to $ctx, as OpenSolaris OS has an extra 4-byte field, "algotype",
- * at the beginning of SHA2_CTX (the next field is 8-byte aligned).
- */
-
-/*
- * This file was generated by a perl script (sha512-x86_64.pl) that were
- * used to generate sha256 and sha512 variants from the same code base.
- * The comments from the original file have been pasted above.
- */
-
-
-#if defined(lint) || defined(__lint)
-#include <sys/stdint.h>
-#include <sha2/sha2.h>
-
-void
-SHA512TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num)
-{
- (void) ctx, (void) in, (void) num;
-}
-
-
-#else
-#define _ASM
-#include <sys/asm_linkage.h>
-
-ENTRY_NP(SHA512TransformBlocks)
-.cfi_startproc
- movq %rsp, %rax
-.cfi_def_cfa_register %rax
- push %rbx
-.cfi_offset %rbx,-16
- push %rbp
-.cfi_offset %rbp,-24
- push %r12
-.cfi_offset %r12,-32
- push %r13
-.cfi_offset %r13,-40
- push %r14
-.cfi_offset %r14,-48
- push %r15
-.cfi_offset %r15,-56
- mov %rsp,%rbp # copy %rsp
- shl $4,%rdx # num*16
- sub $16*8+4*8,%rsp
- lea (%rsi,%rdx,8),%rdx # inp+num*16*8
- and $-64,%rsp # align stack frame
- add $8,%rdi # Skip OpenSolaris field, "algotype"
- mov %rdi,16*8+0*8(%rsp) # save ctx, 1st arg
- mov %rsi,16*8+1*8(%rsp) # save inp, 2nd arg
- mov %rdx,16*8+2*8(%rsp) # save end pointer, "3rd" arg
- mov %rbp,16*8+3*8(%rsp) # save copy of %rsp
-# echo ".cfi_cfa_expression %rsp+152,deref,+56" |
-# openssl/crypto/perlasm/x86_64-xlate.pl
-.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x38
-
- #.picmeup %rbp
- # The .picmeup pseudo-directive, from perlasm/x86_64_xlate.pl, puts
- # the address of the "next" instruction into the target register
- # (%rbp). This generates these 2 instructions:
- lea .Llea(%rip),%rbp
- #nop # .picmeup generates a nop for mod 8 alignment--not needed here
-
-.Llea:
- lea K512-.(%rbp),%rbp
-
- mov 8*0(%rdi),%rax
- mov 8*1(%rdi),%rbx
- mov 8*2(%rdi),%rcx
- mov 8*3(%rdi),%rdx
- mov 8*4(%rdi),%r8
- mov 8*5(%rdi),%r9
- mov 8*6(%rdi),%r10
- mov 8*7(%rdi),%r11
- jmp .Lloop
-
-.align 16
-.Lloop:
- xor %rdi,%rdi
- mov 8*0(%rsi),%r12
- bswap %r12
- mov %r8,%r13
- mov %r8,%r14
- mov %r9,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r10,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r8,%r15 # (f^g)&e
- mov %r12,0(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r10,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r11,%r12 # T1+=h
-
- mov %rax,%r11
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rax,%r13
- mov %rax,%r14
-
- ror $28,%r11
- ror $34,%r13
- mov %rax,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r11
- ror $5,%r13
- or %rcx,%r14 # a|c
-
- xor %r13,%r11 # h=Sigma0(a)
- and %rcx,%r15 # a&c
- add %r12,%rdx # d+=T1
-
- and %rbx,%r14 # (a|c)&b
- add %r12,%r11 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r11 # h+=Maj(a,b,c)
- mov 8*1(%rsi),%r12
- bswap %r12
- mov %rdx,%r13
- mov %rdx,%r14
- mov %r8,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r9,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rdx,%r15 # (f^g)&e
- mov %r12,8(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r9,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r10,%r12 # T1+=h
-
- mov %r11,%r10
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r11,%r13
- mov %r11,%r14
-
- ror $28,%r10
- ror $34,%r13
- mov %r11,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r10
- ror $5,%r13
- or %rbx,%r14 # a|c
-
- xor %r13,%r10 # h=Sigma0(a)
- and %rbx,%r15 # a&c
- add %r12,%rcx # d+=T1
-
- and %rax,%r14 # (a|c)&b
- add %r12,%r10 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r10 # h+=Maj(a,b,c)
- mov 8*2(%rsi),%r12
- bswap %r12
- mov %rcx,%r13
- mov %rcx,%r14
- mov %rdx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r8,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rcx,%r15 # (f^g)&e
- mov %r12,16(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r8,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r9,%r12 # T1+=h
-
- mov %r10,%r9
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r10,%r13
- mov %r10,%r14
-
- ror $28,%r9
- ror $34,%r13
- mov %r10,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r9
- ror $5,%r13
- or %rax,%r14 # a|c
-
- xor %r13,%r9 # h=Sigma0(a)
- and %rax,%r15 # a&c
- add %r12,%rbx # d+=T1
-
- and %r11,%r14 # (a|c)&b
- add %r12,%r9 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r9 # h+=Maj(a,b,c)
- mov 8*3(%rsi),%r12
- bswap %r12
- mov %rbx,%r13
- mov %rbx,%r14
- mov %rcx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rdx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rbx,%r15 # (f^g)&e
- mov %r12,24(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rdx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r8,%r12 # T1+=h
-
- mov %r9,%r8
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r9,%r13
- mov %r9,%r14
-
- ror $28,%r8
- ror $34,%r13
- mov %r9,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r8
- ror $5,%r13
- or %r11,%r14 # a|c
-
- xor %r13,%r8 # h=Sigma0(a)
- and %r11,%r15 # a&c
- add %r12,%rax # d+=T1
-
- and %r10,%r14 # (a|c)&b
- add %r12,%r8 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r8 # h+=Maj(a,b,c)
- mov 8*4(%rsi),%r12
- bswap %r12
- mov %rax,%r13
- mov %rax,%r14
- mov %rbx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rcx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rax,%r15 # (f^g)&e
- mov %r12,32(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rcx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rdx,%r12 # T1+=h
-
- mov %r8,%rdx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r8,%r13
- mov %r8,%r14
-
- ror $28,%rdx
- ror $34,%r13
- mov %r8,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rdx
- ror $5,%r13
- or %r10,%r14 # a|c
-
- xor %r13,%rdx # h=Sigma0(a)
- and %r10,%r15 # a&c
- add %r12,%r11 # d+=T1
-
- and %r9,%r14 # (a|c)&b
- add %r12,%rdx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rdx # h+=Maj(a,b,c)
- mov 8*5(%rsi),%r12
- bswap %r12
- mov %r11,%r13
- mov %r11,%r14
- mov %rax,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rbx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r11,%r15 # (f^g)&e
- mov %r12,40(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rbx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rcx,%r12 # T1+=h
-
- mov %rdx,%rcx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rdx,%r13
- mov %rdx,%r14
-
- ror $28,%rcx
- ror $34,%r13
- mov %rdx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rcx
- ror $5,%r13
- or %r9,%r14 # a|c
-
- xor %r13,%rcx # h=Sigma0(a)
- and %r9,%r15 # a&c
- add %r12,%r10 # d+=T1
-
- and %r8,%r14 # (a|c)&b
- add %r12,%rcx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rcx # h+=Maj(a,b,c)
- mov 8*6(%rsi),%r12
- bswap %r12
- mov %r10,%r13
- mov %r10,%r14
- mov %r11,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rax,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r10,%r15 # (f^g)&e
- mov %r12,48(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rax,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rbx,%r12 # T1+=h
-
- mov %rcx,%rbx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rcx,%r13
- mov %rcx,%r14
-
- ror $28,%rbx
- ror $34,%r13
- mov %rcx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rbx
- ror $5,%r13
- or %r8,%r14 # a|c
-
- xor %r13,%rbx # h=Sigma0(a)
- and %r8,%r15 # a&c
- add %r12,%r9 # d+=T1
-
- and %rdx,%r14 # (a|c)&b
- add %r12,%rbx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rbx # h+=Maj(a,b,c)
- mov 8*7(%rsi),%r12
- bswap %r12
- mov %r9,%r13
- mov %r9,%r14
- mov %r10,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r11,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r9,%r15 # (f^g)&e
- mov %r12,56(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r11,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rax,%r12 # T1+=h
-
- mov %rbx,%rax
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rbx,%r13
- mov %rbx,%r14
-
- ror $28,%rax
- ror $34,%r13
- mov %rbx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rax
- ror $5,%r13
- or %rdx,%r14 # a|c
-
- xor %r13,%rax # h=Sigma0(a)
- and %rdx,%r15 # a&c
- add %r12,%r8 # d+=T1
-
- and %rcx,%r14 # (a|c)&b
- add %r12,%rax # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rax # h+=Maj(a,b,c)
- mov 8*8(%rsi),%r12
- bswap %r12
- mov %r8,%r13
- mov %r8,%r14
- mov %r9,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r10,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r8,%r15 # (f^g)&e
- mov %r12,64(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r10,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r11,%r12 # T1+=h
-
- mov %rax,%r11
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rax,%r13
- mov %rax,%r14
-
- ror $28,%r11
- ror $34,%r13
- mov %rax,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r11
- ror $5,%r13
- or %rcx,%r14 # a|c
-
- xor %r13,%r11 # h=Sigma0(a)
- and %rcx,%r15 # a&c
- add %r12,%rdx # d+=T1
-
- and %rbx,%r14 # (a|c)&b
- add %r12,%r11 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r11 # h+=Maj(a,b,c)
- mov 8*9(%rsi),%r12
- bswap %r12
- mov %rdx,%r13
- mov %rdx,%r14
- mov %r8,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r9,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rdx,%r15 # (f^g)&e
- mov %r12,72(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r9,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r10,%r12 # T1+=h
-
- mov %r11,%r10
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r11,%r13
- mov %r11,%r14
-
- ror $28,%r10
- ror $34,%r13
- mov %r11,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r10
- ror $5,%r13
- or %rbx,%r14 # a|c
-
- xor %r13,%r10 # h=Sigma0(a)
- and %rbx,%r15 # a&c
- add %r12,%rcx # d+=T1
-
- and %rax,%r14 # (a|c)&b
- add %r12,%r10 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r10 # h+=Maj(a,b,c)
- mov 8*10(%rsi),%r12
- bswap %r12
- mov %rcx,%r13
- mov %rcx,%r14
- mov %rdx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r8,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rcx,%r15 # (f^g)&e
- mov %r12,80(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r8,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r9,%r12 # T1+=h
-
- mov %r10,%r9
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r10,%r13
- mov %r10,%r14
-
- ror $28,%r9
- ror $34,%r13
- mov %r10,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r9
- ror $5,%r13
- or %rax,%r14 # a|c
-
- xor %r13,%r9 # h=Sigma0(a)
- and %rax,%r15 # a&c
- add %r12,%rbx # d+=T1
-
- and %r11,%r14 # (a|c)&b
- add %r12,%r9 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r9 # h+=Maj(a,b,c)
- mov 8*11(%rsi),%r12
- bswap %r12
- mov %rbx,%r13
- mov %rbx,%r14
- mov %rcx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rdx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rbx,%r15 # (f^g)&e
- mov %r12,88(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rdx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r8,%r12 # T1+=h
-
- mov %r9,%r8
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r9,%r13
- mov %r9,%r14
-
- ror $28,%r8
- ror $34,%r13
- mov %r9,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r8
- ror $5,%r13
- or %r11,%r14 # a|c
-
- xor %r13,%r8 # h=Sigma0(a)
- and %r11,%r15 # a&c
- add %r12,%rax # d+=T1
-
- and %r10,%r14 # (a|c)&b
- add %r12,%r8 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r8 # h+=Maj(a,b,c)
- mov 8*12(%rsi),%r12
- bswap %r12
- mov %rax,%r13
- mov %rax,%r14
- mov %rbx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rcx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rax,%r15 # (f^g)&e
- mov %r12,96(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rcx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rdx,%r12 # T1+=h
-
- mov %r8,%rdx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r8,%r13
- mov %r8,%r14
-
- ror $28,%rdx
- ror $34,%r13
- mov %r8,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rdx
- ror $5,%r13
- or %r10,%r14 # a|c
-
- xor %r13,%rdx # h=Sigma0(a)
- and %r10,%r15 # a&c
- add %r12,%r11 # d+=T1
-
- and %r9,%r14 # (a|c)&b
- add %r12,%rdx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rdx # h+=Maj(a,b,c)
- mov 8*13(%rsi),%r12
- bswap %r12
- mov %r11,%r13
- mov %r11,%r14
- mov %rax,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rbx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r11,%r15 # (f^g)&e
- mov %r12,104(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rbx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rcx,%r12 # T1+=h
-
- mov %rdx,%rcx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rdx,%r13
- mov %rdx,%r14
-
- ror $28,%rcx
- ror $34,%r13
- mov %rdx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rcx
- ror $5,%r13
- or %r9,%r14 # a|c
-
- xor %r13,%rcx # h=Sigma0(a)
- and %r9,%r15 # a&c
- add %r12,%r10 # d+=T1
-
- and %r8,%r14 # (a|c)&b
- add %r12,%rcx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rcx # h+=Maj(a,b,c)
- mov 8*14(%rsi),%r12
- bswap %r12
- mov %r10,%r13
- mov %r10,%r14
- mov %r11,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rax,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r10,%r15 # (f^g)&e
- mov %r12,112(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rax,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rbx,%r12 # T1+=h
-
- mov %rcx,%rbx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rcx,%r13
- mov %rcx,%r14
-
- ror $28,%rbx
- ror $34,%r13
- mov %rcx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rbx
- ror $5,%r13
- or %r8,%r14 # a|c
-
- xor %r13,%rbx # h=Sigma0(a)
- and %r8,%r15 # a&c
- add %r12,%r9 # d+=T1
-
- and %rdx,%r14 # (a|c)&b
- add %r12,%rbx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rbx # h+=Maj(a,b,c)
- mov 8*15(%rsi),%r12
- bswap %r12
- mov %r9,%r13
- mov %r9,%r14
- mov %r10,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r11,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r9,%r15 # (f^g)&e
- mov %r12,120(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r11,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rax,%r12 # T1+=h
-
- mov %rbx,%rax
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rbx,%r13
- mov %rbx,%r14
-
- ror $28,%rax
- ror $34,%r13
- mov %rbx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rax
- ror $5,%r13
- or %rdx,%r14 # a|c
-
- xor %r13,%rax # h=Sigma0(a)
- and %rdx,%r15 # a&c
- add %r12,%r8 # d+=T1
-
- and %rcx,%r14 # (a|c)&b
- add %r12,%rax # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rax # h+=Maj(a,b,c)
- jmp .Lrounds_16_xx
-.align 16
-.Lrounds_16_xx:
- mov 8(%rsp),%r13
- mov 112(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 72(%rsp),%r12
-
- add 0(%rsp),%r12
- mov %r8,%r13
- mov %r8,%r14
- mov %r9,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r10,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r8,%r15 # (f^g)&e
- mov %r12,0(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r10,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r11,%r12 # T1+=h
-
- mov %rax,%r11
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rax,%r13
- mov %rax,%r14
-
- ror $28,%r11
- ror $34,%r13
- mov %rax,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r11
- ror $5,%r13
- or %rcx,%r14 # a|c
-
- xor %r13,%r11 # h=Sigma0(a)
- and %rcx,%r15 # a&c
- add %r12,%rdx # d+=T1
-
- and %rbx,%r14 # (a|c)&b
- add %r12,%r11 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r11 # h+=Maj(a,b,c)
- mov 16(%rsp),%r13
- mov 120(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 80(%rsp),%r12
-
- add 8(%rsp),%r12
- mov %rdx,%r13
- mov %rdx,%r14
- mov %r8,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r9,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rdx,%r15 # (f^g)&e
- mov %r12,8(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r9,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r10,%r12 # T1+=h
-
- mov %r11,%r10
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r11,%r13
- mov %r11,%r14
-
- ror $28,%r10
- ror $34,%r13
- mov %r11,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r10
- ror $5,%r13
- or %rbx,%r14 # a|c
-
- xor %r13,%r10 # h=Sigma0(a)
- and %rbx,%r15 # a&c
- add %r12,%rcx # d+=T1
-
- and %rax,%r14 # (a|c)&b
- add %r12,%r10 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r10 # h+=Maj(a,b,c)
- mov 24(%rsp),%r13
- mov 0(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 88(%rsp),%r12
-
- add 16(%rsp),%r12
- mov %rcx,%r13
- mov %rcx,%r14
- mov %rdx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r8,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rcx,%r15 # (f^g)&e
- mov %r12,16(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r8,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r9,%r12 # T1+=h
-
- mov %r10,%r9
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r10,%r13
- mov %r10,%r14
-
- ror $28,%r9
- ror $34,%r13
- mov %r10,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r9
- ror $5,%r13
- or %rax,%r14 # a|c
-
- xor %r13,%r9 # h=Sigma0(a)
- and %rax,%r15 # a&c
- add %r12,%rbx # d+=T1
-
- and %r11,%r14 # (a|c)&b
- add %r12,%r9 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r9 # h+=Maj(a,b,c)
- mov 32(%rsp),%r13
- mov 8(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 96(%rsp),%r12
-
- add 24(%rsp),%r12
- mov %rbx,%r13
- mov %rbx,%r14
- mov %rcx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rdx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rbx,%r15 # (f^g)&e
- mov %r12,24(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rdx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r8,%r12 # T1+=h
-
- mov %r9,%r8
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r9,%r13
- mov %r9,%r14
-
- ror $28,%r8
- ror $34,%r13
- mov %r9,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r8
- ror $5,%r13
- or %r11,%r14 # a|c
-
- xor %r13,%r8 # h=Sigma0(a)
- and %r11,%r15 # a&c
- add %r12,%rax # d+=T1
-
- and %r10,%r14 # (a|c)&b
- add %r12,%r8 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r8 # h+=Maj(a,b,c)
- mov 40(%rsp),%r13
- mov 16(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 104(%rsp),%r12
-
- add 32(%rsp),%r12
- mov %rax,%r13
- mov %rax,%r14
- mov %rbx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rcx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rax,%r15 # (f^g)&e
- mov %r12,32(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rcx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rdx,%r12 # T1+=h
-
- mov %r8,%rdx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r8,%r13
- mov %r8,%r14
-
- ror $28,%rdx
- ror $34,%r13
- mov %r8,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rdx
- ror $5,%r13
- or %r10,%r14 # a|c
-
- xor %r13,%rdx # h=Sigma0(a)
- and %r10,%r15 # a&c
- add %r12,%r11 # d+=T1
-
- and %r9,%r14 # (a|c)&b
- add %r12,%rdx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rdx # h+=Maj(a,b,c)
- mov 48(%rsp),%r13
- mov 24(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 112(%rsp),%r12
-
- add 40(%rsp),%r12
- mov %r11,%r13
- mov %r11,%r14
- mov %rax,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rbx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r11,%r15 # (f^g)&e
- mov %r12,40(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rbx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rcx,%r12 # T1+=h
-
- mov %rdx,%rcx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rdx,%r13
- mov %rdx,%r14
-
- ror $28,%rcx
- ror $34,%r13
- mov %rdx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rcx
- ror $5,%r13
- or %r9,%r14 # a|c
-
- xor %r13,%rcx # h=Sigma0(a)
- and %r9,%r15 # a&c
- add %r12,%r10 # d+=T1
-
- and %r8,%r14 # (a|c)&b
- add %r12,%rcx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rcx # h+=Maj(a,b,c)
- mov 56(%rsp),%r13
- mov 32(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 120(%rsp),%r12
-
- add 48(%rsp),%r12
- mov %r10,%r13
- mov %r10,%r14
- mov %r11,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rax,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r10,%r15 # (f^g)&e
- mov %r12,48(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rax,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rbx,%r12 # T1+=h
-
- mov %rcx,%rbx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rcx,%r13
- mov %rcx,%r14
-
- ror $28,%rbx
- ror $34,%r13
- mov %rcx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rbx
- ror $5,%r13
- or %r8,%r14 # a|c
-
- xor %r13,%rbx # h=Sigma0(a)
- and %r8,%r15 # a&c
- add %r12,%r9 # d+=T1
-
- and %rdx,%r14 # (a|c)&b
- add %r12,%rbx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rbx # h+=Maj(a,b,c)
- mov 64(%rsp),%r13
- mov 40(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 0(%rsp),%r12
-
- add 56(%rsp),%r12
- mov %r9,%r13
- mov %r9,%r14
- mov %r10,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r11,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r9,%r15 # (f^g)&e
- mov %r12,56(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r11,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rax,%r12 # T1+=h
-
- mov %rbx,%rax
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rbx,%r13
- mov %rbx,%r14
-
- ror $28,%rax
- ror $34,%r13
- mov %rbx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rax
- ror $5,%r13
- or %rdx,%r14 # a|c
-
- xor %r13,%rax # h=Sigma0(a)
- and %rdx,%r15 # a&c
- add %r12,%r8 # d+=T1
-
- and %rcx,%r14 # (a|c)&b
- add %r12,%rax # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rax # h+=Maj(a,b,c)
- mov 72(%rsp),%r13
- mov 48(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 8(%rsp),%r12
-
- add 64(%rsp),%r12
- mov %r8,%r13
- mov %r8,%r14
- mov %r9,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r10,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r8,%r15 # (f^g)&e
- mov %r12,64(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r10,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r11,%r12 # T1+=h
-
- mov %rax,%r11
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rax,%r13
- mov %rax,%r14
-
- ror $28,%r11
- ror $34,%r13
- mov %rax,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r11
- ror $5,%r13
- or %rcx,%r14 # a|c
-
- xor %r13,%r11 # h=Sigma0(a)
- and %rcx,%r15 # a&c
- add %r12,%rdx # d+=T1
-
- and %rbx,%r14 # (a|c)&b
- add %r12,%r11 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r11 # h+=Maj(a,b,c)
- mov 80(%rsp),%r13
- mov 56(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 16(%rsp),%r12
-
- add 72(%rsp),%r12
- mov %rdx,%r13
- mov %rdx,%r14
- mov %r8,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r9,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rdx,%r15 # (f^g)&e
- mov %r12,72(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r9,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r10,%r12 # T1+=h
-
- mov %r11,%r10
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r11,%r13
- mov %r11,%r14
-
- ror $28,%r10
- ror $34,%r13
- mov %r11,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r10
- ror $5,%r13
- or %rbx,%r14 # a|c
-
- xor %r13,%r10 # h=Sigma0(a)
- and %rbx,%r15 # a&c
- add %r12,%rcx # d+=T1
-
- and %rax,%r14 # (a|c)&b
- add %r12,%r10 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r10 # h+=Maj(a,b,c)
- mov 88(%rsp),%r13
- mov 64(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 24(%rsp),%r12
-
- add 80(%rsp),%r12
- mov %rcx,%r13
- mov %rcx,%r14
- mov %rdx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r8,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rcx,%r15 # (f^g)&e
- mov %r12,80(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r8,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r9,%r12 # T1+=h
-
- mov %r10,%r9
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r10,%r13
- mov %r10,%r14
-
- ror $28,%r9
- ror $34,%r13
- mov %r10,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r9
- ror $5,%r13
- or %rax,%r14 # a|c
-
- xor %r13,%r9 # h=Sigma0(a)
- and %rax,%r15 # a&c
- add %r12,%rbx # d+=T1
-
- and %r11,%r14 # (a|c)&b
- add %r12,%r9 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r9 # h+=Maj(a,b,c)
- mov 96(%rsp),%r13
- mov 72(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 32(%rsp),%r12
-
- add 88(%rsp),%r12
- mov %rbx,%r13
- mov %rbx,%r14
- mov %rcx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rdx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rbx,%r15 # (f^g)&e
- mov %r12,88(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rdx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %r8,%r12 # T1+=h
-
- mov %r9,%r8
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r9,%r13
- mov %r9,%r14
-
- ror $28,%r8
- ror $34,%r13
- mov %r9,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%r8
- ror $5,%r13
- or %r11,%r14 # a|c
-
- xor %r13,%r8 # h=Sigma0(a)
- and %r11,%r15 # a&c
- add %r12,%rax # d+=T1
-
- and %r10,%r14 # (a|c)&b
- add %r12,%r8 # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%r8 # h+=Maj(a,b,c)
- mov 104(%rsp),%r13
- mov 80(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 40(%rsp),%r12
-
- add 96(%rsp),%r12
- mov %rax,%r13
- mov %rax,%r14
- mov %rbx,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rcx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %rax,%r15 # (f^g)&e
- mov %r12,96(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rcx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rdx,%r12 # T1+=h
-
- mov %r8,%rdx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %r8,%r13
- mov %r8,%r14
-
- ror $28,%rdx
- ror $34,%r13
- mov %r8,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rdx
- ror $5,%r13
- or %r10,%r14 # a|c
-
- xor %r13,%rdx # h=Sigma0(a)
- and %r10,%r15 # a&c
- add %r12,%r11 # d+=T1
-
- and %r9,%r14 # (a|c)&b
- add %r12,%rdx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rdx # h+=Maj(a,b,c)
- mov 112(%rsp),%r13
- mov 88(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 48(%rsp),%r12
-
- add 104(%rsp),%r12
- mov %r11,%r13
- mov %r11,%r14
- mov %rax,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rbx,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r11,%r15 # (f^g)&e
- mov %r12,104(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rbx,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rcx,%r12 # T1+=h
-
- mov %rdx,%rcx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rdx,%r13
- mov %rdx,%r14
-
- ror $28,%rcx
- ror $34,%r13
- mov %rdx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rcx
- ror $5,%r13
- or %r9,%r14 # a|c
-
- xor %r13,%rcx # h=Sigma0(a)
- and %r9,%r15 # a&c
- add %r12,%r10 # d+=T1
-
- and %r8,%r14 # (a|c)&b
- add %r12,%rcx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rcx # h+=Maj(a,b,c)
- mov 120(%rsp),%r13
- mov 96(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 56(%rsp),%r12
-
- add 112(%rsp),%r12
- mov %r10,%r13
- mov %r10,%r14
- mov %r11,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %rax,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r10,%r15 # (f^g)&e
- mov %r12,112(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %rax,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rbx,%r12 # T1+=h
-
- mov %rcx,%rbx
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rcx,%r13
- mov %rcx,%r14
-
- ror $28,%rbx
- ror $34,%r13
- mov %rcx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rbx
- ror $5,%r13
- or %r8,%r14 # a|c
-
- xor %r13,%rbx # h=Sigma0(a)
- and %r8,%r15 # a&c
- add %r12,%r9 # d+=T1
-
- and %rdx,%r14 # (a|c)&b
- add %r12,%rbx # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rbx # h+=Maj(a,b,c)
- mov 0(%rsp),%r13
- mov 104(%rsp),%r12
-
- mov %r13,%r15
-
- shr $7,%r13
- ror $1,%r15
-
- xor %r15,%r13
- ror $7,%r15
-
- xor %r15,%r13 # sigma0(X[(i+1)&0xf])
- mov %r12,%r14
-
- shr $6,%r12
- ror $19,%r14
-
- xor %r14,%r12
- ror $42,%r14
-
- xor %r14,%r12 # sigma1(X[(i+14)&0xf])
-
- add %r13,%r12
-
- add 64(%rsp),%r12
-
- add 120(%rsp),%r12
- mov %r9,%r13
- mov %r9,%r14
- mov %r10,%r15
-
- ror $14,%r13
- ror $18,%r14
- xor %r11,%r15 # f^g
-
- xor %r14,%r13
- ror $23,%r14
- and %r9,%r15 # (f^g)&e
- mov %r12,120(%rsp)
-
- xor %r14,%r13 # Sigma1(e)
- xor %r11,%r15 # Ch(e,f,g)=((f^g)&e)^g
- add %rax,%r12 # T1+=h
-
- mov %rbx,%rax
- add %r13,%r12 # T1+=Sigma1(e)
-
- add %r15,%r12 # T1+=Ch(e,f,g)
- mov %rbx,%r13
- mov %rbx,%r14
-
- ror $28,%rax
- ror $34,%r13
- mov %rbx,%r15
- add (%rbp,%rdi,8),%r12 # T1+=K[round]
-
- xor %r13,%rax
- ror $5,%r13
- or %rdx,%r14 # a|c
-
- xor %r13,%rax # h=Sigma0(a)
- and %rdx,%r15 # a&c
- add %r12,%r8 # d+=T1
-
- and %rcx,%r14 # (a|c)&b
- add %r12,%rax # h+=T1
-
- or %r15,%r14 # Maj(a,b,c)=((a|c)&b)|(a&c)
- lea 1(%rdi),%rdi # round++
-
- add %r14,%rax # h+=Maj(a,b,c)
- cmp $80,%rdi
- jb .Lrounds_16_xx
-
- mov 16*8+0*8(%rsp),%rdi
- lea 16*8(%rsi),%rsi
-
- add 8*0(%rdi),%rax
- add 8*1(%rdi),%rbx
- add 8*2(%rdi),%rcx
- add 8*3(%rdi),%rdx
- add 8*4(%rdi),%r8
- add 8*5(%rdi),%r9
- add 8*6(%rdi),%r10
- add 8*7(%rdi),%r11
-
- cmp 16*8+2*8(%rsp),%rsi
-
- mov %rax,8*0(%rdi)
- mov %rbx,8*1(%rdi)
- mov %rcx,8*2(%rdi)
- mov %rdx,8*3(%rdi)
- mov %r8,8*4(%rdi)
- mov %r9,8*5(%rdi)
- mov %r10,8*6(%rdi)
- mov %r11,8*7(%rdi)
- jb .Lloop
-
- mov 16*8+3*8(%rsp),%rsp
-.cfi_def_cfa %rsp,56
- pop %r15
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r15
- pop %r14
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r14
- pop %r13
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r13
- pop %r12
-.cfi_adjust_cfa_offset -8
-.cfi_restore %r12
- pop %rbp
-.cfi_adjust_cfa_offset -8
-.cfi_restore %rbp
- pop %rbx
-.cfi_adjust_cfa_offset -8
-.cfi_restore %rbx
-
- RET
-.cfi_endproc
-SET_SIZE(SHA512TransformBlocks)
-
-.section .rodata
-.align 64
-.type K512,@object
-K512:
- .quad 0x428a2f98d728ae22,0x7137449123ef65cd
- .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
- .quad 0x3956c25bf348b538,0x59f111f1b605d019
- .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
- .quad 0xd807aa98a3030242,0x12835b0145706fbe
- .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
- .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
- .quad 0x9bdc06a725c71235,0xc19bf174cf692694
- .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
- .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
- .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
- .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
- .quad 0x983e5152ee66dfab,0xa831c66d2db43210
- .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
- .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
- .quad 0x06ca6351e003826f,0x142929670a0e6e70
- .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
- .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
- .quad 0x650a73548baf63de,0x766a0abb3c77b2a8
- .quad 0x81c2c92e47edaee6,0x92722c851482353b
- .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
- .quad 0xc24b8b70d0f89791,0xc76c51a30654be30
- .quad 0xd192e819d6ef5218,0xd69906245565a910
- .quad 0xf40e35855771202a,0x106aa07032bbd1b8
- .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
- .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
- .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
- .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
- .quad 0x748f82ee5defb2fc,0x78a5636f43172f60
- .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
- .quad 0x90befffa23631e28,0xa4506cebde82bde9
- .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
- .quad 0xca273eceea26619c,0xd186b8c721c0c207
- .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
- .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
- .quad 0x113f9804bef90dae,0x1b710b35131c471b
- .quad 0x28db77f523047d84,0x32caab7b40c72493
- .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
- .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
- .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
-#endif /* !lint && !__lint */
-
-#ifdef __ELF__
-.section .note.GNU-stack,"",%progbits
-#endif
diff --git a/module/icp/core/kcf_callprov.c b/module/icp/core/kcf_callprov.c
index b5ef5f111d50..b1822dd5b878 100644
--- a/module/icp/core/kcf_callprov.c
+++ b/module/icp/core/kcf_callprov.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -63,7 +63,7 @@ is_in_triedlist(kcf_provider_desc_t *pd, kcf_prov_tried_t *triedl)
if (triedl->pt_pd == pd)
return (B_TRUE);
triedl = triedl->pt_next;
- };
+ }
return (B_FALSE);
}
diff --git a/module/icp/core/kcf_mech_tabs.c b/module/icp/core/kcf_mech_tabs.c
index ec43d53dc3ff..41705e84bc4b 100644
--- a/module/icp/core/kcf_mech_tabs.c
+++ b/module/icp/core/kcf_mech_tabs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -342,8 +342,8 @@ kcf_remove_mech_provider(const char *mech_name, kcf_provider_desc_t *prov_desc)
mech_entry->me_sw_prov = NULL;
/* 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_lib.c b/module/icp/core/kcf_prov_lib.c
index 4bc99a8eb84c..9dca3882e174 100644
--- a/module/icp/core/kcf_prov_lib.c
+++ b/module/icp/core/kcf_prov_lib.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/core/kcf_prov_tabs.c b/module/icp/core/kcf_prov_tabs.c
index 029d0526ec97..93af61a235d0 100644
--- a/module/icp/core/kcf_prov_tabs.c
+++ b/module/icp/core/kcf_prov_tabs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -158,8 +158,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 7d2b46a5f1f8..360ecfb2be19 100644
--- a/module/icp/core/kcf_sched.c
+++ b/module/icp/core/kcf_sched.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/illumos-crypto.c b/module/icp/illumos-crypto.c
index d17b90e7200a..13f05c06ed5c 100644
--- a/module/icp/illumos-crypto.c
+++ b/module/icp/illumos-crypto.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/include/aes/aes_impl.h b/module/icp/include/aes/aes_impl.h
index b2348022e1db..66eb4a6c8fb6 100644
--- a/module/icp/include/aes/aes_impl.h
+++ b/module/icp/include/aes/aes_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -36,6 +36,7 @@ extern "C" {
#include <sys/zfs_context.h>
#include <sys/crypto/common.h>
+#include <sys/asm_linkage.h>
/* Similar to sysmacros.h IS_P2ALIGNED, but checks two pointers: */
#define IS_P2ALIGNED2(v, w, a) \
@@ -190,13 +191,13 @@ extern const aes_impl_ops_t aes_generic_impl;
extern const aes_impl_ops_t aes_x86_64_impl;
/* These functions are used to execute amd64 instructions for AMD or Intel: */
-extern int rijndael_key_setup_enc_amd64(uint32_t rk[],
+extern ASMABI int rijndael_key_setup_enc_amd64(uint32_t rk[],
const uint32_t cipherKey[], int keyBits);
-extern int rijndael_key_setup_dec_amd64(uint32_t rk[],
+extern ASMABI int rijndael_key_setup_dec_amd64(uint32_t rk[],
const uint32_t cipherKey[], int keyBits);
-extern void aes_encrypt_amd64(const uint32_t rk[], int Nr,
+extern ASMABI void aes_encrypt_amd64(const uint32_t rk[], int Nr,
const uint32_t pt[4], uint32_t ct[4]);
-extern void aes_decrypt_amd64(const uint32_t rk[], int Nr,
+extern ASMABI void aes_decrypt_amd64(const uint32_t rk[], int Nr,
const uint32_t ct[4], uint32_t pt[4]);
#endif
#if defined(__x86_64) && defined(HAVE_AES)
diff --git a/module/icp/include/generic_impl.c b/module/icp/include/generic_impl.c
new file mode 100644
index 000000000000..16f802cf7558
--- /dev/null
+++ b/module/icp/include/generic_impl.c
@@ -0,0 +1,233 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2003, 2010 Oracle and/or its affiliates.
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+/*
+ * This file gets included by c files for implementing the full set
+ * of zfs_impl.h defines.
+ *
+ * It's ment for easier maintaining multiple implementations of
+ * algorithms. Look into blake3_impl.c, sha256_impl.c or sha512_impl.c
+ * for reference.
+ */
+
+#include <sys/zfs_context.h>
+#include <sys/zio_checksum.h>
+#include <sys/zfs_impl.h>
+
+/* Two default implementations */
+#define IMPL_FASTEST (UINT32_MAX)
+#define IMPL_CYCLE (UINT32_MAX - 1)
+
+#define IMPL_READ(i) (*(volatile uint32_t *) &(i))
+
+/* Implementation that contains the fastest method */
+static IMPL_OPS_T generic_fastest_impl = {
+ .name = "fastest"
+};
+
+/* Hold all supported implementations */
+static const IMPL_OPS_T *generic_supp_impls[ARRAY_SIZE(IMPL_ARRAY)];
+static uint32_t generic_supp_impls_cnt = 0;
+
+/* Currently selected implementation */
+static uint32_t generic_impl_chosen = IMPL_FASTEST;
+
+static struct generic_impl_selector {
+ const char *name;
+ uint32_t sel;
+} generic_impl_selectors[] = {
+ { "cycle", IMPL_CYCLE },
+ { "fastest", IMPL_FASTEST }
+};
+
+/* check the supported implementations */
+static void
+generic_impl_init(void)
+{
+ int i, c;
+
+ /* init only once */
+ if (likely(generic_supp_impls_cnt != 0))
+ return;
+
+ /* Move supported implementations into generic_supp_impls */
+ for (i = 0, c = 0; i < ARRAY_SIZE(IMPL_ARRAY); i++) {
+ const IMPL_OPS_T *impl = IMPL_ARRAY[i];
+
+ if (impl->is_supported && impl->is_supported())
+ generic_supp_impls[c++] = impl;
+ }
+ generic_supp_impls_cnt = c;
+
+ /* first init generic impl, may be changed via set_fastest() */
+ memcpy(&generic_fastest_impl, generic_supp_impls[0],
+ sizeof (generic_fastest_impl));
+}
+
+/* get number of supported implementations */
+static uint32_t
+generic_impl_getcnt(void)
+{
+ generic_impl_init();
+ return (generic_supp_impls_cnt);
+}
+
+/* get id of selected implementation */
+static uint32_t
+generic_impl_getid(void)
+{
+ generic_impl_init();
+ return (IMPL_READ(generic_impl_chosen));
+}
+
+/* get name of selected implementation */
+static const char *
+generic_impl_getname(void)
+{
+ uint32_t impl = IMPL_READ(generic_impl_chosen);
+
+ generic_impl_init();
+ switch (impl) {
+ case IMPL_FASTEST:
+ return ("fastest");
+ case IMPL_CYCLE:
+ return ("cycle");
+ default:
+ return (generic_supp_impls[impl]->name);
+ }
+}
+
+/* set implementation by id */
+static void
+generic_impl_setid(uint32_t id)
+{
+ generic_impl_init();
+ switch (id) {
+ case IMPL_FASTEST:
+ atomic_swap_32(&generic_impl_chosen, IMPL_FASTEST);
+ break;
+ case IMPL_CYCLE:
+ atomic_swap_32(&generic_impl_chosen, IMPL_CYCLE);
+ break;
+ default:
+ ASSERT3U(id, <, generic_supp_impls_cnt);
+ atomic_swap_32(&generic_impl_chosen, id);
+ break;
+ }
+}
+
+/* set implementation by name */
+static int
+generic_impl_setname(const char *val)
+{
+ uint32_t impl = IMPL_READ(generic_impl_chosen);
+ size_t val_len;
+ int i, err = -EINVAL;
+
+ generic_impl_init();
+ val_len = strlen(val);
+ while ((val_len > 0) && !!isspace(val[val_len-1])) /* trim '\n' */
+ val_len--;
+
+ /* check mandatory implementations */
+ for (i = 0; i < ARRAY_SIZE(generic_impl_selectors); i++) {
+ const char *name = generic_impl_selectors[i].name;
+
+ if (val_len == strlen(name) &&
+ strncmp(val, name, val_len) == 0) {
+ impl = generic_impl_selectors[i].sel;
+ err = 0;
+ break;
+ }
+ }
+
+ /* check all supported implementations */
+ if (err != 0) {
+ for (i = 0; i < generic_supp_impls_cnt; i++) {
+ const char *name = generic_supp_impls[i]->name;
+
+ if (val_len == strlen(name) &&
+ strncmp(val, name, val_len) == 0) {
+ impl = i;
+ err = 0;
+ break;
+ }
+ }
+ }
+
+ if (err == 0) {
+ atomic_swap_32(&generic_impl_chosen, impl);
+ }
+
+ return (err);
+}
+
+/* setup id as fastest implementation */
+static void
+generic_impl_set_fastest(uint32_t id)
+{
+ generic_impl_init();
+ memcpy(&generic_fastest_impl, generic_supp_impls[id],
+ sizeof (generic_fastest_impl));
+}
+
+/* return impl iterating functions */
+const zfs_impl_t ZFS_IMPL_OPS = {
+ .name = IMPL_NAME,
+ .getcnt = generic_impl_getcnt,
+ .getid = generic_impl_getid,
+ .getname = generic_impl_getname,
+ .set_fastest = generic_impl_set_fastest,
+ .setid = generic_impl_setid,
+ .setname = generic_impl_setname
+};
+
+/* get impl ops_t of selected implementation */
+const IMPL_OPS_T *
+IMPL_GET_OPS(void)
+{
+ const IMPL_OPS_T *ops = NULL;
+ uint32_t idx, impl = IMPL_READ(generic_impl_chosen);
+ static uint32_t cycle_count = 0;
+
+ generic_impl_init();
+ switch (impl) {
+ case IMPL_FASTEST:
+ ops = &generic_fastest_impl;
+ break;
+ case IMPL_CYCLE:
+ idx = (++cycle_count) % generic_supp_impls_cnt;
+ ops = generic_supp_impls[idx];
+ break;
+ default:
+ ASSERT3U(impl, <, generic_supp_impls_cnt);
+ ops = generic_supp_impls[impl];
+ break;
+ }
+
+ ASSERT3P(ops, !=, NULL);
+ return (ops);
+}
diff --git a/module/icp/include/modes/gcm_impl.h b/module/icp/include/modes/gcm_impl.h
index 28c8f63a7d46..3afc9e2c6317 100644
--- a/module/icp/include/modes/gcm_impl.h
+++ b/module/icp/include/modes/gcm_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/include/modes/modes.h b/module/icp/include/modes/modes.h
index aa88ea97e045..23bf46ab51a0 100644
--- a/module/icp/include/modes/modes.h
+++ b/module/icp/include/modes/modes.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -244,6 +244,8 @@ typedef struct gcm_ctx {
#define AES_GMAC_IV_LEN 12
#define AES_GMAC_TAG_BITS 128
+void gcm_clear_ctx(gcm_ctx_t *ctx);
+
typedef struct aes_ctx {
union {
ecb_ctx_t acu_ecb;
diff --git a/module/icp/include/sha2/sha2_consts.h b/module/icp/include/sha2/sha2_consts.h
deleted file mode 100644
index 3a6645508fe9..000000000000
--- a/module/icp/include/sha2/sha2_consts.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_SHA2_CONSTS_H
-#define _SYS_SHA2_CONSTS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Loading 32-bit constants on a sparc is expensive since it involves both
- * a `sethi' and an `or'. thus, we instead use `ld' to load the constants
- * from an array called `sha2_consts'. however, on intel (and perhaps other
- * processors), it is cheaper to load the constant directly. thus, the c
- * code in SHA transform functions uses the macro SHA2_CONST() which either
- * expands to a constant or an array reference, depending on
- * the architecture the code is being compiled for.
- *
- * SHA512 constants are used for SHA384
- */
-
-#include <sys/types.h> /* uint32_t */
-
-extern const uint32_t sha256_consts[];
-extern const uint64_t sha512_consts[];
-
-#if defined(__sparc)
-#define SHA256_CONST(x) (sha256_consts[x])
-#define SHA512_CONST(x) (sha512_consts[x])
-#else
-#define SHA256_CONST(x) (SHA256_CONST_ ## x)
-#define SHA512_CONST(x) (SHA512_CONST_ ## x)
-#endif
-
-/* constants, as provided in FIPS 180-2 */
-
-#define SHA256_CONST_0 0x428a2f98U
-#define SHA256_CONST_1 0x71374491U
-#define SHA256_CONST_2 0xb5c0fbcfU
-#define SHA256_CONST_3 0xe9b5dba5U
-#define SHA256_CONST_4 0x3956c25bU
-#define SHA256_CONST_5 0x59f111f1U
-#define SHA256_CONST_6 0x923f82a4U
-#define SHA256_CONST_7 0xab1c5ed5U
-
-#define SHA256_CONST_8 0xd807aa98U
-#define SHA256_CONST_9 0x12835b01U
-#define SHA256_CONST_10 0x243185beU
-#define SHA256_CONST_11 0x550c7dc3U
-#define SHA256_CONST_12 0x72be5d74U
-#define SHA256_CONST_13 0x80deb1feU
-#define SHA256_CONST_14 0x9bdc06a7U
-#define SHA256_CONST_15 0xc19bf174U
-
-#define SHA256_CONST_16 0xe49b69c1U
-#define SHA256_CONST_17 0xefbe4786U
-#define SHA256_CONST_18 0x0fc19dc6U
-#define SHA256_CONST_19 0x240ca1ccU
-#define SHA256_CONST_20 0x2de92c6fU
-#define SHA256_CONST_21 0x4a7484aaU
-#define SHA256_CONST_22 0x5cb0a9dcU
-#define SHA256_CONST_23 0x76f988daU
-
-#define SHA256_CONST_24 0x983e5152U
-#define SHA256_CONST_25 0xa831c66dU
-#define SHA256_CONST_26 0xb00327c8U
-#define SHA256_CONST_27 0xbf597fc7U
-#define SHA256_CONST_28 0xc6e00bf3U
-#define SHA256_CONST_29 0xd5a79147U
-#define SHA256_CONST_30 0x06ca6351U
-#define SHA256_CONST_31 0x14292967U
-
-#define SHA256_CONST_32 0x27b70a85U
-#define SHA256_CONST_33 0x2e1b2138U
-#define SHA256_CONST_34 0x4d2c6dfcU
-#define SHA256_CONST_35 0x53380d13U
-#define SHA256_CONST_36 0x650a7354U
-#define SHA256_CONST_37 0x766a0abbU
-#define SHA256_CONST_38 0x81c2c92eU
-#define SHA256_CONST_39 0x92722c85U
-
-#define SHA256_CONST_40 0xa2bfe8a1U
-#define SHA256_CONST_41 0xa81a664bU
-#define SHA256_CONST_42 0xc24b8b70U
-#define SHA256_CONST_43 0xc76c51a3U
-#define SHA256_CONST_44 0xd192e819U
-#define SHA256_CONST_45 0xd6990624U
-#define SHA256_CONST_46 0xf40e3585U
-#define SHA256_CONST_47 0x106aa070U
-
-#define SHA256_CONST_48 0x19a4c116U
-#define SHA256_CONST_49 0x1e376c08U
-#define SHA256_CONST_50 0x2748774cU
-#define SHA256_CONST_51 0x34b0bcb5U
-#define SHA256_CONST_52 0x391c0cb3U
-#define SHA256_CONST_53 0x4ed8aa4aU
-#define SHA256_CONST_54 0x5b9cca4fU
-#define SHA256_CONST_55 0x682e6ff3U
-
-#define SHA256_CONST_56 0x748f82eeU
-#define SHA256_CONST_57 0x78a5636fU
-#define SHA256_CONST_58 0x84c87814U
-#define SHA256_CONST_59 0x8cc70208U
-#define SHA256_CONST_60 0x90befffaU
-#define SHA256_CONST_61 0xa4506cebU
-#define SHA256_CONST_62 0xbef9a3f7U
-#define SHA256_CONST_63 0xc67178f2U
-
-#define SHA512_CONST_0 0x428a2f98d728ae22ULL
-#define SHA512_CONST_1 0x7137449123ef65cdULL
-#define SHA512_CONST_2 0xb5c0fbcfec4d3b2fULL
-#define SHA512_CONST_3 0xe9b5dba58189dbbcULL
-#define SHA512_CONST_4 0x3956c25bf348b538ULL
-#define SHA512_CONST_5 0x59f111f1b605d019ULL
-#define SHA512_CONST_6 0x923f82a4af194f9bULL
-#define SHA512_CONST_7 0xab1c5ed5da6d8118ULL
-#define SHA512_CONST_8 0xd807aa98a3030242ULL
-#define SHA512_CONST_9 0x12835b0145706fbeULL
-#define SHA512_CONST_10 0x243185be4ee4b28cULL
-#define SHA512_CONST_11 0x550c7dc3d5ffb4e2ULL
-#define SHA512_CONST_12 0x72be5d74f27b896fULL
-#define SHA512_CONST_13 0x80deb1fe3b1696b1ULL
-#define SHA512_CONST_14 0x9bdc06a725c71235ULL
-#define SHA512_CONST_15 0xc19bf174cf692694ULL
-#define SHA512_CONST_16 0xe49b69c19ef14ad2ULL
-#define SHA512_CONST_17 0xefbe4786384f25e3ULL
-#define SHA512_CONST_18 0x0fc19dc68b8cd5b5ULL
-#define SHA512_CONST_19 0x240ca1cc77ac9c65ULL
-#define SHA512_CONST_20 0x2de92c6f592b0275ULL
-#define SHA512_CONST_21 0x4a7484aa6ea6e483ULL
-#define SHA512_CONST_22 0x5cb0a9dcbd41fbd4ULL
-#define SHA512_CONST_23 0x76f988da831153b5ULL
-#define SHA512_CONST_24 0x983e5152ee66dfabULL
-#define SHA512_CONST_25 0xa831c66d2db43210ULL
-#define SHA512_CONST_26 0xb00327c898fb213fULL
-#define SHA512_CONST_27 0xbf597fc7beef0ee4ULL
-#define SHA512_CONST_28 0xc6e00bf33da88fc2ULL
-#define SHA512_CONST_29 0xd5a79147930aa725ULL
-#define SHA512_CONST_30 0x06ca6351e003826fULL
-#define SHA512_CONST_31 0x142929670a0e6e70ULL
-#define SHA512_CONST_32 0x27b70a8546d22ffcULL
-#define SHA512_CONST_33 0x2e1b21385c26c926ULL
-#define SHA512_CONST_34 0x4d2c6dfc5ac42aedULL
-#define SHA512_CONST_35 0x53380d139d95b3dfULL
-#define SHA512_CONST_36 0x650a73548baf63deULL
-#define SHA512_CONST_37 0x766a0abb3c77b2a8ULL
-#define SHA512_CONST_38 0x81c2c92e47edaee6ULL
-#define SHA512_CONST_39 0x92722c851482353bULL
-#define SHA512_CONST_40 0xa2bfe8a14cf10364ULL
-#define SHA512_CONST_41 0xa81a664bbc423001ULL
-#define SHA512_CONST_42 0xc24b8b70d0f89791ULL
-#define SHA512_CONST_43 0xc76c51a30654be30ULL
-#define SHA512_CONST_44 0xd192e819d6ef5218ULL
-#define SHA512_CONST_45 0xd69906245565a910ULL
-#define SHA512_CONST_46 0xf40e35855771202aULL
-#define SHA512_CONST_47 0x106aa07032bbd1b8ULL
-#define SHA512_CONST_48 0x19a4c116b8d2d0c8ULL
-#define SHA512_CONST_49 0x1e376c085141ab53ULL
-#define SHA512_CONST_50 0x2748774cdf8eeb99ULL
-#define SHA512_CONST_51 0x34b0bcb5e19b48a8ULL
-#define SHA512_CONST_52 0x391c0cb3c5c95a63ULL
-#define SHA512_CONST_53 0x4ed8aa4ae3418acbULL
-#define SHA512_CONST_54 0x5b9cca4f7763e373ULL
-#define SHA512_CONST_55 0x682e6ff3d6b2b8a3ULL
-#define SHA512_CONST_56 0x748f82ee5defb2fcULL
-#define SHA512_CONST_57 0x78a5636f43172f60ULL
-#define SHA512_CONST_58 0x84c87814a1f0ab72ULL
-#define SHA512_CONST_59 0x8cc702081a6439ecULL
-#define SHA512_CONST_60 0x90befffa23631e28ULL
-#define SHA512_CONST_61 0xa4506cebde82bde9ULL
-#define SHA512_CONST_62 0xbef9a3f7b2c67915ULL
-#define SHA512_CONST_63 0xc67178f2e372532bULL
-#define SHA512_CONST_64 0xca273eceea26619cULL
-#define SHA512_CONST_65 0xd186b8c721c0c207ULL
-#define SHA512_CONST_66 0xeada7dd6cde0eb1eULL
-#define SHA512_CONST_67 0xf57d4f7fee6ed178ULL
-#define SHA512_CONST_68 0x06f067aa72176fbaULL
-#define SHA512_CONST_69 0x0a637dc5a2c898a6ULL
-#define SHA512_CONST_70 0x113f9804bef90daeULL
-#define SHA512_CONST_71 0x1b710b35131c471bULL
-#define SHA512_CONST_72 0x28db77f523047d84ULL
-#define SHA512_CONST_73 0x32caab7b40c72493ULL
-#define SHA512_CONST_74 0x3c9ebe0a15c9bebcULL
-#define SHA512_CONST_75 0x431d67c49c100d4cULL
-#define SHA512_CONST_76 0x4cc5d4becb3e42b6ULL
-#define SHA512_CONST_77 0x597f299cfc657e2aULL
-#define SHA512_CONST_78 0x5fcb6fab3ad6faecULL
-#define SHA512_CONST_79 0x6c44198c4a475817ULL
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SHA2_CONSTS_H */
diff --git a/module/icp/include/sha2/sha2_impl.h b/module/icp/include/sha2/sha2_impl.h
index b9768d344e95..9a1bd38f1a77 100644
--- a/module/icp/include/sha2/sha2_impl.h
+++ b/module/icp/include/sha2/sha2_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -18,9 +18,10 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
#ifndef _SHA2_IMPL_H
@@ -32,6 +33,28 @@
extern "C" {
#endif
+/* transform function definition */
+typedef void (*sha256_f)(uint32_t state[8], const void *data, size_t blks);
+typedef void (*sha512_f)(uint64_t state[8], const void *data, size_t blks);
+
+/* needed for checking valid implementations */
+typedef boolean_t (*sha2_is_supported_f)(void);
+
+typedef struct {
+ const char *name;
+ sha256_f transform;
+ sha2_is_supported_f is_supported;
+} sha256_ops_t;
+
+typedef struct {
+ const char *name;
+ sha512_f transform;
+ sha2_is_supported_f is_supported;
+} sha512_ops_t;
+
+extern const sha256_ops_t *sha256_get_ops(void);
+extern const sha512_ops_t *sha512_get_ops(void);
+
typedef enum {
SHA1_TYPE,
SHA256_TYPE,
diff --git a/module/icp/include/sys/crypto/impl.h b/module/icp/include/sys/crypto/impl.h
index dca7aa1b562f..4d17221ea9a3 100644
--- a/module/icp/include/sys/crypto/impl.h
+++ b/module/icp/include/sys/crypto/impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -126,28 +126,26 @@ typedef struct kcf_provider_desc {
crypto_provider_id_t pd_prov_id;
} kcf_provider_desc_t;
-/* atomic operations in linux implicitly form a memory barrier */
-#define membar_exit()
-
/*
* If a component has a reference to a kcf_provider_desc_t,
* it REFHOLD()s. A new provider descriptor which is referenced only
* by the providers table has a reference counter of one.
*/
-#define KCF_PROV_REFHOLD(desc) { \
- atomic_add_32(&(desc)->pd_refcnt, 1); \
- ASSERT((desc)->pd_refcnt != 0); \
+#define KCF_PROV_REFHOLD(desc) { \
+ int newval = atomic_add_32_nv(&(desc)->pd_refcnt, 1); \
+ ASSERT(newval != 0); \
}
-#define KCF_PROV_IREFHOLD(desc) { \
- atomic_add_32(&(desc)->pd_irefcnt, 1); \
- ASSERT((desc)->pd_irefcnt != 0); \
+#define KCF_PROV_IREFHOLD(desc) { \
+ int newval = atomic_add_32_nv(&(desc)->pd_irefcnt, 1); \
+ ASSERT(newval != 0); \
}
#define KCF_PROV_IREFRELE(desc) { \
- ASSERT((desc)->pd_irefcnt != 0); \
- membar_exit(); \
- if (atomic_add_32_nv(&(desc)->pd_irefcnt, -1) == 0) { \
+ membar_producer(); \
+ int newval = atomic_add_32_nv(&(desc)->pd_irefcnt, -1); \
+ ASSERT(newval != -1); \
+ if (newval == 0) { \
cv_broadcast(&(desc)->pd_remove_cv); \
} \
}
@@ -155,9 +153,10 @@ typedef struct kcf_provider_desc {
#define KCF_PROV_REFHELD(desc) ((desc)->pd_refcnt >= 1)
#define KCF_PROV_REFRELE(desc) { \
- ASSERT((desc)->pd_refcnt != 0); \
- membar_exit(); \
- if (atomic_add_32_nv(&(desc)->pd_refcnt, -1) == 0) { \
+ membar_producer(); \
+ int newval = atomic_add_32_nv(&(desc)->pd_refcnt, -1); \
+ ASSERT(newval != -1); \
+ if (newval == 0) { \
kcf_provider_zero_refcnt((desc)); \
} \
}
@@ -193,9 +192,9 @@ typedef struct kcf_mech_entry {
* it REFHOLD()s. A new policy descriptor which is referenced only
* by the policy table has a reference count of one.
*/
-#define KCF_POLICY_REFHOLD(desc) { \
- atomic_add_32(&(desc)->pd_refcnt, 1); \
- ASSERT((desc)->pd_refcnt != 0); \
+#define KCF_POLICY_REFHOLD(desc) { \
+ int newval = atomic_add_32_nv(&(desc)->pd_refcnt, 1); \
+ ASSERT(newval != 0); \
}
/*
@@ -203,9 +202,10 @@ typedef struct kcf_mech_entry {
* reference is released, the descriptor is freed.
*/
#define KCF_POLICY_REFRELE(desc) { \
- ASSERT((desc)->pd_refcnt != 0); \
- membar_exit(); \
- if (atomic_add_32_nv(&(desc)->pd_refcnt, -1) == 0) \
+ membar_producer(); \
+ int newval = atomic_add_32_nv(&(desc)->pd_refcnt, -1); \
+ ASSERT(newval != -1); \
+ if (newval == 0) \
kcf_policy_free_desc(desc); \
}
diff --git a/module/icp/include/sys/crypto/sched_impl.h b/module/icp/include/sys/crypto/sched_impl.h
index 1de4bd8b94f4..355c1a87faa4 100644
--- a/module/icp/include/sys/crypto/sched_impl.h
+++ b/module/icp/include/sys/crypto/sched_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -73,9 +73,10 @@ typedef struct kcf_context {
* context structure is freed along with the global context.
*/
#define KCF_CONTEXT_REFRELE(ictx) { \
- ASSERT((ictx)->kc_refcnt != 0); \
- membar_exit(); \
- if (atomic_add_32_nv(&(ictx)->kc_refcnt, -1) == 0) \
+ membar_producer(); \
+ int newval = atomic_add_32_nv(&(ictx)->kc_refcnt, -1); \
+ ASSERT(newval != -1); \
+ if (newval == 0) \
kcf_free_context(ictx); \
}
diff --git a/module/icp/include/sys/crypto/spi.h b/module/icp/include/sys/crypto/spi.h
index ef525265747e..63dfce7957a8 100644
--- a/module/icp/include/sys/crypto/spi.h
+++ b/module/icp/include/sys/crypto/spi.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/include/sys/ia32/stack.h b/module/icp/include/sys/ia32/stack.h
deleted file mode 100644
index 9e7c089e1182..000000000000
--- a/module/icp/include/sys/ia32/stack.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _IA32_SYS_STACK_H
-#define _IA32_SYS_STACK_H
-
-#if !defined(_ASM)
-
-#include <sys/types.h>
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * In the x86 world, a stack frame looks like this:
- *
- * |--------------------------|
- * 4n+8(%ebp) ->| argument word n |
- * | ... | (Previous frame)
- * 8(%ebp) ->| argument word 0 |
- * |--------------------------|--------------------
- * 4(%ebp) ->| return address |
- * |--------------------------|
- * 0(%ebp) ->| previous %ebp (optional) |
- * |--------------------------|
- * -4(%ebp) ->| unspecified | (Current frame)
- * | ... |
- * 0(%esp) ->| variable size |
- * |--------------------------|
- */
-
-/*
- * Stack alignment macros.
- */
-
-#define STACK_ALIGN32 4
-#define STACK_ENTRY_ALIGN32 4
-#define STACK_BIAS32 0
-#define SA32(x) (((x)+(STACK_ALIGN32-1)) & ~(STACK_ALIGN32-1))
-#define STACK_RESERVE32 0
-#define MINFRAME32 0
-
-#if defined(__amd64)
-
-/*
- * In the amd64 world, a stack frame looks like this:
- *
- * |--------------------------|
- * 8n+16(%rbp)->| argument word n |
- * | ... | (Previous frame)
- * 16(%rbp) ->| argument word 0 |
- * |--------------------------|--------------------
- * 8(%rbp) ->| return address |
- * |--------------------------|
- * 0(%rbp) ->| previous %rbp |
- * |--------------------------|
- * -8(%rbp) ->| unspecified | (Current frame)
- * | ... |
- * 0(%rsp) ->| variable size |
- * |--------------------------|
- * -128(%rsp) ->| reserved for function |
- * |--------------------------|
- *
- * The end of the input argument area must be aligned on a 16-byte
- * boundary; i.e. (%rsp - 8) % 16 == 0 at function entry.
- *
- * The 128-byte location beyond %rsp is considered to be reserved for
- * functions and is NOT modified by signal handlers. It can be used
- * to store temporary data that is not needed across function calls.
- */
-
-/*
- * Stack alignment macros.
- */
-
-#define STACK_ALIGN64 16
-#define STACK_ENTRY_ALIGN64 8
-#define STACK_BIAS64 0
-#define SA64(x) (((x)+(STACK_ALIGN64-1)) & ~(STACK_ALIGN64-1))
-#define STACK_RESERVE64 128
-#define MINFRAME64 0
-
-#define STACK_ALIGN STACK_ALIGN64
-#define STACK_ENTRY_ALIGN STACK_ENTRY_ALIGN64
-#define STACK_BIAS STACK_BIAS64
-#define SA(x) SA64(x)
-#define STACK_RESERVE STACK_RESERVE64
-#define MINFRAME MINFRAME64
-
-#elif defined(__i386)
-
-#define STACK_ALIGN STACK_ALIGN32
-#define STACK_ENTRY_ALIGN STACK_ENTRY_ALIGN32
-#define STACK_BIAS STACK_BIAS32
-#define SA(x) SA32(x)
-#define STACK_RESERVE STACK_RESERVE32
-#define MINFRAME MINFRAME32
-
-#endif /* __i386 */
-
-#if defined(_KERNEL) && !defined(_ASM)
-
-#if defined(ZFS_DEBUG)
-#if STACK_ALIGN == 4
-#define ASSERT_STACK_ALIGNED() \
- { \
- uint32_t __tmp; \
- ASSERT((((uintptr_t)&__tmp) & (STACK_ALIGN - 1)) == 0); \
- }
-#elif (STACK_ALIGN == 16) && (_LONG_DOUBLE_ALIGNMENT == 16)
-#define ASSERT_STACK_ALIGNED() \
- { \
- long double __tmp; \
- ASSERT((((uintptr_t)&__tmp) & (STACK_ALIGN - 1)) == 0); \
- }
-#endif
-#else /* DEBUG */
-#define ASSERT_STACK_ALIGNED()
-#endif /* DEBUG */
-
-struct regs;
-
-void traceregs(struct regs *);
-void traceback(caddr_t);
-
-#endif /* defined(_KERNEL) && !defined(_ASM) */
-
-#define STACK_GROWTH_DOWN /* stacks grow from high to low addresses */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _IA32_SYS_STACK_H */
diff --git a/module/icp/include/sys/ia32/trap.h b/module/icp/include/sys/ia32/trap.h
deleted file mode 100644
index 55b94969b80b..000000000000
--- a/module/icp/include/sys/ia32/trap.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
-/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
-/* All Rights Reserved */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _IA32_SYS_TRAP_H
-#define _IA32_SYS_TRAP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Trap type values
- */
-
-#define T_ZERODIV 0x0 /* #de divide by 0 error */
-#define T_SGLSTP 0x1 /* #db single step */
-#define T_NMIFLT 0x2 /* NMI */
-#define T_BPTFLT 0x3 /* #bp breakpoint fault, INT3 insn */
-#define T_OVFLW 0x4 /* #of INTO overflow fault */
-#define T_BOUNDFLT 0x5 /* #br BOUND insn fault */
-#define T_ILLINST 0x6 /* #ud invalid opcode fault */
-#define T_NOEXTFLT 0x7 /* #nm device not available: x87 */
-#define T_DBLFLT 0x8 /* #df double fault */
-#define T_EXTOVRFLT 0x9 /* [not generated: 386 only] */
-#define T_TSSFLT 0xa /* #ts invalid TSS fault */
-#define T_SEGFLT 0xb /* #np segment not present fault */
-#define T_STKFLT 0xc /* #ss stack fault */
-#define T_GPFLT 0xd /* #gp general protection fault */
-#define T_PGFLT 0xe /* #pf page fault */
-#define T_EXTERRFLT 0x10 /* #mf x87 FPU error fault */
-#define T_ALIGNMENT 0x11 /* #ac alignment check error */
-#define T_MCE 0x12 /* #mc machine check exception */
-#define T_SIMDFPE 0x13 /* #xm SSE/SSE exception */
-#define T_DBGENTR 0x14 /* debugger entry */
-#define T_ENDPERR 0x21 /* emulated extension error flt */
-#define T_ENOEXTFLT 0x20 /* emulated ext not present */
-#define T_FASTTRAP 0xd2 /* fast system call */
-#define T_SYSCALLINT 0x91 /* general system call */
-#define T_DTRACE_RET 0x7f /* DTrace pid return */
-#define T_INT80 0x80 /* int80 handler for linux emulation */
-#define T_SOFTINT 0x50fd /* pseudo softint trap type */
-
-/*
- * Pseudo traps.
- */
-#define T_INTERRUPT 0x100
-#define T_FAULT 0x200
-#define T_AST 0x400
-#define T_SYSCALL 0x180
-
-
-/*
- * Values of error code on stack in case of page fault
- */
-
-#define PF_ERR_MASK 0x01 /* Mask for error bit */
-#define PF_ERR_PAGE 0x00 /* page not present */
-#define PF_ERR_PROT 0x01 /* protection error */
-#define PF_ERR_WRITE 0x02 /* fault caused by write (else read) */
-#define PF_ERR_USER 0x04 /* processor was in user mode */
- /* (else supervisor) */
-#define PF_ERR_EXEC 0x10 /* attempt to execute a No eXec page (AMD) */
-
-/*
- * Definitions for fast system call subfunctions
- */
-#define T_FNULL 0 /* Null trap for testing */
-#define T_FGETFP 1 /* Get emulated FP context */
-#define T_FSETFP 2 /* Set emulated FP context */
-#define T_GETHRTIME 3 /* Get high resolution time */
-#define T_GETHRVTIME 4 /* Get high resolution virtual time */
-#define T_GETHRESTIME 5 /* Get high resolution time */
-#define T_GETLGRP 6 /* Get home lgrpid */
-
-#define T_LASTFAST 6 /* Last valid subfunction */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _IA32_SYS_TRAP_H */
diff --git a/module/icp/include/sys/stack.h b/module/icp/include/sys/stack.h
index 64fecf409b5c..0bace018b5ab 100644
--- a/module/icp/include/sys/stack.h
+++ b/module/icp/include/sys/stack.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/include/sys/trap.h b/module/icp/include/sys/trap.h
index 7f9fd375805f..2f47d43939c1 100644
--- a/module/icp/include/sys/trap.h
+++ b/module/icp/include/sys/trap.h
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/icp/io/aes.c b/module/icp/io/aes.c
index 945d560ebe57..d6f01304f56b 100644
--- a/module/icp/io/aes.c
+++ b/module/icp/io/aes.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -945,17 +945,9 @@ out:
memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
}
-#ifdef CAN_USE_GCM_ASM
- if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE) &&
- ((gcm_ctx_t *)&aes_ctx)->gcm_Htable != NULL) {
-
- gcm_ctx_t *ctx = (gcm_ctx_t *)&aes_ctx;
-
- memset(ctx->gcm_Htable, 0, ctx->gcm_htab_len);
- kmem_free(ctx->gcm_Htable, ctx->gcm_htab_len);
+ if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
+ gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
}
-#endif
-
return (ret);
}
@@ -1101,18 +1093,7 @@ out:
vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
}
} else if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
- if (((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf != NULL) {
- vmem_free(((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf,
- ((gcm_ctx_t *)&aes_ctx)->gcm_pt_buf_len);
- }
-#ifdef CAN_USE_GCM_ASM
- if (((gcm_ctx_t *)&aes_ctx)->gcm_Htable != NULL) {
- gcm_ctx_t *ctx = (gcm_ctx_t *)&aes_ctx;
-
- memset(ctx->gcm_Htable, 0, ctx->gcm_htab_len);
- kmem_free(ctx->gcm_Htable, ctx->gcm_htab_len);
- }
-#endif
+ gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
}
return (ret);
diff --git a/module/icp/io/sha2_mod.c b/module/icp/io/sha2_mod.c
index 4a218b500325..f068951b07f5 100644
--- a/module/icp/io/sha2_mod.c
+++ b/module/icp/io/sha2_mod.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,7 +28,6 @@
#include <sys/crypto/common.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/icp.h>
-#define _SHA2_IMPL
#include <sys/sha2.h>
#include <sha2/sha2_impl.h>
@@ -737,12 +736,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/icp/io/skein_mod.c b/module/icp/io/skein_mod.c
index a2ed6cedd8c6..221e1debd45b 100644
--- a/module/icp/io/skein_mod.c
+++ b/module/icp/io/skein_mod.c
@@ -421,7 +421,7 @@ skein_update(crypto_ctx_t *ctx, crypto_data_t *data)
* Supported output digest formats are raw, uio and mblk.
*/
static int
-skein_final(crypto_ctx_t *ctx, crypto_data_t *digest)
+skein_final_nofree(crypto_ctx_t *ctx, crypto_data_t *digest)
{
int error = CRYPTO_SUCCESS;
@@ -452,6 +452,17 @@ skein_final(crypto_ctx_t *ctx, crypto_data_t *digest)
else
digest->cd_length = 0;
+ return (error);
+}
+
+static int
+skein_final(crypto_ctx_t *ctx, crypto_data_t *digest)
+{
+ int error = skein_final_nofree(ctx, digest);
+
+ if (error == CRYPTO_BUFFER_TOO_SMALL)
+ return (error);
+
memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx))));
SKEIN_CTX_LVALUE(ctx) = NULL;
@@ -485,7 +496,7 @@ skein_digest_atomic(crypto_mechanism_t *mechanism, crypto_data_t *data,
if ((error = skein_update(&ctx, data)) != CRYPTO_SUCCESS)
goto out;
- if ((error = skein_final(&ctx, data)) != CRYPTO_SUCCESS)
+ if ((error = skein_final_nofree(&ctx, data)) != CRYPTO_SUCCESS)
goto out;
out:
@@ -588,7 +599,7 @@ skein_mac_atomic(crypto_mechanism_t *mechanism,
if ((error = skein_update(&ctx, data)) != CRYPTO_SUCCESS)
goto errout;
- if ((error = skein_final(&ctx, mac)) != CRYPTO_SUCCESS)
+ if ((error = skein_final_nofree(&ctx, mac)) != CRYPTO_SUCCESS)
goto errout;
return (CRYPTO_SUCCESS);
diff --git a/module/icp/spi/kcf_spi.c b/module/icp/spi/kcf_spi.c
index 87e765d4786c..b0af101990ed 100644
--- a/module/icp/spi/kcf_spi.c
+++ b/module/icp/spi/kcf_spi.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/lua/lapi.c b/module/lua/lapi.c
index 726e5c2ad4bb..703cf4cc2a36 100644
--- a/module/lua/lapi.c
+++ b/module/lua/lapi.c
@@ -250,6 +250,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);
}
@@ -442,7 +444,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TTABLE: return hvalue(o);
case LUA_TLCL: return clLvalue(o);
case LUA_TCCL: return clCvalue(o);
- case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
+ case LUA_TLCF: return cast(void *, cast(uintptr_t, fvalue(o)));
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
diff --git a/module/lua/ldebug.c b/module/lua/ldebug.c
index 0092474c762d..23e321bb1247 100644
--- a/module/lua/ldebug.c
+++ b/module/lua/ldebug.c
@@ -111,10 +111,11 @@ static const char *upvalname (Proto *p, int uv) {
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
int nparams = clLvalue(ci->func)->p->numparams;
- if (n >= ci->u.l.base - ci->func - nparams)
+ int nvararg = cast_int(ci->u.l.base - ci->func) - nparams;
+ if (n <= -nvararg)
return NULL; /* no such vararg */
else {
- *pos = ci->func + nparams + n;
+ *pos = ci->func + nparams - n;
return "(*vararg)"; /* generic name for any vararg */
}
}
@@ -126,7 +127,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n,
StkId base;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
- return findvararg(ci, -n, pos);
+ return findvararg(ci, n, pos);
else {
base = ci->u.l.base;
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
diff --git a/module/lua/ldo.c b/module/lua/ldo.c
index b9368d9ceab6..38bd4e08a73d 100644
--- a/module/lua/ldo.c
+++ b/module/lua/ldo.c
@@ -9,6 +9,7 @@
#define LUA_CORE
#include <sys/lua/lua.h>
+#include <sys/asm_linkage.h>
#include "lapi.h"
#include "ldebug.h"
@@ -27,7 +28,6 @@
#include "lzio.h"
-
/* Return the number of bytes available on the stack. */
#if defined (_KERNEL) && defined(__linux__)
#include <asm/current.h>
@@ -84,14 +84,16 @@ static intptr_t stack_remaining(void) {
#define JMP_BUF_CNT 18
#elif defined(__riscv)
#define JMP_BUF_CNT 64
+#elif defined(__loongarch_lp64)
+#define JMP_BUF_CNT 64
#else
#define JMP_BUF_CNT 1
#endif
typedef struct _label_t { long long unsigned val[JMP_BUF_CNT]; } label_t;
-int setjmp(label_t *) __attribute__ ((__nothrow__));
-extern __attribute__((noreturn)) void longjmp(label_t *);
+int ASMABI setjmp(label_t *) __attribute__ ((__nothrow__));
+extern __attribute__((noreturn)) void ASMABI longjmp(label_t *);
#define LUAI_THROW(L,c) longjmp(&(c)->b)
#define LUAI_TRY(L,c,a) if (setjmp(&(c)->b) == 0) { a }
@@ -170,7 +172,8 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
/*
* Silence infinite recursion warning which was added to -Wall in gcc 12.1
*/
-#if defined(HAVE_INFINITE_RECURSION)
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(HAVE_KERNEL_INFINITE_RECURSION)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winfinite-recursion"
#endif
@@ -196,7 +199,8 @@ l_noret luaD_throw (lua_State *L, int errcode) {
}
}
-#if defined(HAVE_INFINITE_RECURSION)
+#if defined(__GNUC__) && !defined(__clang__) && \
+ defined(HAVE_INFINITE_RECURSION)
#pragma GCC diagnostic pop
#endif
@@ -405,7 +409,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
StkId base;
Proto *p = clLvalue(func)->p;
n = cast_int(L->top - func) - 1; /* number of real arguments */
- luaD_checkstack(L, p->maxstacksize);
+ luaD_checkstack(L, p->maxstacksize + p->numparams);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
if (!p->is_vararg) {
@@ -452,7 +456,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
}
res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults;
- L->ci = ci = ci->previous; /* back to caller */
+ L->ci = ci->previous; /* back to caller */
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--)
setobjs2s(L, res++, firstResult++);
diff --git a/module/lua/lfunc.h b/module/lua/lfunc.h
index ca0d3a3e0b03..1dc6995ca9d7 100644
--- a/module/lua/lfunc.h
+++ b/module/lua/lfunc.h
@@ -12,10 +12,10 @@
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
- cast(int, sizeof(TValue)*((n)-1)))
+ cast(int, sizeof(TValue)*((n))))
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
- cast(int, sizeof(TValue *)*((n)-1)))
+ cast(int, sizeof(TValue *)*((n))))
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
diff --git a/module/lua/lgc.c b/module/lua/lgc.c
index 0ec18ea4839f..ccb8c019b94a 100644
--- a/module/lua/lgc.c
+++ b/module/lua/lgc.c
@@ -1056,7 +1056,7 @@ static lu_mem singlestep (lua_State *L) {
lu_mem work;
int sw;
g->gcstate = GCSatomic; /* finish mark phase */
- g->GCestimate = g->GCmemtrav; /* save what was counted */;
+ g->GCestimate = g->GCmemtrav; /* save what was counted */
work = atomic(L); /* add what was traversed by 'atomic' */
g->GCestimate += work; /* estimate of total memory traversed */
sw = entersweep(L);
diff --git a/module/lua/lgc.h b/module/lua/lgc.h
index 84bb1cdf99fa..02f17fe1239e 100644
--- a/module/lua/lgc.h
+++ b/module/lua/lgc.h
@@ -120,7 +120,7 @@
#define luaC_condGC(L,c) \
- {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
+ {if (G(L)->GCdebt > 0) {c;} condchangemem(L);}
#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);)
diff --git a/module/lua/lobject.c b/module/lua/lobject.c
index f74dacdf5faf..ea1f9a8e3b92 100644
--- a/module/lua/lobject.c
+++ b/module/lua/lobject.c
@@ -143,7 +143,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/lobject.h b/module/lua/lobject.h
index d29d0068c7e6..b7c6b41ac7f4 100644
--- a/module/lua/lobject.h
+++ b/module/lua/lobject.h
@@ -513,14 +513,14 @@ typedef struct UpVal {
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
- TValue upvalue[1]; /* list of upvalues */
+ TValue upvalue[]; /* list of upvalues */
} CClosure;
typedef struct LClosure {
ClosureHeader;
struct Proto *p;
- UpVal *upvals[1]; /* list of upvalues */
+ UpVal *upvals[]; /* list of upvalues */
} LClosure;
diff --git a/module/lua/lvm.c b/module/lua/lvm.c
index b5545732535c..53b9884f0a71 100644
--- a/module/lua/lvm.c
+++ b/module/lua/lvm.c
@@ -568,7 +568,7 @@ void luaV_finishOp (lua_State *L) {
#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); }
-#define Protect(x) { {x;}; base = ci->u.l.base; }
+#define Protect(x) { {x;} base = ci->u.l.base; }
#define checkGC(L,c) \
Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \
diff --git a/module/lua/setjmp/setjmp.S b/module/lua/setjmp/setjmp.S
index 1f461a0a4ef3..6f03eea92711 100644
--- a/module/lua/setjmp/setjmp.S
+++ b/module/lua/setjmp/setjmp.S
@@ -16,4 +16,6 @@
#include "setjmp_s390x.S"
#elif defined(__riscv)
#include "setjmp_rv64g.S"
+#elif defined(__loongarch_lp64)
+#include "setjmp_loongarch64.S"
#endif
diff --git a/module/lua/setjmp/setjmp_aarch64.S b/module/lua/setjmp/setjmp_aarch64.S
index a5a9a85fd57e..040ef1821ab0 100644
--- a/module/lua/setjmp/setjmp_aarch64.S
+++ b/module/lua/setjmp/setjmp_aarch64.S
@@ -35,7 +35,7 @@
#define ENTRY(sym) \
.text; \
.globl sym; \
- .align 2; \
+ .balign 2; \
.type sym,#function; \
sym:
diff --git a/module/lua/setjmp/setjmp_arm.S b/module/lua/setjmp/setjmp_arm.S
index 78bc3e0b347d..0b18a96282cf 100644
--- a/module/lua/setjmp/setjmp_arm.S
+++ b/module/lua/setjmp/setjmp_arm.S
@@ -40,7 +40,7 @@
#define ENTRY(x) \
.text; \
.syntax unified; \
- .align 2; \
+ .balign 2; \
.global x; \
.type x,#function; \
_FUNC_MODE; \
diff --git a/module/lua/setjmp/setjmp_i386.S b/module/lua/setjmp/setjmp_i386.S
index 6d6a5f332688..87f9cb08c292 100644
--- a/module/lua/setjmp/setjmp_i386.S
+++ b/module/lua/setjmp/setjmp_i386.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,7 +25,7 @@
#define ENTRY(x) \
.text; \
- .align 8; \
+ .balign 8; \
.globl x; \
.type x, @function; \
x:
diff --git a/module/lua/setjmp/setjmp_loongarch64.S b/module/lua/setjmp/setjmp_loongarch64.S
new file mode 100644
index 000000000000..216b829ff236
--- /dev/null
+++ b/module/lua/setjmp/setjmp_loongarch64.S
@@ -0,0 +1,82 @@
+/*-
+ * Copyright 2022 Han Gao <gaohan@uniontech.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if __loongarch_lp64
+
+#define ENTRY(symbol) \
+ .text; \
+ .globl symbol; \
+ .align 3; \
+ .type symbol, @function; \
+ symbol:
+
+#define END(function) \
+ .size function, .- function;
+
+ENTRY(setjmp)
+ st.d $ra, $a0, 0*8
+ st.d $sp, $a0, 1*8
+ st.d $r21, $a0, 2*8
+ st.d $fp, $a0, 3*8
+ st.d $s0, $a0, 4*8
+ st.d $s1, $a0, 5*8
+ st.d $s2, $a0, 6*8
+ st.d $s3, $a0, 7*8
+ st.d $s4, $a0, 8*8
+ st.d $s5, $a0, 9*8
+ st.d $s6, $a0, 10*8
+ st.d $s7, $a0, 11*8
+ st.d $s8, $a0, 12*8
+
+ li.w $a0, 0
+ jr $ra
+END(setjmp)
+
+ENTRY(longjmp)
+ ld.d $ra, $a0, 0*8
+ ld.d $sp, $a0, 1*8
+ ld.d $r21, $a0, 2*8
+ ld.d $fp, $a0, 3*8
+ ld.d $s0, $a0, 4*8
+ ld.d $s1, $a0, 5*8
+ ld.d $s2, $a0, 6*8
+ ld.d $s3, $a0, 7*8
+ ld.d $s4, $a0, 8*8
+ ld.d $s5, $a0, 9*8
+ ld.d $s6, $a0, 10*8
+ ld.d $s7, $a0, 11*8
+ ld.d $s8, $a0, 12*8
+
+ sltui $a0, $a1, 1
+ add.d $a0, $a0, $a1 // a0 = (a1 == 0) ? 1 : a1
+ jr $ra
+END(longjmp)
+
+#ifdef __ELF__
+.section .note.GNU-stack,"",%progbits
+#endif
+
+#endif
diff --git a/module/lua/setjmp/setjmp_ppc.S b/module/lua/setjmp/setjmp_ppc.S
index 72aa5d5ab5b0..a035cd11b33b 100644
--- a/module/lua/setjmp/setjmp_ppc.S
+++ b/module/lua/setjmp/setjmp_ppc.S
@@ -54,7 +54,7 @@
#ifdef PPC64_ELF_ABI_v2
#define ENTRY(name) \
- .align 2 ; \
+ .balign 2 ; \
.type name,@function; \
.weak name; \
name:
@@ -64,7 +64,7 @@ name:
#define XGLUE(a,b) a##b
#define GLUE(a,b) XGLUE(a,b)
#define ENTRY(name) \
- .align 2 ; \
+ .balign 2 ; \
.weak name; \
.weak GLUE(.,name); \
.pushsection ".opd","aw"; \
diff --git a/module/lua/setjmp/setjmp_sparc64.S b/module/lua/setjmp/setjmp_sparc64.S
index a37a71cbce33..e1099643de92 100644
--- a/module/lua/setjmp/setjmp_sparc64.S
+++ b/module/lua/setjmp/setjmp_sparc64.S
@@ -50,7 +50,7 @@
#define ENTRY(x) \
.text ; \
- .align 32 ; \
+ .balign 32 ; \
.globl x ; \
.type x,@function ; \
x:
diff --git a/module/lua/setjmp/setjmp_x86_64.S b/module/lua/setjmp/setjmp_x86_64.S
index 34cf2c7dce93..337fceb15b00 100644
--- a/module/lua/setjmp/setjmp_x86_64.S
+++ b/module/lua/setjmp/setjmp_x86_64.S
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,22 +23,8 @@
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-
-#define ENTRY(x) \
- .text; \
- .align 8; \
- .globl x; \
- .type x, @function; \
-x:
-
-#define SET_SIZE(x) \
- .size x, [.-x]
-
-
-#if defined(__linux__) && defined(CONFIG_SLS)
-#define RET ret; int3
-#else
-#define RET ret
+#if defined(_KERNEL) && defined(__linux__)
+#include <linux/linkage.h>
#endif
/*
@@ -47,7 +33,10 @@ x:
*/
#ifdef __x86_64__
- ENTRY(setjmp)
+#define _ASM
+#include <sys/asm_linkage.h>
+
+ENTRY_ALIGN(setjmp, 8)
movq %rsp, 0(%rdi)
movq %rbp, 8(%rdi)
movq %rbx, 16(%rdi)
@@ -61,7 +50,7 @@ x:
RET
SET_SIZE(setjmp)
- ENTRY(longjmp)
+ENTRY_ALIGN(longjmp, 8)
movq 0(%rdi), %rsp
movq 8(%rdi), %rbp
movq 16(%rdi), %rbx
diff --git a/module/nvpair/fnvpair.c b/module/nvpair/fnvpair.c
index 43c4b73590c4..cc2233c40391 100644
--- a/module/nvpair/fnvpair.c
+++ b/module/nvpair/fnvpair.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -402,10 +402,10 @@ fnvlist_lookup_uint64(const nvlist_t *nvl, const char *name)
return (rv);
}
-char *
-fnvlist_lookup_string(nvlist_t *nvl, const char *name)
+const char *
+fnvlist_lookup_string(const nvlist_t *nvl, const char *name)
{
- char *rv;
+ const char *rv;
VERIFY0(nvlist_lookup_string(nvl, name, &rv));
return (rv);
}
@@ -577,10 +577,10 @@ fnvpair_value_uint64(const nvpair_t *nvp)
return (rv);
}
-char *
-fnvpair_value_string(nvpair_t *nvp)
+const char *
+fnvpair_value_string(const nvpair_t *nvp)
{
- char *rv;
+ const char *rv;
VERIFY0(nvpair_value_string(nvp, &rv));
return (rv);
}
diff --git a/module/nvpair/nvpair.c b/module/nvpair/nvpair.c
index a442990dade0..887f7d32df4a 100644
--- a/module/nvpair/nvpair.c
+++ b/module/nvpair/nvpair.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,6 +41,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/string.h>
+#include <rpc/types.h>
#include <rpc/xdr.h>
#include <sys/mod.h>
@@ -473,7 +474,7 @@ nvt_remove_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
}
i_nvp_t **tab = priv->nvp_hashtable;
- char *name = NVP_NAME(nvp);
+ const char *name = NVP_NAME(nvp);
uint64_t hash = nvt_hash(name);
uint64_t index = hash & (priv->nvp_nbuckets - 1);
@@ -528,7 +529,7 @@ nvt_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
}
i_nvp_t **tab = priv->nvp_hashtable;
- char *name = NVP_NAME(nvp);
+ const char *name = NVP_NAME(nvp);
uint64_t hash = nvt_hash(name);
uint64_t index = hash & (priv->nvp_nbuckets - 1);
@@ -1517,7 +1518,7 @@ nvlist_empty(const nvlist_t *nvl)
return (priv->nvp_list == NULL);
}
-char *
+const char *
nvpair_name(const nvpair_t *nvp)
{
return (NVP_NAME(nvp));
@@ -1731,7 +1732,7 @@ nvlist_lookup_double(const nvlist_t *nvl, const char *name, double *val)
#endif
int
-nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
+nvlist_lookup_string(const nvlist_t *nvl, const char *name, const char **val)
{
return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
}
@@ -1917,7 +1918,7 @@ nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
*/
static int
nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
- nvpair_t **ret, int *ip, char **ep)
+ nvpair_t **ret, int *ip, const char **ep)
{
nvpair_t *nvp;
const char *np;
@@ -2057,8 +2058,11 @@ nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
nvl = EMBEDDED_NVL(nvp);
break;
} else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
- (void) nvpair_value_nvlist_array(nvp,
- &nva, (uint_t *)&n);
+ if (nvpair_value_nvlist_array(nvp,
+ &nva, (uint_t *)&n) != 0)
+ goto fail;
+ if (nva == NULL)
+ goto fail;
if ((n < 0) || (idx >= n))
goto fail;
nvl = nva[idx];
@@ -2094,7 +2098,7 @@ nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
* description.
*/
int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
- const char *name, nvpair_t **ret, int *ip, char **ep)
+ const char *name, nvpair_t **ret, int *ip, const char **ep)
{
return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
}
@@ -2189,7 +2193,7 @@ nvpair_value_double(const nvpair_t *nvp, double *val)
#endif
int
-nvpair_value_string(nvpair_t *nvp, char **val)
+nvpair_value_string(const nvpair_t *nvp, const char **val)
{
return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
}
@@ -2261,7 +2265,7 @@ nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
}
int
-nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
+nvpair_value_string_array(nvpair_t *nvp, const char ***val, uint_t *nelem)
{
return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
}
@@ -2808,7 +2812,7 @@ nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
static void
nvs_native_destroy(nvstream_t *nvs)
{
- (void) nvs;
+ nvs->nvs_private = NULL;
}
static int
@@ -3189,7 +3193,7 @@ nvs_xdr_destroy(nvstream_t *nvs)
switch (nvs->nvs_op) {
case NVS_OP_ENCODE:
case NVS_OP_DECODE:
- xdr_destroy((XDR *)nvs->nvs_private);
+ nvs->nvs_private = NULL;
break;
default:
break;
diff --git a/module/nvpair/nvpair_alloc_fixed.c b/module/nvpair/nvpair_alloc_fixed.c
index d7d3e7afd520..34adb86e0301 100644
--- a/module/nvpair/nvpair_alloc_fixed.c
+++ b/module/nvpair/nvpair_alloc_fixed.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/nvpair/nvpair_alloc_spl.c b/module/nvpair/nvpair_alloc_spl.c
index aa344b6423e8..4ecb029961f5 100644
--- a/module/nvpair/nvpair_alloc_spl.c
+++ b/module/nvpair/nvpair_alloc_spl.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at * usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/freebsd/spl/acl_common.c b/module/os/freebsd/spl/acl_common.c
index 334a8b46398b..04a5d2869d1b 100644
--- a/module/os/freebsd/spl/acl_common.c
+++ b/module/os/freebsd/spl/acl_common.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -1654,13 +1654,13 @@ acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
*/
int
ace_trivial_common(void *acep, int aclcnt,
- uint64_t (*walk)(void *, uint64_t, int aclcnt,
+ uintptr_t (*walk)(void *, uintptr_t, int aclcnt,
uint16_t *, uint16_t *, uint32_t *))
{
uint16_t flags;
uint32_t mask;
uint16_t type;
- uint64_t cookie = 0;
+ uintptr_t cookie = 0;
while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {
switch (flags & ACE_TYPE_FLAGS) {
diff --git a/module/os/freebsd/spl/callb.c b/module/os/freebsd/spl/callb.c
index 5db95bd9716e..850f37ddf5a8 100644
--- a/module/os/freebsd/spl/callb.c
+++ b/module/os/freebsd/spl/callb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -146,7 +146,7 @@ callb_add_common(boolean_t (*func)(void *arg, int code),
cv_wait(&ct->ct_busy_cv, &ct->ct_lock);
if ((cp = ct->ct_freelist) == NULL) {
ct->ct_ncallb++;
- cp = (callb_t *)kmem_zalloc(sizeof (callb_t), KM_SLEEP);
+ cp = kmem_zalloc(sizeof (callb_t), KM_SLEEP);
}
ct->ct_freelist = cp->c_next;
cp->c_thread = t;
@@ -160,8 +160,7 @@ callb_add_common(boolean_t (*func)(void *arg, int code),
"too long -- truncated to %d chars",
name, CB_MAXNAME);
#endif
- (void) strncpy(cp->c_name, name, CB_MAXNAME);
- cp->c_name[CB_MAXNAME] = '\0';
+ (void) strlcpy(cp->c_name, name, sizeof (cp->c_name));
/*
* Insert the new callb at the head of its class list.
@@ -264,7 +263,7 @@ callb_execute_class(int class, int code)
mutex_enter(&ct->ct_lock);
for (cp = ct->ct_first_cb[class];
- cp != NULL && ret == 0; cp = cp->c_next) {
+ cp != NULL && ret == NULL; cp = cp->c_next) {
while (cp->c_flag & CALLB_EXECUTING)
cv_wait(&cp->c_done_cv, &ct->ct_lock);
/*
diff --git a/module/os/freebsd/spl/list.c b/module/os/freebsd/spl/list.c
index 62374a417704..56432050fdc6 100644
--- a/module/os/freebsd/spl/list.c
+++ b/module/os/freebsd/spl/list.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -64,7 +64,8 @@ list_create(list_t *list, size_t size, size_t offset)
ASSERT3P(list, !=, NULL);
ASSERT3U(size, >=, offset + sizeof (list_node_t));
- list->list_size = size;
+ (void) size;
+
list->list_offset = offset;
list->list_head.list_next = list->list_head.list_prev =
&list->list_head;
@@ -194,7 +195,6 @@ list_move_tail(list_t *dst, list_t *src)
list_node_t *dstnode = &dst->list_head;
list_node_t *srcnode = &src->list_head;
- ASSERT3U(dst->list_size, ==, src->list_size);
ASSERT3U(dst->list_offset, ==, src->list_offset);
if (list_empty(src))
diff --git a/module/os/freebsd/spl/sha224.h b/module/os/freebsd/spl/sha224.h
deleted file mode 100644
index 0abd43068708..000000000000
--- a/module/os/freebsd/spl/sha224.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SHA224_H_
-#define _SHA224_H_
-
-#ifndef _KERNEL
-#include <sys/types.h>
-#endif
-
-#define SHA224_BLOCK_LENGTH 64
-#define SHA224_DIGEST_LENGTH 28
-#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
-
-typedef struct SHA224Context {
- uint32_t state[8];
- uint64_t count;
- uint8_t buf[SHA224_BLOCK_LENGTH];
-} SHA224_CTX;
-
-__BEGIN_DECLS
-
-/* Ensure libmd symbols do not clash with libcrypto */
-
-#ifndef SHA224_Init
-#define SHA224_Init _libmd_SHA224_Init
-#endif
-#ifndef SHA224_Update
-#define SHA224_Update _libmd_SHA224_Update
-#endif
-#ifndef SHA224_Final
-#define SHA224_Final _libmd_SHA224_Final
-#endif
-#ifndef SHA224_End
-#define SHA224_End _libmd_SHA224_End
-#endif
-#ifndef SHA224_Fd
-#define SHA224_Fd _libmd_SHA224_Fd
-#endif
-#ifndef SHA224_FdChunk
-#define SHA224_FdChunk _libmd_SHA224_FdChunk
-#endif
-#ifndef SHA224_File
-#define SHA224_File _libmd_SHA224_File
-#endif
-#ifndef SHA224_FileChunk
-#define SHA224_FileChunk _libmd_SHA224_FileChunk
-#endif
-#ifndef SHA224_Data
-#define SHA224_Data _libmd_SHA224_Data
-#endif
-
-#ifndef SHA224_version
-#define SHA224_version _libmd_SHA224_version
-#endif
-
-void SHA224_Init(SHA224_CTX *);
-void SHA224_Update(SHA224_CTX *, const void *, size_t);
-void SHA224_Final(unsigned char [__min_size(SHA224_DIGEST_LENGTH)],
- SHA224_CTX *);
-#ifndef _KERNEL
-char *SHA224_End(SHA224_CTX *, char *);
-char *SHA224_Data(const void *, unsigned int, char *);
-char *SHA224_Fd(int, char *);
-char *SHA224_FdChunk(int, char *, off_t, off_t);
-char *SHA224_File(const char *, char *);
-char *SHA224_FileChunk(const char *, char *, off_t, off_t);
-#endif
-__END_DECLS
-
-#endif /* !_SHA224_H_ */
diff --git a/module/os/freebsd/spl/sha256.h b/module/os/freebsd/spl/sha256.h
deleted file mode 100644
index 193c0c025120..000000000000
--- a/module/os/freebsd/spl/sha256.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SHA256_H_
-#define _SHA256_H_
-
-#ifndef _KERNEL
-#include <sys/types.h>
-#endif
-
-#define SHA256_BLOCK_LENGTH 64
-#define SHA256_DIGEST_LENGTH 32
-#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
-
-typedef struct SHA256Context {
- uint32_t state[8];
- uint64_t count;
- uint8_t buf[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-
-__BEGIN_DECLS
-
-/* Ensure libmd symbols do not clash with libcrypto */
-
-#ifndef SHA256_Init
-#define SHA256_Init _libmd_SHA256_Init
-#endif
-#ifndef SHA256_Update
-#define SHA256_Update _libmd_SHA256_Update
-#endif
-#ifndef SHA256_Final
-#define SHA256_Final _libmd_SHA256_Final
-#endif
-#ifndef SHA256_End
-#define SHA256_End _libmd_SHA256_End
-#endif
-#ifndef SHA256_Fd
-#define SHA256_Fd _libmd_SHA256_Fd
-#endif
-#ifndef SHA256_FdChunk
-#define SHA256_FdChunk _libmd_SHA256_FdChunk
-#endif
-#ifndef SHA256_File
-#define SHA256_File _libmd_SHA256_File
-#endif
-#ifndef SHA256_FileChunk
-#define SHA256_FileChunk _libmd_SHA256_FileChunk
-#endif
-#ifndef SHA256_Data
-#define SHA256_Data _libmd_SHA256_Data
-#endif
-
-#ifndef SHA256_Transform
-#define SHA256_Transform _libmd_SHA256_Transform
-#endif
-#ifndef SHA256_version
-#define SHA256_version _libmd_SHA256_version
-#endif
-
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Update(SHA256_CTX *, const void *, size_t);
-void SHA256_Final(unsigned char [__min_size(SHA256_DIGEST_LENGTH)],
- SHA256_CTX *);
-#ifndef _KERNEL
-char *SHA256_End(SHA256_CTX *, char *);
-char *SHA256_Data(const void *, unsigned int, char *);
-char *SHA256_Fd(int, char *);
-char *SHA256_FdChunk(int, char *, off_t, off_t);
-char *SHA256_File(const char *, char *);
-char *SHA256_FileChunk(const char *, char *, off_t, off_t);
-#endif
-__END_DECLS
-
-#endif /* !_SHA256_H_ */
diff --git a/module/os/freebsd/spl/sha256c.c b/module/os/freebsd/spl/sha256c.c
deleted file mode 100644
index 52cf0df6c99d..000000000000
--- a/module/os/freebsd/spl/sha256c.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-
-#ifdef _KERNEL
-#include <sys/systm.h>
-#else
-#include <string.h>
-#endif
-
-
-#include <sys/byteorder.h>
-#include <sys/endian.h>
-#include "sha224.h"
-#include "sha256.h"
-
-#if BYTE_ORDER == BIG_ENDIAN
-
-/* Copy a vector of big-endian uint32_t into a vector of bytes */
-#define be32enc_vect(dst, src, len) \
- memcpy((void *)dst, (const void *)src, (size_t)len)
-
-/* Copy a vector of bytes into a vector of big-endian uint32_t */
-#define be32dec_vect(dst, src, len) \
- memcpy((void *)dst, (const void *)src, (size_t)len)
-
-#else /* BYTE_ORDER != BIG_ENDIAN */
-
-/*
- * Encode a length len/4 vector of (uint32_t) into a length len vector of
- * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
- */
-static void
-be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len / 4; i++)
- be32enc(dst + i * 4, src[i]);
-}
-
-/*
- * Decode a big-endian length len vector of (unsigned char) into a length
- * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
- */
-static void
-be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len / 4; i++)
- dst[i] = be32dec(src + i * 4);
-}
-
-#endif /* BYTE_ORDER != BIG_ENDIAN */
-
-/* SHA256 round constants. */
-static const uint32_t K[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-/* Elementary functions used by SHA256 */
-#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
-#define Maj(x, y, z) ((x & (y | z)) | (y & z))
-#define SHR(x, n) (x >> n)
-#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
-#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
-#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
-#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
-#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
-
-/* SHA256 round function */
-#define RND(a, b, c, d, e, f, g, h, k) \
- h += S1(e) + Ch(e, f, g) + k; \
- d += h; \
- h += S0(a) + Maj(a, b, c);
-
-/* Adjusted round function for rotating state */
-#define RNDr(S, W, i, ii) \
- RND(S[(64 - i) % 8], S[(65 - i) % 8], \
- S[(66 - i) % 8], S[(67 - i) % 8], \
- S[(68 - i) % 8], S[(69 - i) % 8], \
- S[(70 - i) % 8], S[(71 - i) % 8], \
- W[i + ii] + K[i + ii])
-
-/* Message schedule computation */
-#define MSCH(W, ii, i) \
- W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + \
- s0(W[i + ii + 1]) + W[i + ii]
-
-/*
- * SHA256 block compression function. The 256-bit state is transformed via
- * the 512-bit input block to produce a new state.
- */
-static void
-SHA256_Transform(uint32_t *state, const unsigned char block[64])
-{
- uint32_t W[64];
- uint32_t S[8];
- int i;
-
- /* 1. Prepare the first part of the message schedule W. */
- be32dec_vect(W, block, 64);
-
- /* 2. Initialize working variables. */
- memcpy(S, state, 32);
-
- /* 3. Mix. */
- for (i = 0; i < 64; i += 16) {
- RNDr(S, W, 0, i);
- RNDr(S, W, 1, i);
- RNDr(S, W, 2, i);
- RNDr(S, W, 3, i);
- RNDr(S, W, 4, i);
- RNDr(S, W, 5, i);
- RNDr(S, W, 6, i);
- RNDr(S, W, 7, i);
- RNDr(S, W, 8, i);
- RNDr(S, W, 9, i);
- RNDr(S, W, 10, i);
- RNDr(S, W, 11, i);
- RNDr(S, W, 12, i);
- RNDr(S, W, 13, i);
- RNDr(S, W, 14, i);
- RNDr(S, W, 15, i);
-
- if (i == 48)
- break;
- MSCH(W, 0, i);
- MSCH(W, 1, i);
- MSCH(W, 2, i);
- MSCH(W, 3, i);
- MSCH(W, 4, i);
- MSCH(W, 5, i);
- MSCH(W, 6, i);
- MSCH(W, 7, i);
- MSCH(W, 8, i);
- MSCH(W, 9, i);
- MSCH(W, 10, i);
- MSCH(W, 11, i);
- MSCH(W, 12, i);
- MSCH(W, 13, i);
- MSCH(W, 14, i);
- MSCH(W, 15, i);
- }
-
- /* 4. Mix local working variables into global state */
- for (i = 0; i < 8; i++)
- state[i] += S[i];
-}
-
-static unsigned char PAD[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* Add padding and terminating bit-count. */
-static void
-SHA256_Pad(SHA256_CTX * ctx)
-{
- size_t r;
-
- /* Figure out how many bytes we have buffered. */
- r = (ctx->count >> 3) & 0x3f;
-
- /* Pad to 56 mod 64, transforming if we finish a block en route. */
- if (r < 56) {
- /* Pad to 56 mod 64. */
- memcpy(&ctx->buf[r], PAD, 56 - r);
- } else {
- /* Finish the current block and mix. */
- memcpy(&ctx->buf[r], PAD, 64 - r);
- SHA256_Transform(ctx->state, ctx->buf);
-
- /* The start of the final block is all zeroes. */
- memset(&ctx->buf[0], 0, 56);
- }
-
- /* Add the terminating bit-count. */
- be64enc(&ctx->buf[56], ctx->count);
-
- /* Mix in the final block. */
- SHA256_Transform(ctx->state, ctx->buf);
-}
-
-/* SHA-256 initialization. Begins a SHA-256 operation. */
-void
-SHA256_Init(SHA256_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0x6A09E667;
- ctx->state[1] = 0xBB67AE85;
- ctx->state[2] = 0x3C6EF372;
- ctx->state[3] = 0xA54FF53A;
- ctx->state[4] = 0x510E527F;
- ctx->state[5] = 0x9B05688C;
- ctx->state[6] = 0x1F83D9AB;
- ctx->state[7] = 0x5BE0CD19;
-}
-
-/* Add bytes into the hash */
-void
-SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
-{
- uint64_t bitlen;
- uint32_t r;
- const unsigned char *src = in;
-
- /* Number of bytes left in the buffer from previous updates */
- r = (ctx->count >> 3) & 0x3f;
-
- /* Convert the length into a number of bits */
- bitlen = len << 3;
-
- /* Update number of bits */
- ctx->count += bitlen;
-
- /* Handle the case where we don't need to perform any transforms */
- if (len < 64 - r) {
- memcpy(&ctx->buf[r], src, len);
- return;
- }
-
- /* Finish the current block */
- memcpy(&ctx->buf[r], src, 64 - r);
- SHA256_Transform(ctx->state, ctx->buf);
- src += 64 - r;
- len -= 64 - r;
-
- /* Perform complete blocks */
- while (len >= 64) {
- SHA256_Transform(ctx->state, src);
- src += 64;
- len -= 64;
- }
-
- /* Copy left over data into buffer */
- memcpy(ctx->buf, src, len);
-}
-
-/*
- * SHA-256 finalization. Pads the input data, exports the hash value,
- * and clears the context state.
- */
-void
-SHA256_Final(unsigned char digest[static SHA256_DIGEST_LENGTH], SHA256_CTX *ctx)
-{
-
- /* Add padding */
- SHA256_Pad(ctx);
-
- /* Write the hash */
- be32enc_vect(digest, ctx->state, SHA256_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-/* SHA-224: ******************************************************* */
-/*
- * the SHA224 and SHA256 transforms are identical
- */
-
-/* SHA-224 initialization. Begins a SHA-224 operation. */
-void
-SHA224_Init(SHA224_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0xC1059ED8;
- ctx->state[1] = 0x367CD507;
- ctx->state[2] = 0x3070DD17;
- ctx->state[3] = 0xF70E5939;
- ctx->state[4] = 0xFFC00B31;
- ctx->state[5] = 0x68581511;
- ctx->state[6] = 0x64f98FA7;
- ctx->state[7] = 0xBEFA4FA4;
-}
-
-/* Add bytes into the SHA-224 hash */
-void
-SHA224_Update(SHA224_CTX * ctx, const void *in, size_t len)
-{
-
- SHA256_Update((SHA256_CTX *)ctx, in, len);
-}
-
-/*
- * SHA-224 finalization. Pads the input data, exports the hash value,
- * and clears the context state.
- */
-void
-SHA224_Final(unsigned char digest[static SHA224_DIGEST_LENGTH], SHA224_CTX *ctx)
-{
-
- /* Add padding */
- SHA256_Pad((SHA256_CTX *)ctx);
-
- /* Write the hash */
- be32enc_vect(digest, ctx->state, SHA224_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-#ifdef WEAK_REFS
-/*
- * When building libmd, provide weak references. Note: this is not
- * activated in the context of compiling these sources for internal
- * use in libcrypt.
- */
-#undef SHA256_Init
-__weak_reference(_libmd_SHA256_Init, SHA256_Init);
-#undef SHA256_Update
-__weak_reference(_libmd_SHA256_Update, SHA256_Update);
-#undef SHA256_Final
-__weak_reference(_libmd_SHA256_Final, SHA256_Final);
-#undef SHA256_Transform
-__weak_reference(_libmd_SHA256_Transform, SHA256_Transform);
-
-#undef SHA224_Init
-__weak_reference(_libmd_SHA224_Init, SHA224_Init);
-#undef SHA224_Update
-__weak_reference(_libmd_SHA224_Update, SHA224_Update);
-#undef SHA224_Final
-__weak_reference(_libmd_SHA224_Final, SHA224_Final);
-#endif
diff --git a/module/os/freebsd/spl/sha384.h b/module/os/freebsd/spl/sha384.h
deleted file mode 100644
index 67250cee0313..000000000000
--- a/module/os/freebsd/spl/sha384.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SHA384_H_
-#define _SHA384_H_
-
-#ifndef _KERNEL
-#include <sys/types.h>
-#endif
-
-#define SHA384_BLOCK_LENGTH 128
-#define SHA384_DIGEST_LENGTH 48
-#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
-
-typedef struct SHA384Context {
- uint64_t state[8];
- uint64_t count[2];
- uint8_t buf[SHA384_BLOCK_LENGTH];
-} SHA384_CTX;
-
-__BEGIN_DECLS
-
-/* Ensure libmd symbols do not clash with libcrypto */
-#ifndef SHA384_Init
-#define SHA384_Init _libmd_SHA384_Init
-#endif
-#ifndef SHA384_Update
-#define SHA384_Update _libmd_SHA384_Update
-#endif
-#ifndef SHA384_Final
-#define SHA384_Final _libmd_SHA384_Final
-#endif
-#ifndef SHA384_End
-#define SHA384_End _libmd_SHA384_End
-#endif
-#ifndef SHA384_Fd
-#define SHA384_Fd _libmd_SHA384_Fd
-#endif
-#ifndef SHA384_FdChunk
-#define SHA384_FdChunk _libmd_SHA384_FdChunk
-#endif
-#ifndef SHA384_File
-#define SHA384_File _libmd_SHA384_File
-#endif
-#ifndef SHA384_FileChunk
-#define SHA384_FileChunk _libmd_SHA384_FileChunk
-#endif
-#ifndef SHA384_Data
-#define SHA384_Data _libmd_SHA384_Data
-#endif
-
-#ifndef SHA384_version
-#define SHA384_version _libmd_SHA384_version
-#endif
-
-void SHA384_Init(SHA384_CTX *);
-void SHA384_Update(SHA384_CTX *, const void *, size_t);
-void SHA384_Final(unsigned char [__min_size(SHA384_DIGEST_LENGTH)],
- SHA384_CTX *);
-#ifndef _KERNEL
-char *SHA384_End(SHA384_CTX *, char *);
-char *SHA384_Data(const void *, unsigned int, char *);
-char *SHA384_Fd(int, char *);
-char *SHA384_FdChunk(int, char *, off_t, off_t);
-char *SHA384_File(const char *, char *);
-char *SHA384_FileChunk(const char *, char *, off_t, off_t);
-#endif
-
-__END_DECLS
-
-#endif /* !_SHA384_H_ */
diff --git a/module/os/freebsd/spl/sha512.h b/module/os/freebsd/spl/sha512.h
deleted file mode 100644
index b6fb733ca54e..000000000000
--- a/module/os/freebsd/spl/sha512.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SHA512_H_
-#define _SHA512_H_
-
-#ifndef _KERNEL
-#include <sys/types.h>
-#endif
-
-#define SHA512_BLOCK_LENGTH 128
-#define SHA512_DIGEST_LENGTH 64
-#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
-
-typedef struct SHA512Context {
- uint64_t state[8];
- uint64_t count[2];
- uint8_t buf[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
-
-__BEGIN_DECLS
-
-/* Ensure libmd symbols do not clash with libcrypto */
-#if 0
-#ifndef SHA512_Init
-#define SHA512_Init _libmd_SHA512_Init
-#endif
-#ifndef SHA512_Update
-#define SHA512_Update _libmd_SHA512_Update
-#endif
-#ifndef SHA512_Final
-#define SHA512_Final _libmd_SHA512_Final
-#endif
-#endif
-#ifndef SHA512_End
-#define SHA512_End _libmd_SHA512_End
-#endif
-#ifndef SHA512_Fd
-#define SHA512_Fd _libmd_SHA512_Fd
-#endif
-#ifndef SHA512_FdChunk
-#define SHA512_FdChunk _libmd_SHA512_FdChunk
-#endif
-#ifndef SHA512_File
-#define SHA512_File _libmd_SHA512_File
-#endif
-#ifndef SHA512_FileChunk
-#define SHA512_FileChunk _libmd_SHA512_FileChunk
-#endif
-#ifndef SHA512_Data
-#define SHA512_Data _libmd_SHA512_Data
-#endif
-
-#ifndef SHA512_Transform
-#define SHA512_Transform _libmd_SHA512_Transform
-#endif
-#ifndef SHA512_version
-#define SHA512_version _libmd_SHA512_version
-#endif
-
-void SHA512_Init(SHA512_CTX *);
-void SHA512_Update(SHA512_CTX *, const void *, size_t);
-void SHA512_Final(unsigned char [__min_size(SHA512_DIGEST_LENGTH)],
- SHA512_CTX *);
-#ifndef _KERNEL
-char *SHA512_End(SHA512_CTX *, char *);
-char *SHA512_Data(const void *, unsigned int, char *);
-char *SHA512_Fd(int, char *);
-char *SHA512_FdChunk(int, char *, off_t, off_t);
-char *SHA512_File(const char *, char *);
-char *SHA512_FileChunk(const char *, char *, off_t, off_t);
-#endif
-
-__END_DECLS
-
-#endif /* !_SHA512_H_ */
diff --git a/module/os/freebsd/spl/sha512c.c b/module/os/freebsd/spl/sha512c.c
deleted file mode 100644
index 254cc21565c1..000000000000
--- a/module/os/freebsd/spl/sha512c.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright 2005 Colin Percival
- * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/endian.h>
-#include <sys/types.h>
-
-#ifdef _KERNEL
-#include <sys/systm.h>
-#else
-#include <string.h>
-#endif
-
-#include "sha512.h"
-#include "sha512t.h"
-#include "sha384.h"
-
-#if BYTE_ORDER == BIG_ENDIAN
-
-/* Copy a vector of big-endian uint64_t into a vector of bytes */
-#define be64enc_vect(dst, src, len) \
- memcpy((void *)dst, (const void *)src, (size_t)len)
-
-/* Copy a vector of bytes into a vector of big-endian uint64_t */
-#define be64dec_vect(dst, src, len) \
- memcpy((void *)dst, (const void *)src, (size_t)len)
-
-#else /* BYTE_ORDER != BIG_ENDIAN */
-
-/*
- * Encode a length len/4 vector of (uint64_t) into a length len vector of
- * (unsigned char) in big-endian form. Assumes len is a multiple of 8.
- */
-static void
-be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len / 8; i++)
- be64enc(dst + i * 8, src[i]);
-}
-
-/*
- * Decode a big-endian length len vector of (unsigned char) into a length
- * len/4 vector of (uint64_t). Assumes len is a multiple of 8.
- */
-static void
-be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len / 8; i++)
- dst[i] = be64dec(src + i * 8);
-}
-
-#endif /* BYTE_ORDER != BIG_ENDIAN */
-
-/* SHA512 round constants. */
-static const uint64_t K[80] = {
- 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
- 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
- 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
- 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
- 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
- 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
- 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
- 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
- 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
- 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
- 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
- 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
- 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
- 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
- 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
- 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
- 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
- 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
- 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
- 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
- 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
- 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
- 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
- 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
- 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
- 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
- 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
- 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
- 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
- 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
- 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
- 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
- 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
- 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
- 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
- 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
- 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
- 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
- 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
- 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
-};
-
-/* Elementary functions used by SHA512 */
-#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
-#define Maj(x, y, z) ((x & (y | z)) | (y & z))
-#define SHR(x, n) (x >> n)
-#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
-#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
-#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
-#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
-#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
-
-/* SHA512 round function */
-#define RND(a, b, c, d, e, f, g, h, k) \
- h += S1(e) + Ch(e, f, g) + k; \
- d += h; \
- h += S0(a) + Maj(a, b, c);
-
-/* Adjusted round function for rotating state */
-#define RNDr(S, W, i, ii) \
- RND(S[(80 - i) % 8], S[(81 - i) % 8], \
- S[(82 - i) % 8], S[(83 - i) % 8], \
- S[(84 - i) % 8], S[(85 - i) % 8], \
- S[(86 - i) % 8], S[(87 - i) % 8], \
- W[i + ii] + K[i + ii])
-
-/* Message schedule computation */
-#define MSCH(W, ii, i) \
- W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + \
- s0(W[i + ii + 1]) + W[i + ii]
-
-/*
- * SHA512 block compression function. The 512-bit state is transformed via
- * the 512-bit input block to produce a new state.
- */
-static void
-SHA512_Transform(uint64_t *state,
- const unsigned char block[SHA512_BLOCK_LENGTH])
-{
- uint64_t W[80];
- uint64_t S[8];
- int i;
-
- /* 1. Prepare the first part of the message schedule W. */
- be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
-
- /* 2. Initialize working variables. */
- memcpy(S, state, SHA512_DIGEST_LENGTH);
-
- /* 3. Mix. */
- for (i = 0; i < 80; i += 16) {
- RNDr(S, W, 0, i);
- RNDr(S, W, 1, i);
- RNDr(S, W, 2, i);
- RNDr(S, W, 3, i);
- RNDr(S, W, 4, i);
- RNDr(S, W, 5, i);
- RNDr(S, W, 6, i);
- RNDr(S, W, 7, i);
- RNDr(S, W, 8, i);
- RNDr(S, W, 9, i);
- RNDr(S, W, 10, i);
- RNDr(S, W, 11, i);
- RNDr(S, W, 12, i);
- RNDr(S, W, 13, i);
- RNDr(S, W, 14, i);
- RNDr(S, W, 15, i);
-
- if (i == 64)
- break;
- MSCH(W, 0, i);
- MSCH(W, 1, i);
- MSCH(W, 2, i);
- MSCH(W, 3, i);
- MSCH(W, 4, i);
- MSCH(W, 5, i);
- MSCH(W, 6, i);
- MSCH(W, 7, i);
- MSCH(W, 8, i);
- MSCH(W, 9, i);
- MSCH(W, 10, i);
- MSCH(W, 11, i);
- MSCH(W, 12, i);
- MSCH(W, 13, i);
- MSCH(W, 14, i);
- MSCH(W, 15, i);
- }
-
- /* 4. Mix local working variables into global state */
- for (i = 0; i < 8; i++)
- state[i] += S[i];
-}
-
-static unsigned char PAD[SHA512_BLOCK_LENGTH] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* Add padding and terminating bit-count. */
-static void
-SHA512_Pad(SHA512_CTX * ctx)
-{
- size_t r;
-
- /* Figure out how many bytes we have buffered. */
- r = (ctx->count[1] >> 3) & 0x7f;
-
- /* Pad to 112 mod 128, transforming if we finish a block en route. */
- if (r < 112) {
- /* Pad to 112 mod 128. */
- memcpy(&ctx->buf[r], PAD, 112 - r);
- } else {
- /* Finish the current block and mix. */
- memcpy(&ctx->buf[r], PAD, 128 - r);
- SHA512_Transform(ctx->state, ctx->buf);
-
- /* The start of the final block is all zeroes. */
- memset(&ctx->buf[0], 0, 112);
- }
-
- /* Add the terminating bit-count. */
- be64enc_vect(&ctx->buf[112], ctx->count, 16);
-
- /* Mix in the final block. */
- SHA512_Transform(ctx->state, ctx->buf);
-}
-
-/* SHA-512 initialization. Begins a SHA-512 operation. */
-void
-SHA512_Init(SHA512_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count[0] = ctx->count[1] = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0x6a09e667f3bcc908ULL;
- ctx->state[1] = 0xbb67ae8584caa73bULL;
- ctx->state[2] = 0x3c6ef372fe94f82bULL;
- ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
- ctx->state[4] = 0x510e527fade682d1ULL;
- ctx->state[5] = 0x9b05688c2b3e6c1fULL;
- ctx->state[6] = 0x1f83d9abfb41bd6bULL;
- ctx->state[7] = 0x5be0cd19137e2179ULL;
-}
-
-/* Add bytes into the hash */
-void
-SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
-{
- uint64_t bitlen[2];
- uint64_t r;
- const unsigned char *src = in;
-
- /* Number of bytes left in the buffer from previous updates */
- r = (ctx->count[1] >> 3) & 0x7f;
-
- /* Convert the length into a number of bits */
- bitlen[1] = ((uint64_t)len) << 3;
- bitlen[0] = ((uint64_t)len) >> 61;
-
- /* Update number of bits */
- if ((ctx->count[1] += bitlen[1]) < bitlen[1])
- ctx->count[0]++;
- ctx->count[0] += bitlen[0];
-
- /* Handle the case where we don't need to perform any transforms */
- if (len < SHA512_BLOCK_LENGTH - r) {
- memcpy(&ctx->buf[r], src, len);
- return;
- }
-
- /* Finish the current block */
- memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r);
- SHA512_Transform(ctx->state, ctx->buf);
- src += SHA512_BLOCK_LENGTH - r;
- len -= SHA512_BLOCK_LENGTH - r;
-
- /* Perform complete blocks */
- while (len >= SHA512_BLOCK_LENGTH) {
- SHA512_Transform(ctx->state, src);
- src += SHA512_BLOCK_LENGTH;
- len -= SHA512_BLOCK_LENGTH;
- }
-
- /* Copy left over data into buffer */
- memcpy(ctx->buf, src, len);
-}
-
-/*
- * SHA-512 finalization. Pads the input data, exports the hash value,
- * and clears the context state.
- */
-void
-SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
-{
-
- /* Add padding */
- SHA512_Pad(ctx);
-
- /* Write the hash */
- be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-/* SHA-512t: ******************************************************** */
-/*
- * the SHA512t transforms are identical to SHA512 so reuse the existing function
- */
-void
-SHA512_224_Init(SHA512_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count[0] = ctx->count[1] = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0x8c3d37c819544da2ULL;
- ctx->state[1] = 0x73e1996689dcd4d6ULL;
- ctx->state[2] = 0x1dfab7ae32ff9c82ULL;
- ctx->state[3] = 0x679dd514582f9fcfULL;
- ctx->state[4] = 0x0f6d2b697bd44da8ULL;
- ctx->state[5] = 0x77e36f7304c48942ULL;
- ctx->state[6] = 0x3f9d85a86a1d36c8ULL;
- ctx->state[7] = 0x1112e6ad91d692a1ULL;
-}
-
-void
-SHA512_224_Update(SHA512_CTX * ctx, const void *in, size_t len)
-{
-
- SHA512_Update(ctx, in, len);
-}
-
-void
-SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH],
- SHA512_CTX *ctx)
-{
-
- /* Add padding */
- SHA512_Pad(ctx);
-
- /* Write the hash */
- be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-void
-SHA512_256_Init(SHA512_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count[0] = ctx->count[1] = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0x22312194fc2bf72cULL;
- ctx->state[1] = 0x9f555fa3c84c64c2ULL;
- ctx->state[2] = 0x2393b86b6f53b151ULL;
- ctx->state[3] = 0x963877195940eabdULL;
- ctx->state[4] = 0x96283ee2a88effe3ULL;
- ctx->state[5] = 0xbe5e1e2553863992ULL;
- ctx->state[6] = 0x2b0199fc2c85b8aaULL;
- ctx->state[7] = 0x0eb72ddc81c52ca2ULL;
-}
-
-void
-SHA512_256_Update(SHA512_CTX * ctx, const void *in, size_t len)
-{
-
- SHA512_Update(ctx, in, len);
-}
-
-void
-SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH],
- SHA512_CTX * ctx)
-{
-
- /* Add padding */
- SHA512_Pad(ctx);
-
- /* Write the hash */
- be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-/* ** SHA-384: ******************************************************** */
-/*
- * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
- */
-
-/* SHA-384 initialization. Begins a SHA-384 operation. */
-void
-SHA384_Init(SHA384_CTX * ctx)
-{
-
- /* Zero bits processed so far */
- ctx->count[0] = ctx->count[1] = 0;
-
- /* Magic initialization constants */
- ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
- ctx->state[1] = 0x629a292a367cd507ULL;
- ctx->state[2] = 0x9159015a3070dd17ULL;
- ctx->state[3] = 0x152fecd8f70e5939ULL;
- ctx->state[4] = 0x67332667ffc00b31ULL;
- ctx->state[5] = 0x8eb44a8768581511ULL;
- ctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
- ctx->state[7] = 0x47b5481dbefa4fa4ULL;
-}
-
-/* Add bytes into the SHA-384 hash */
-void
-SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len)
-{
-
- SHA512_Update((SHA512_CTX *)ctx, in, len);
-}
-
-/*
- * SHA-384 finalization. Pads the input data, exports the hash value,
- * and clears the context state.
- */
-void
-SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH], SHA384_CTX *ctx)
-{
-
- /* Add padding */
- SHA512_Pad((SHA512_CTX *)ctx);
-
- /* Write the hash */
- be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
-
- /* Clear the context state */
- memset(ctx, 0, sizeof (*ctx));
-}
-
-#if 0
-/*
- * When building libmd, provide weak references. Note: this is not
- * activated in the context of compiling these sources for internal
- * use in libcrypt.
- */
-#undef SHA512_Init
-__weak_reference(_libmd_SHA512_Init, SHA512_Init);
-#undef SHA512_Update
-__weak_reference(_libmd_SHA512_Update, SHA512_Update);
-#undef SHA512_Final
-__weak_reference(_libmd_SHA512_Final, SHA512_Final);
-#undef SHA512_Transform
-__weak_reference(_libmd_SHA512_Transform, SHA512_Transform);
-
-#undef SHA512_224_Init
-__weak_reference(_libmd_SHA512_224_Init, SHA512_224_Init);
-#undef SHA512_224_Update
-__weak_reference(_libmd_SHA512_224_Update, SHA512_224_Update);
-#undef SHA512_224_Final
-__weak_reference(_libmd_SHA512_224_Final, SHA512_224_Final);
-
-#undef SHA512_256_Init
-__weak_reference(_libmd_SHA512_256_Init, SHA512_256_Init);
-#undef SHA512_256_Update
-__weak_reference(_libmd_SHA512_256_Update, SHA512_256_Update);
-#undef SHA512_256_Final
-__weak_reference(_libmd_SHA512_256_Final, SHA512_256_Final);
-
-#undef SHA384_Init
-__weak_reference(_libmd_SHA384_Init, SHA384_Init);
-#undef SHA384_Update
-__weak_reference(_libmd_SHA384_Update, SHA384_Update);
-#undef SHA384_Final
-__weak_reference(_libmd_SHA384_Final, SHA384_Final);
-#endif
diff --git a/module/os/freebsd/spl/sha512t.h b/module/os/freebsd/spl/sha512t.h
deleted file mode 100644
index 703867fc0288..000000000000
--- a/module/os/freebsd/spl/sha512t.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _SHA512T_H_
-#define _SHA512T_H_
-
-#include "sha512.h"
-
-#ifndef _KERNEL
-#include <sys/types.h>
-#endif
-
-#define SHA512_224_DIGEST_LENGTH 28
-#define SHA512_224_DIGEST_STRING_LENGTH (SHA512_224_DIGEST_LENGTH * 2 + 1)
-#define SHA512_256_DIGEST_LENGTH 32
-#define SHA512_256_DIGEST_STRING_LENGTH (SHA512_256_DIGEST_LENGTH * 2 + 1)
-
-__BEGIN_DECLS
-
-/* Ensure libmd symbols do not clash with libcrypto */
-#ifndef SHA512_224_Init
-#define SHA512_224_Init _libmd_SHA512_224_Init
-#endif
-#ifndef SHA512_224_Update
-#define SHA512_224_Update _libmd_SHA512_224_Update
-#endif
-#ifndef SHA512_224_Final
-#define SHA512_224_Final _libmd_SHA512_224_Final
-#endif
-#ifndef SHA512_224_End
-#define SHA512_224_End _libmd_SHA512_224_End
-#endif
-#ifndef SHA512_224_Fd
-#define SHA512_224_Fd _libmd_SHA512_224_Fd
-#endif
-#ifndef SHA512_224_FdChunk
-#define SHA512_224_FdChunk _libmd_SHA512_224_FdChunk
-#endif
-#ifndef SHA512_224_File
-#define SHA512_224_File _libmd_SHA512_224_File
-#endif
-#ifndef SHA512_224_FileChunk
-#define SHA512_224_FileChunk _libmd_SHA512_224_FileChunk
-#endif
-#ifndef SHA512_224_Data
-#define SHA512_224_Data _libmd_SHA512_224_Data
-#endif
-
-#ifndef SHA512_224_Transform
-#define SHA512_224_Transform _libmd_SHA512_224_Transform
-#endif
-#ifndef SHA512_224_version
-#define SHA512_224_version _libmd_SHA512_224_version
-#endif
-
-#ifndef SHA512_256_Init
-#define SHA512_256_Init _libmd_SHA512_256_Init
-#endif
-#ifndef SHA512_256_Update
-#define SHA512_256_Update _libmd_SHA512_256_Update
-#endif
-#ifndef SHA512_256_Final
-#define SHA512_256_Final _libmd_SHA512_256_Final
-#endif
-#ifndef SHA512_256_End
-#define SHA512_256_End _libmd_SHA512_256_End
-#endif
-#ifndef SHA512_256_Fd
-#define SHA512_256_Fd _libmd_SHA512_256_Fd
-#endif
-#ifndef SHA512_256_FdChunk
-#define SHA512_256_FdChunk _libmd_SHA512_256_FdChunk
-#endif
-#ifndef SHA512_256_File
-#define SHA512_256_File _libmd_SHA512_256_File
-#endif
-#ifndef SHA512_256_FileChunk
-#define SHA512_256_FileChunk _libmd_SHA512_256_FileChunk
-#endif
-#ifndef SHA512_256_Data
-#define SHA512_256_Data _libmd_SHA512_256_Data
-#endif
-
-#ifndef SHA512_256_Transform
-#define SHA512_256_Transform _libmd_SHA512_256_Transform
-#endif
-#ifndef SHA512_256_version
-#define SHA512_256_version _libmd_SHA512_256_version
-#endif
-
-void SHA512_224_Init(SHA512_CTX *);
-void SHA512_224_Update(SHA512_CTX *, const void *, size_t);
-void SHA512_224_Final(unsigned char [__min_size(SHA512_224_DIGEST_LENGTH)],
- SHA512_CTX *);
-#ifndef _KERNEL
-char *SHA512_224_End(SHA512_CTX *, char *);
-char *SHA512_224_Data(const void *, unsigned int, char *);
-char *SHA512_224_Fd(int, char *);
-char *SHA512_224_FdChunk(int, char *, off_t, off_t);
-char *SHA512_224_File(const char *, char *);
-char *SHA512_224_FileChunk(const char *, char *, off_t, off_t);
-#endif
-void SHA512_256_Init(SHA512_CTX *);
-void SHA512_256_Update(SHA512_CTX *, const void *, size_t);
-void SHA512_256_Final(unsigned char [__min_size(SHA512_256_DIGEST_LENGTH)],
- SHA512_CTX *);
-#ifndef _KERNEL
-char *SHA512_256_End(SHA512_CTX *, char *);
-char *SHA512_256_Data(const void *, unsigned int, char *);
-char *SHA512_256_Fd(int, char *);
-char *SHA512_256_FdChunk(int, char *, off_t, off_t);
-char *SHA512_256_File(const char *, char *);
-char *SHA512_256_FileChunk(const char *, char *, off_t, off_t);
-#endif
-
-__END_DECLS
-
-#endif /* !_SHA512T_H_ */
diff --git a/module/os/freebsd/spl/spl_acl.c b/module/os/freebsd/spl/spl_acl.c
index 4d67cbb183ec..c820d7a6d22d 100644
--- a/module/os/freebsd/spl/spl_acl.c
+++ b/module/os/freebsd/spl/spl_acl.c
@@ -23,9 +23,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
diff --git a/module/os/freebsd/spl/spl_atomic.c b/module/os/freebsd/spl/spl_atomic.c
index 80040fc6a3e3..cdfd37f3e05f 100644
--- a/module/os/freebsd/spl/spl_atomic.c
+++ b/module/os/freebsd/spl/spl_atomic.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
diff --git a/module/os/freebsd/spl/spl_cmn_err.c b/module/os/freebsd/spl/spl_cmn_err.c
index 22c7338b7399..2157da8ebf20 100644
--- a/module/os/freebsd/spl/spl_cmn_err.c
+++ b/module/os/freebsd/spl/spl_cmn_err.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/freebsd/spl/spl_dtrace.c b/module/os/freebsd/spl/spl_dtrace.c
index 6b2872bcc066..4b9cc65d641e 100644
--- a/module/os/freebsd/spl/spl_dtrace.c
+++ b/module/os/freebsd/spl/spl_dtrace.c
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/queue.h>
diff --git a/module/os/freebsd/spl/spl_kmem.c b/module/os/freebsd/spl/spl_kmem.c
index ca9a677567d9..95af6200cd01 100644
--- a/module/os/freebsd/spl/spl_kmem.c
+++ b/module/os/freebsd/spl/spl_kmem.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/byteorder.h>
diff --git a/module/os/freebsd/spl/spl_kstat.c b/module/os/freebsd/spl/spl_kstat.c
index 059ada235c4a..f657ef2a3acb 100644
--- a/module/os/freebsd/spl/spl_kstat.c
+++ b/module/os/freebsd/spl/spl_kstat.c
@@ -28,9 +28,6 @@
* [2] https://illumos.org/man/9f/kstat_create
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/kernel.h>
@@ -39,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kstat.h>
#include <sys/sbuf.h>
+#include <sys/zone.h>
static MALLOC_DEFINE(M_KSTAT, "kstat_data", "Kernel statistics");
@@ -135,21 +133,69 @@ kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
}
static int
+kstat_sysctl_dataset(SYSCTL_HANDLER_ARGS)
+{
+ kstat_t *ksp = arg1;
+ kstat_named_t *ksent;
+ kstat_named_t *ksent_ds;
+ uint64_t val;
+ char *ds_name;
+ uint32_t ds_len = 0;
+
+ ksent_ds = ksent = ksp->ks_data;
+ ds_name = KSTAT_NAMED_STR_PTR(ksent_ds);
+ ds_len = KSTAT_NAMED_STR_BUFLEN(ksent_ds);
+ ds_name[ds_len-1] = '\0';
+
+ if (!zone_dataset_visible(ds_name, NULL)) {
+ return (EPERM);
+ }
+
+ /* Select the correct element */
+ ksent += arg2;
+ /* Update the aggsums before reading */
+ (void) ksp->ks_update(ksp, KSTAT_READ);
+ val = ksent->value.ui64;
+
+ return (sysctl_handle_64(oidp, &val, 0, req));
+}
+
+static int
+kstat_sysctl_dataset_string(SYSCTL_HANDLER_ARGS)
+{
+ kstat_t *ksp = arg1;
+ kstat_named_t *ksent = ksp->ks_data;
+ char *val;
+ uint32_t len = 0;
+
+ /* Select the correct element */
+ ksent += arg2;
+ val = KSTAT_NAMED_STR_PTR(ksent);
+ len = KSTAT_NAMED_STR_BUFLEN(ksent);
+ val[len-1] = '\0';
+
+ if (!zone_dataset_visible(val, NULL)) {
+ return (EPERM);
+ }
+
+ return (sysctl_handle_string(oidp, val, len, req));
+}
+
+static int
kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
{
- struct sbuf *sb;
+ struct sbuf sb;
kstat_t *ksp = arg1;
kstat_io_t *kip = ksp->ks_data;
int rc;
- sb = sbuf_new_auto();
- if (sb == NULL)
- return (ENOMEM);
+ sbuf_new_for_sysctl(&sb, NULL, 0, req);
+
/* Update the aggsums before reading */
(void) ksp->ks_update(ksp, KSTAT_READ);
/* though wlentime & friends are signed, they will never be negative */
- sbuf_printf(sb,
+ sbuf_printf(&sb,
"%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
"%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
kip->nread, kip->nwritten,
@@ -157,25 +203,21 @@ kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
kip->wtime, kip->wlentime, kip->wlastupdate,
kip->rtime, kip->rlentime, kip->rlastupdate,
kip->wcnt, kip->rcnt);
- rc = sbuf_finish(sb);
- if (rc == 0)
- rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
- sbuf_delete(sb);
+ rc = sbuf_finish(&sb);
+ sbuf_delete(&sb);
return (rc);
}
static int
kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
{
- struct sbuf *sb;
+ struct sbuf sb;
void *data;
kstat_t *ksp = arg1;
void *(*addr_op)(kstat_t *ksp, loff_t index);
int n, has_header, rc = 0;
- sb = sbuf_new_auto();
- if (sb == NULL)
- return (ENOMEM);
+ sbuf_new_for_sysctl(&sb, NULL, PAGE_SIZE, req);
if (ksp->ks_raw_ops.addr)
addr_op = ksp->ks_raw_ops.addr;
@@ -208,8 +250,10 @@ restart_headers:
if (has_header) {
if (rc == ENOMEM && !kstat_resize_raw(ksp))
goto restart_headers;
- if (rc == 0)
- sbuf_printf(sb, "\n%s", ksp->ks_raw_buf);
+ if (rc == 0) {
+ sbuf_cat(&sb, "\n");
+ sbuf_cat(&sb, ksp->ks_raw_buf);
+ }
}
while ((data = addr_op(ksp, n)) != NULL) {
@@ -220,22 +264,19 @@ restart:
if (rc == ENOMEM && !kstat_resize_raw(ksp))
goto restart;
if (rc == 0)
- sbuf_printf(sb, "%s", ksp->ks_raw_buf);
+ sbuf_cat(&sb, ksp->ks_raw_buf);
} else {
ASSERT3U(ksp->ks_ndata, ==, 1);
- sbuf_hexdump(sb, ksp->ks_data,
+ sbuf_hexdump(&sb, ksp->ks_data,
ksp->ks_data_size, NULL, 0);
}
n++;
}
free(ksp->ks_raw_buf, M_TEMP);
mutex_exit(ksp->ks_lock);
- sbuf_trim(sb);
- rc = sbuf_finish(sb);
- if (rc == 0)
- rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
- sbuf_delete(sb);
+ rc = sbuf_finish(&sb);
+ sbuf_delete(&sb);
return (rc);
}
@@ -422,11 +463,20 @@ kstat_install_named(kstat_t *ksp)
ksp, i, kstat_sysctl, "Q", namelast);
break;
case KSTAT_DATA_UINT64:
- SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
- SYSCTL_CHILDREN(ksp->ks_sysctl_root),
- OID_AUTO, namelast,
- CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
- ksp, i, kstat_sysctl, "QU", namelast);
+ if (strcmp(ksp->ks_class, "dataset") == 0) {
+ SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, namelast,
+ CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ ksp, i, kstat_sysctl_dataset, "QU",
+ namelast);
+ } else {
+ SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, namelast,
+ CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ ksp, i, kstat_sysctl, "QU", namelast);
+ }
break;
case KSTAT_DATA_LONG:
SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
@@ -443,11 +493,21 @@ kstat_install_named(kstat_t *ksp)
ksp, i, kstat_sysctl, "LU", namelast);
break;
case KSTAT_DATA_STRING:
- SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
- SYSCTL_CHILDREN(ksp->ks_sysctl_root),
- OID_AUTO, namelast,
- CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
- ksp, i, kstat_sysctl_string, "A", namelast);
+ if (strcmp(ksp->ks_class, "dataset") == 0) {
+ SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, namelast, CTLTYPE_STRING |
+ CTLFLAG_RD | CTLFLAG_MPSAFE,
+ ksp, i, kstat_sysctl_dataset_string, "A",
+ namelast);
+ } else {
+ SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, namelast, CTLTYPE_STRING |
+ CTLFLAG_RD | CTLFLAG_MPSAFE,
+ ksp, i, kstat_sysctl_string, "A",
+ namelast);
+ }
break;
default:
panic("unsupported type: %d", typelast);
diff --git a/module/os/freebsd/spl/spl_misc.c b/module/os/freebsd/spl/spl_misc.c
index e46271a039de..a5fc996b6550 100644
--- a/module/os/freebsd/spl/spl_misc.c
+++ b/module/os/freebsd/spl/spl_misc.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/jail.h>
@@ -94,7 +91,7 @@ ddi_copyout(const void *from, void *to, size_t len, int flags)
return (copyout(from, to, len));
}
-int
+void
spl_panic(const char *file, const char *func, int line, const char *fmt, ...)
{
va_list ap;
diff --git a/module/os/freebsd/spl/spl_policy.c b/module/os/freebsd/spl/spl_policy.c
index 5ecd3d310361..f2dd7c8e7f8a 100644
--- a/module/os/freebsd/spl/spl_policy.c
+++ b/module/os/freebsd/spl/spl_policy.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/priv.h>
diff --git a/module/os/freebsd/spl/spl_procfs_list.c b/module/os/freebsd/spl/spl_procfs_list.c
index e8448ce00686..77d33ee2e1f3 100644
--- a/module/os/freebsd/spl/spl_procfs_list.c
+++ b/module/os/freebsd/spl/spl_procfs_list.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/list.h>
#include <sys/mutex.h>
#include <sys/procfs_list.h>
diff --git a/module/os/freebsd/spl/spl_string.c b/module/os/freebsd/spl/spl_string.c
index 00b1df766ab9..eb74720c984a 100644
--- a/module/os/freebsd/spl/spl_string.c
+++ b/module/os/freebsd/spl/spl_string.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -105,3 +105,33 @@ kmem_strfree(char *str)
ASSERT3P(str, !=, NULL);
kmem_free(str, strlen(str) + 1);
}
+
+/*
+ * kmem_scnprintf() will return the number of characters that it would have
+ * printed whenever it is limited by value of the size variable, rather than
+ * the number of characters that it did print. This can cause misbehavior on
+ * subsequent uses of the return value, so we define a safe version that will
+ * return the number of characters actually printed, minus the NULL format
+ * character. Subsequent use of this by the safe string functions is safe
+ * whether it is snprintf(), strlcat() or strlcpy().
+ */
+
+int
+kmem_scnprintf(char *restrict str, size_t size, const char *restrict fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ /* Make the 0 case a no-op so that we do not return -1 */
+ if (size == 0)
+ return (0);
+
+ va_start(ap, fmt);
+ n = vsnprintf(str, size, fmt, ap);
+ va_end(ap);
+
+ if (n >= size)
+ n = size - 1;
+
+ return (n);
+}
diff --git a/module/os/freebsd/spl/spl_sunddi.c b/module/os/freebsd/spl/spl_sunddi.c
index 2a3c027c9389..4c97c9f12caf 100644
--- a/module/os/freebsd/spl/spl_sunddi.c
+++ b/module/os/freebsd/spl/spl_sunddi.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/jail.h>
diff --git a/module/os/freebsd/spl/spl_sysevent.c b/module/os/freebsd/spl/spl_sysevent.c
index 16188c71b53d..dc5ed81057b8 100644
--- a/module/os/freebsd/spl/spl_sysevent.c
+++ b/module/os/freebsd/spl/spl_sysevent.c
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/kernel.h>
@@ -114,7 +111,7 @@ log_sysevent(nvlist_t *event)
}
case DATA_TYPE_STRING:
{
- char *value;
+ const char *value;
(void) nvpair_value_string(elem, &value);
sbuf_printf(sb, " %s=%s", nvpair_name(elem), value);
@@ -180,7 +177,7 @@ log_sysevent(nvlist_t *event)
}
case DATA_TYPE_STRING_ARRAY:
{
- char **strarr;
+ const char **strarr;
uint_t ii, nelem;
(void) nvpair_value_string_array(elem, &strarr, &nelem);
diff --git a/module/os/freebsd/spl/spl_taskq.c b/module/os/freebsd/spl/spl_taskq.c
index ba22c77b69c3..67c0a4c94134 100644
--- a/module/os/freebsd/spl/spl_taskq.c
+++ b/module/os/freebsd/spl/spl_taskq.c
@@ -26,12 +26,7 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
-#include <sys/ck.h>
-#include <sys/epoch.h>
#include <sys/kernel.h>
#include <sys/kmem.h>
#include <sys/lock.h>
@@ -66,11 +61,9 @@ taskq_t *dynamic_taskq = NULL;
proc_t *system_proc;
-extern int uma_align_cache;
-
static MALLOC_DEFINE(M_TASKQ, "taskq", "taskq structures");
-static CK_LIST_HEAD(tqenthashhead, taskq_ent) *tqenthashtbl;
+static LIST_HEAD(tqenthashhead, taskq_ent) *tqenthashtbl;
static unsigned long tqenthash;
static unsigned long tqenthashlock;
static struct sx *tqenthashtbl_lock;
@@ -80,8 +73,8 @@ static taskqid_t tqidnext;
#define TQIDHASH(tqid) (&tqenthashtbl[(tqid) & tqenthash])
#define TQIDHASHLOCK(tqid) (&tqenthashtbl_lock[((tqid) & tqenthashlock)])
+#define NORMAL_TASK 0
#define TIMEOUT_TASK 1
-#define NORMAL_TASK 2
static void
system_taskq_init(void *arg)
@@ -121,7 +114,7 @@ system_taskq_fini(void *arg)
for (i = 0; i < tqenthashlock + 1; i++)
sx_destroy(&tqenthashtbl_lock[i]);
for (i = 0; i < tqenthash + 1; i++)
- VERIFY(CK_LIST_EMPTY(&tqenthashtbl[i]));
+ VERIFY(LIST_EMPTY(&tqenthashtbl[i]));
free(tqenthashtbl_lock, M_TASKQ);
free(tqenthashtbl, M_TASKQ);
}
@@ -162,27 +155,27 @@ taskq_lookup(taskqid_t tqid)
{
taskq_ent_t *ent = NULL;
- sx_xlock(TQIDHASHLOCK(tqid));
- CK_LIST_FOREACH(ent, TQIDHASH(tqid), tqent_hash) {
+ if (tqid == 0)
+ return (NULL);
+ sx_slock(TQIDHASHLOCK(tqid));
+ LIST_FOREACH(ent, TQIDHASH(tqid), tqent_hash) {
if (ent->tqent_id == tqid)
break;
}
if (ent != NULL)
refcount_acquire(&ent->tqent_rc);
- sx_xunlock(TQIDHASHLOCK(tqid));
+ sx_sunlock(TQIDHASHLOCK(tqid));
return (ent);
}
static taskqid_t
taskq_insert(taskq_ent_t *ent)
{
- taskqid_t tqid;
+ taskqid_t tqid = __taskq_genid();
- tqid = __taskq_genid();
ent->tqent_id = tqid;
- ent->tqent_registered = B_TRUE;
sx_xlock(TQIDHASHLOCK(tqid));
- CK_LIST_INSERT_HEAD(TQIDHASH(tqid), ent, tqent_hash);
+ LIST_INSERT_HEAD(TQIDHASH(tqid), ent, tqent_hash);
sx_xunlock(TQIDHASHLOCK(tqid));
return (tqid);
}
@@ -192,13 +185,14 @@ taskq_remove(taskq_ent_t *ent)
{
taskqid_t tqid = ent->tqent_id;
- if (!ent->tqent_registered)
+ if (tqid == 0)
return;
-
sx_xlock(TQIDHASHLOCK(tqid));
- CK_LIST_REMOVE(ent, tqent_hash);
+ if (ent->tqent_id != 0) {
+ LIST_REMOVE(ent, tqent_hash);
+ ent->tqent_id = 0;
+ }
sx_xunlock(TQIDHASHLOCK(tqid));
- ent->tqent_registered = B_FALSE;
}
static void
@@ -223,6 +217,7 @@ taskq_create_impl(const char *name, int nthreads, pri_t pri,
nthreads = MAX((mp_ncpus * nthreads) / 100, 1);
tq = kmem_alloc(sizeof (*tq), KM_SLEEP);
+ tq->tq_nthreads = nthreads;
tq->tq_queue = taskqueue_create(name, M_WAITOK,
taskqueue_thread_enqueue, &tq->tq_queue);
taskqueue_set_callback(tq->tq_queue, TASKQUEUE_CALLBACK_TYPE_INIT,
@@ -257,6 +252,87 @@ taskq_destroy(taskq_t *tq)
kmem_free(tq, sizeof (*tq));
}
+static void taskq_sync_assign(void *arg);
+
+typedef struct taskq_sync_arg {
+ kthread_t *tqa_thread;
+ kcondvar_t tqa_cv;
+ kmutex_t tqa_lock;
+ int tqa_ready;
+} taskq_sync_arg_t;
+
+static void
+taskq_sync_assign(void *arg)
+{
+ taskq_sync_arg_t *tqa = arg;
+
+ mutex_enter(&tqa->tqa_lock);
+ tqa->tqa_thread = curthread;
+ tqa->tqa_ready = 1;
+ cv_signal(&tqa->tqa_cv);
+ while (tqa->tqa_ready == 1)
+ cv_wait(&tqa->tqa_cv, &tqa->tqa_lock);
+ mutex_exit(&tqa->tqa_lock);
+}
+
+/*
+ * Create a taskq with a specified number of pool threads. Allocate
+ * and return an array of nthreads kthread_t pointers, one for each
+ * thread in the pool. The array is not ordered and must be freed
+ * by the caller.
+ */
+taskq_t *
+taskq_create_synced(const char *name, int nthreads, pri_t pri,
+ int minalloc, int maxalloc, uint_t flags, kthread_t ***ktpp)
+{
+ taskq_t *tq;
+ taskq_sync_arg_t *tqs = kmem_zalloc(sizeof (*tqs) * nthreads, KM_SLEEP);
+ kthread_t **kthreads = kmem_zalloc(sizeof (*kthreads) * nthreads,
+ KM_SLEEP);
+
+ flags &= ~(TASKQ_DYNAMIC | TASKQ_THREADS_CPU_PCT | TASKQ_DC_BATCH);
+
+ tq = taskq_create(name, nthreads, minclsyspri, nthreads, INT_MAX,
+ flags | TASKQ_PREPOPULATE);
+ VERIFY(tq != NULL);
+ VERIFY(tq->tq_nthreads == nthreads);
+
+ /* spawn all syncthreads */
+ for (int i = 0; i < nthreads; i++) {
+ cv_init(&tqs[i].tqa_cv, NULL, CV_DEFAULT, NULL);
+ mutex_init(&tqs[i].tqa_lock, NULL, MUTEX_DEFAULT, NULL);
+ (void) taskq_dispatch(tq, taskq_sync_assign,
+ &tqs[i], TQ_FRONT);
+ }
+
+ /* wait on all syncthreads to start */
+ for (int i = 0; i < nthreads; i++) {
+ mutex_enter(&tqs[i].tqa_lock);
+ while (tqs[i].tqa_ready == 0)
+ cv_wait(&tqs[i].tqa_cv, &tqs[i].tqa_lock);
+ mutex_exit(&tqs[i].tqa_lock);
+ }
+
+ /* let all syncthreads resume, finish */
+ for (int i = 0; i < nthreads; i++) {
+ mutex_enter(&tqs[i].tqa_lock);
+ tqs[i].tqa_ready = 2;
+ cv_broadcast(&tqs[i].tqa_cv);
+ mutex_exit(&tqs[i].tqa_lock);
+ }
+ taskq_wait(tq);
+
+ for (int i = 0; i < nthreads; i++) {
+ kthreads[i] = tqs[i].tqa_thread;
+ mutex_destroy(&tqs[i].tqa_lock);
+ cv_destroy(&tqs[i].tqa_cv);
+ }
+ kmem_free(tqs, sizeof (*tqs) * nthreads);
+
+ *ktpp = kthreads;
+ return (tq);
+}
+
int
taskq_member(taskq_t *tq, kthread_t *thread)
{
@@ -285,21 +361,22 @@ taskq_cancel_id(taskq_t *tq, taskqid_t tid)
int rc;
taskq_ent_t *ent;
- if (tid == 0)
- return (0);
-
if ((ent = taskq_lookup(tid)) == NULL)
return (0);
- ent->tqent_cancelled = B_TRUE;
- if (ent->tqent_type == TIMEOUT_TASK) {
+ if (ent->tqent_type == NORMAL_TASK) {
+ rc = taskqueue_cancel(tq->tq_queue, &ent->tqent_task, &pend);
+ if (rc == EBUSY)
+ taskqueue_drain(tq->tq_queue, &ent->tqent_task);
+ } else {
rc = taskqueue_cancel_timeout(tq->tq_queue,
&ent->tqent_timeout_task, &pend);
- } else
- rc = taskqueue_cancel(tq->tq_queue, &ent->tqent_task, &pend);
- if (rc == EBUSY) {
- taskqueue_drain(tq->tq_queue, &ent->tqent_task);
- } else if (pend) {
+ if (rc == EBUSY) {
+ taskqueue_drain_timeout(tq->tq_queue,
+ &ent->tqent_timeout_task);
+ }
+ }
+ if (pend) {
/*
* Tasks normally free themselves when run, but here the task
* was cancelled so it did not free itself.
@@ -312,12 +389,13 @@ taskq_cancel_id(taskq_t *tq, taskqid_t tid)
}
static void
-taskq_run(void *arg, int pending __unused)
+taskq_run(void *arg, int pending)
{
taskq_ent_t *task = arg;
- if (!task->tqent_cancelled)
- task->tqent_func(task->tqent_arg);
+ if (pending == 0)
+ return;
+ task->tqent_func(task->tqent_arg);
taskq_free(task);
}
@@ -345,7 +423,6 @@ taskq_dispatch_delay(taskq_t *tq, task_func_t func, void *arg,
task->tqent_func = func;
task->tqent_arg = arg;
task->tqent_type = TIMEOUT_TASK;
- task->tqent_cancelled = B_FALSE;
refcount_init(&task->tqent_rc, 1);
tqid = taskq_insert(task);
TIMEOUT_TASK_INIT(tq->tq_queue, &task->tqent_timeout_task, 0,
@@ -379,7 +456,6 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
refcount_init(&task->tqent_rc, 1);
task->tqent_func = func;
task->tqent_arg = arg;
- task->tqent_cancelled = B_FALSE;
task->tqent_type = NORMAL_TASK;
tqid = taskq_insert(task);
TASK_INIT(&task->tqent_task, prio, taskq_run, task);
@@ -388,10 +464,12 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
}
static void
-taskq_run_ent(void *arg, int pending __unused)
+taskq_run_ent(void *arg, int pending)
{
taskq_ent_t *task = arg;
+ if (pending == 0)
+ return;
task->tqent_func(task->tqent_arg);
}
@@ -399,24 +477,34 @@ void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint32_t flags,
taskq_ent_t *task)
{
- int prio;
-
/*
* If TQ_FRONT is given, we want higher priority for this task, so it
* can go at the front of the queue.
*/
- prio = !!(flags & TQ_FRONT);
- task->tqent_cancelled = B_FALSE;
- task->tqent_registered = B_FALSE;
- task->tqent_id = 0;
+ task->tqent_task.ta_priority = !!(flags & TQ_FRONT);
task->tqent_func = func;
task->tqent_arg = arg;
-
- TASK_INIT(&task->tqent_task, prio, taskq_run_ent, task);
taskqueue_enqueue(tq->tq_queue, &task->tqent_task);
}
void
+taskq_init_ent(taskq_ent_t *task)
+{
+ TASK_INIT(&task->tqent_task, 0, taskq_run_ent, task);
+ task->tqent_func = NULL;
+ task->tqent_arg = NULL;
+ task->tqent_id = 0;
+ task->tqent_type = NORMAL_TASK;
+ task->tqent_rc = 0;
+}
+
+int
+taskq_empty_ent(taskq_ent_t *task)
+{
+ return (task->tqent_task.ta_pending == 0);
+}
+
+void
taskq_wait(taskq_t *tq)
{
taskqueue_quiesce(tq->tq_queue);
@@ -427,12 +515,13 @@ taskq_wait_id(taskq_t *tq, taskqid_t tid)
{
taskq_ent_t *ent;
- if (tid == 0)
- return;
if ((ent = taskq_lookup(tid)) == NULL)
return;
- taskqueue_drain(tq->tq_queue, &ent->tqent_task);
+ if (ent->tqent_type == NORMAL_TASK)
+ taskqueue_drain(tq->tq_queue, &ent->tqent_task);
+ else
+ taskqueue_drain_timeout(tq->tq_queue, &ent->tqent_timeout_task);
taskq_free(ent);
}
@@ -441,9 +530,3 @@ taskq_wait_outstanding(taskq_t *tq, taskqid_t id __unused)
{
taskqueue_drain_all(tq->tq_queue);
}
-
-int
-taskq_empty_ent(taskq_ent_t *t)
-{
- return (t->tqent_task.ta_pending == 0);
-}
diff --git a/module/os/freebsd/spl/spl_uio.c b/module/os/freebsd/spl/spl_uio.c
index 0bf251a1edac..ffccb6f2594e 100644
--- a/module/os/freebsd/spl/spl_uio.c
+++ b/module/os/freebsd/spl/spl_uio.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/freebsd/spl/spl_vfs.c b/module/os/freebsd/spl/spl_vfs.c
index ff11f5d7acb8..724709ddee9d 100644
--- a/module/os/freebsd/spl/spl_vfs.c
+++ b/module/os/freebsd/spl/spl_vfs.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/kernel.h>
@@ -120,12 +117,11 @@ vfs_optionisset(const vfs_t *vfsp, const char *opt, char **argp)
int
mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
- char *fspec, int fsflags)
+ char *fspec, int fsflags, vfs_t *parent_vfsp)
{
struct vfsconf *vfsp;
struct mount *mp;
vnode_t *vp, *mvp;
- struct ucred *pcr, *tcr;
int error;
ASSERT_VOP_ELOCKED(*vpp, "mount_snapshot");
@@ -195,18 +191,7 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
*/
mp->mnt_flag |= MNT_IGNORE;
- /*
- * XXX: This is evil, but we can't mount a snapshot as a regular user.
- * XXX: Is is safe when snapshot is mounted from within a jail?
- */
- tcr = td->td_ucred;
- pcr = td->td_proc->p_ucred;
- td->td_ucred = kcred;
- td->td_proc->p_ucred = kcred;
error = VFS_MOUNT(mp);
- td->td_ucred = tcr;
- td->td_proc->p_ucred = pcr;
-
if (error != 0) {
/*
* Clear VI_MOUNT and decrement the use count "atomically",
@@ -232,6 +217,13 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
mp->mnt_opt = mp->mnt_optnew;
(void) VFS_STATFS(mp, &mp->mnt_stat);
+#ifdef VFS_SUPPORTS_EXJAIL_CLONE
+ /*
+ * Clone the mnt_exjail credentials of the parent, as required.
+ */
+ vfs_exjail_clone(parent_vfsp, mp);
+#endif
+
/*
* Prevent external consumers of mount options from reading
* mnt_optnew.
diff --git a/module/os/freebsd/spl/spl_vm.c b/module/os/freebsd/spl/spl_vm.c
index 739ddb05e895..e6f019cb9a46 100644
--- a/module/os/freebsd/spl/spl_vm.c
+++ b/module/os/freebsd/spl/spl_vm.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/counter.h>
diff --git a/module/os/freebsd/spl/spl_zlib.c b/module/os/freebsd/spl/spl_zlib.c
index 8bd3bdedf268..4a2bb3884caa 100644
--- a/module/os/freebsd/spl/spl_zlib.c
+++ b/module/os/freebsd/spl/spl_zlib.c
@@ -25,18 +25,11 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/kmem_cache.h>
#include <sys/zmod.h>
-#if __FreeBSD_version >= 1300041
#include <contrib/zlib/zlib.h>
-#else
-#include <sys/zlib.h>
-#endif
#include <sys/kobj.h>
@@ -90,11 +83,7 @@ zlib_inflateInit(z_stream *stream)
static int
zlib_inflate(z_stream *stream, int finish)
{
-#if __FreeBSD_version >= 1300024
return (inflate(stream, finish));
-#else
- return (_zlib104_inflate(stream, finish));
-#endif
}
diff --git a/module/os/freebsd/spl/spl_zone.c b/module/os/freebsd/spl/spl_zone.c
index 658ef0bf056d..7f2b5c712c42 100644
--- a/module/os/freebsd/spl/spl_zone.c
+++ b/module/os/freebsd/spl/spl_zone.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/kernel.h>
diff --git a/module/os/freebsd/zfs/abd_os.c b/module/os/freebsd/zfs/abd_os.c
index 58a37df62b69..3b812271f98b 100644
--- a/module/os/freebsd/zfs/abd_os.c
+++ b/module/os/freebsd/zfs/abd_os.c
@@ -417,10 +417,8 @@ abd_iter_init(struct abd_iter *aiter, abd_t *abd)
{
ASSERT(!abd_is_gang(abd));
abd_verify(abd);
+ memset(aiter, 0, sizeof (struct abd_iter));
aiter->iter_abd = abd;
- aiter->iter_pos = 0;
- aiter->iter_mapaddr = NULL;
- aiter->iter_mapsize = 0;
}
/*
diff --git a/module/os/freebsd/zfs/arc_os.c b/module/os/freebsd/zfs/arc_os.c
index b6f19207f324..92696c0bf1ae 100644
--- a/module/os/freebsd/zfs/arc_os.c
+++ b/module/os/freebsd/zfs/arc_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,6 +27,7 @@
#include <sys/zio_checksum.h>
#include <sys/zfs_context.h>
#include <sys/arc.h>
+#include <sys/arc_os.h>
#include <sys/zfs_refcount.h>
#include <sys/vdev.h>
#include <sys/vdev_trim.h>
@@ -51,11 +52,6 @@
#include <sys/vm.h>
#include <sys/vmmeter.h>
-#if __FreeBSD_version >= 1300139
-static struct sx arc_vnlru_lock;
-static struct vnode *arc_vnlru_marker;
-#endif
-
extern struct vfsops zfs_vfsops;
uint_t zfs_arc_free_target = 0;
@@ -72,31 +68,12 @@ SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY,
* We don't have a tunable for arc_free_target due to the dependency on
* pagedaemon initialisation.
*/
-static int
-sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS)
-{
- uint_t val;
- int err;
-
- val = zfs_arc_free_target;
- err = sysctl_handle_int(oidp, &val, 0, req);
- if (err != 0 || req->newptr == NULL)
- return (err);
-
- if (val < minfree)
- return (EINVAL);
- if (val > vm_cnt.v_page_count)
- return (EINVAL);
-
- zfs_arc_free_target = val;
-
- return (0);
-}
-SYSCTL_DECL(_vfs_zfs);
-SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_free_target,
- CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof (uint_t),
- sysctl_vfs_zfs_arc_free_target, "IU",
+ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, free_target,
+ param_set_arc_free_target, 0, CTLFLAG_RW,
"Desired number of free pages below which ARC triggers reclaim");
+ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, no_grow_shift,
+ param_set_arc_no_grow_shift, 0, ZMOD_RW,
+ "log2(fraction of ARC which must be free to allow growing)");
int64_t
arc_available_memory(void)
@@ -149,49 +126,6 @@ arc_default_max(uint64_t min, uint64_t allmem)
return (MAX(allmem * 5 / 8, size));
}
-/*
- * Helper function for arc_prune_async() it is responsible for safely
- * handling the execution of a registered arc_prune_func_t.
- */
-static void
-arc_prune_task(void *arg)
-{
- int64_t nr_scan = (intptr_t)arg;
-
- arc_reduce_target_size(ptob(nr_scan));
-#if __FreeBSD_version >= 1300139
- sx_xlock(&arc_vnlru_lock);
- vnlru_free_vfsops(nr_scan, &zfs_vfsops, arc_vnlru_marker);
- sx_xunlock(&arc_vnlru_lock);
-#else
- vnlru_free(nr_scan, &zfs_vfsops);
-#endif
-}
-
-/*
- * Notify registered consumers they must drop holds on a portion of the ARC
- * buffered they reference. This provides a mechanism to ensure the ARC can
- * honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This
- * is analogous to dnlc_reduce_cache() but more generic.
- *
- * This operation is performed asynchronously so it may be safely called
- * in the context of the arc_reclaim_thread(). A reference is taken here
- * for each registered arc_prune_t and the arc_prune_task() is responsible
- * for releasing it once the registered arc_prune_func_t has completed.
- */
-void
-arc_prune_async(int64_t adjust)
-{
-
-#ifndef __LP64__
- if (adjust > INTPTR_MAX)
- adjust = INTPTR_MAX;
-#endif
- taskq_dispatch(arc_prune_taskq, arc_prune_task,
- (void *)(intptr_t)adjust, TQ_SLEEP);
- ARCSTAT_BUMP(arcstat_prune);
-}
-
uint64_t
arc_all_memory(void)
{
@@ -221,7 +155,10 @@ arc_lowmem(void *arg __unused, int howto __unused)
arc_warm = B_TRUE;
arc_growtime = gethrtime() + SEC2NSEC(arc_grow_retry);
free_memory = arc_available_memory();
- to_free = (arc_c >> arc_shrink_shift) - MIN(free_memory, 0);
+ int64_t can_free = arc_c - arc_c_min;
+ if (can_free <= 0)
+ return;
+ to_free = (can_free >> arc_shrink_shift) - MIN(free_memory, 0);
DTRACE_PROBE2(arc__needfree, int64_t, free_memory, int64_t, to_free);
arc_reduce_target_size(to_free);
@@ -239,10 +176,6 @@ arc_lowmem_init(void)
{
arc_event_lowmem = EVENTHANDLER_REGISTER(vm_lowmem, arc_lowmem, NULL,
EVENTHANDLER_PRI_FIRST);
-#if __FreeBSD_version >= 1300139
- arc_vnlru_marker = vnlru_alloc_marker();
- sx_init(&arc_vnlru_lock, "arc vnlru lock");
-#endif
}
void
@@ -250,12 +183,6 @@ arc_lowmem_fini(void)
{
if (arc_event_lowmem != NULL)
EVENTHANDLER_DEREGISTER(vm_lowmem, arc_event_lowmem);
-#if __FreeBSD_version >= 1300139
- if (arc_vnlru_marker != NULL) {
- vnlru_free_marker(arc_vnlru_marker);
- sx_destroy(&arc_vnlru_lock);
- }
-#endif
}
void
diff --git a/module/os/freebsd/zfs/crypto_os.c b/module/os/freebsd/zfs/crypto_os.c
index 1f139ea5b807..ed8d2407613e 100644
--- a/module/os/freebsd/zfs/crypto_os.c
+++ b/module/os/freebsd/zfs/crypto_os.c
@@ -27,9 +27,6 @@
* Portions of this file are derived from sys/geom/eli/g_eli_hmac.c
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/errno.h>
diff --git a/module/os/freebsd/zfs/dmu_os.c b/module/os/freebsd/zfs/dmu_os.c
index a5f486b95db4..48ea37cbad59 100644
--- a/module/os/freebsd/zfs/dmu_os.c
+++ b/module/os/freebsd/zfs/dmu_os.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dmu.h>
@@ -110,7 +107,7 @@ dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
if (tocpy == db->db_size)
- dmu_buf_will_fill(db, tx);
+ dmu_buf_will_fill(db, tx, B_FALSE);
else
dmu_buf_will_dirty(db, tx);
@@ -126,7 +123,7 @@ dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
}
if (tocpy == db->db_size)
- dmu_buf_fill_done(db, tx);
+ dmu_buf_fill_done(db, tx, B_FALSE);
offset += tocpy;
size -= tocpy;
diff --git a/module/os/freebsd/zfs/event_os.c b/module/os/freebsd/zfs/event_os.c
new file mode 100644
index 000000000000..e774fbaaf867
--- /dev/null
+++ b/module/os/freebsd/zfs/event_os.c
@@ -0,0 +1,83 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Rob Wing
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/event.h>
+
+#include <sys/freebsd_event.h>
+
+static void
+knlist_sx_xlock(void *arg)
+{
+
+ sx_xlock((struct sx *)arg);
+}
+
+static void
+knlist_sx_xunlock(void *arg)
+{
+
+ sx_xunlock((struct sx *)arg);
+}
+
+#if __FreeBSD_version >= 1300128
+static void
+knlist_sx_assert_lock(void *arg, int what)
+{
+
+ if (what == LA_LOCKED)
+ sx_assert((struct sx *)arg, SX_LOCKED);
+ else
+ sx_assert((struct sx *)arg, SX_UNLOCKED);
+}
+#else
+static void
+knlist_sx_assert_locked(void *arg)
+{
+ sx_assert((struct sx *)arg, SX_LOCKED);
+}
+static void
+knlist_sx_assert_unlocked(void *arg)
+{
+ sx_assert((struct sx *)arg, SX_UNLOCKED);
+}
+#endif
+
+void
+knlist_init_sx(struct knlist *knl, struct sx *lock)
+{
+
+#if __FreeBSD_version >= 1300128
+ knlist_init(knl, lock, knlist_sx_xlock, knlist_sx_xunlock,
+ knlist_sx_assert_lock);
+#else
+ knlist_init(knl, lock, knlist_sx_xlock, knlist_sx_xunlock,
+ knlist_sx_assert_locked, knlist_sx_assert_unlocked);
+#endif
+}
diff --git a/module/os/freebsd/zfs/kmod_core.c b/module/os/freebsd/zfs/kmod_core.c
index 2b808357ecc8..2bced9ab6446 100644
--- a/module/os/freebsd/zfs/kmod_core.c
+++ b/module/os/freebsd/zfs/kmod_core.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/cmn_err.h>
@@ -65,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/spa_impl.h>
#include <sys/stat.h>
#include <sys/sunddi.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <sys/uio.h>
@@ -124,56 +122,65 @@ zfsdev_ioctl(struct cdev *dev, ulong_t zcmd, caddr_t arg, int flag,
int vecnum;
zfs_iocparm_t *zp;
zfs_cmd_t *zc;
+#ifdef ZFS_LEGACY_SUPPORT
zfs_cmd_legacy_t *zcl;
+#endif
int rc, error;
void *uaddr;
len = IOCPARM_LEN(zcmd);
vecnum = zcmd & 0xff;
zp = (void *)arg;
- uaddr = (void *)zp->zfs_cmd;
error = 0;
+#ifdef ZFS_LEGACY_SUPPORT
zcl = NULL;
+#endif
- if (len != sizeof (zfs_iocparm_t)) {
- printf("len %d vecnum: %d sizeof (zfs_cmd_t) %ju\n",
- len, vecnum, (uintmax_t)sizeof (zfs_cmd_t));
+ if (len != sizeof (zfs_iocparm_t))
return (EINVAL);
- }
- zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
+ uaddr = (void *)(uintptr_t)zp->zfs_cmd;
+ zc = vmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
+#ifdef ZFS_LEGACY_SUPPORT
/*
* Remap ioctl code for legacy user binaries
*/
if (zp->zfs_ioctl_version == ZFS_IOCVER_LEGACY) {
vecnum = zfs_ioctl_legacy_to_ozfs(vecnum);
if (vecnum < 0) {
- kmem_free(zc, sizeof (zfs_cmd_t));
+ vmem_free(zc, sizeof (zfs_cmd_t));
return (ENOTSUP);
}
- zcl = kmem_zalloc(sizeof (zfs_cmd_legacy_t), KM_SLEEP);
+ zcl = vmem_zalloc(sizeof (zfs_cmd_legacy_t), KM_SLEEP);
if (copyin(uaddr, zcl, sizeof (zfs_cmd_legacy_t))) {
error = SET_ERROR(EFAULT);
goto out;
}
zfs_cmd_legacy_to_ozfs(zcl, zc);
- } else if (copyin(uaddr, zc, sizeof (zfs_cmd_t))) {
+ } else
+#endif
+ if (copyin(uaddr, zc, sizeof (zfs_cmd_t))) {
error = SET_ERROR(EFAULT);
goto out;
}
error = zfsdev_ioctl_common(vecnum, zc, 0);
+#ifdef ZFS_LEGACY_SUPPORT
if (zcl) {
zfs_cmd_ozfs_to_legacy(zc, zcl);
rc = copyout(zcl, uaddr, sizeof (*zcl));
- } else {
+ } else
+#endif
+ {
rc = copyout(zc, uaddr, sizeof (*zc));
}
if (error == 0 && rc != 0)
error = SET_ERROR(EFAULT);
out:
+#ifdef ZFS_LEGACY_SUPPORT
if (zcl)
- kmem_free(zcl, sizeof (zfs_cmd_legacy_t));
- kmem_free(zc, sizeof (zfs_cmd_t));
+ vmem_free(zcl, sizeof (zfs_cmd_legacy_t));
+#endif
+ vmem_free(zc, sizeof (zfs_cmd_t));
MPASS(tsd_get(rrw_tsd_key) == NULL);
return (error);
}
@@ -219,9 +226,16 @@ static struct cdevsw zfs_cdevsw = {
int
zfsdev_attach(void)
{
- zfsdev = make_dev(&zfs_cdevsw, 0x0, UID_ROOT, GID_OPERATOR, 0666,
- ZFS_DRIVER);
- return (0);
+ struct make_dev_args args;
+
+ make_dev_args_init(&args);
+ args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
+ args.mda_devsw = &zfs_cdevsw;
+ args.mda_cr = NULL;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_OPERATOR;
+ args.mda_mode = 0666;
+ return (make_dev_s(&args, &zfsdev, ZFS_DRIVER));
}
void
@@ -320,6 +334,8 @@ static moduledata_t zfs_mod = {
EVENTHANDLER_DEFINE(mountroot, spa_boot_init, NULL, 0);
#endif
+FEATURE(zfs, "OpenZFS support");
+
DECLARE_MODULE(zfsctrl, zfs_mod, SI_SUB_CLOCKS, SI_ORDER_ANY);
MODULE_VERSION(zfsctrl, 1);
#if __FreeBSD_version > 1300092
diff --git a/module/os/freebsd/zfs/spa_os.c b/module/os/freebsd/zfs/spa_os.c
index 6ebb4c285edd..1b9f1a4ec9dc 100644
--- a/module/os/freebsd/zfs/spa_os.c
+++ b/module/os/freebsd/zfs/spa_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -58,7 +58,6 @@
#include <sys/fs/zfs.h>
#include <sys/arc.h>
#include <sys/callb.h>
-#include <sys/spa_boot.h>
#include <sys/zfs_ioctl.h>
#include <sys/dsl_scan.h>
#include <sys/dmu_send.h>
@@ -95,6 +94,8 @@ spa_generate_rootconf(const char *name)
for (i = 0; i < count; i++) {
uint64_t txg;
+ if (configs[i] == NULL)
+ continue;
txg = fnvlist_lookup_uint64(configs[i], ZPOOL_CONFIG_POOL_TXG);
if (txg > best_txg) {
best_txg = txg;
@@ -183,7 +184,7 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
spa_t *spa;
vdev_t *rvd;
nvlist_t *config, *nvtop;
- char *pname;
+ const char *pname;
int error;
/*
@@ -250,7 +251,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/sysctl_os.c b/module/os/freebsd/zfs/sysctl_os.c
index c774f05ff706..30983b13f7d1 100644
--- a/module/os/freebsd/zfs/sysctl_os.c
+++ b/module/os/freebsd/zfs/sysctl_os.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/spa_impl.h>
#include <sys/vdev.h>
#include <sys/vdev_impl.h>
+#include <sys/arc_os.h>
#include <sys/dmu.h>
#include <sys/dsl_dir.h>
#include <sys/dsl_dataset.h>
@@ -91,10 +89,13 @@ __FBSDID("$FreeBSD$");
#include <sys/arc_impl.h>
#include <sys/dsl_pool.h>
+#include <sys/vmmeter.h>
SYSCTL_DECL(_vfs_zfs);
SYSCTL_NODE(_vfs_zfs, OID_AUTO, arc, CTLFLAG_RW, 0,
"ZFS adaptive replacement cache");
+SYSCTL_NODE(_vfs_zfs, OID_AUTO, brt, CTLFLAG_RW, 0,
+ "ZFS Block Reference Table");
SYSCTL_NODE(_vfs_zfs, OID_AUTO, condense, CTLFLAG_RW, 0, "ZFS condense");
SYSCTL_NODE(_vfs_zfs, OID_AUTO, dbuf, CTLFLAG_RW, 0, "ZFS disk buf cache");
SYSCTL_NODE(_vfs_zfs, OID_AUTO, dbuf_cache, CTLFLAG_RW, 0,
@@ -132,28 +133,44 @@ SYSCTL_DECL(_vfs_zfs_version);
SYSCTL_CONST_STRING(_vfs_zfs_version, OID_AUTO, module, CTLFLAG_RD,
(ZFS_META_VERSION "-" ZFS_META_RELEASE), "OpenZFS module version");
-extern arc_state_t ARC_anon;
-extern arc_state_t ARC_mru;
-extern arc_state_t ARC_mru_ghost;
-extern arc_state_t ARC_mfu;
-extern arc_state_t ARC_mfu_ghost;
-extern arc_state_t ARC_l2c_only;
+/* arc.c */
-/*
- * minimum lifespan of a prefetch block in clock ticks
- * (initialized in arc_init())
- */
+int
+param_set_arc_u64(SYSCTL_HANDLER_ARGS)
+{
+ int err;
-/* arc.c */
+ err = sysctl_handle_64(oidp, arg1, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ arc_tuning_update(B_TRUE);
+
+ return (0);
+}
+
+int
+param_set_arc_int(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+
+ err = sysctl_handle_int(oidp, arg1, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ arc_tuning_update(B_TRUE);
+
+ return (0);
+}
int
param_set_arc_max(SYSCTL_HANDLER_ARGS)
{
- uint64_t val;
+ unsigned long val;
int err;
val = zfs_arc_max;
- err = sysctl_handle_long(oidp, &val, 0, req);
+ err = sysctl_handle_64(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (SET_ERROR(err));
@@ -171,10 +188,17 @@ param_set_arc_max(SYSCTL_HANDLER_ARGS)
return (0);
}
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max,
+ CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, param_set_arc_max, "LU",
+ "Maximum ARC size in bytes (LEGACY)");
+/* END CSTYLED */
+
int
param_set_arc_min(SYSCTL_HANDLER_ARGS)
{
- uint64_t val;
+ unsigned long val;
int err;
val = zfs_arc_min;
@@ -195,87 +219,50 @@ param_set_arc_min(SYSCTL_HANDLER_ARGS)
return (0);
}
-/* legacy compat */
-extern uint64_t l2arc_write_max; /* def max write size */
-extern uint64_t l2arc_write_boost; /* extra warmup write */
-extern uint64_t l2arc_headroom; /* # of dev writes */
-extern uint64_t l2arc_headroom_boost;
-extern uint64_t l2arc_feed_secs; /* interval seconds */
-extern uint64_t l2arc_feed_min_ms; /* min interval msecs */
-extern int l2arc_noprefetch; /* don't cache prefetch bufs */
-extern int l2arc_feed_again; /* turbo warmup */
-extern int l2arc_norw; /* no reads during writes */
-
-/* BEGIN CSTYLED */
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_write_max, CTLFLAG_RW,
- &l2arc_write_max, 0, "max write size (LEGACY)");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_write_boost, CTLFLAG_RW,
- &l2arc_write_boost, 0, "extra write during warmup (LEGACY)");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_headroom, CTLFLAG_RW,
- &l2arc_headroom, 0, "number of dev writes (LEGACY)");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_feed_secs, CTLFLAG_RW,
- &l2arc_feed_secs, 0, "interval seconds (LEGACY)");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_feed_min_ms, CTLFLAG_RW,
- &l2arc_feed_min_ms, 0, "min interval milliseconds (LEGACY)");
-
-SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_noprefetch, CTLFLAG_RW,
- &l2arc_noprefetch, 0, "don't cache prefetch bufs (LEGACY)");
-SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_feed_again, CTLFLAG_RW,
- &l2arc_feed_again, 0, "turbo warmup (LEGACY)");
-SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_norw, CTLFLAG_RW,
- &l2arc_norw, 0, "no reads during writes (LEGACY)");
-
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_size, CTLFLAG_RD,
- &ARC_anon.arcs_size.rc_count, 0, "size of anonymous state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_metadata_esize, CTLFLAG_RD,
- &ARC_anon.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
- "size of anonymous state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_data_esize, CTLFLAG_RD,
- &ARC_anon.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
- "size of anonymous state");
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min,
+ CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, param_set_arc_min, "LU",
+ "Minimum ARC size in bytes (LEGACY)");
+/* END CSTYLED */
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_size, CTLFLAG_RD,
- &ARC_mru.arcs_size.rc_count, 0, "size of mru state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_metadata_esize, CTLFLAG_RD,
- &ARC_mru.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
- "size of metadata in mru state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_data_esize, CTLFLAG_RD,
- &ARC_mru.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
- "size of data in mru state");
+extern uint_t zfs_arc_free_target;
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_size, CTLFLAG_RD,
- &ARC_mru_ghost.arcs_size.rc_count, 0, "size of mru ghost state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_metadata_esize, CTLFLAG_RD,
- &ARC_mru_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
- "size of metadata in mru ghost state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_data_esize, CTLFLAG_RD,
- &ARC_mru_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
- "size of data in mru ghost state");
+int
+param_set_arc_free_target(SYSCTL_HANDLER_ARGS)
+{
+ uint_t val;
+ int err;
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_size, CTLFLAG_RD,
- &ARC_mfu.arcs_size.rc_count, 0, "size of mfu state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_metadata_esize, CTLFLAG_RD,
- &ARC_mfu.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
- "size of metadata in mfu state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_data_esize, CTLFLAG_RD,
- &ARC_mfu.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
- "size of data in mfu state");
+ val = zfs_arc_free_target;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_size, CTLFLAG_RD,
- &ARC_mfu_ghost.arcs_size.rc_count, 0, "size of mfu ghost state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_metadata_esize, CTLFLAG_RD,
- &ARC_mfu_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
- "size of metadata in mfu ghost state");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_data_esize, CTLFLAG_RD,
- &ARC_mfu_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
- "size of data in mfu ghost state");
+ if (val < minfree)
+ return (EINVAL);
+ if (val > vm_cnt.v_page_count)
+ return (EINVAL);
+
+ zfs_arc_free_target = val;
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2c_only_size, CTLFLAG_RD,
- &ARC_l2c_only.arcs_size.rc_count, 0, "size of mru state");
+ return (0);
+}
+
+/*
+ * NOTE: This sysctl is CTLFLAG_RW not CTLFLAG_RWTUN due to its dependency on
+ * pagedaemon initialization.
+ */
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_free_target,
+ CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+ NULL, 0, param_set_arc_free_target, "IU",
+ "Desired number of free pages below which ARC triggers reclaim"
+ " (LEGACY)");
/* END CSTYLED */
-static int
-sysctl_vfs_zfs_arc_no_grow_shift(SYSCTL_HANDLER_ARGS)
+int
+param_set_arc_no_grow_shift(SYSCTL_HANDLER_ARGS)
{
int err, val;
@@ -288,91 +275,249 @@ sysctl_vfs_zfs_arc_no_grow_shift(SYSCTL_HANDLER_ARGS)
return (EINVAL);
arc_no_grow_shift = val;
+
return (0);
}
+/* BEGIN CSTYLED */
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_no_grow_shift,
- CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, NULL, sizeof (int),
- sysctl_vfs_zfs_arc_no_grow_shift, "I",
- "log2(fraction of ARC which must be free to allow growing)");
+ CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, param_set_arc_no_grow_shift, "I",
+ "log2(fraction of ARC which must be free to allow growing) (LEGACY)");
+/* END CSTYLED */
-int
-param_set_arc_long(SYSCTL_HANDLER_ARGS)
-{
- int err;
+extern uint64_t l2arc_write_max;
- err = sysctl_handle_long(oidp, arg1, 0, req);
- if (err != 0 || req->newptr == NULL)
- return (err);
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_write_max,
+ CTLFLAG_RWTUN, &l2arc_write_max, 0,
+ "Max write bytes per interval (LEGACY)");
+/* END CSTYLED */
- arc_tuning_update(B_TRUE);
+extern uint64_t l2arc_write_boost;
- return (0);
-}
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_write_boost,
+ CTLFLAG_RWTUN, &l2arc_write_boost, 0,
+ "Extra write bytes during device warmup (LEGACY)");
+/* END CSTYLED */
-int
-param_set_arc_int(SYSCTL_HANDLER_ARGS)
-{
- int err;
+extern uint64_t l2arc_headroom;
- err = sysctl_handle_int(oidp, arg1, 0, req);
- if (err != 0 || req->newptr == NULL)
- return (err);
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_headroom,
+ CTLFLAG_RWTUN, &l2arc_headroom, 0,
+ "Number of max device writes to precache (LEGACY)");
+/* END CSTYLED */
- arc_tuning_update(B_TRUE);
+extern uint64_t l2arc_headroom_boost;
- return (0);
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_headroom_boost,
+ CTLFLAG_RWTUN, &l2arc_headroom_boost, 0,
+ "Compressed l2arc_headroom multiplier (LEGACY)");
+/* END CSTYLED */
+
+extern uint64_t l2arc_feed_secs;
+
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_feed_secs,
+ CTLFLAG_RWTUN, &l2arc_feed_secs, 0,
+ "Seconds between L2ARC writing (LEGACY)");
+/* END CSTYLED */
+
+extern uint64_t l2arc_feed_min_ms;
+
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, l2arc_feed_min_ms,
+ CTLFLAG_RWTUN, &l2arc_feed_min_ms, 0,
+ "Min feed interval in milliseconds (LEGACY)");
+/* END CSTYLED */
+
+extern int l2arc_noprefetch;
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_noprefetch,
+ CTLFLAG_RWTUN, &l2arc_noprefetch, 0,
+ "Skip caching prefetched buffers (LEGACY)");
+/* END CSTYLED */
+
+extern int l2arc_feed_again;
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_feed_again,
+ CTLFLAG_RWTUN, &l2arc_feed_again, 0,
+ "Turbo L2ARC warmup (LEGACY)");
+/* END CSTYLED */
+
+extern int l2arc_norw;
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, l2arc_norw,
+ CTLFLAG_RWTUN, &l2arc_norw, 0,
+ "No reads during writes (LEGACY)");
+/* END CSTYLED */
+
+static int
+param_get_arc_state_size(SYSCTL_HANDLER_ARGS)
+{
+ arc_state_t *state = (arc_state_t *)arg1;
+ int64_t val;
+
+ val = zfs_refcount_count(&state->arcs_size[ARC_BUFC_DATA]) +
+ zfs_refcount_count(&state->arcs_size[ARC_BUFC_METADATA]);
+ return (sysctl_handle_64(oidp, &val, 0, req));
}
+extern arc_state_t ARC_anon;
+
/* BEGIN CSTYLED */
-SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min,
- CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- &zfs_arc_min, sizeof (zfs_arc_min), param_set_arc_min, "LU",
- "min arc size (LEGACY)");
-SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max,
- CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- &zfs_arc_max, sizeof (zfs_arc_max), param_set_arc_max, "LU",
- "max arc size (LEGACY)");
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, anon_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_anon, 0, param_get_arc_state_size, "Q",
+ "size of anonymous state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_metadata_esize, CTLFLAG_RD,
+ &ARC_anon.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in anonymous state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, anon_data_esize, CTLFLAG_RD,
+ &ARC_anon.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in anonymous state");
/* END CSTYLED */
-/* dbuf.c */
+extern arc_state_t ARC_mru;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, mru_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_mru, 0, param_get_arc_state_size, "Q",
+ "size of mru state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_metadata_esize, CTLFLAG_RD,
+ &ARC_mru.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in mru state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_data_esize, CTLFLAG_RD,
+ &ARC_mru.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in mru state");
+/* END CSTYLED */
+
+extern arc_state_t ARC_mru_ghost;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, mru_ghost_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_mru_ghost, 0, param_get_arc_state_size, "Q",
+ "size of mru ghost state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_metadata_esize, CTLFLAG_RD,
+ &ARC_mru_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in mru ghost state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mru_ghost_data_esize, CTLFLAG_RD,
+ &ARC_mru_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in mru ghost state");
+/* END CSTYLED */
+
+extern arc_state_t ARC_mfu;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, mfu_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_mfu, 0, param_get_arc_state_size, "Q",
+ "size of mfu state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_metadata_esize, CTLFLAG_RD,
+ &ARC_mfu.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in mfu state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_data_esize, CTLFLAG_RD,
+ &ARC_mfu.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in mfu state");
+/* END CSTYLED */
+extern arc_state_t ARC_mfu_ghost;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, mfu_ghost_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_mfu_ghost, 0, param_get_arc_state_size, "Q",
+ "size of mfu ghost state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_metadata_esize, CTLFLAG_RD,
+ &ARC_mfu_ghost.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in mfu ghost state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, mfu_ghost_data_esize, CTLFLAG_RD,
+ &ARC_mfu_ghost.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in mfu ghost state");
+/* END CSTYLED */
+
+extern arc_state_t ARC_uncached;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, uncached_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_uncached, 0, param_get_arc_state_size, "Q",
+ "size of uncached state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, uncached_metadata_esize, CTLFLAG_RD,
+ &ARC_uncached.arcs_esize[ARC_BUFC_METADATA].rc_count, 0,
+ "size of evictable metadata in uncached state");
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, uncached_data_esize, CTLFLAG_RD,
+ &ARC_uncached.arcs_esize[ARC_BUFC_DATA].rc_count, 0,
+ "size of evictable data in uncached state");
+/* END CSTYLED */
+
+extern arc_state_t ARC_l2c_only;
+
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, l2c_only_size,
+ CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ARC_l2c_only, 0, param_get_arc_state_size, "Q",
+ "size of l2c_only state");
+/* END CSTYLED */
+
+/* dbuf.c */
/* dmu.c */
/* dmu_zfetch.c */
+
SYSCTL_NODE(_vfs_zfs, OID_AUTO, zfetch, CTLFLAG_RW, 0, "ZFS ZFETCH (LEGACY)");
-/* max bytes to prefetch per stream (default 8MB) */
extern uint32_t zfetch_max_distance;
-SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_distance, CTLFLAG_RWTUN,
- &zfetch_max_distance, 0, "Max bytes to prefetch per stream (LEGACY)");
-/* max bytes to prefetch indirects for per stream (default 64MB) */
+/* BEGIN CSTYLED */
+SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_distance,
+ CTLFLAG_RWTUN, &zfetch_max_distance, 0,
+ "Max bytes to prefetch per stream (LEGACY)");
+/* END CSTYLED */
+
extern uint32_t zfetch_max_idistance;
+
/* BEGIN CSTYLED */
-SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_idistance, CTLFLAG_RWTUN,
- &zfetch_max_idistance, 0,
+SYSCTL_UINT(_vfs_zfs_zfetch, OID_AUTO, max_idistance,
+ CTLFLAG_RWTUN, &zfetch_max_idistance, 0,
"Max bytes to prefetch indirects for per stream (LEGACY)");
/* END CSTYLED */
/* dsl_pool.c */
/* dnode.c */
-extern int zfs_default_bs;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, default_bs, CTLFLAG_RWTUN,
- &zfs_default_bs, 0, "Default dnode block shift");
-
-extern int zfs_default_ibs;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, default_ibs, CTLFLAG_RWTUN,
- &zfs_default_ibs, 0, "Default dnode indirect block shift");
-
/* dsl_scan.c */
/* metaslab.c */
-/* BEGIN CSTYLED */
+int
+param_set_active_allocator(SYSCTL_HANDLER_ARGS)
+{
+ char buf[16];
+ int rc;
+
+ if (req->newptr == NULL)
+ strlcpy(buf, zfs_active_allocator, sizeof (buf));
+
+ rc = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (rc || req->newptr == NULL)
+ return (rc);
+ if (strcmp(buf, zfs_active_allocator) == 0)
+ return (0);
+
+ return (param_set_active_allocator_common(buf));
+}
+
/*
* In pools where the log space map feature is not enabled we touch
* multiple metaslabs (and their respective space maps) with each
@@ -382,10 +527,13 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, default_ibs, CTLFLAG_RWTUN,
* is 8~16K.
*/
extern int zfs_metaslab_sm_blksz_no_log;
-SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_no_log, CTLFLAG_RDTUN,
- &zfs_metaslab_sm_blksz_no_log, 0,
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_no_log,
+ CTLFLAG_RDTUN, &zfs_metaslab_sm_blksz_no_log, 0,
"Block size for space map in pools with log space map disabled. "
"Power of 2 greater than 4096.");
+/* END CSTYLED */
/*
* When the log space map feature is enabled, we accumulate a lot of
@@ -393,10 +541,13 @@ SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_no_log, CTLFLAG_RDTUN,
* from a bigger block size like 128K for the metaslab space maps.
*/
extern int zfs_metaslab_sm_blksz_with_log;
-SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_with_log, CTLFLAG_RDTUN,
- &zfs_metaslab_sm_blksz_with_log, 0,
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_with_log,
+ CTLFLAG_RDTUN, &zfs_metaslab_sm_blksz_with_log, 0,
"Block size for space map in pools with log space map enabled. "
"Power of 2 greater than 4096.");
+/* END CSTYLED */
/*
* The in-core space map representation is more compact than its on-disk form.
@@ -404,22 +555,31 @@ SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, sm_blksz_with_log, CTLFLAG_RDTUN,
* space map representation must be before we compact it on-disk.
* Values should be greater than or equal to 100.
*/
-extern int zfs_condense_pct;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, condense_pct, CTLFLAG_RWTUN,
- &zfs_condense_pct, 0,
+extern uint_t zfs_condense_pct;
+
+/* BEGIN CSTYLED */
+SYSCTL_UINT(_vfs_zfs, OID_AUTO, condense_pct,
+ CTLFLAG_RWTUN, &zfs_condense_pct, 0,
"Condense on-disk spacemap when it is more than this many percents"
" of in-memory counterpart");
+/* END CSTYLED */
+
+extern uint_t zfs_remove_max_segment;
-extern int zfs_remove_max_segment;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, remove_max_segment, CTLFLAG_RWTUN,
- &zfs_remove_max_segment, 0, "Largest contiguous segment ZFS will"
- " attempt to allocate when removing a device");
+/* BEGIN CSTYLED */
+SYSCTL_UINT(_vfs_zfs, OID_AUTO, remove_max_segment,
+ CTLFLAG_RWTUN, &zfs_remove_max_segment, 0,
+ "Largest contiguous segment ZFS will attempt to allocate when removing"
+ " a device");
+/* END CSTYLED */
extern int zfs_removal_suspend_progress;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, removal_suspend_progress, CTLFLAG_RWTUN,
- &zfs_removal_suspend_progress, 0,
- "Ensures certain actions can happen while in the middle of a removal");
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, removal_suspend_progress,
+ CTLFLAG_RWTUN, &zfs_removal_suspend_progress, 0,
+ "Ensures certain actions can happen while in the middle of a removal");
+/* END CSTYLED */
/*
* Minimum size which forces the dynamic allocator to change
@@ -428,9 +588,13 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, removal_suspend_progress, CTLFLAG_RWTUN,
* aggressive strategy (i.e search by size rather than offset).
*/
extern uint64_t metaslab_df_alloc_threshold;
-SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, df_alloc_threshold, CTLFLAG_RWTUN,
- &metaslab_df_alloc_threshold, 0, "Minimum size which forces the dynamic"
- " allocator to change its allocation strategy");
+
+/* BEGIN CSTYLED */
+SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, df_alloc_threshold,
+ CTLFLAG_RWTUN, &metaslab_df_alloc_threshold, 0,
+ "Minimum size which forces the dynamic allocator to change its"
+ " allocation strategy");
+/* END CSTYLED */
/*
* The minimum free space, in percent, which must be available
@@ -438,47 +602,63 @@ SYSCTL_QUAD(_vfs_zfs_metaslab, OID_AUTO, df_alloc_threshold, CTLFLAG_RWTUN,
* Once the space map's free space drops below this level we dynamically
* switch to using best-fit allocations.
*/
-extern int metaslab_df_free_pct;
-SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, df_free_pct, CTLFLAG_RWTUN,
- &metaslab_df_free_pct, 0,
+extern uint_t metaslab_df_free_pct;
+
+/* BEGIN CSTYLED */
+SYSCTL_UINT(_vfs_zfs_metaslab, OID_AUTO, df_free_pct,
+ CTLFLAG_RWTUN, &metaslab_df_free_pct, 0,
"The minimum free space, in percent, which must be available in a"
" space map to continue allocations in a first-fit fashion");
+/* END CSTYLED */
-/*
- * Percentage of all cpus that can be used by the metaslab taskq.
- */
-extern int metaslab_load_pct;
-SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, load_pct, CTLFLAG_RWTUN,
- &metaslab_load_pct, 0,
- "Percentage of cpus that can be used by the metaslab taskq");
+/* mmp.c */
-/*
- * Max number of metaslabs per group to preload.
- */
-extern int metaslab_preload_limit;
-SYSCTL_INT(_vfs_zfs_metaslab, OID_AUTO, preload_limit, CTLFLAG_RWTUN,
- &metaslab_preload_limit, 0,
- "Max number of metaslabs per group to preload");
+int
+param_set_multihost_interval(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+
+ err = sysctl_handle_64(oidp, &zfs_multihost_interval, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ if (spa_mode_global != SPA_MODE_UNINIT)
+ mmp_signal_all_threads();
+
+ return (0);
+}
/* spa.c */
+
extern int zfs_ccw_retry_interval;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, ccw_retry_interval, CTLFLAG_RWTUN,
- &zfs_ccw_retry_interval, 0, "Configuration cache file write,"
- " retry after failure, interval (seconds)");
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, ccw_retry_interval,
+ CTLFLAG_RWTUN, &zfs_ccw_retry_interval, 0,
+ "Configuration cache file write, retry after failure, interval"
+ " (seconds)");
+/* END CSTYLED */
extern uint64_t zfs_max_missing_tvds_cachefile;
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, max_missing_tvds_cachefile, CTLFLAG_RWTUN,
- &zfs_max_missing_tvds_cachefile, 0,
- "allow importing pools with missing top-level vdevs in cache file");
+
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, max_missing_tvds_cachefile,
+ CTLFLAG_RWTUN, &zfs_max_missing_tvds_cachefile, 0,
+ "Allow importing pools with missing top-level vdevs in cache file");
+/* END CSTYLED */
extern uint64_t zfs_max_missing_tvds_scan;
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, max_missing_tvds_scan, CTLFLAG_RWTUN,
- &zfs_max_missing_tvds_scan, 0,
- "allow importing pools with missing top-level vdevs during scan");
+
+/* BEGIN CSTYLED */
+SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, max_missing_tvds_scan,
+ CTLFLAG_RWTUN, &zfs_max_missing_tvds_scan, 0,
+ "Allow importing pools with missing top-level vdevs during scan");
/* END CSTYLED */
/* spa_misc.c */
+
extern int zfs_flags;
+
static int
sysctl_vfs_zfs_debug_flags(SYSCTL_HANDLER_ARGS)
{
@@ -515,7 +695,7 @@ param_set_deadman_synctime(SYSCTL_HANDLER_ARGS)
int err;
val = zfs_deadman_synctime_ms;
- err = sysctl_handle_long(oidp, &val, 0, req);
+ err = sysctl_handle_64(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (err);
zfs_deadman_synctime_ms = val;
@@ -532,7 +712,7 @@ param_set_deadman_ziotime(SYSCTL_HANDLER_ARGS)
int err;
val = zfs_deadman_ziotime_ms;
- err = sysctl_handle_long(oidp, &val, 0, req);
+ err = sysctl_handle_64(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (err);
zfs_deadman_ziotime_ms = val;
@@ -566,22 +746,45 @@ param_set_deadman_failmode(SYSCTL_HANDLER_ARGS)
return (-param_set_deadman_failmode_common(buf));
}
+int
+param_set_slop_shift(SYSCTL_HANDLER_ARGS)
+{
+ int val;
+ int err;
+
+ val = spa_slop_shift;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ if (val < 1 || val > 31)
+ return (EINVAL);
+
+ spa_slop_shift = val;
+
+ return (0);
+}
/* spacemap.c */
+
extern int space_map_ibs;
+
+/* BEGIN CSTYLED */
SYSCTL_INT(_vfs_zfs, OID_AUTO, space_map_ibs, CTLFLAG_RWTUN,
&space_map_ibs, 0, "Space map indirect block shift");
+/* END CSTYLED */
/* vdev.c */
+
int
param_set_min_auto_ashift(SYSCTL_HANDLER_ARGS)
{
- uint64_t val;
+ int val;
int err;
val = zfs_vdev_min_auto_ashift;
- err = sysctl_handle_64(oidp, &val, 0, req);
+ err = sysctl_handle_int(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (SET_ERROR(err));
@@ -593,14 +796,22 @@ param_set_min_auto_ashift(SYSCTL_HANDLER_ARGS)
return (0);
}
+/* BEGIN CSTYLED */
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, min_auto_ashift,
+ CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ &zfs_vdev_min_auto_ashift, sizeof (zfs_vdev_min_auto_ashift),
+ param_set_min_auto_ashift, "IU",
+ "Min ashift used when creating new top-level vdev. (LEGACY)");
+/* END CSTYLED */
+
int
param_set_max_auto_ashift(SYSCTL_HANDLER_ARGS)
{
- uint64_t val;
+ int val;
int err;
val = zfs_vdev_max_auto_ashift;
- err = sysctl_handle_64(oidp, &val, 0, req);
+ err = sysctl_handle_int(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (SET_ERROR(err));
@@ -613,26 +824,25 @@ param_set_max_auto_ashift(SYSCTL_HANDLER_ARGS)
}
/* BEGIN CSTYLED */
-SYSCTL_PROC(_vfs_zfs, OID_AUTO, min_auto_ashift,
- CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
- &zfs_vdev_min_auto_ashift, sizeof (zfs_vdev_min_auto_ashift),
- param_set_min_auto_ashift, "QU",
- "Min ashift used when creating new top-level vdev. (LEGACY)");
SYSCTL_PROC(_vfs_zfs, OID_AUTO, max_auto_ashift,
- CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
&zfs_vdev_max_auto_ashift, sizeof (zfs_vdev_max_auto_ashift),
- param_set_max_auto_ashift, "QU",
+ param_set_max_auto_ashift, "IU",
"Max ashift used when optimizing for logical -> physical sector size on"
" new top-level vdevs. (LEGACY)");
+/* END CSTYLED */
/*
* Since the DTL space map of a vdev is not expected to have a lot of
* entries, we default its block size to 4K.
*/
extern int zfs_vdev_dtl_sm_blksz;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, dtl_sm_blksz, CTLFLAG_RDTUN,
- &zfs_vdev_dtl_sm_blksz, 0,
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, dtl_sm_blksz,
+ CTLFLAG_RDTUN, &zfs_vdev_dtl_sm_blksz, 0,
"Block size for DTL space map. Power of 2 greater than 4096.");
+/* END CSTYLED */
/*
* vdev-wide space maps that have lots of entries written to them at
@@ -640,80 +850,38 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, dtl_sm_blksz, CTLFLAG_RDTUN,
* (e.g. vdev_obsolete_sm), thus we default their block size to 128K.
*/
extern int zfs_vdev_standard_sm_blksz;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, standard_sm_blksz, CTLFLAG_RDTUN,
- &zfs_vdev_standard_sm_blksz, 0,
+
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, standard_sm_blksz,
+ CTLFLAG_RDTUN, &zfs_vdev_standard_sm_blksz, 0,
"Block size for standard space map. Power of 2 greater than 4096.");
/* END CSTYLED */
extern int vdev_validate_skip;
-SYSCTL_INT(_vfs_zfs, OID_AUTO, validate_skip, CTLFLAG_RDTUN,
- &vdev_validate_skip, 0, "Enable to bypass vdev_validate().");
-
-/* vdev_cache.c */
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs, OID_AUTO, validate_skip,
+ CTLFLAG_RDTUN, &vdev_validate_skip, 0,
+ "Enable to bypass vdev_validate().");
+/* END CSTYLED */
/* vdev_mirror.c */
-/*
- * The load configuration settings below are tuned by default for
- * the case where all devices are of the same rotational type.
- *
- * If there is a mixture of rotating and non-rotating media, setting
- * non_rotating_seek_inc to 0 may well provide better results as it
- * will direct more reads to the non-rotating vdevs which are more
- * likely to have a higher performance.
- */
-
/* vdev_queue.c */
+
+extern uint_t zfs_vdev_max_active;
+
/* BEGIN CSTYLED */
-extern uint32_t zfs_vdev_max_active;
-SYSCTL_UINT(_vfs_zfs, OID_AUTO, top_maxinflight, CTLFLAG_RWTUN,
- &zfs_vdev_max_active, 0,
+SYSCTL_UINT(_vfs_zfs, OID_AUTO, top_maxinflight,
+ CTLFLAG_RWTUN, &zfs_vdev_max_active, 0,
"The maximum number of I/Os of all types active for each device."
" (LEGACY)");
+/* END CSTYLED */
-extern int zfs_vdev_def_queue_depth;
-SYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, def_queue_depth, CTLFLAG_RWTUN,
- &zfs_vdev_def_queue_depth, 0,
- "Default queue depth for each allocator");
-
+/* zio.c */
-SYSCTL_INT(_vfs_zfs_zio, OID_AUTO, exclude_metadata, CTLFLAG_RDTUN,
- &zio_exclude_metadata, 0,
+/* BEGIN CSTYLED */
+SYSCTL_INT(_vfs_zfs_zio, OID_AUTO, exclude_metadata,
+ CTLFLAG_RDTUN, &zio_exclude_metadata, 0,
"Exclude metadata buffers from dumps as well");
/* END CSTYLED */
-
-int
-param_set_slop_shift(SYSCTL_HANDLER_ARGS)
-{
- int val;
- int err;
-
- val = *(int *)arg1;
-
- err = sysctl_handle_int(oidp, &val, 0, req);
- if (err != 0 || req->newptr == NULL)
- return (err);
-
- if (val < 1 || val > 31)
- return (EINVAL);
-
- *(int *)arg1 = val;
-
- return (0);
-}
-
-int
-param_set_multihost_interval(SYSCTL_HANDLER_ARGS)
-{
- int err;
-
- err = sysctl_handle_long(oidp, arg1, 0, req);
- if (err != 0 || req->newptr == NULL)
- return (err);
-
- if (spa_mode_global != SPA_MODE_UNINIT)
- mmp_signal_all_threads();
-
- return (0);
-}
diff --git a/module/os/freebsd/zfs/vdev_file.c b/module/os/freebsd/zfs/vdev_file.c
index ef87d6610977..869093afa3ed 100644
--- a/module/os/freebsd/zfs/vdev_file.c
+++ b/module/os/freebsd/zfs/vdev_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -40,8 +40,8 @@
static taskq_t *vdev_file_taskq;
-static unsigned long vdev_file_logical_ashift = SPA_MINBLOCKSHIFT;
-static unsigned long vdev_file_physical_ashift = SPA_MINBLOCKSHIFT;
+static uint_t vdev_file_logical_ashift = SPA_MINBLOCKSHIFT;
+static uint_t vdev_file_physical_ashift = SPA_MINBLOCKSHIFT;
void
vdev_file_init(void)
@@ -247,7 +247,7 @@ vdev_file_io_start(zio_t *zio)
vdev_t *vd = zio->io_vd;
vdev_file_t *vf = vd->vdev_tsd;
- if (zio->io_type == ZIO_TYPE_IOCTL) {
+ if (zio->io_type == ZIO_TYPE_FLUSH) {
/* XXPOLICY */
if (!vdev_readable(vd)) {
zio->io_error = SET_ERROR(ENXIO);
@@ -255,14 +255,7 @@ vdev_file_io_start(zio_t *zio)
return;
}
- switch (zio->io_cmd) {
- case DKIOCFLUSHWRITECACHE:
- zio->io_error = zfs_file_fsync(vf->vf_file,
- O_SYNC|O_DSYNC);
- break;
- default:
- zio->io_error = SET_ERROR(ENOTSUP);
- }
+ zio->io_error = zfs_file_fsync(vf->vf_file, O_SYNC|O_DSYNC);
zio_execute(zio);
return;
@@ -350,7 +343,7 @@ vdev_ops_t vdev_disk_ops = {
#endif
-ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, logical_ashift, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, logical_ashift, UINT, ZMOD_RW,
"Logical ashift for file-based devices");
-ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, physical_ashift, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, physical_ashift, UINT, ZMOD_RW,
"Physical ashift for file-based devices");
diff --git a/module/os/freebsd/zfs/vdev_geom.c b/module/os/freebsd/zfs/vdev_geom.c
index 1ac41f616a0d..9d88971919db 100644
--- a/module/os/freebsd/zfs/vdev_geom.c
+++ b/module/os/freebsd/zfs/vdev_geom.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -543,7 +543,7 @@ process_vdev_config(nvlist_t ***configs, uint64_t *count, nvlist_t *cfg,
uint64_t pool_guid;
uint64_t vdev_guid;
uint64_t id, txg, known_txg;
- char *pname;
+ const char *pname;
if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &pname) != 0 ||
strcmp(pname, name) != 0)
@@ -955,8 +955,7 @@ skip_open:
*logical_ashift = highbit(MAX(pp->sectorsize, SPA_MINBLOCKSIZE)) - 1;
*physical_ashift = 0;
if (pp->stripesize && pp->stripesize > (1 << *logical_ashift) &&
- ISP2(pp->stripesize) && pp->stripesize <= (1 << ASHIFT_MAX) &&
- pp->stripeoffset == 0)
+ ISP2(pp->stripesize) && pp->stripeoffset == 0)
*physical_ashift = highbit(pp->stripesize) - 1;
/*
@@ -1054,7 +1053,7 @@ vdev_geom_io_intr(struct bio *bp)
/*
* We have to split bio freeing into two parts, because the ABD code
* cannot be called in this context and vdev_op_io_done is not called
- * for ZIO_TYPE_IOCTL zio-s.
+ * for ZIO_TYPE_FLUSH zio-s.
*/
if (zio->io_type != ZIO_TYPE_READ && zio->io_type != ZIO_TYPE_WRITE) {
g_destroy_bio(bp);
@@ -1154,46 +1153,35 @@ vdev_geom_io_start(zio_t *zio)
vd = zio->io_vd;
- switch (zio->io_type) {
- case ZIO_TYPE_IOCTL:
+ if (zio->io_type == ZIO_TYPE_FLUSH) {
/* XXPOLICY */
if (!vdev_readable(vd)) {
zio->io_error = SET_ERROR(ENXIO);
zio_interrupt(zio);
return;
- } else {
- switch (zio->io_cmd) {
- case DKIOCFLUSHWRITECACHE:
- if (zfs_nocacheflush ||
- vdev_geom_bio_flush_disable)
- break;
- if (vd->vdev_nowritecache) {
- zio->io_error = SET_ERROR(ENOTSUP);
- break;
- }
- goto sendreq;
- default:
- zio->io_error = SET_ERROR(ENOTSUP);
- }
}
- zio_execute(zio);
- return;
- case ZIO_TYPE_TRIM:
- if (!vdev_geom_bio_delete_disable) {
- goto sendreq;
+ if (zfs_nocacheflush || vdev_geom_bio_flush_disable) {
+ zio_execute(zio);
+ return;
+ }
+
+ if (vd->vdev_nowritecache) {
+ zio->io_error = SET_ERROR(ENOTSUP);
+ zio_execute(zio);
+ return;
+ }
+ } else if (zio->io_type == ZIO_TYPE_TRIM) {
+ if (vdev_geom_bio_delete_disable) {
+ zio_execute(zio);
+ return;
}
- zio_execute(zio);
- return;
- default:
- ;
- /* PASSTHROUGH --- placate compiler */
}
-sendreq:
+
ASSERT(zio->io_type == ZIO_TYPE_READ ||
zio->io_type == ZIO_TYPE_WRITE ||
zio->io_type == ZIO_TYPE_TRIM ||
- zio->io_type == ZIO_TYPE_IOCTL);
+ zio->io_type == ZIO_TYPE_FLUSH);
cp = vd->vdev_tsd;
if (cp == NULL) {
@@ -1245,7 +1233,7 @@ sendreq:
bp->bio_offset = zio->io_offset;
bp->bio_length = zio->io_size;
break;
- case ZIO_TYPE_IOCTL:
+ case ZIO_TYPE_FLUSH:
bp->bio_cmd = BIO_FLUSH;
bp->bio_data = NULL;
bp->bio_offset = cp->provider->mediasize;
diff --git a/module/os/freebsd/zfs/vdev_label_os.c b/module/os/freebsd/zfs/vdev_label_os.c
index 48f58807e800..79732d9173e8 100644
--- a/module/os/freebsd/zfs/vdev_label_os.c
+++ b/module/os/freebsd/zfs/vdev_label_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -55,8 +55,8 @@ vdev_label_write_pad2(vdev_t *vd, const char *buf, size_t size)
ASSERT3U(spa_config_held(spa, SCL_ALL, RW_WRITER), ==, SCL_ALL);
pad2 = abd_alloc_for_io(VDEV_PAD_SIZE, B_TRUE);
- abd_zero(pad2, VDEV_PAD_SIZE);
abd_copy_from_buf(pad2, buf, size);
+ abd_zero_off(pad2, size, VDEV_PAD_SIZE - size);
retry:
zio = zio_root(spa, NULL, NULL, flags);
@@ -72,3 +72,62 @@ retry:
abd_free(pad2);
return (error);
}
+
+static void
+vdev_child_done(zio_t *zio)
+{
+ zio_t *pio = zio->io_private;
+
+ mutex_enter(&pio->io_lock);
+ pio->io_error = zio_worst_error(pio->io_error, zio->io_error);
+ mutex_exit(&pio->io_lock);
+}
+
+/*
+ * Check if the reserved boot area is in-use.
+ *
+ * When booting FreeBSD with an MBR partition with ZFS, the zfsboot file
+ * (which understands the ZFS file system) is written to the ZFS BOOT
+ * reserve area (at offset 512K). We check for that here before attaching
+ * a disk to raidz which would then corrupt this boot data.
+ */
+int
+vdev_check_boot_reserve(spa_t *spa, vdev_t *childvd)
+{
+ ASSERT(childvd->vdev_ops->vdev_op_leaf);
+
+ size_t size = SPA_MINBLOCKSIZE;
+ abd_t *abd = abd_alloc_linear(size, B_FALSE);
+
+ zio_t *pio = zio_root(spa, NULL, NULL, 0);
+ /*
+ * Note: zio_vdev_child_io() adds VDEV_LABEL_START_SIZE to the offset
+ * to calculate the physical offset to write to. Passing in a negative
+ * offset lets us access the boot area.
+ */
+ zio_nowait(zio_vdev_child_io(pio, NULL, childvd,
+ VDEV_BOOT_OFFSET - VDEV_LABEL_START_SIZE, abd, size, ZIO_TYPE_READ,
+ ZIO_PRIORITY_ASYNC_READ, 0, vdev_child_done, pio));
+ zio_wait(pio);
+
+ unsigned char *buf = abd_to_buf(abd);
+
+ /*
+ * The BTX server has a special header at the begining.
+ *
+ * btx_hdr: .byte 0xeb # Machine ID
+ * .byte 0xe # Header size
+ * .ascii "BTX" # Magic
+ * .byte 0x1 # Major version
+ * .byte 0x2 # Minor version
+ * .byte BTX_FLAGS # Flags
+ */
+ if (buf[0] == 0xeb && buf[1] == 0x0e &&
+ buf[2] == 'B' && buf[3] == 'T' && buf[4] == 'X') {
+ abd_free(abd);
+ return (EBUSY);
+ }
+
+ abd_free(abd);
+ return (0);
+}
diff --git a/module/os/freebsd/zfs/zfs_acl.c b/module/os/freebsd/zfs/zfs_acl.c
index 107ffa4c8978..20466aeaaa05 100644
--- a/module/os/freebsd/zfs/zfs_acl.c
+++ b/module/os/freebsd/zfs/zfs_acl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -495,10 +495,8 @@ zfs_acl_release_nodes(zfs_acl_t *aclp)
{
zfs_acl_node_t *aclnode;
- while ((aclnode = list_head(&aclp->z_acl))) {
- list_remove(&aclp->z_acl, aclnode);
+ while ((aclnode = list_remove_head(&aclp->z_acl)))
zfs_acl_node_free(aclnode);
- }
aclp->z_acl_count = 0;
aclp->z_acl_bytes = 0;
}
@@ -527,7 +525,7 @@ zfs_acl_valid_ace_type(uint_t type, uint_t flags)
entry_type == ACE_EVERYONE || entry_type == 0 ||
entry_type == ACE_IDENTIFIER_GROUP);
default:
- if (type >= MIN_ACE_TYPE && type <= MAX_ACE_TYPE)
+ if (type <= MAX_ACE_TYPE)
return (B_TRUE);
}
return (B_FALSE);
@@ -631,8 +629,8 @@ zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who,
return (NULL);
}
-static uint64_t
-zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
+static uintptr_t
+zfs_ace_walk(void *datap, uintptr_t cookie, int aclcnt,
uint16_t *flags, uint16_t *type, uint32_t *mask)
{
(void) aclcnt;
@@ -642,7 +640,7 @@ zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
acep = zfs_acl_next_ace(aclp, acep, &who, mask,
flags, type);
- return ((uint64_t)(uintptr_t)acep);
+ return ((uintptr_t)acep);
}
/*
@@ -1133,6 +1131,7 @@ zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen,
cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl,
cb->cb_acl_node);
}
+ ASSERT3P(cb->cb_acl_node, !=, NULL);
*dataptr = cb->cb_acl_node->z_acldata;
*length = cb->cb_acl_node->z_size;
}
@@ -1618,7 +1617,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
*/
int
zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids)
+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns)
{
int error;
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
@@ -1788,7 +1787,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
if (mask == 0)
return (SET_ERROR(ENOSYS));
- if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)))
+ if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL)))
return (error);
mutex_enter(&zp->z_acl_lock);
@@ -1951,7 +1950,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
if (zp->z_pflags & ZFS_IMMUTABLE)
return (SET_ERROR(EPERM));
- if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)))
+ if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL)))
return (error);
error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp,
@@ -2040,8 +2039,7 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
{
if ((v4_mode & WRITE_MASK) &&
(zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
- (!IS_DEVVP(ZTOV(zp)) ||
- (IS_DEVVP(ZTOV(zp)) && (v4_mode & WRITE_MASK_ATTRS)))) {
+ (!IS_DEVVP(ZTOV(zp)) || (v4_mode & WRITE_MASK_ATTRS))) {
return (SET_ERROR(EROFS));
}
@@ -2340,7 +2338,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
* can define any form of access.
*/
int
-zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
+zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,
+ zidmap_t *mnt_ns)
{
uint32_t working_mode;
int error;
@@ -2413,7 +2412,6 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
* read_acl/read_attributes
*/
- error = 0;
ASSERT3U(working_mode, !=, 0);
if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&
@@ -2470,20 +2468,22 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
* NFSv4-style ZFS ACL format and call zfs_zaccess()
*/
int
-zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr)
+zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr,
+ zidmap_t *mnt_ns)
{
- return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr));
+ return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr,
+ mnt_ns));
}
/*
* Access function for secpolicy_vnode_setattr
*/
int
-zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr)
+zfs_zaccess_unix(void *zp, int mode, cred_t *cr)
{
int v4_mode = zfs_unix_to_v4(mode >> 6);
- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr));
+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL));
}
static int
@@ -2539,7 +2539,7 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp,
*
*/
int
-zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns)
{
uint32_t dzp_working_mode = 0;
uint32_t zp_working_mode = 0;
@@ -2626,7 +2626,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
int
zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
- znode_t *tzp, cred_t *cr)
+ znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns)
{
int add_perm;
int error;
@@ -2646,7 +2646,8 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
* to another.
*/
if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) {
- if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr)))
+ if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr,
+ mnt_ns)))
return (error);
}
@@ -2656,19 +2657,19 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
* If that succeeds then check for add_file/add_subdir permissions
*/
- if ((error = zfs_zaccess_delete(sdzp, szp, cr)))
+ if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns)))
return (error);
/*
* If we have a tzp, see if we can delete it?
*/
- if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr)))
+ if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns)))
return (error);
/*
* Now check for add permissions
*/
- error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr);
+ error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns);
return (error);
}
diff --git a/module/os/freebsd/zfs/zfs_ctldir.c b/module/os/freebsd/zfs/zfs_ctldir.c
index 4db5cb583327..a753e91da4fe 100644
--- a/module/os/freebsd/zfs/zfs_ctldir.c
+++ b/module/os/freebsd/zfs/zfs_ctldir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -204,6 +204,10 @@ sfs_vgetx(struct mount *mp, int flags, uint64_t parent_id, uint64_t id,
return (error);
}
+#if __FreeBSD_version >= 1400077
+ vn_set_state(vp, VSTATE_CONSTRUCTED);
+#endif
+
*vpp = vp;
return (0);
}
@@ -675,6 +679,17 @@ zfsctl_root_readdir(struct vop_readdir_args *ap)
ASSERT3S(vp->v_type, ==, VDIR);
+ /*
+ * FIXME: this routine only ever emits 3 entries and does not tolerate
+ * being called with a buffer too small to handle all of them.
+ *
+ * The check below facilitates the idiom of repeating calls until the
+ * count to return is 0.
+ */
+ if (zfs_uio_offset(&uio) == 3 * sizeof (entry)) {
+ return (0);
+ }
+
error = sfs_readdir_common(zfsvfs->z_root, ZFSCTL_INO_ROOT, ap, &uio,
&dots_offset);
if (error != 0) {
@@ -802,6 +817,9 @@ static struct vop_vector zfsctl_ops_root = {
#if __FreeBSD_version >= 1300121
.vop_fplookup_vexec = VOP_EAGAIN,
#endif
+#if __FreeBSD_version >= 1300139
+ .vop_fplookup_symlink = VOP_EAGAIN,
+#endif
.vop_open = zfsctl_common_open,
.vop_close = zfsctl_common_close,
.vop_ioctl = VOP_EINVAL,
@@ -977,12 +995,13 @@ zfsctl_snapdir_lookup(struct vop_lookup_args *ap)
*/
VI_LOCK(*vpp);
if (((*vpp)->v_iflag & VI_MOUNT) == 0) {
+ VI_UNLOCK(*vpp);
/*
* Upgrade to exclusive lock in order to:
* - avoid race conditions
* - satisfy the contract of mount_snapshot()
*/
- err = VOP_LOCK(*vpp, LK_TRYUPGRADE | LK_INTERLOCK);
+ err = VOP_LOCK(*vpp, LK_TRYUPGRADE);
if (err == 0)
break;
} else {
@@ -1007,7 +1026,8 @@ zfsctl_snapdir_lookup(struct vop_lookup_args *ap)
"%s/" ZFS_CTLDIR_NAME "/snapshot/%s",
dvp->v_vfsp->mnt_stat.f_mntonname, name);
- err = mount_snapshot(curthread, vpp, "zfs", mountpoint, fullname, 0);
+ err = mount_snapshot(curthread, vpp, "zfs", mountpoint, fullname, 0,
+ dvp->v_vfsp);
kmem_free(mountpoint, mountpoint_len);
if (err == 0) {
/*
@@ -1053,7 +1073,8 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
return (error);
}
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
for (;;) {
uint64_t cookie;
uint64_t id;
@@ -1070,7 +1091,7 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
*eofp = 1;
error = 0;
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1083,7 +1104,7 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
if (error != 0) {
if (error == ENAMETOOLONG)
error = 0;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(error));
}
zfs_uio_setoffset(&uio, cookie + dots_offset);
@@ -1101,7 +1122,8 @@ zfsctl_snapdir_getattr(struct vop_getattr_args *ap)
uint64_t snap_count;
int err;
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
ds = dmu_objset_ds(zfsvfs->z_os);
zfsctl_common_getattr(vp, vap);
vap->va_ctime = dmu_objset_snap_cmtime(zfsvfs->z_os);
@@ -1111,14 +1133,14 @@ zfsctl_snapdir_getattr(struct vop_getattr_args *ap)
err = zap_count(dmu_objset_pool(ds->ds_objset)->dp_meta_objset,
dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
if (err != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
vap->va_nlink += snap_count;
}
vap->va_size = vap->va_nlink;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1127,6 +1149,9 @@ static struct vop_vector zfsctl_ops_snapdir = {
#if __FreeBSD_version >= 1300121
.vop_fplookup_vexec = VOP_EAGAIN,
#endif
+#if __FreeBSD_version >= 1300139
+ .vop_fplookup_symlink = VOP_EAGAIN,
+#endif
.vop_open = zfsctl_common_open,
.vop_close = zfsctl_common_close,
.vop_getattr = zfsctl_snapdir_getattr,
@@ -1150,7 +1175,7 @@ zfsctl_snapshot_inactive(struct vop_inactive_args *ap)
{
vnode_t *vp = ap->a_vp;
- VERIFY3S(vrecycle(vp), ==, 1);
+ vrecycle(vp);
return (0);
}
@@ -1234,6 +1259,11 @@ static struct vop_vector zfsctl_ops_snapshot = {
#if __FreeBSD_version >= 1300121
.vop_fplookup_vexec = VOP_EAGAIN,
#endif
+#if __FreeBSD_version >= 1300139
+ .vop_fplookup_symlink = VOP_EAGAIN,
+#endif
+ .vop_open = zfsctl_common_open,
+ .vop_close = zfsctl_common_close,
.vop_inactive = zfsctl_snapshot_inactive,
#if __FreeBSD_version >= 1300045
.vop_need_inactive = vop_stdneed_inactive,
diff --git a/module/os/freebsd/zfs/zfs_debug.c b/module/os/freebsd/zfs/zfs_debug.c
index 60596aa912f2..78d50c6fd8b7 100644
--- a/module/os/freebsd/zfs/zfs_debug.c
+++ b/module/os/freebsd/zfs/zfs_debug.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -29,14 +29,14 @@
typedef struct zfs_dbgmsg {
list_node_t zdm_node;
time_t zdm_timestamp;
- int zdm_size;
- char zdm_msg[1]; /* variable length allocation */
+ uint_t zdm_size;
+ char zdm_msg[];
} zfs_dbgmsg_t;
static list_t zfs_dbgmsgs;
-static int zfs_dbgmsg_size = 0;
+static uint_t zfs_dbgmsg_size = 0;
static kmutex_t zfs_dbgmsgs_lock;
-int zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
+uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
static kstat_t *zfs_dbgmsg_kstat;
/*
@@ -88,10 +88,10 @@ zfs_dbgmsg_addr(kstat_t *ksp, loff_t n)
}
static void
-zfs_dbgmsg_purge(int max_size)
+zfs_dbgmsg_purge(uint_t max_size)
{
zfs_dbgmsg_t *zdm;
- int size;
+ uint_t size;
ASSERT(MUTEX_HELD(&zfs_dbgmsgs_lock));
@@ -155,11 +155,11 @@ void
__zfs_dbgmsg(char *buf)
{
zfs_dbgmsg_t *zdm;
- int size;
+ uint_t size;
DTRACE_PROBE1(zfs__dbgmsg, char *, buf);
- size = sizeof (zfs_dbgmsg_t) + strlen(buf);
+ size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
zdm = kmem_zalloc(size, KM_SLEEP);
zdm->zdm_size = size;
zdm->zdm_timestamp = gethrestime_sec();
@@ -168,7 +168,7 @@ __zfs_dbgmsg(char *buf)
mutex_enter(&zfs_dbgmsgs_lock);
list_insert_tail(&zfs_dbgmsgs, zdm);
zfs_dbgmsg_size += size;
- zfs_dbgmsg_purge(MAX(zfs_dbgmsg_maxsize, 0));
+ zfs_dbgmsg_purge(zfs_dbgmsg_maxsize);
mutex_exit(&zfs_dbgmsgs_lock);
}
@@ -248,5 +248,5 @@ zfs_dbgmsg_print(const char *tag)
ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_enable, INT, ZMOD_RW,
"Enable ZFS debug message log");
-ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_maxsize, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_maxsize, UINT, ZMOD_RW,
"Maximum ZFS debug log size");
diff --git a/module/os/freebsd/zfs/zfs_dir.c b/module/os/freebsd/zfs/zfs_dir.c
index 7fff329a939c..948df8e50de1 100644
--- a/module/os/freebsd/zfs/zfs_dir.c
+++ b/module/os/freebsd/zfs/zfs_dir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,7 +33,6 @@
#include <sys/resource.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
-#include <sys/extdirent.h>
#include <sys/file.h>
#include <sys/kmem.h>
#include <sys/uio.h>
@@ -427,6 +426,7 @@ zfs_rmnode(znode_t *zp)
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os = zfsvfs->z_os;
dmu_tx_t *tx;
+ uint64_t z_id = zp->z_id;
uint64_t acl_obj;
uint64_t xattr_obj;
uint64_t count;
@@ -446,8 +446,10 @@ zfs_rmnode(znode_t *zp)
* Not enough space to delete some xattrs.
* Leave it in the unlinked set.
*/
+ ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
zfs_znode_free(zp);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
return;
}
} else {
@@ -465,8 +467,10 @@ zfs_rmnode(znode_t *zp)
* Not enough space or we were interrupted by unmount.
* Leave the file in the unlinked set.
*/
+ ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
zfs_znode_free(zp);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
return;
}
}
@@ -502,8 +506,10 @@ zfs_rmnode(znode_t *zp)
* which point we'll call zfs_unlinked_drain() to process it).
*/
dmu_tx_abort(tx);
+ ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
zfs_znode_free(zp);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
return;
}
@@ -810,7 +816,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xvpp, cred_t *cr)
*xvpp = NULL;
if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL,
- &acl_ids)) != 0)
+ &acl_ids, NULL)) != 0)
return (error);
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, 0)) {
zfs_acl_ids_free(&acl_ids);
@@ -956,7 +962,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
if ((uid = crgetuid(cr)) == downer || uid == fowner ||
(ZTOV(zp)->v_type == VREG &&
- zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0))
+ zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0))
return (0);
else
return (secpolicy_vnode_remove(ZTOV(zp), cr));
diff --git a/module/os/freebsd/zfs/zfs_file_os.c b/module/os/freebsd/zfs/zfs_file_os.c
index fd86a75416e6..b337932b9dcc 100644
--- a/module/os/freebsd/zfs/zfs_file_os.c
+++ b/module/os/freebsd/zfs/zfs_file_os.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/dmu.h>
#include <sys/dmu_impl.h>
#include <sys/dmu_recv.h>
@@ -53,26 +50,65 @@ int
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
{
struct thread *td;
- int rc, fd;
+ struct vnode *vp;
+ struct file *fp;
+ struct nameidata nd;
+ int error;
td = curthread;
pwd_ensure_dirs();
- /* 12.x doesn't take a const char * */
- rc = kern_openat(td, AT_FDCWD, __DECONST(char *, path),
- UIO_SYSSPACE, flags, mode);
- if (rc)
- return (SET_ERROR(rc));
- fd = td->td_retval[0];
- td->td_retval[0] = 0;
- if (fget(curthread, fd, &cap_no_rights, fpp))
- kern_close(td, fd);
+
+ KASSERT((flags & (O_EXEC | O_PATH)) == 0,
+ ("invalid flags: 0x%x", flags));
+ KASSERT((flags & O_ACCMODE) != O_ACCMODE,
+ ("invalid flags: 0x%x", flags));
+ flags = FFLAGS(flags);
+
+ error = falloc_noinstall(td, &fp);
+ if (error != 0) {
+ return (error);
+ }
+ fp->f_flag = flags & FMASK;
+
+#if __FreeBSD_version >= 1400043
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path);
+#else
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
+#endif
+ error = vn_open(&nd, &flags, mode, fp);
+ if (error != 0) {
+ falloc_abort(td, fp);
+ return (SET_ERROR(error));
+ }
+ NDFREE_PNBUF(&nd);
+ vp = nd.ni_vp;
+ fp->f_vnode = vp;
+ if (fp->f_ops == &badfileops) {
+ finit_vnode(fp, flags, NULL, &vnops);
+ }
+ VOP_UNLOCK(vp);
+ if (vp->v_type != VREG) {
+ zfs_file_close(fp);
+ return (SET_ERROR(EACCES));
+ }
+
+ if (flags & O_TRUNC) {
+ error = fo_truncate(fp, 0, td->td_ucred, td);
+ if (error != 0) {
+ zfs_file_close(fp);
+ return (SET_ERROR(error));
+ }
+ }
+
+ *fpp = fp;
+
return (0);
}
void
zfs_file_close(zfs_file_t *fp)
{
- fo_close(fp, curthread);
+ fdrop(fp, curthread);
}
static int
@@ -226,7 +262,11 @@ zfs_vop_fsync(vnode_t *vp)
struct mount *mp;
int error;
+#if __FreeBSD_version < 1400068
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+#else
+ if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0)
+#endif
goto drop;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_FSYNC(vp, MNT_WAIT, curthread);
@@ -259,7 +299,7 @@ zfs_file_get(int fd)
void
zfs_file_put(zfs_file_t *fp)
{
- fdrop(fp, curthread);
+ zfs_file_close(fp);
}
loff_t
diff --git a/module/os/freebsd/zfs/zfs_ioctl_compat.c b/module/os/freebsd/zfs/zfs_ioctl_compat.c
index 81967bed73f9..4a7beb650a8d 100644
--- a/module/os/freebsd/zfs/zfs_ioctl_compat.c
+++ b/module/os/freebsd/zfs/zfs_ioctl_compat.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/conf.h>
@@ -39,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cmn_err.h>
#include <sys/zfs_ioctl_compat.h>
+#ifdef ZFS_LEGACY_SUPPORT
enum zfs_ioc_legacy {
ZFS_IOC_LEGACY_NONE = -1,
ZFS_IOC_LEGACY_FIRST = 0,
@@ -125,7 +123,7 @@ enum zfs_ioc_legacy {
ZFS_IOC_LEGACY_LAST
};
-unsigned static long zfs_ioctl_legacy_to_ozfs_[] = {
+static unsigned long zfs_ioctl_legacy_to_ozfs_[] = {
ZFS_IOC_POOL_CREATE, /* 0x00 */
ZFS_IOC_POOL_DESTROY, /* 0x01 */
ZFS_IOC_POOL_IMPORT, /* 0x02 */
@@ -208,7 +206,7 @@ unsigned static long zfs_ioctl_legacy_to_ozfs_[] = {
ZFS_IOC_POOL_INITIALIZE, /* 0x4d:0x4f */
};
-unsigned static long zfs_ioctl_ozfs_to_legacy_common_[] = {
+static unsigned long zfs_ioctl_ozfs_to_legacy_common_[] = {
ZFS_IOC_POOL_CREATE, /* 0x00 */
ZFS_IOC_POOL_DESTROY, /* 0x01 */
ZFS_IOC_POOL_IMPORT, /* 0x02 */
@@ -297,7 +295,7 @@ unsigned static long zfs_ioctl_ozfs_to_legacy_common_[] = {
ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_WAIT_FS */
};
-unsigned static long zfs_ioctl_ozfs_to_legacy_platform_[] = {
+static unsigned long zfs_ioctl_ozfs_to_legacy_platform_[] = {
ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_NEXT */
ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_CLEAR */
ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_SEEK */
@@ -319,7 +317,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) {
@@ -361,3 +359,4 @@ zfs_cmd_ozfs_to_legacy(zfs_cmd_t *src, zfs_cmd_legacy_t *dst)
sizeof (zfs_cmd_t) - 8 - offsetof(zfs_cmd_t, zc_sendobj));
dst->zc_jailid = src->zc_zoneid;
}
+#endif /* ZFS_LEGACY_SUPPORT */
diff --git a/module/os/freebsd/zfs/zfs_ioctl_os.c b/module/os/freebsd/zfs/zfs_ioctl_os.c
index 7f7e2b72c51a..b8f5fa4e7543 100644
--- a/module/os/freebsd/zfs/zfs_ioctl_os.c
+++ b/module/os/freebsd/zfs/zfs_ioctl_os.c
@@ -25,9 +25,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/nvpair.h>
@@ -59,7 +56,7 @@ zfs_vfs_ref(zfsvfs_t **zfvp)
return (error);
}
-int
+boolean_t
zfs_vfs_held(zfsvfs_t *zfsvfs)
{
return (zfsvfs->z_vfs != NULL);
@@ -99,7 +96,7 @@ zfs_ioc_nextboot(const char *unused, nvlist_t *innvl, nvlist_t *outnvl)
char name[MAXNAMELEN];
spa_t *spa;
vdev_t *vd;
- char *command;
+ const char *command;
uint64_t pool_guid;
uint64_t vdev_guid;
int error;
diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c
index b68d84e3b858..a972c720dfdb 100644
--- a/module/os/freebsd/zfs/zfs_vfsops.c
+++ b/module/os/freebsd/zfs/zfs_vfsops.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -62,8 +62,8 @@
#include <sys/sunddi.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_dir.h>
-#include <sys/spa_boot.h>
#include <sys/jail.h>
+#include <sys/osd.h>
#include <ufs/ufs/quota.h>
#include <sys/zfs_quota.h>
@@ -89,6 +89,20 @@ int zfs_debug_level;
SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0,
"Debug level");
+struct zfs_jailparam {
+ int mount_snapshot;
+};
+
+static struct zfs_jailparam zfs_jailparam0 = {
+ .mount_snapshot = 0,
+};
+
+static int zfs_jailparam_slot;
+
+SYSCTL_JAIL_PARAM_SYS_NODE(zfs, CTLFLAG_RW, "Jail ZFS parameters");
+SYSCTL_JAIL_PARAM(_zfs, mount_snapshot, CTLTYPE_INT | CTLFLAG_RW, "I",
+ "Allow mounting snapshots in the .zfs directory for unjailed datasets");
+
SYSCTL_NODE(_vfs_zfs, OID_AUTO, version, CTLFLAG_RD, 0, "ZFS versions");
static int zfs_version_acl = ZFS_ACL_VERSION;
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0,
@@ -139,7 +153,12 @@ struct vfsops zfs_vfsops = {
.vfs_quotactl = zfs_quotactl,
};
-VFS_SET(zfs_vfsops, zfs, VFCF_JAIL | VFCF_DELEGADMIN);
+#ifdef VFCF_CROSS_COPY_FILE_RANGE
+VFS_SET(zfs_vfsops, zfs,
+ VFCF_DELEGADMIN | VFCF_JAIL | VFCF_CROSS_COPY_FILE_RANGE);
+#else
+VFS_SET(zfs_vfsops, zfs, VFCF_DELEGADMIN | VFCF_JAIL);
+#endif
/*
* We need to keep a count of active fs's.
@@ -216,7 +235,8 @@ zfs_get_temporary_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, uint64_t *val,
vfs_unbusy(vfsp);
if (tmp != *val) {
- (void) strcpy(setpoint, "temporary");
+ if (setpoint)
+ (void) strcpy(setpoint, "temporary");
*val = tmp;
}
return (0);
@@ -287,7 +307,8 @@ zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg)
cmd = cmds >> SUBCMDSHIFT;
type = cmds & SUBCMDMASK;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (id == -1) {
switch (type) {
case USRQUOTA:
@@ -386,7 +407,7 @@ zfs_quotactl(vfs_t *vfsp, int cmds, uid_t id, void *arg)
break;
}
done:
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -423,11 +444,8 @@ zfs_sync(vfs_t *vfsp, int waitfor)
dsl_pool_t *dp;
int error;
- error = vfs_stdsync(vfsp, waitfor);
- if (error != 0)
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
return (error);
-
- ZFS_ENTER(zfsvfs);
dp = dmu_objset_pool(zfsvfs->z_os);
/*
@@ -435,14 +453,14 @@ zfs_sync(vfs_t *vfsp, int waitfor)
* filesystems which may exist on a suspended pool.
*/
if (rebooting && spa_suspended(dp->dp_spa)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
if (zfsvfs->z_log != NULL)
zil_commit(zfsvfs->z_log, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
} else {
/*
* Sync all ZFS filesystems. This is what happens when you
@@ -709,7 +727,7 @@ zfs_register_callbacks(vfs_t *vfsp)
nbmand = B_FALSE;
} else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
nbmand = B_TRUE;
- } else if ((error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand) != 0)) {
+ } else if ((error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand)) != 0) {
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
return (error);
}
@@ -1027,8 +1045,6 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
if (error)
return (error);
- zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
-
/*
* If we are not mounting (ie: online recv), then we don't
* have to worry about replaying the log as we blocked all
@@ -1038,7 +1054,11 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
boolean_t readonly;
ASSERT3P(zfsvfs->z_kstat.dk_kstats, ==, NULL);
- dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os);
+ error = dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os);
+ if (error)
+ return (error);
+ zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data,
+ &zfsvfs->z_kstat.dk_zil_sums);
/*
* During replay we remove the read only flag to
@@ -1109,6 +1129,10 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
/* restore readonly bit */
if (readonly != 0)
zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY;
+ } else {
+ ASSERT3P(zfsvfs->z_kstat.dk_kstats, !=, NULL);
+ zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data,
+ &zfsvfs->z_kstat.dk_zil_sums);
}
/*
@@ -1130,7 +1154,6 @@ zfsvfs_free(zfsvfs_t *zfsvfs)
mutex_destroy(&zfsvfs->z_znodes_lock);
mutex_destroy(&zfsvfs->z_lock);
- ASSERT3U(zfsvfs->z_nr_znodes, ==, 0);
list_destroy(&zfsvfs->z_all_znodes);
ZFS_TEARDOWN_DESTROY(zfsvfs);
ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs);
@@ -1145,23 +1168,6 @@ static void
zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
{
zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
- if (zfsvfs->z_vfs) {
- if (zfsvfs->z_use_fuids) {
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
- } else {
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
- vfs_clear_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
- }
- }
zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
}
@@ -1220,15 +1226,6 @@ zfs_domount(vfs_t *vfsp, char *osname)
* Set features for file system.
*/
zfs_set_fuid_feature(zfsvfs);
- if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
- vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
- vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
- vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE);
- } else if (zfsvfs->z_case == ZFS_CASE_MIXED) {
- vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
- vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
- }
- vfs_set_feature(vfsp, VFSFT_ZEROCOPY_SUPPORTED);
if (dmu_objset_is_snapshot(zfsvfs->z_os)) {
uint64_t pval;
@@ -1291,8 +1288,7 @@ getpoolname(const char *osname, char *poolname)
} else {
if (p - osname >= MAXNAMELEN)
return (ENAMETOOLONG);
- (void) strncpy(poolname, osname, p - osname);
- poolname[p - osname] = '\0';
+ (void) strlcpy(poolname, osname, p - osname + 1);
}
return (0);
}
@@ -1318,7 +1314,7 @@ zfs_mount(vfs_t *vfsp)
char *osname;
int error = 0;
int canwrite;
- bool checkpointrewind;
+ bool checkpointrewind, isctlsnap = false;
if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL))
return (SET_ERROR(EINVAL));
@@ -1333,6 +1329,8 @@ zfs_mount(vfs_t *vfsp)
}
fetch_osname_options(osname, &checkpointrewind);
+ isctlsnap = (mvp != NULL && zfsctl_is_node(mvp) &&
+ strchr(osname, '@') != NULL);
/*
* Check for mount privilege?
@@ -1341,7 +1339,9 @@ zfs_mount(vfs_t *vfsp)
* we have local permission to allow it
*/
error = secpolicy_fs_mount(cr, mvp, vfsp);
- if (error) {
+ if (error && isctlsnap) {
+ secpolicy_fs_mount_clearopts(cr, vfsp);
+ } else if (error) {
if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0)
goto out;
@@ -1378,8 +1378,27 @@ zfs_mount(vfs_t *vfsp)
*/
if (!INGLOBALZONE(curproc) &&
(!zone_dataset_visible(osname, &canwrite) || !canwrite)) {
- error = SET_ERROR(EPERM);
- goto out;
+ boolean_t mount_snapshot = B_FALSE;
+
+ /*
+ * Snapshots may be mounted in .zfs for unjailed datasets
+ * if allowed by the jail param zfs.mount_snapshot.
+ */
+ if (isctlsnap) {
+ struct prison *pr;
+ struct zfs_jailparam *zjp;
+
+ pr = curthread->td_ucred->cr_prison;
+ mtx_lock(&pr->pr_mtx);
+ zjp = osd_jail_get(pr, zfs_jailparam_slot);
+ mtx_unlock(&pr->pr_mtx);
+ if (zjp && zjp->mount_snapshot)
+ mount_snapshot = B_TRUE;
+ }
+ if (!mount_snapshot) {
+ error = SET_ERROR(EPERM);
+ goto out;
+ }
}
vfsp->vfs_flag |= MNT_NFS4ACLS;
@@ -1429,10 +1448,12 @@ zfs_statfs(vfs_t *vfsp, struct statfs *statp)
{
zfsvfs_t *zfsvfs = vfsp->vfs_data;
uint64_t refdbytes, availbytes, usedobjs, availobjs;
+ int error;
statp->f_version = STATFS_VERSION;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
dmu_objset_space(zfsvfs->z_os,
&refdbytes, &availbytes, &usedobjs, &availobjs);
@@ -1479,7 +1500,7 @@ zfs_statfs(vfs_t *vfsp, struct statfs *statp)
statp->f_namemax = MAXNAMELEN - 1;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1490,13 +1511,14 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp)
znode_t *rootzp;
int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
if (error == 0)
*vpp = ZTOV(rootzp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error == 0) {
error = vn_lock(*vpp, flags);
@@ -1535,12 +1557,11 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
* may add the parents of dir-based xattrs to the taskq
* so we want to wait for these.
*
- * We can safely read z_nr_znodes without locking because the
- * VFS has already blocked operations which add to the
- * z_all_znodes list and thus increment z_nr_znodes.
+ * We can safely check z_all_znodes for being empty because the
+ * VFS has already blocked operations which add to it.
*/
int round = 0;
- while (zfsvfs->z_nr_znodes > 0) {
+ while (!list_is_empty(&zfsvfs->z_all_znodes)) {
taskq_wait_outstanding(dsl_pool_zrele_taskq(
dmu_objset_pool(zfsvfs->z_os)), 0);
if (++round > 1 && !unmounting)
@@ -1733,7 +1754,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
(zfsvfs->z_shares_dir != 0 && ino == zfsvfs->z_shares_dir))
return (EOPNOTSUPP);
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
err = zfs_zget(zfsvfs, ino, &zp);
if (err == 0 && zp->z_unlinked) {
vrele(ZTOV(zp));
@@ -1741,7 +1763,7 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
}
if (err == 0)
*vpp = ZTOV(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (err == 0) {
err = vn_lock(*vpp, flags);
if (err != 0)
@@ -1795,7 +1817,8 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
*vpp = NULL;
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
/*
* On FreeBSD we can get snapshot's mount point or its parent file
@@ -1811,12 +1834,13 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs);
if (err)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
}
if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) {
@@ -1828,11 +1852,12 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
for (i = 0; i < sizeof (zfid->zf_gen); i++)
fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i);
} else {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
- if (fidp->fid_len == LONG_FID_LEN && (fid_gen > 1 || setgen != 0)) {
+ if (fidp->fid_len == LONG_FID_LEN && setgen != 0) {
+ zfs_exit(zfsvfs, FTAG);
dprintf("snapdir fid: fid_gen (%llu) and setgen (%llu)\n",
(u_longlong_t)fid_gen, (u_longlong_t)setgen);
return (SET_ERROR(EINVAL));
@@ -1846,7 +1871,7 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
if ((fid_gen == 0 &&
(object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) ||
(zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
VERIFY0(zfsctl_root(zfsvfs, LK_SHARED, &dvp));
if (object == ZFSCTL_INO_SNAPDIR) {
cn.cn_nameptr = "snapshot";
@@ -1881,7 +1906,7 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
(u_longlong_t)fid_gen,
(u_longlong_t)gen_mask);
if ((err = zfs_zget(zfsvfs, object, &zp))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen,
@@ -1893,12 +1918,12 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
dprintf("znode gen (%llu) != fid gen (%llu)\n",
(u_longlong_t)zp_gen, (u_longlong_t)fid_gen);
vrele(ZTOV(zp));
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
*vpp = ZTOV(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
err = vn_lock(*vpp, flags);
if (err == 0)
vnode_create_vobject(*vpp, zp->z_size, curthread);
@@ -1966,7 +1991,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
/*
* Attempt to re-establish all the active znodes with
* their dbufs. If a zfs_rezget() fails, then we'll let
- * any potential callers discover that via ZFS_ENTER_VERIFY_VP
+ * any potential callers discover that via zfs_enter_verify_zp
* when they try to use their znode.
*/
mutex_enter(&zfsvfs->z_znodes_lock);
@@ -2045,6 +2070,26 @@ zfs_vnodes_adjust_back(void)
#endif
}
+#if __FreeBSD_version >= 1300139
+static struct sx zfs_vnlru_lock;
+static struct vnode *zfs_vnlru_marker;
+#endif
+static arc_prune_t *zfs_prune;
+
+static void
+zfs_prune_task(uint64_t nr_to_scan, void *arg __unused)
+{
+ if (nr_to_scan > INT_MAX)
+ nr_to_scan = INT_MAX;
+#if __FreeBSD_version >= 1300139
+ sx_xlock(&zfs_vnlru_lock);
+ vnlru_free_vfsops(nr_to_scan, &zfs_vfsops, zfs_vnlru_marker);
+ sx_xunlock(&zfs_vnlru_lock);
+#else
+ vnlru_free(nr_to_scan, &zfs_vfsops);
+#endif
+}
+
void
zfs_init(void)
{
@@ -2071,11 +2116,23 @@ zfs_init(void)
dmu_objset_register_type(DMU_OST_ZFS, zpl_get_file_info);
zfsvfs_taskq = taskq_create("zfsvfs", 1, minclsyspri, 0, 0, 0);
+
+#if __FreeBSD_version >= 1300139
+ zfs_vnlru_marker = vnlru_alloc_marker();
+ sx_init(&zfs_vnlru_lock, "zfs vnlru lock");
+#endif
+ zfs_prune = arc_add_prune_callback(zfs_prune_task, NULL);
}
void
zfs_fini(void)
{
+ arc_remove_prune_callback(zfs_prune);
+#if __FreeBSD_version >= 1300139
+ vnlru_free_marker(zfs_vnlru_marker);
+ sx_destroy(&zfs_vnlru_lock);
+#endif
+
taskq_destroy(zfsvfs_taskq);
zfsctl_fini();
zfs_znode_fini();
@@ -2190,92 +2247,6 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
}
/*
- * Read a property stored within the master node.
- */
-int
-zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
-{
- uint64_t *cached_copy = NULL;
-
- /*
- * Figure out where in the objset_t the cached copy would live, if it
- * is available for the requested property.
- */
- if (os != NULL) {
- switch (prop) {
- case ZFS_PROP_VERSION:
- cached_copy = &os->os_version;
- break;
- case ZFS_PROP_NORMALIZE:
- cached_copy = &os->os_normalization;
- break;
- case ZFS_PROP_UTF8ONLY:
- cached_copy = &os->os_utf8only;
- break;
- case ZFS_PROP_CASE:
- cached_copy = &os->os_casesensitivity;
- break;
- default:
- break;
- }
- }
- if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
- *value = *cached_copy;
- return (0);
- }
-
- /*
- * If the property wasn't cached, look up the file system's value for
- * the property. For the version property, we look up a slightly
- * different string.
- */
- const char *pname;
- int error = ENOENT;
- if (prop == ZFS_PROP_VERSION) {
- pname = ZPL_VERSION_STR;
- } else {
- pname = zfs_prop_to_name(prop);
- }
-
- if (os != NULL) {
- ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
- error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
- }
-
- if (error == ENOENT) {
- /* No value set, use the default value */
- switch (prop) {
- case ZFS_PROP_VERSION:
- *value = ZPL_VERSION;
- break;
- case ZFS_PROP_NORMALIZE:
- case ZFS_PROP_UTF8ONLY:
- *value = 0;
- break;
- case ZFS_PROP_CASE:
- *value = ZFS_CASE_SENSITIVE;
- break;
- case ZFS_PROP_ACLTYPE:
- *value = ZFS_ACLTYPE_NFSV4;
- break;
- default:
- return (error);
- }
- error = 0;
- }
-
- /*
- * If one of the methods for getting the property value above worked,
- * copy it into the objset_t's cache.
- */
- if (error == 0 && cached_copy != NULL) {
- *cached_copy = *value;
- }
-
- return (error);
-}
-
-/*
* Return true if the corresponding vfs's unmounted flag is set.
* Otherwise return false.
* If this function returns true we know VFS unmount has been initiated.
@@ -2329,3 +2300,248 @@ zfsvfs_update_fromname(const char *oldname, const char *newname)
mtx_unlock(&mountlist_mtx);
}
#endif
+
+/*
+ * Find a prison with ZFS info.
+ * Return the ZFS info and the (locked) prison.
+ */
+static struct zfs_jailparam *
+zfs_jailparam_find(struct prison *spr, struct prison **prp)
+{
+ struct prison *pr;
+ struct zfs_jailparam *zjp;
+
+ for (pr = spr; ; pr = pr->pr_parent) {
+ mtx_lock(&pr->pr_mtx);
+ if (pr == &prison0) {
+ zjp = &zfs_jailparam0;
+ break;
+ }
+ zjp = osd_jail_get(pr, zfs_jailparam_slot);
+ if (zjp != NULL)
+ break;
+ mtx_unlock(&pr->pr_mtx);
+ }
+ *prp = pr;
+
+ return (zjp);
+}
+
+/*
+ * Ensure a prison has its own ZFS info. If zjpp is non-null, point it to the
+ * ZFS info and lock the prison.
+ */
+static void
+zfs_jailparam_alloc(struct prison *pr, struct zfs_jailparam **zjpp)
+{
+ struct prison *ppr;
+ struct zfs_jailparam *zjp, *nzjp;
+ void **rsv;
+
+ /* If this prison already has ZFS info, return that. */
+ zjp = zfs_jailparam_find(pr, &ppr);
+ if (ppr == pr)
+ goto done;
+
+ /*
+ * Allocate a new info record. Then check again, in case something
+ * changed during the allocation.
+ */
+ mtx_unlock(&ppr->pr_mtx);
+ nzjp = malloc(sizeof (struct zfs_jailparam), M_PRISON, M_WAITOK);
+ rsv = osd_reserve(zfs_jailparam_slot);
+ zjp = zfs_jailparam_find(pr, &ppr);
+ if (ppr == pr) {
+ free(nzjp, M_PRISON);
+ osd_free_reserved(rsv);
+ goto done;
+ }
+ /* Inherit the initial values from the ancestor. */
+ mtx_lock(&pr->pr_mtx);
+ (void) osd_jail_set_reserved(pr, zfs_jailparam_slot, rsv, nzjp);
+ (void) memcpy(nzjp, zjp, sizeof (*zjp));
+ zjp = nzjp;
+ mtx_unlock(&ppr->pr_mtx);
+done:
+ if (zjpp != NULL)
+ *zjpp = zjp;
+ else
+ mtx_unlock(&pr->pr_mtx);
+}
+
+/*
+ * Jail OSD methods for ZFS VFS info.
+ */
+static int
+zfs_jailparam_create(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ int jsys;
+
+ if (vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys)) == 0 &&
+ jsys == JAIL_SYS_INHERIT)
+ return (0);
+ /*
+ * Inherit a prison's initial values from its parent
+ * (different from JAIL_SYS_INHERIT which also inherits changes).
+ */
+ zfs_jailparam_alloc(pr, NULL);
+ return (0);
+}
+
+static int
+zfs_jailparam_get(void *obj, void *data)
+{
+ struct prison *ppr, *pr = obj;
+ struct vfsoptlist *opts = data;
+ struct zfs_jailparam *zjp;
+ int jsys, error;
+
+ zjp = zfs_jailparam_find(pr, &ppr);
+ jsys = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
+ error = vfs_setopt(opts, "zfs", &jsys, sizeof (jsys));
+ if (error != 0 && error != ENOENT)
+ goto done;
+ if (jsys == JAIL_SYS_NEW) {
+ error = vfs_setopt(opts, "zfs.mount_snapshot",
+ &zjp->mount_snapshot, sizeof (zjp->mount_snapshot));
+ if (error != 0 && error != ENOENT)
+ goto done;
+ } else {
+ /*
+ * If this prison is inheriting its ZFS info, report
+ * empty/zero parameters.
+ */
+ static int mount_snapshot = 0;
+
+ error = vfs_setopt(opts, "zfs.mount_snapshot",
+ &mount_snapshot, sizeof (mount_snapshot));
+ if (error != 0 && error != ENOENT)
+ goto done;
+ }
+ error = 0;
+done:
+ mtx_unlock(&ppr->pr_mtx);
+ return (error);
+}
+
+static int
+zfs_jailparam_set(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct prison *ppr;
+ struct vfsoptlist *opts = data;
+ int error, jsys, mount_snapshot;
+
+ /* Set the parameters, which should be correct. */
+ error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys));
+ if (error == ENOENT)
+ jsys = -1;
+ error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot,
+ sizeof (mount_snapshot));
+ if (error == ENOENT)
+ mount_snapshot = -1;
+ else
+ jsys = JAIL_SYS_NEW;
+ switch (jsys) {
+ case JAIL_SYS_NEW:
+ {
+ /* "zfs=new" or "zfs.*": the prison gets its own ZFS info. */
+ struct zfs_jailparam *zjp;
+
+ /*
+ * A child jail cannot have more permissions than its parent
+ */
+ if (pr->pr_parent != &prison0) {
+ zjp = zfs_jailparam_find(pr->pr_parent, &ppr);
+ mtx_unlock(&ppr->pr_mtx);
+ if (zjp->mount_snapshot < mount_snapshot) {
+ return (EPERM);
+ }
+ }
+ zfs_jailparam_alloc(pr, &zjp);
+ if (mount_snapshot != -1)
+ zjp->mount_snapshot = mount_snapshot;
+ mtx_unlock(&pr->pr_mtx);
+ break;
+ }
+ case JAIL_SYS_INHERIT:
+ /* "zfs=inherit": inherit the parent's ZFS info. */
+ mtx_lock(&pr->pr_mtx);
+ osd_jail_del(pr, zfs_jailparam_slot);
+ mtx_unlock(&pr->pr_mtx);
+ break;
+ case -1:
+ /*
+ * If the setting being changed is not ZFS related
+ * then do nothing.
+ */
+ break;
+ }
+
+ return (0);
+}
+
+static int
+zfs_jailparam_check(void *obj __unused, void *data)
+{
+ struct vfsoptlist *opts = data;
+ int error, jsys, mount_snapshot;
+
+ /* Check that the parameters are correct. */
+ error = vfs_copyopt(opts, "zfs", &jsys, sizeof (jsys));
+ if (error != ENOENT) {
+ if (error != 0)
+ return (error);
+ if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT)
+ return (EINVAL);
+ }
+ error = vfs_copyopt(opts, "zfs.mount_snapshot", &mount_snapshot,
+ sizeof (mount_snapshot));
+ if (error != ENOENT) {
+ if (error != 0)
+ return (error);
+ if (mount_snapshot != 0 && mount_snapshot != 1)
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static void
+zfs_jailparam_destroy(void *data)
+{
+
+ free(data, M_PRISON);
+}
+
+static void
+zfs_jailparam_sysinit(void *arg __unused)
+{
+ struct prison *pr;
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_CREATE] = zfs_jailparam_create,
+ [PR_METHOD_GET] = zfs_jailparam_get,
+ [PR_METHOD_SET] = zfs_jailparam_set,
+ [PR_METHOD_CHECK] = zfs_jailparam_check,
+ };
+
+ zfs_jailparam_slot = osd_jail_register(zfs_jailparam_destroy, methods);
+ /* Copy the defaults to any existing prisons. */
+ sx_slock(&allprison_lock);
+ TAILQ_FOREACH(pr, &allprison, pr_list)
+ zfs_jailparam_alloc(pr, NULL);
+ sx_sunlock(&allprison_lock);
+}
+
+static void
+zfs_jailparam_sysuninit(void *arg __unused)
+{
+
+ osd_jail_deregister(zfs_jailparam_slot);
+}
+
+SYSINIT(zfs_jailparam_sysinit, SI_SUB_DRIVERS, SI_ORDER_ANY,
+ zfs_jailparam_sysinit, NULL);
+SYSUNINIT(zfs_jailparam_sysuninit, SI_SUB_DRIVERS, SI_ORDER_ANY,
+ zfs_jailparam_sysuninit, NULL);
diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c
index e57855770293..d9a8c8a0d769 100644
--- a/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -29,13 +29,12 @@
/* Portions Copyright 2007 Jeremy Teo */
/* Portions Copyright 2010 Robert Milkowski */
-
-#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <sys/resource.h>
+#include <security/mac/mac_framework.h>
#include <sys/vfs.h>
#include <sys/endian.h>
#include <sys/vm.h>
@@ -76,7 +75,6 @@
#include <sys/zfs_quota.h>
#include <sys/zfs_sa.h>
#include <sys/zfs_rlock.h>
-#include <sys/extdirent.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/sched.h>
@@ -85,6 +83,11 @@
#include <vm/vm_param.h>
#include <sys/zil.h>
#include <sys/zfs_vnops.h>
+#include <sys/module.h>
+#include <sys/sysent.h>
+#include <sys/dmu_impl.h>
+#include <sys/brt.h>
+#include <sys/zfeature.h>
#include <vm/vm_object.h>
@@ -135,13 +138,13 @@ typedef ulong_t cookie_t;
* to freed memory. The example below illustrates the following Big Rules:
*
* (1) A check must be made in each zfs thread for a mounted file system.
- * This is done avoiding races using ZFS_ENTER(zfsvfs).
- * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes
- * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros
+ * This is done avoiding races using zfs_enter(zfsvfs).
+ * A zfs_exit(zfsvfs) is needed before all returns. Any znodes
+ * must be checked with zfs_verify_zp(zp). Both of these macros
* can return EIO from the calling function.
*
* (2) VN_RELE() should always be the last thing except for zil_commit()
- * (if necessary) and ZFS_EXIT(). This is for 3 reasons:
+ * (if necessary) and zfs_exit(). This is for 3 reasons:
* First, if it's the last reference, the vnode/znode
* can be freed, so the zp may point to freed memory. Second, the last
* reference will call zfs_zinactive(), which may induce a lot of work --
@@ -157,7 +160,7 @@ typedef ulong_t cookie_t;
* dmu_tx_assign(). This is critical because we don't want to block
* while holding locks.
*
- * If no ZPL locks are held (aside from ZFS_ENTER()), use TXG_WAIT. This
+ * If no ZPL locks are held (aside from zfs_enter()), use TXG_WAIT. This
* reduces lock contention and CPU usage when we must wait (note that if
* throughput is constrained by the storage, nearly every transaction
* must wait).
@@ -192,7 +195,7 @@ typedef ulong_t cookie_t;
*
* In general, this is how things should be ordered in each vnode op:
*
- * ZFS_ENTER(zfsvfs); // exit if unmounted
+ * zfs_enter(zfsvfs); // exit if unmounted
* top:
* zfs_dirent_lookup(&dl, ...) // lock directory entry (may VN_HOLD())
* rw_enter(...); // grab any other locks you need
@@ -210,7 +213,7 @@ typedef ulong_t cookie_t;
* goto top;
* }
* dmu_tx_abort(tx); // abort DMU tx
- * ZFS_EXIT(zfsvfs); // finished in zfs
+ * zfs_exit(zfsvfs); // finished in zfs
* return (error); // really out of space
* }
* error = do_real_work(); // do whatever this VOP does
@@ -221,7 +224,7 @@ typedef ulong_t cookie_t;
* zfs_dirent_unlock(dl); // unlock directory entry
* VN_RELE(...); // release held vnodes
* zil_commit(zilog, foid); // synchronous when necessary
- * ZFS_EXIT(zfsvfs); // finished in zfs
+ * zfs_exit(zfsvfs); // finished in zfs
* return (error); // done, report error
*/
static int
@@ -230,21 +233,28 @@ zfs_open(vnode_t **vpp, int flag, cred_t *cr)
(void) cr;
znode_t *zp = VTOZ(*vpp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if ((flag & FWRITE) && (zp->z_pflags & ZFS_APPENDONLY) &&
((flag & FAPPEND) == 0)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- /* Keep a count of the synchronous opens in the znode */
- if (flag & O_SYNC)
- atomic_inc_32(&zp->z_sync_cnt);
+ /*
+ * Keep a count of the synchronous opens in the znode. On first
+ * synchronous open we must convert all previous async transactions
+ * into sync to keep correct ordering.
+ */
+ if (flag & O_SYNC) {
+ if (atomic_inc_32_nv(&zp->z_sync_cnt) == 1)
+ zil_async_to_sync(zfsvfs->z_log, zp->z_id);
+ }
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -254,15 +264,16 @@ zfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
(void) offset, (void) cr;
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
/* Decrement the synchronous opens in the znode */
if ((flag & O_SYNC) && (count == 1))
atomic_dec_32(&zp->z_sync_cnt);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -800,8 +811,8 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
DTRACE_PROBE2(zfs__fastpath__lookup__miss, vnode_t *, dvp,
const char *, nm);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zdp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zdp, FTAG)) != 0)
+ return (error);
#if __FreeBSD_version > 1300124
dvp_seqc = vn_seqc_read_notmodify(dvp);
@@ -814,7 +825,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
* If the xattr property is off, refuse the lookup request.
*/
if (!(zfsvfs->z_flags & ZSB_XATTR)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EOPNOTSUPP));
}
@@ -823,12 +834,12 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
* Maybe someday we will.
*/
if (zdp->z_pflags & ZFS_XATTR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if ((error = zfs_get_xattrdir(VTOZ(dvp), &zp, cr, flags))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
*vpp = ZTOV(zp);
@@ -836,12 +847,12 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
/*
* Do we have permission to get into attribute directory?
*/
- error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr);
+ error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr, NULL);
if (error) {
vrele(ZTOV(zp));
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -855,15 +866,16 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
cnp->cn_flags &= ~NOEXECCHECK;
} else
#endif
- if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr,
+ NULL))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
@@ -881,7 +893,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
vnode_t *zfsctl_vp;
int ltype;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
ltype = VOP_ISLOCKED(dvp);
VOP_UNLOCK1(dvp);
error = zfsctl_root(zfsvfs->z_parent, LK_SHARED,
@@ -900,7 +912,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
}
}
if (zfs_has_ctldir(zdp) && strcmp(nm, ZFS_CTLDIR_NAME) == 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if ((cnp->cn_flags & ISLASTCN) != 0 && nameiop != LOOKUP)
return (SET_ERROR(ENOTSUP));
error = zfsctl_root(zfsvfs, cnp->cn_lkflags, vpp);
@@ -918,7 +930,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
if (error == 0)
*vpp = ZTOV(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error != 0)
break;
@@ -936,7 +948,11 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
if ((cnp->cn_flags & ISDOTDOT) == 0)
break;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0) {
+ vput(ZTOV(zp));
+ *vpp = NULL;
+ return (error);
+ }
if (zdp->z_sa_hdl == NULL) {
error = SET_ERROR(EIO);
} else {
@@ -944,12 +960,12 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
&parent, sizeof (parent));
}
if (error != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
vput(ZTOV(zp));
break;
}
if (zp->z_id == parent) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
break;
}
vput(ZTOV(zp));
@@ -965,13 +981,17 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
case RENAME:
if (error == ENOENT) {
error = EJUSTRETURN;
+#if __FreeBSD_version < 1400068
cnp->cn_flags |= SAVENAME;
+#endif
break;
}
zfs_fallthrough;
case DELETE:
+#if __FreeBSD_version < 1400068
if (error == 0)
cnp->cn_flags |= SAVENAME;
+#endif
break;
}
}
@@ -1027,6 +1047,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
* flag - large file flag [UNUSED].
* ct - caller context
* vsecp - ACL to be set
+ * mnt_ns - Unused on FreeBSD
*
* OUT: vpp - vnode of created or trunc'd entry.
*
@@ -1038,7 +1059,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
*/
int
zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
- znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp)
+ znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, zidmap_t *mnt_ns)
{
(void) excl, (void) mode, (void) flag;
znode_t *zp;
@@ -1066,21 +1087,21 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (vap->va_mask & AT_XVATTR) {
if ((error = secpolicy_xvattr(ZTOV(dzp), (xvattr_t *)vap,
crgetuid(cr), cr, vap->va_type)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
@@ -1092,7 +1113,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
error = zfs_dirent_lookup(dzp, name, &zp, ZNEW);
if (error) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
ASSERT3P(zp, ==, NULL);
@@ -1101,7 +1122,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
* Create a new file object and update the directory
* to reference it.
*/
- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) {
goto out;
}
@@ -1117,7 +1138,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
}
if ((error = zfs_acl_ids_create(dzp, 0, vap,
- cr, vsecp, &acl_ids)) != 0)
+ cr, vsecp, &acl_ids, NULL)) != 0)
goto out;
if (S_ISREG(vap->va_mode) || S_ISDIR(vap->va_mode))
@@ -1150,7 +1171,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
getnewvnode_drop_reserve();
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
@@ -1175,7 +1196,7 @@ out:
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1210,16 +1231,19 @@ zfs_remove_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr)
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zp = VTOZ(vp);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_verify_zp(zp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
zilog = zfsvfs->z_log;
xattr_obj = 0;
xzp = NULL;
- if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) {
goto out;
}
@@ -1271,7 +1295,7 @@ zfs_remove_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr)
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1303,7 +1327,7 @@ out:
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1318,7 +1342,10 @@ zfs_lookup_internal(znode_t *dzp, const char *name, vnode_t **vpp,
cnp->cn_nameptr = __DECONST(char *, name);
cnp->cn_namelen = strlen(name);
cnp->cn_nameiop = nameiop;
- cnp->cn_flags = ISLASTCN | SAVENAME;
+ cnp->cn_flags = ISLASTCN;
+#if __FreeBSD_version < 1400068
+ cnp->cn_flags |= SAVENAME;
+#endif
cnp->cn_lkflags = LK_EXCLUSIVE | LK_RETRY;
cnp->cn_cred = kcred;
#if __FreeBSD_version < 1400037
@@ -1372,6 +1399,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags)
* ct - caller context
* flags - case flags
* vsecp - ACL to be set
+ * mnt_ns - Unused on FreeBSD
*
* OUT: vpp - vnode of created directory.
*
@@ -1383,7 +1411,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags)
*/
int
zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
- cred_t *cr, int flags, vsecattr_t *vsecp)
+ cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns)
{
(void) flags, (void) vsecp;
znode_t *zp;
@@ -1408,32 +1436,32 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (dzp->z_pflags & ZFS_XATTR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if (zfsvfs->z_utf8 && u8_validate(dirname,
strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (vap->va_mask & AT_XVATTR) {
if ((error = secpolicy_xvattr(ZTOV(dzp), (xvattr_t *)vap,
crgetuid(cr), cr, vap->va_type)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
if ((error = zfs_acl_ids_create(dzp, 0, vap, cr,
- NULL, &acl_ids)) != 0) {
- ZFS_EXIT(zfsvfs);
+ NULL, &acl_ids, NULL)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1448,20 +1476,21 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
if ((error = zfs_dirent_lookup(dzp, dirname, &zp, ZNEW))) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
ASSERT3P(zp, ==, NULL);
- if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr,
+ mnt_ns))) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zfs_inherit_projid(dzp))) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EDQUOT));
}
@@ -1488,7 +1517,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
getnewvnode_drop_reserve();
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1520,7 +1549,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1561,13 +1590,16 @@ zfs_rmdir_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr)
dmu_tx_t *tx;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
+ if ((error = zfs_verify_zp(zp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
zilog = zfsvfs->z_log;
- if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
+ if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) {
goto out;
}
@@ -1588,7 +1620,7 @@ zfs_rmdir_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr)
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1602,12 +1634,13 @@ zfs_rmdir_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr)
dmu_tx_commit(tx);
- cache_vop_rmdir(dvp, vp);
+ if (zfsvfs->z_use_namecache)
+ cache_vop_rmdir(dvp, vp);
out:
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1636,10 +1669,11 @@ zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd, cred_t *cr, int flags)
* and return buffer.
* cr - credentials of caller.
* ct - caller context
- * flags - case flags
*
* OUT: uio - updated offset and range, buffer filled.
* eofp - set to true if end-of-file detected.
+ * ncookies- number of entries in cookies
+ * cookies - offsets to directory entries
*
* RETURN: 0 on success, error code on failure.
*
@@ -1657,7 +1691,6 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
{
znode_t *zp = VTOZ(vp);
iovec_t *iovp;
- edirent_t *eodp;
dirent64_t *odp;
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os;
@@ -1672,18 +1705,16 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
int outcount;
int error;
uint8_t prefetch;
- boolean_t check_sysattrs;
uint8_t type;
int ncooks;
cookie_t *cooks = NULL;
- int flags = 0;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
&parent, sizeof (parent))) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1698,7 +1729,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
* Check for valid iov_len.
*/
if (GET_UIO_STRUCT(uio)->uio_iov->iov_len <= 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -1706,7 +1737,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
* Quit if directory has been removed (posix)
*/
if ((*eofp = zp->z_unlinked) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1744,7 +1775,6 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
outbuf = NULL;
odp = (struct dirent64 *)iovp->iov_base;
}
- eodp = (struct edirent *)odp;
if (ncookies != NULL) {
/*
@@ -1756,19 +1786,6 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
*cookies = cooks;
*ncookies = ncooks;
}
- /*
- * If this VFS supports the system attribute view interface; and
- * we're looking at an extended attribute directory; and we care
- * about normalization conflicts on this vfs; then we must check
- * for normalization conflicts with the sysattr name space.
- */
-#ifdef TODO
- check_sysattrs = vfs_has_feature(vp->v_vfsp, VFSFT_SYSATTR_VIEWS) &&
- (vp->v_flag & V_XATTRDIR) && zfsvfs->z_norm &&
- (flags & V_RDDIR_ENTFLAGS);
-#else
- check_sysattrs = 0;
-#endif
/*
* Transform to file-system independent format
@@ -1824,36 +1841,9 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
* uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer);
*/
type = ZFS_DIRENT_TYPE(zap.za_first_integer);
-
- if (check_sysattrs && !zap.za_normalization_conflict) {
-#ifdef TODO
- zap.za_normalization_conflict =
- xattr_sysattr_casechk(zap.za_name);
-#else
- panic("%s:%u: TODO", __func__, __LINE__);
-#endif
- }
}
- if (flags & V_RDDIR_ACCFILTER) {
- /*
- * If we have no access at all, don't include
- * this entry in the returned information
- */
- znode_t *ezp;
- if (zfs_zget(zp->z_zfsvfs, objnum, &ezp) != 0)
- goto skip_entry;
- if (!zfs_has_access(ezp, cr)) {
- vrele(ZTOV(ezp));
- goto skip_entry;
- }
- vrele(ZTOV(ezp));
- }
-
- if (flags & V_RDDIR_ENTFLAGS)
- reclen = EDIRENT_RECLEN(strlen(zap.za_name));
- else
- reclen = DIRENT64_RECLEN(strlen(zap.za_name));
+ reclen = DIRENT64_RECLEN(strlen(zap.za_name));
/*
* Will this entry fit in the buffer?
@@ -1868,43 +1858,26 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
}
break;
}
- if (flags & V_RDDIR_ENTFLAGS) {
- /*
- * Add extended flag entry:
- */
- eodp->ed_ino = objnum;
- eodp->ed_reclen = reclen;
- /* NOTE: ed_off is the offset for the *next* entry */
- next = &(eodp->ed_off);
- eodp->ed_eflags = zap.za_normalization_conflict ?
- ED_CASE_CONFLICT : 0;
- (void) strncpy(eodp->ed_name, zap.za_name,
- EDIRENT_NAMELEN(reclen));
- eodp = (edirent_t *)((intptr_t)eodp + reclen);
- } else {
- /*
- * Add normal entry:
- */
- odp->d_ino = objnum;
- odp->d_reclen = reclen;
- odp->d_namlen = strlen(zap.za_name);
- /* NOTE: d_off is the offset for the *next* entry. */
- next = &odp->d_off;
- strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
- odp->d_type = type;
- dirent_terminate(odp);
- odp = (dirent64_t *)((intptr_t)odp + reclen);
- }
+ /*
+ * Add normal entry:
+ */
+ odp->d_ino = objnum;
+ odp->d_reclen = reclen;
+ odp->d_namlen = strlen(zap.za_name);
+ /* NOTE: d_off is the offset for the *next* entry. */
+ next = &odp->d_off;
+ strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
+ odp->d_type = type;
+ dirent_terminate(odp);
+ odp = (dirent64_t *)((intptr_t)odp + reclen);
+
outcount += reclen;
ASSERT3S(outcount, <=, bufsize);
- /* Prefetch znode */
if (prefetch)
- dmu_prefetch(os, objnum, 0, 0, 0,
- ZIO_PRIORITY_SYNC_READ);
+ dmu_prefetch_dnode(os, objnum, ZIO_PRIORITY_SYNC_READ);
- skip_entry:
/*
* Move to the next entry, fill in the previous offset.
*/
@@ -1953,7 +1926,7 @@ update:
ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
zfs_uio_setoffset(uio, offset);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error != 0 && cookies != NULL) {
free(*cookies, M_TEMP);
*cookies = NULL;
@@ -1991,8 +1964,8 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
sa_bulk_attr_t bulk[4];
int count = 0;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
zfs_fuid_map_ids(zp, cr, &vap->va_uid, &vap->va_gid);
@@ -2004,7 +1977,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
&rdev, 8);
if ((error = sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -2016,8 +1989,8 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) &&
(vap->va_uid != crgetuid(cr))) {
if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0,
- skipaclchk, cr))) {
- ZFS_EXIT(zfsvfs);
+ skipaclchk, cr, NULL))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
@@ -2038,6 +2011,8 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
vap->va_size = zp->z_size;
if (vp->v_type == VBLK || vp->v_type == VCHR)
vap->va_rdev = zfs_cmpldev(rdev);
+ else
+ vap->va_rdev = 0;
vap->va_gen = zp->z_gen;
vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */
vap->va_filerev = zp->z_seq;
@@ -2168,7 +2143,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
vap->va_blksize = zfsvfs->z_max_blksz;
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -2182,7 +2157,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
* flags - ATTR_UTIME set if non-default time values provided.
* - ATTR_NOACLCHECK (CIFS context only).
* cr - credentials of caller.
- * ct - caller context
+ * mnt_ns - Unused on FreeBSD
*
* RETURN: 0 on success, error code on failure.
*
@@ -2190,7 +2165,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
* vp - ctime updated, mtime updated if size changed.
*/
int
-zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
{
vnode_t *vp = ZTOV(zp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
@@ -2226,8 +2201,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
if (mask & AT_NOSET)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((err = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (err);
os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
@@ -2241,17 +2216,17 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
(((mask & AT_UID) && IS_EPHEMERAL(vap->va_uid)) ||
((mask & AT_GID) && IS_EPHEMERAL(vap->va_gid)) ||
(mask & AT_XVATTR))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if (mask & AT_SIZE && vp->v_type == VDIR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EISDIR));
}
if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -2269,7 +2244,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
if ((zp->z_pflags & ZFS_IMMUTABLE) &&
((mask & (AT_SIZE|AT_UID|AT_GID|AT_MTIME|AT_MODE)) ||
((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
@@ -2286,27 +2261,27 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
if (mask & (AT_ATIME | AT_MTIME)) {
if (((mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) ||
((mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EOVERFLOW));
}
}
if (xoap != NULL && (mask & AT_XVATTR)) {
if (XVA_ISSET_REQ(xvap, XAT_CREATETIME) &&
TIMESPEC_OVERFLOW(&vap->va_birthtime)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EOVERFLOW));
}
if (XVA_ISSET_REQ(xvap, XAT_PROJID)) {
if (!dmu_objset_projectquota_enabled(os) ||
(!S_ISREG(zp->z_mode) && !S_ISDIR(zp->z_mode))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EOPNOTSUPP));
}
projid = xoap->xoa_projid;
if (unlikely(projid == ZFS_INVALID_PROJID)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -2321,7 +2296,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
((zp->z_pflags & ZFS_PROJINHERIT) != 0)) &&
(!dmu_objset_projectquota_enabled(os) ||
(!S_ISREG(zp->z_mode) && !S_ISDIR(zp->z_mode)))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EOPNOTSUPP));
}
}
@@ -2330,7 +2305,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
aclp = NULL;
if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EROFS));
}
@@ -2348,7 +2323,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
/* XXX - would it be OK to generate a log record here? */
err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE);
if (err) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
}
@@ -2362,7 +2337,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
XVA_ISSET_REQ(xvap, XAT_CREATETIME) ||
XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) {
need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0,
- skipaclchk, cr);
+ skipaclchk, cr, mnt_ns);
}
if (mask & (AT_UID|AT_GID)) {
@@ -2399,7 +2374,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
((idmask == AT_UID) && take_owner) ||
((idmask == AT_GID) && take_group)) {
if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0,
- skipaclchk, cr) == 0) {
+ skipaclchk, cr, mnt_ns) == 0) {
/*
* Remove setuid/setgid for non-privileged users
*/
@@ -2496,7 +2471,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
}
if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
@@ -2508,11 +2483,12 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
}
if (mask & AT_MODE) {
- if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) {
+ if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr,
+ mnt_ns) == 0) {
err = secpolicy_setid_setsticky_clear(vp, vap,
&oldva, cr);
if (err) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
trim_mask |= AT_MODE;
@@ -2544,7 +2520,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
(int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp);
if (err) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -2902,7 +2878,7 @@ out2:
if (os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -2927,14 +2903,17 @@ zfs_rename_relock_lookup(znode_t *sdzp, const struct componentname *scnp,
* The current code can invalidate the znode without acquiring the
* corresponding vnode lock if the object represented by the znode
* and vnode is no longer valid after a rollback or receive operation.
- * z_teardown_lock hidden behind ZFS_ENTER and ZFS_EXIT is the lock
+ * z_teardown_lock hidden behind zfs_enter and zfs_exit is the lock
* that protects the znodes from the invalidation.
*/
zfsvfs = sdzp->z_zfsvfs;
ASSERT3P(zfsvfs, ==, tdzp->z_zfsvfs);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(sdzp);
- ZFS_VERIFY_ZP(tdzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, sdzp, FTAG)) != 0)
+ return (error);
+ if ((error = zfs_verify_zp(tdzp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
/*
* Re-resolve svp to be certain it still exists and fetch the
@@ -2962,7 +2941,7 @@ zfs_rename_relock_lookup(znode_t *sdzp, const struct componentname *scnp,
}
*tzpp = tzp;
out:
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3232,9 +3211,12 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
sdzp = VTOZ(sdvp);
zfsvfs = tdzp->z_zfsvfs;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(tdzp);
- ZFS_VERIFY_ZP(sdzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, tdzp, FTAG)) != 0)
+ return (error);
+ if ((error = zfs_verify_zp(sdzp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(tnm,
@@ -3257,10 +3239,17 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
}
szp = VTOZ(*svpp);
- ZFS_VERIFY_ZP(szp);
+ if ((error = zfs_verify_zp(szp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
tzp = *tvpp == NULL ? NULL : VTOZ(*tvpp);
- if (tzp != NULL)
- ZFS_VERIFY_ZP(tzp);
+ if (tzp != NULL) {
+ if ((error = zfs_verify_zp(tzp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
+ }
/*
* This is to prevent the creation of links into attribute space
@@ -3291,7 +3280,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
* Note that if target and source are the same, this can be
* done in a single check.
*/
- if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)))
+ if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, NULL)))
goto out;
if ((*svpp)->v_type == VDIR) {
@@ -3395,11 +3384,6 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
if (error == 0) {
zfs_log_rename(zilog, tx, TX_RENAME, sdzp,
snm, tdzp, tnm, szp);
-
- /*
- * Update path information for the target vnode
- */
- vn_renamepath(tdvp, *svpp, tnm, strlen(tnm));
} else {
/*
* At this point, we have successfully created
@@ -3435,14 +3419,14 @@ out_seq:
out:
if (error == 0 && zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
int
zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
- cred_t *cr, int flags)
+ cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap, zidmap_t *mnt_ns)
{
struct componentname scn, tcn;
vnode_t *sdvp, *tdvp;
@@ -3450,6 +3434,9 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
int error;
svp = tvp = NULL;
+ if (rflags != 0 || wo_vap != NULL)
+ return (SET_ERROR(EINVAL));
+
sdvp = ZTOV(sdzp);
tdvp = ZTOV(tdzp);
error = zfs_lookup_internal(sdzp, sname, &svp, &scn, DELETE);
@@ -3487,6 +3474,7 @@ fail:
* cr - credentials of caller.
* ct - caller context
* flags - case flags
+ * mnt_ns - Unused on FreeBSD
*
* RETURN: 0 on success, error code on failure.
*
@@ -3495,7 +3483,7 @@ fail:
*/
int
zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
- const char *link, znode_t **zpp, cred_t *cr, int flags)
+ const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns)
{
(void) flags;
znode_t *zp;
@@ -3510,24 +3498,24 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
ASSERT3S(vap->va_type, ==, VLNK);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (len > MAXPATHLEN) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENAMETOOLONG));
}
if ((error = zfs_acl_ids_create(dzp, 0,
- vap, cr, NULL, &acl_ids)) != 0) {
- ZFS_EXIT(zfsvfs);
+ vap, cr, NULL, &acl_ids, NULL)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3537,20 +3525,20 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
error = zfs_dirent_lookup(dzp, name, &zp, ZNEW);
if (error) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids,
0 /* projid */)) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EDQUOT));
}
@@ -3573,7 +3561,7 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
getnewvnode_drop_reserve();
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3612,7 +3600,7 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3640,8 +3628,8 @@ zfs_readlink(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, caller_context_t *ct)
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if (zp->z_is_sa)
error = sa_lookup_uio(zp->z_sa_hdl,
@@ -3651,7 +3639,7 @@ zfs_readlink(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, caller_context_t *ct)
ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3684,8 +3672,8 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
ASSERT3S(ZTOV(tdzp)->v_type, ==, VDIR);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(tdzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, tdzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
/*
@@ -3693,11 +3681,14 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
* Better choices include ENOTSUP or EISDIR.
*/
if (ZTOV(szp)->v_type == VDIR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- ZFS_VERIFY_ZP(szp);
+ if ((error = zfs_verify_zp(szp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
/*
* If we are using project inheritance, means if the directory has
@@ -3708,13 +3699,13 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
*/
if (tdzp->z_pflags & ZFS_PROJINHERIT &&
tdzp->z_projid != szp->z_projid) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EXDEV));
}
if (szp->z_pflags & (ZFS_APPENDONLY |
ZFS_IMMUTABLE | ZFS_READONLY)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
@@ -3722,17 +3713,17 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
if ((error = sa_lookup(szp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
&parent, sizeof (uint64_t))) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (parent == zfsvfs->z_shares_dir) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
if (zfsvfs->z_utf8 && u8_validate(name,
strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
@@ -3743,19 +3734,19 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
* imposed in attribute space.
*/
if ((szp->z_pflags & ZFS_XATTR) != (tdzp->z_pflags & ZFS_XATTR)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
owner = zfs_fuid_map_id(zfsvfs, szp->z_uid, cr, ZFS_OWNER);
if (owner != crgetuid(cr) && secpolicy_basic_link(ZTOV(szp), cr) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3764,7 +3755,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
*/
error = zfs_dirent_lookup(tdzp, name, &tzp, ZNEW);
if (error) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3776,7 +3767,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3796,7 +3787,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr,
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3827,11 +3818,11 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
uint64_t off, len;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if (cmd != F_FREESP) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -3840,12 +3831,12 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
* so check it explicitly here.
*/
if (zfs_is_readonly(zfsvfs)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EROFS));
}
if (bfp->l_len < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -3855,8 +3846,8 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
* On Linux we can get here through truncate_range() which
* operates directly on inodes, so we need to check access rights.
*/
- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3865,7 +3856,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
error = zfs_freesp(zp, off, len, flag, TRUE);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3933,12 +3924,12 @@ zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
zfid_short_t *zfid;
int size, i, error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
&gen64, sizeof (uint64_t))) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3974,7 +3965,7 @@ zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
zlfid->zf_setgen[i] = 0;
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3984,6 +3975,7 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
{
znode_t *zp;
zfsvfs_t *zfsvfs;
+ int error;
switch (cmd) {
case _PC_LINK_MAX:
@@ -4000,10 +3992,10 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
#if 0 /* POSIX ACLs are not implemented for ZFS on FreeBSD yet. */
zp = VTOZ(vp);
zfsvfs = zp->z_zfsvfs;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
*valp = zfsvfs->z_acl_type == ZFSACLTYPE_POSIX ? 1 : 0;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
#else
*valp = 0;
#endif
@@ -4012,10 +4004,10 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
case _PC_ACL_NFS4:
zp = VTOZ(vp);
zfsvfs = zp->z_zfsvfs;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
*valp = zfsvfs->z_acl_type == ZFS_ACLTYPE_NFSV4 ? 1 : 0;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
case _PC_ACL_PATH_MAX:
@@ -4040,8 +4032,8 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
int pgsin_b, pgsin_a;
int error;
- ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
- ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
+ if (zfs_enter_verify_zp(zfsvfs, zp, FTAG) != 0)
+ return (zfs_vm_pagerret_error);
start = IDX_TO_OFF(ma[0]->pindex);
end = IDX_TO_OFF(ma[count - 1]->pindex + 1);
@@ -4078,7 +4070,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
if (IDX_TO_OFF(ma[count - 1]->pindex) >= obj_size) {
if (lr != NULL)
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (zfs_vm_pagerret_bad);
}
@@ -4111,7 +4103,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, count*PAGE_SIZE);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error != 0)
return (zfs_vm_pagerret_error);
@@ -4174,8 +4166,8 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
for (i = 0; i < pcount; i++)
rtvals[i] = zfs_vm_pagerret_error;
- ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
- ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
+ if (zfs_enter_verify_zp(zfsvfs, zp, FTAG) != 0)
+ return (zfs_vm_pagerret_error);
off = IDX_TO_OFF(ma[0]->pindex);
blksz = zp->z_blksz;
@@ -4217,6 +4209,10 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
}
zfs_vmobject_wunlock(object);
+ boolean_t commit = (flags & (zfs_vm_pagerput_sync |
+ zfs_vm_pagerput_inval)) != 0 ||
+ zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS;
+
if (ncount == 0)
goto out;
@@ -4269,7 +4265,7 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
* but that would make the locking messier
*/
zfs_log_write(zfsvfs->z_log, tx, TX_WRITE, zp, off,
- len, 0, NULL, NULL);
+ len, commit, NULL, NULL);
zfs_vmobject_wlock(object);
for (i = 0; i < ncount; i++) {
@@ -4284,13 +4280,12 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
out:
zfs_rangelock_exit(lr);
- if ((flags & (zfs_vm_pagerput_sync | zfs_vm_pagerput_inval)) != 0 ||
- zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+ if (commit)
zil_commit(zfsvfs->z_log, zp->z_id);
dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, len);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (rtvals[0]);
}
@@ -4620,7 +4615,9 @@ zfs_freebsd_create(struct vop_create_args *ap)
znode_t *zp = NULL;
int rc, mode;
+#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
+#endif
vattr_init_mask(vap);
mode = vap->va_mode & ALLPERMS;
@@ -4628,7 +4625,7 @@ zfs_freebsd_create(struct vop_create_args *ap)
*ap->a_vpp = NULL;
rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode,
- &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */);
+ &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL);
if (rc == 0)
*ap->a_vpp = ZTOV(zp);
if (zfsvfs->z_use_namecache &&
@@ -4650,7 +4647,9 @@ static int
zfs_freebsd_remove(struct vop_remove_args *ap)
{
+#if __FreeBSD_version < 1400068
ASSERT(ap->a_cnp->cn_flags & SAVENAME);
+#endif
return (zfs_remove_(ap->a_dvp, ap->a_vp, ap->a_cnp->cn_nameptr,
ap->a_cnp->cn_cred));
@@ -4672,13 +4671,15 @@ zfs_freebsd_mkdir(struct vop_mkdir_args *ap)
znode_t *zp = NULL;
int rc;
+#if __FreeBSD_version < 1400068
ASSERT(ap->a_cnp->cn_flags & SAVENAME);
+#endif
vattr_init_mask(vap);
*ap->a_vpp = NULL;
rc = zfs_mkdir(VTOZ(ap->a_dvp), ap->a_cnp->cn_nameptr, vap, &zp,
- ap->a_cnp->cn_cred, 0, NULL);
+ ap->a_cnp->cn_cred, 0, NULL, NULL);
if (rc == 0)
*ap->a_vpp = ZTOV(zp);
@@ -4698,7 +4699,9 @@ zfs_freebsd_rmdir(struct vop_rmdir_args *ap)
{
struct componentname *cnp = ap->a_cnp;
+#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
+#endif
return (zfs_rmdir_(ap->a_dvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred));
}
@@ -4735,7 +4738,6 @@ static int
zfs_freebsd_fsync(struct vop_fsync_args *ap)
{
- vop_stdfsync(ap);
return (zfs_fsync(VTOZ(ap->a_vp), 0, ap->a_td->td_ucred));
}
@@ -4929,7 +4931,7 @@ zfs_freebsd_setattr(struct vop_setattr_args *ap)
xvap.xva_vattr.va_mask |= AT_XVATTR;
XVA_SET_REQ(&xvap, XAT_CREATETIME);
}
- return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred));
+ return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred, NULL));
}
#ifndef _SYS_SYSPROTO_H_
@@ -4952,8 +4954,10 @@ zfs_freebsd_rename(struct vop_rename_args *ap)
vnode_t *tvp = ap->a_tvp;
int error;
+#if __FreeBSD_version < 1400068
ASSERT(ap->a_fcnp->cn_flags & (SAVENAME|SAVESTART));
ASSERT(ap->a_tcnp->cn_flags & (SAVENAME|SAVESTART));
+#endif
error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
ap->a_tcnp, ap->a_fcnp->cn_cred);
@@ -4989,14 +4993,16 @@ zfs_freebsd_symlink(struct vop_symlink_args *ap)
#endif
int rc;
+#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
+#endif
vap->va_type = VLNK; /* FreeBSD: Syscall only sets va_mode. */
vattr_init_mask(vap);
*ap->a_vpp = NULL;
rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap,
- ap->a_target, &zp, cnp->cn_cred, 0 /* flags */);
+ ap->a_target, &zp, cnp->cn_cred, 0 /* flags */, NULL);
if (rc == 0) {
*ap->a_vpp = ZTOV(zp);
ASSERT_VOP_ELOCKED(ZTOV(zp), __func__);
@@ -5083,7 +5089,9 @@ zfs_freebsd_link(struct vop_link_args *ap)
if (tdvp->v_mount != vp->v_mount)
return (EXDEV);
+#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
+#endif
return (zfs_link(VTOZ(tdvp), VTOZ(vp),
cnp->cn_nameptr, cnp->cn_cred, 0));
@@ -5355,10 +5363,10 @@ zfs_getextattr_dir(struct vop_getextattr_args *ap, const char *attrname)
NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, attrname, xvp);
#endif
error = vn_open_cred(&nd, &flags, 0, VN_OPEN_INVFS, ap->a_cred, NULL);
- vp = nd.ni_vp;
- NDFREE_PNBUF(&nd);
if (error != 0)
return (SET_ERROR(error));
+ vp = nd.ni_vp;
+ NDFREE_PNBUF(&nd);
if (ap->a_size != NULL) {
error = VOP_GETATTR(vp, &va, ap->a_cred);
@@ -5448,9 +5456,9 @@ zfs_getextattr(struct vop_getextattr_args *ap)
if (error != 0)
return (error);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
error = ENOENT;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
rw_enter(&zp->z_xattr_lock, RW_READER);
error = zfs_getextattr_impl(ap, zfs_xattr_compat);
@@ -5464,7 +5472,7 @@ zfs_getextattr(struct vop_getextattr_args *ap)
}
rw_exit(&zp->z_xattr_lock);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error == ENOENT)
error = SET_ERROR(ENOATTR);
return (error);
@@ -5500,12 +5508,10 @@ zfs_deleteextattr_dir(struct vop_deleteextattr_args *ap, const char *attrname)
UIO_SYSSPACE, attrname, xvp);
#endif
error = namei(&nd);
- vp = nd.ni_vp;
- if (error != 0) {
- NDFREE_PNBUF(&nd);
+ if (error != 0)
return (SET_ERROR(error));
- }
+ vp = nd.ni_vp;
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
NDFREE_PNBUF(&nd);
@@ -5591,8 +5597,8 @@ zfs_deleteextattr(struct vop_deleteextattr_args *ap)
if (error != 0)
return (error);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
rw_enter(&zp->z_xattr_lock, RW_WRITER);
error = zfs_deleteextattr_impl(ap, zfs_xattr_compat);
@@ -5606,7 +5612,7 @@ zfs_deleteextattr(struct vop_deleteextattr_args *ap)
}
rw_exit(&zp->z_xattr_lock);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
if (error == ENOENT)
error = SET_ERROR(ENOATTR);
return (error);
@@ -5645,10 +5651,10 @@ zfs_setextattr_dir(struct vop_setextattr_args *ap, const char *attrname)
#endif
error = vn_open_cred(&nd, &flags, 0600, VN_OPEN_INVFS, ap->a_cred,
NULL);
- vp = nd.ni_vp;
- NDFREE_PNBUF(&nd);
if (error != 0)
return (SET_ERROR(error));
+ vp = nd.ni_vp;
+ NDFREE_PNBUF(&nd);
VATTR_NULL(&va);
va.va_size = 0;
@@ -5779,14 +5785,14 @@ zfs_setextattr(struct vop_setextattr_args *ap)
if (error != 0)
return (error);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
rw_enter(&zp->z_xattr_lock, RW_WRITER);
error = zfs_setextattr_impl(ap, zfs_xattr_compat);
rw_exit(&zp->z_xattr_lock);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -5832,10 +5838,10 @@ zfs_listextattr_dir(struct vop_listextattr_args *ap, const char *attrprefix)
UIO_SYSSPACE, ".", xvp);
#endif
error = namei(&nd);
- vp = nd.ni_vp;
- NDFREE_PNBUF(&nd);
if (error != 0)
return (SET_ERROR(error));
+ vp = nd.ni_vp;
+ NDFREE_PNBUF(&nd);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
@@ -5983,8 +5989,8 @@ zfs_listextattr(struct vop_listextattr_args *ap)
if (error != 0)
return (SET_ERROR(error));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
rw_enter(&zp->z_xattr_lock, RW_READER);
error = zfs_listextattr_impl(ap, zfs_xattr_compat);
@@ -5994,7 +6000,7 @@ zfs_listextattr(struct vop_listextattr_args *ap)
}
rw_exit(&zp->z_xattr_lock);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -6110,8 +6116,8 @@ zfs_vptocnp(struct vop_vptocnp_args *ap)
int ltype;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
/*
* If we are a snapshot mounted under .zfs, run the operation
@@ -6133,10 +6139,10 @@ zfs_vptocnp(struct vop_vptocnp_args *ap)
memcpy(ap->a_buf + *ap->a_buflen, name, len);
*ap->a_vpp = ZTOV(dzp);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
covered_vp = vp->v_mount->mnt_vnodecovered;
#if __FreeBSD_version >= 1300045
@@ -6177,15 +6183,15 @@ zfs_deallocate(struct vop_deallocate_args *ap)
off_t off, len, file_sz;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
/*
* Callers might not be able to detect properly that we are read-only,
* so check it explicitly here.
*/
if (zfs_is_readonly(zfsvfs)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EROFS));
}
@@ -6198,7 +6204,7 @@ zfs_deallocate(struct vop_deallocate_args *ap)
/* Fast path for out-of-range request. */
if (len <= 0) {
*ap->a_len = 0;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -6211,7 +6217,116 @@ zfs_deallocate(struct vop_deallocate_args *ap)
*ap->a_len = 0;
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+}
+#endif
+
+#if __FreeBSD_version >= 1300039
+#ifndef _SYS_SYSPROTO_H_
+struct vop_copy_file_range_args {
+ struct vnode *a_invp;
+ off_t *a_inoffp;
+ struct vnode *a_outvp;
+ off_t *a_outoffp;
+ size_t *a_lenp;
+ unsigned int a_flags;
+ struct ucred *a_incred;
+ struct ucred *a_outcred;
+ struct thread *a_fsizetd;
+}
+#endif
+/*
+ * TODO: FreeBSD will only call file system-specific copy_file_range() if both
+ * files resides under the same mountpoint. In case of ZFS we want to be called
+ * even is files are in different datasets (but on the same pools, but we need
+ * to check that ourselves).
+ */
+static int
+zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap)
+{
+ zfsvfs_t *outzfsvfs;
+ struct vnode *invp = ap->a_invp;
+ struct vnode *outvp = ap->a_outvp;
+ struct mount *mp;
+ struct uio io;
+ int error;
+ uint64_t len = *ap->a_lenp;
+
+ if (!zfs_bclone_enabled) {
+ mp = NULL;
+ goto bad_write_fallback;
+ }
+
+ /*
+ * TODO: If offset/length is not aligned to recordsize, use
+ * vn_generic_copy_file_range() on this fragment.
+ * It would be better to do this after we lock the vnodes, but then we
+ * need something else than vn_generic_copy_file_range().
+ */
+
+ vn_start_write(outvp, &mp, V_WAIT);
+ if (__predict_true(mp == outvp->v_mount)) {
+ outzfsvfs = (zfsvfs_t *)mp->mnt_data;
+ if (!spa_feature_is_enabled(dmu_objset_spa(outzfsvfs->z_os),
+ SPA_FEATURE_BLOCK_CLONING)) {
+ goto bad_write_fallback;
+ }
+ }
+ if (invp == outvp) {
+ if (vn_lock(outvp, LK_EXCLUSIVE) != 0) {
+ goto bad_write_fallback;
+ }
+ } else {
+#if (__FreeBSD_version >= 1302506 && __FreeBSD_version < 1400000) || \
+ __FreeBSD_version >= 1400086
+ vn_lock_pair(invp, false, LK_EXCLUSIVE, outvp, false,
+ LK_EXCLUSIVE);
+#else
+ vn_lock_pair(invp, false, outvp, false);
+#endif
+ if (VN_IS_DOOMED(invp) || VN_IS_DOOMED(outvp)) {
+ goto bad_locked_fallback;
+ }
+ }
+
+#ifdef MAC
+ error = mac_vnode_check_write(curthread->td_ucred, ap->a_outcred,
+ outvp);
+ if (error != 0)
+ goto out_locked;
+#endif
+
+ io.uio_offset = *ap->a_outoffp;
+ io.uio_resid = *ap->a_lenp;
+ error = vn_rlimit_fsize(outvp, &io, ap->a_fsizetd);
+ if (error != 0)
+ goto out_locked;
+
+ error = zfs_clone_range(VTOZ(invp), ap->a_inoffp, VTOZ(outvp),
+ ap->a_outoffp, &len, ap->a_outcred);
+ if (error == EXDEV || error == EAGAIN || error == EINVAL ||
+ error == EOPNOTSUPP)
+ goto bad_locked_fallback;
+ *ap->a_lenp = (size_t)len;
+out_locked:
+ if (invp != outvp)
+ VOP_UNLOCK(invp);
+ VOP_UNLOCK(outvp);
+ if (mp != NULL)
+ vn_finished_write(mp);
+ return (error);
+
+bad_locked_fallback:
+ if (invp != outvp)
+ VOP_UNLOCK(invp);
+ VOP_UNLOCK(outvp);
+bad_write_fallback:
+ if (mp != NULL)
+ vn_finished_write(mp);
+ error = vn_generic_copy_file_range(ap->a_invp, ap->a_inoffp,
+ ap->a_outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags,
+ ap->a_incred, ap->a_outcred, ap->a_fsizetd);
return (error);
}
#endif
@@ -6279,6 +6394,9 @@ struct vop_vector zfs_vnodeops = {
#if __FreeBSD_version >= 1400043
.vop_add_writecount = vop_stdadd_writecount_nomsync,
#endif
+#if __FreeBSD_version >= 1300039
+ .vop_copy_file_range = zfs_freebsd_copy_file_range,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfs_vnodeops);
diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c
index 6115ac7a566e..0d4c94555c6b 100644
--- a/module/os/freebsd/zfs/zfs_znode.c
+++ b/module/os/freebsd/zfs/zfs_znode.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -34,6 +34,7 @@
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <sys/resource.h>
+#include <sys/resourcevar.h>
#include <sys/mntent.h>
#include <sys/u8_textprep.h>
#include <sys/dsl_dataset.h>
@@ -298,7 +299,7 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
sharezp->z_is_sa = zfsvfs->z_use_sa;
VERIFY0(zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr,
- kcred, NULL, &acl_ids));
+ kcred, NULL, &acl_ids, NULL));
zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids);
ASSERT3P(zp, ==, sharezp);
POINTER_INVALIDATE(&sharezp->z_zfsvfs);
@@ -386,7 +387,6 @@ void
zfs_znode_dmu_fini(znode_t *zp)
{
ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
- zp->z_unlinked ||
ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zp->z_zfsvfs));
sa_handle_destroy(zp->z_sa_hdl);
@@ -449,6 +449,13 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
zp->z_vnode = vp;
vp->v_data = zp;
+ /*
+ * Acquire the vnode lock before any possible interaction with the
+ * outside world. Specifically, there is an error path that calls
+ * zfs_vnode_forget() and the vnode should be exclusively locked.
+ */
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
zp->z_sa_hdl = NULL;
@@ -465,8 +472,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
atomic_store_ptr(&zp->z_cached_symlink, NULL);
#endif
- vp = ZTOV(zp);
-
zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
@@ -532,14 +537,12 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp);
- zfsvfs->z_nr_znodes++;
zp->z_zfsvfs = zfsvfs;
mutex_exit(&zfsvfs->z_znodes_lock);
- /*
- * Acquire vnode lock before making it available to the world.
- */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+#if __FreeBSD_version >= 1400077
+ vn_set_state(vp, VSTATE_CONSTRUCTED);
+#endif
VN_LOCK_AREC(vp);
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
@@ -1282,7 +1285,6 @@ zfs_znode_free(znode_t *zp)
mutex_enter(&zfsvfs->z_znodes_lock);
POINTER_INVALIDATE(&zp->z_zfsvfs);
list_remove(&zfsvfs->z_all_znodes, zp);
- zfsvfs->z_nr_znodes--;
mutex_exit(&zfsvfs->z_znodes_lock);
#if __FreeBSD_version >= 1300139
@@ -1686,7 +1688,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
/* For the moment we expect all zpl props to be uint64_ts */
uint64_t val;
- char *name;
+ const char *name;
ASSERT3S(nvpair_type(elem), ==, DATA_TYPE_UINT64);
val = fnvpair_value_uint64(elem);
@@ -1705,6 +1707,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
}
ASSERT3U(version, !=, 0);
error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
+ ASSERT0(error);
/*
* Create zap object used for SA attribute registration
@@ -1773,7 +1776,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
rootzp->z_zfsvfs = zfsvfs;
VERIFY0(zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
- cr, NULL, &acl_ids));
+ cr, NULL, &acl_ids, NULL));
zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
ASSERT3P(zp, ==, rootzp);
error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
@@ -1949,7 +1952,6 @@ zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
} else if (error != ENOENT) {
return (error);
}
- error = 0;
for (;;) {
uint64_t pobj;
@@ -2065,6 +2067,93 @@ zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
return (error);
}
+/*
+ * Read a property stored within the master node.
+ */
+int
+zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
+{
+ uint64_t *cached_copy = NULL;
+
+ /*
+ * Figure out where in the objset_t the cached copy would live, if it
+ * is available for the requested property.
+ */
+ if (os != NULL) {
+ switch (prop) {
+ case ZFS_PROP_VERSION:
+ cached_copy = &os->os_version;
+ break;
+ case ZFS_PROP_NORMALIZE:
+ cached_copy = &os->os_normalization;
+ break;
+ case ZFS_PROP_UTF8ONLY:
+ cached_copy = &os->os_utf8only;
+ break;
+ case ZFS_PROP_CASE:
+ cached_copy = &os->os_casesensitivity;
+ break;
+ default:
+ break;
+ }
+ }
+ if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
+ *value = *cached_copy;
+ return (0);
+ }
+
+ /*
+ * If the property wasn't cached, look up the file system's value for
+ * the property. For the version property, we look up a slightly
+ * different string.
+ */
+ const char *pname;
+ int error = ENOENT;
+ if (prop == ZFS_PROP_VERSION) {
+ pname = ZPL_VERSION_STR;
+ } else {
+ pname = zfs_prop_to_name(prop);
+ }
+
+ if (os != NULL) {
+ ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
+ error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
+ }
+
+ if (error == ENOENT) {
+ /* No value set, use the default value */
+ switch (prop) {
+ case ZFS_PROP_VERSION:
+ *value = ZPL_VERSION;
+ break;
+ case ZFS_PROP_NORMALIZE:
+ case ZFS_PROP_UTF8ONLY:
+ *value = 0;
+ break;
+ case ZFS_PROP_CASE:
+ *value = ZFS_CASE_SENSITIVE;
+ break;
+ case ZFS_PROP_ACLTYPE:
+ *value = ZFS_ACLTYPE_NFSV4;
+ break;
+ default:
+ return (error);
+ }
+ error = 0;
+ }
+
+ /*
+ * If one of the methods for getting the property value above worked,
+ * copy it into the objset_t's cache.
+ */
+ if (error == 0 && cached_copy != NULL) {
+ *cached_copy = *value;
+ }
+
+ return (error);
+}
+
+
void
zfs_znode_update_vfs(znode_t *zp)
@@ -2110,3 +2199,28 @@ zfs_znode_parent_and_name(znode_t *zp, znode_t **dzpp, char *buf)
return (err);
}
#endif /* _KERNEL */
+
+#ifdef _KERNEL
+int
+zfs_rlimit_fsize(off_t fsize)
+{
+ struct thread *td = curthread;
+ off_t lim;
+
+ if (td == NULL)
+ return (0);
+
+ lim = lim_cur(td, RLIMIT_FSIZE);
+ if (__predict_true((uoff_t)fsize <= lim))
+ return (0);
+
+ /*
+ * The limit is reached.
+ */
+ PROC_LOCK(td->td_proc);
+ kern_psignal(td->td_proc, SIGXFSZ);
+ PROC_UNLOCK(td->td_proc);
+
+ return (EFBIG);
+}
+#endif /* _KERNEL */
diff --git a/module/os/freebsd/zfs/zio_crypt.c b/module/os/freebsd/zfs/zio_crypt.c
index 0410ddd65a5c..2b62abcccb78 100644
--- a/module/os/freebsd/zfs/zio_crypt.c
+++ b/module/os/freebsd/zfs/zio_crypt.c
@@ -1251,7 +1251,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
iovec_t *dst_iovecs;
zil_chain_t *zilc;
lr_t *lr;
- uint64_t txtype, lr_len;
+ uint64_t txtype, lr_len, nused;
uint_t crypt_len, nr_iovecs, vec;
uint_t aad_len = 0, total_len = 0;
@@ -1268,7 +1268,10 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
zilc = (zil_chain_t *)src;
slrp = src + sizeof (zil_chain_t);
aadp = aadbuf;
- blkend = src + ((byteswap) ? BSWAP_64(zilc->zc_nused) : zilc->zc_nused);
+ nused = ((byteswap) ? BSWAP_64(zilc->zc_nused) : zilc->zc_nused);
+ ASSERT3U(nused, >=, sizeof (zil_chain_t));
+ ASSERT3U(nused, <=, datalen);
+ blkend = src + nused;
/*
* Calculate the number of encrypted iovecs we will need.
@@ -1287,6 +1290,8 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
txtype = lr->lrc_txtype;
lr_len = lr->lrc_reclen;
}
+ ASSERT3U(lr_len, >=, sizeof (lr_t));
+ ASSERT3U(lr_len, <=, blkend - slrp);
nr_iovecs++;
if (txtype == TX_WRITE && lr_len != sizeof (lr_write_t))
@@ -1338,19 +1343,14 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
* authenticate it.
*/
if (txtype == TX_WRITE) {
- crypt_len = sizeof (lr_write_t) -
- sizeof (lr_t) - sizeof (blkptr_t);
- dst_iovecs[vec].iov_base = (char *)dlrp +
- sizeof (lr_t);
+ const size_t o = offsetof(lr_write_t, lr_blkptr);
+ crypt_len = o - sizeof (lr_t);
+ dst_iovecs[vec].iov_base = (char *)dlrp + sizeof (lr_t);
dst_iovecs[vec].iov_len = crypt_len;
/* copy the bp now since it will not be encrypted */
- memcpy(dlrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- slrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- sizeof (blkptr_t));
- memcpy(aadp,
- slrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- sizeof (blkptr_t));
+ memcpy(dlrp + o, slrp + o, sizeof (blkptr_t));
+ memcpy(aadp, slrp + o, sizeof (blkptr_t));
aadp += sizeof (blkptr_t);
aad_len += sizeof (blkptr_t);
vec++;
@@ -1364,10 +1364,22 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
vec++;
total_len += crypt_len;
}
+ } else if (txtype == TX_CLONE_RANGE) {
+ const size_t o = offsetof(lr_clone_range_t, lr_nbps);
+ crypt_len = o - sizeof (lr_t);
+ dst_iovecs[vec].iov_base = (char *)dlrp + sizeof (lr_t);
+ dst_iovecs[vec].iov_len = crypt_len;
+
+ /* copy the bps now since they will not be encrypted */
+ memcpy(dlrp + o, slrp + o, lr_len - o);
+ memcpy(aadp, slrp + o, lr_len - o);
+ aadp += lr_len - o;
+ aad_len += lr_len - o;
+ vec++;
+ total_len += crypt_len;
} else {
crypt_len = lr_len - sizeof (lr_t);
- dst_iovecs[vec].iov_base = (char *)dlrp +
- sizeof (lr_t);
+ dst_iovecs[vec].iov_base = (char *)dlrp + sizeof (lr_t);
dst_iovecs[vec].iov_len = crypt_len;
vec++;
total_len += crypt_len;
@@ -1555,13 +1567,12 @@ zio_crypt_init_uios_normal(boolean_t encrypt, uint8_t *plainbuf,
iovec_t *plain_iovecs = NULL, *cipher_iovecs = NULL;
void *src, *dst;
- cipher_iovecs = kmem_alloc(nr_cipher * sizeof (iovec_t),
+ cipher_iovecs = kmem_zalloc(nr_cipher * sizeof (iovec_t),
KM_SLEEP);
if (!cipher_iovecs) {
ret = SET_ERROR(ENOMEM);
goto error;
}
- memset(cipher_iovecs, 0, nr_cipher * sizeof (iovec_t));
if (encrypt) {
src = plainbuf;
@@ -1735,7 +1746,6 @@ zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key,
goto error;
if (locked) {
rw_exit(&key->zk_salt_lock);
- locked = B_FALSE;
}
if (authbuf != NULL)
diff --git a/module/os/freebsd/zfs/zvol_os.c b/module/os/freebsd/zfs/zvol_os.c
index 1011aaf68ac6..712ff1b837d7 100644
--- a/module/os/freebsd/zfs/zvol_os.c
+++ b/module/os/freebsd/zfs/zvol_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -92,6 +92,7 @@
#include <sys/zio_checksum.h>
#include <sys/zil_impl.h>
#include <sys/filio.h>
+#include <sys/freebsd_event.h>
#include <geom/geom.h>
#include <sys/zvol.h>
@@ -122,7 +123,7 @@ struct zvol_state_os {
/* volmode=dev */
struct zvol_state_dev {
struct cdev *zsd_cdev;
- uint64_t zsd_sync_cnt;
+ struct selinfo zsd_selinfo;
} _zso_dev;
/* volmode=geom */
@@ -167,6 +168,7 @@ static d_ioctl_t zvol_cdev_ioctl;
static d_read_t zvol_cdev_read;
static d_write_t zvol_cdev_write;
static d_strategy_t zvol_geom_bio_strategy;
+static d_kqfilter_t zvol_cdev_kqfilter;
static struct cdevsw zvol_cdevsw = {
.d_name = "zvol",
@@ -178,6 +180,16 @@ static struct cdevsw zvol_cdevsw = {
.d_read = zvol_cdev_read,
.d_write = zvol_cdev_write,
.d_strategy = zvol_geom_bio_strategy,
+ .d_kqfilter = zvol_cdev_kqfilter,
+};
+
+static void zvol_filter_detach(struct knote *kn);
+static int zvol_filter_vnode(struct knote *kn, long hint);
+
+static struct filterops zvol_filterops_vnode = {
+ .f_isfd = 1,
+ .f_detach = zvol_filter_detach,
+ .f_event = zvol_filter_vnode,
};
extern uint_t zfs_geom_probe_vdev_key;
@@ -602,6 +614,49 @@ zvol_geom_bio_getattr(struct bio *bp)
}
static void
+zvol_filter_detach(struct knote *kn)
+{
+ zvol_state_t *zv;
+ struct zvol_state_dev *zsd;
+
+ zv = kn->kn_hook;
+ zsd = &zv->zv_zso->zso_dev;
+
+ knlist_remove(&zsd->zsd_selinfo.si_note, kn, 0);
+}
+
+static int
+zvol_filter_vnode(struct knote *kn, long hint)
+{
+ kn->kn_fflags |= kn->kn_sfflags & hint;
+
+ return (kn->kn_fflags != 0);
+}
+
+static int
+zvol_cdev_kqfilter(struct cdev *dev, struct knote *kn)
+{
+ zvol_state_t *zv;
+ struct zvol_state_dev *zsd;
+
+ zv = dev->si_drv2;
+ zsd = &zv->zv_zso->zso_dev;
+
+ if (kn->kn_filter != EVFILT_VNODE)
+ return (EINVAL);
+
+ /* XXX: extend support for other NOTE_* events */
+ if (kn->kn_sfflags != NOTE_ATTRIB)
+ return (EINVAL);
+
+ kn->kn_fop = &zvol_filterops_vnode;
+ kn->kn_hook = zv;
+ knlist_add(&zsd->zsd_selinfo.si_note, kn, 0);
+
+ return (0);
+}
+
+static void
zvol_geom_bio_strategy(struct bio *bp)
{
zvol_state_t *zv;
@@ -613,7 +668,7 @@ zvol_geom_bio_strategy(struct bio *bp)
int error = 0;
boolean_t doread = B_FALSE;
boolean_t is_dumpified;
- boolean_t sync;
+ boolean_t commit;
if (bp->bio_to)
zv = bp->bio_to->private;
@@ -640,7 +695,7 @@ zvol_geom_bio_strategy(struct bio *bp)
}
zvol_ensure_zilog(zv);
if (bp->bio_cmd == BIO_FLUSH)
- goto sync;
+ goto commit;
break;
default:
error = SET_ERROR(EOPNOTSUPP);
@@ -662,7 +717,7 @@ zvol_geom_bio_strategy(struct bio *bp)
}
is_dumpified = B_FALSE;
- sync = !doread && !is_dumpified &&
+ commit = !doread && !is_dumpified &&
zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS;
/*
@@ -678,7 +733,7 @@ zvol_geom_bio_strategy(struct bio *bp)
if (error != 0) {
dmu_tx_abort(tx);
} else {
- zvol_log_truncate(zv, tx, off, resid, sync);
+ zvol_log_truncate(zv, tx, off, resid);
dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ,
off, resid);
@@ -699,7 +754,7 @@ zvol_geom_bio_strategy(struct bio *bp)
dmu_tx_abort(tx);
} else {
dmu_write(os, ZVOL_OBJ, off, size, addr, tx);
- zvol_log_write(zv, tx, off, size, sync);
+ zvol_log_write(zv, tx, off, size, commit);
dmu_tx_commit(tx);
}
}
@@ -737,8 +792,8 @@ unlock:
break;
}
- if (sync) {
-sync:
+ if (commit) {
+commit:
zil_commit(zv->zv_zilog, ZVOL_OBJ);
}
resume:
@@ -776,6 +831,7 @@ zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag)
(zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize))
return (SET_ERROR(EIO));
+ rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
ssize_t start_resid = zfs_uio_resid(&uio);
lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio),
zfs_uio_resid(&uio), RL_READER);
@@ -797,6 +853,7 @@ zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag)
zfs_rangelock_exit(lr);
int64_t nread = start_resid - zfs_uio_resid(&uio);
dataset_kstats_update_read_kstats(&zv->zv_kstat, nread);
+ rw_exit(&zv->zv_suspend_lock);
return (error);
}
@@ -808,7 +865,7 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag)
uint64_t volsize;
zfs_locked_range_t *lr;
int error = 0;
- boolean_t sync;
+ boolean_t commit;
zfs_uio_t uio;
zv = dev->si_drv2;
@@ -822,7 +879,7 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag)
return (SET_ERROR(EIO));
ssize_t start_resid = zfs_uio_resid(&uio);
- sync = (ioflag & IO_SYNC) ||
+ commit = (ioflag & IO_SYNC) ||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS);
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
@@ -846,7 +903,7 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag)
}
error = dmu_write_uio_dnode(zv->zv_dn, &uio, bytes, tx);
if (error == 0)
- zvol_log_write(zv, tx, off, bytes, sync);
+ zvol_log_write(zv, tx, off, bytes, commit);
dmu_tx_commit(tx);
if (error)
@@ -855,7 +912,7 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag)
zfs_rangelock_exit(lr);
int64_t nwritten = start_resid - zfs_uio_resid(&uio);
dataset_kstats_update_write_kstats(&zv->zv_kstat, nwritten);
- if (sync)
+ if (commit)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
rw_exit(&zv->zv_suspend_lock);
return (error);
@@ -865,7 +922,6 @@ static int
zvol_cdev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
{
zvol_state_t *zv;
- struct zvol_state_dev *zsd;
int err = 0;
boolean_t drop_suspend = B_FALSE;
@@ -959,13 +1015,6 @@ retry:
}
zv->zv_open_count++;
- if (flags & O_SYNC) {
- zsd = &zv->zv_zso->zso_dev;
- zsd->zsd_sync_cnt++;
- if (zsd->zsd_sync_cnt == 1 &&
- (zv->zv_flags & ZVOL_WRITTEN_TO) != 0)
- zil_async_to_sync(zv->zv_zilog, ZVOL_OBJ);
- }
out_opened:
if (zv->zv_open_count == 0) {
zvol_last_close(zv);
@@ -983,7 +1032,6 @@ static int
zvol_cdev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
{
zvol_state_t *zv;
- struct zvol_state_dev *zsd;
boolean_t drop_suspend = B_TRUE;
rw_enter(&zvol_state_lock, ZVOL_RW_READER);
@@ -1033,10 +1081,6 @@ zvol_cdev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
* You may get multiple opens, but only one close.
*/
zv->zv_open_count--;
- if (flags & O_SYNC) {
- zsd = &zv->zv_zso->zso_dev;
- zsd->zsd_sync_cnt--;
- }
if (zv->zv_open_count == 0) {
ASSERT(ZVOL_RW_READ_HELD(&zv->zv_suspend_lock));
@@ -1105,7 +1149,7 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
dmu_tx_abort(tx);
} else {
sync = (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS);
- zvol_log_truncate(zv, tx, offset, length, sync);
+ zvol_log_truncate(zv, tx, offset, length);
dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ,
offset, length);
@@ -1156,7 +1200,10 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
hole = (cmd == FIOSEEKHOLE);
noff = *off;
+ lr = zfs_rangelock_enter(&zv->zv_rangelock, 0, UINT64_MAX,
+ RL_READER);
error = dmu_offset_next(zv->zv_objset, ZVOL_OBJ, hole, &noff);
+ zfs_rangelock_exit(lr);
*off = noff;
break;
}
@@ -1189,7 +1236,7 @@ zvol_ensure_zilog(zvol_state_t *zv)
}
if (zv->zv_zilog == NULL) {
zv->zv_zilog = zil_open(zv->zv_objset,
- zvol_get_data);
+ zvol_get_data, &zv->zv_kstat.dk_zil_sums);
zv->zv_flags |= ZVOL_WRITTEN_TO;
/* replay / destroy done in zvol_os_create_minor() */
VERIFY0(zv->zv_zilog->zl_header->zh_flags &
@@ -1212,7 +1259,7 @@ zvol_os_rename_minor(zvol_state_t *zv, const char *newname)
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
/* Move to a new hashtable entry. */
- zv->zv_hash = zvol_name_hash(zv->zv_name);
+ zv->zv_hash = zvol_name_hash(newname);
hlist_del(&zv->zv_hlink);
hlist_add_head(&zv->zv_hlink, ZVOL_HT_HEAD(zv->zv_hash));
@@ -1272,6 +1319,7 @@ zvol_os_rename_minor(zvol_state_t *zv, const char *newname)
}
}
strlcpy(zv->zv_name, newname, sizeof (zv->zv_name));
+ dataset_kstats_rename(&zv->zv_kstat, newname);
}
/*
@@ -1306,6 +1354,8 @@ zvol_os_free(zvol_state_t *zv)
if (dev != NULL) {
ASSERT3P(dev->si_drv2, ==, NULL);
destroy_dev(dev);
+ knlist_clear(&zsd->zsd_selinfo.si_note, 0);
+ knlist_destroy(&zsd->zsd_selinfo.si_note);
}
}
@@ -1328,6 +1378,7 @@ zvol_os_create_minor(const char *name)
uint64_t volsize;
uint64_t volmode, hash;
int error;
+ bool replayed_zil = B_FALSE;
ZFS_LOG(1, "Creating ZVOL %s...", name);
hash = zvol_name_hash(name);
@@ -1409,6 +1460,8 @@ zvol_os_create_minor(const char *name)
dev->si_iosize_max = MAXPHYS;
#endif
zsd->zsd_cdev = dev;
+ knlist_init_sx(&zsd->zsd_selinfo.si_note,
+ &zv->zv_state_lock);
}
}
(void) strlcpy(zv->zv_name, name, MAXPATHLEN);
@@ -1422,18 +1475,21 @@ zvol_os_create_minor(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;
+ ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
+ error = dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
+ if (error)
+ goto out_dmu_objset_disown;
ASSERT3P(zv->zv_zilog, ==, NULL);
- zv->zv_zilog = zil_open(os, zvol_get_data);
+ zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(zv->zv_zilog, B_FALSE);
+ replayed_zil = zil_destroy(zv->zv_zilog, B_FALSE);
else
- zil_replay(os, zv, zvol_replay_vector);
+ replayed_zil = zil_replay(os, zv, zvol_replay_vector);
}
- zil_close(zv->zv_zilog);
+ if (replayed_zil)
+ 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);
/* TODO: prefetch for geom tasting */
@@ -1513,6 +1569,10 @@ zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize)
g_resize_provider(pp, zv->zv_volsize);
g_topology_unlock();
+ } else if (zv->zv_volmode == ZFS_VOLMODE_DEV) {
+ struct zvol_state_dev *zsd = &zv->zv_zso->zso_dev;
+
+ KNOTE_UNLOCKED(&zsd->zsd_selinfo.si_note, NOTE_ATTRIB);
}
return (0);
}
diff --git a/module/os/linux/spl/spl-condvar.c b/module/os/linux/spl/spl-condvar.c
index d0461a9f1298..5898789ad53d 100644
--- a/module/os/linux/spl/spl-condvar.c
+++ b/module/os/linux/spl/spl-condvar.c
@@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License along
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
*
- * Solaris Porting Layer (SPL) Credential Implementation.
+ * Solaris Porting Layer (SPL) Condition Variables Implementation.
*/
#include <sys/condvar.h>
@@ -37,7 +37,7 @@
#endif
#define MAX_HRTIMEOUT_SLACK_US 1000
-unsigned int spl_schedule_hrtimeout_slack_us = 0;
+static unsigned int spl_schedule_hrtimeout_slack_us = 0;
static int
param_set_hrtimeout_slack(const char *buf, zfs_kernel_param_t *kp)
diff --git a/module/os/linux/spl/spl-cred.c b/module/os/linux/spl/spl-cred.c
index f81b9540a639..d407fc66b2de 100644
--- a/module/os/linux/spl/spl-cred.c
+++ b/module/os/linux/spl/spl-cred.c
@@ -145,6 +145,18 @@ crgetgid(const cred_t *cr)
return (KGID_TO_SGID(cr->fsgid));
}
+/* Return the initial user ns or nop_mnt_idmap */
+zidmap_t *
+zfs_get_init_idmap(void)
+{
+#ifdef HAVE_IOPS_CREATE_IDMAP
+ return ((zidmap_t *)&nop_mnt_idmap);
+#else
+ return ((zidmap_t *)&init_user_ns);
+#endif
+}
+
+EXPORT_SYMBOL(zfs_get_init_idmap);
EXPORT_SYMBOL(crhold);
EXPORT_SYMBOL(crfree);
EXPORT_SYMBOL(crgetuid);
diff --git a/module/os/linux/spl/spl-err.c b/module/os/linux/spl/spl-err.c
index c84c39b56bf7..29781b9515b2 100644
--- a/module/os/linux/spl/spl-err.c
+++ b/module/os/linux/spl/spl-err.c
@@ -32,7 +32,7 @@
* analysis and other such goodies.
* But we would still default to the current default of not to do that.
*/
-unsigned int spl_panic_halt;
+static unsigned int spl_panic_halt;
/* CSTYLED */
module_param(spl_panic_halt, uint, 0644);
MODULE_PARM_DESC(spl_panic_halt, "Cause kernel panic on assertion failures");
@@ -45,7 +45,7 @@ spl_dumpstack(void)
}
EXPORT_SYMBOL(spl_dumpstack);
-int
+void
spl_panic(const char *file, const char *func, int line, const char *fmt, ...)
{
const char *newfile;
@@ -75,7 +75,6 @@ spl_panic(const char *file, const char *func, int line, const char *fmt, ...)
schedule();
/* Unreachable */
- return (1);
}
EXPORT_SYMBOL(spl_panic);
diff --git a/module/os/linux/spl/spl-generic.c b/module/os/linux/spl/spl-generic.c
index 5179100d1665..986db1518456 100644
--- a/module/os/linux/spl/spl-generic.c
+++ b/module/os/linux/spl/spl-generic.c
@@ -23,6 +23,7 @@
* Solaris Porting Layer (SPL) Generic Implementation.
*/
+#include <sys/isa_defs.h>
#include <sys/sysmacros.h>
#include <sys/systeminfo.h>
#include <sys/vmsystm.h>
@@ -47,6 +48,8 @@
#include <linux/mod_compat.h>
#include <sys/cred.h>
#include <sys/vnode.h>
+#include <sys/misc.h>
+#include <linux/mod_compat.h>
unsigned long spl_hostid = 0;
EXPORT_SYMBOL(spl_hostid);
@@ -59,10 +62,10 @@ proc_t p0;
EXPORT_SYMBOL(p0);
/*
- * Xorshift Pseudo Random Number Generator based on work by Sebastiano Vigna
+ * xoshiro256++ 1.0 PRNG by David Blackman and Sebastiano Vigna
*
- * "Further scramblings of Marsaglia's xorshift generators"
- * http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
+ * "Scrambled Linear Pseudorandom Number Generators∗"
+ * https://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf
*
* random_get_pseudo_bytes() is an API function on Illumos whose sole purpose
* is to provide bytes containing random numbers. It is mapped to /dev/urandom
@@ -74,66 +77,85 @@ EXPORT_SYMBOL(p0);
* free of atomic instructions.
*
* A consequence of using a fast PRNG is that using random_get_pseudo_bytes()
- * to generate words larger than 128 bits will paradoxically be limited to
- * `2^128 - 1` possibilities. This is because we have a sequence of `2^128 - 1`
- * 128-bit words and selecting the first will implicitly select the second. If
+ * to generate words larger than 256 bits will paradoxically be limited to
+ * `2^256 - 1` possibilities. This is because we have a sequence of `2^256 - 1`
+ * 256-bit words and selecting the first will implicitly select the second. If
* a caller finds this behavior undesirable, random_get_bytes() should be used
* instead.
*
* XXX: Linux interrupt handlers that trigger within the critical section
- * formed by `s[1] = xp[1];` and `xp[0] = s[0];` and call this function will
+ * formed by `s[3] = xp[3];` and `xp[0] = s[0];` and call this function will
* see the same numbers. Nothing in the code currently calls this in an
* interrupt handler, so this is considered to be okay. If that becomes a
* problem, we could create a set of per-cpu variables for interrupt handlers
* and use them when in_interrupt() from linux/preempt_mask.h evaluates to
* true.
*/
-void __percpu *spl_pseudo_entropy;
+static void __percpu *spl_pseudo_entropy;
/*
- * spl_rand_next()/spl_rand_jump() are copied from the following CC-0 licensed
- * file:
+ * rotl()/spl_rand_next()/spl_rand_jump() are copied from the following CC-0
+ * licensed file:
*
- * http://xorshift.di.unimi.it/xorshift128plus.c
+ * https://prng.di.unimi.it/xoshiro256plusplus.c
*/
+static inline uint64_t rotl(const uint64_t x, int k)
+{
+ return ((x << k) | (x >> (64 - k)));
+}
+
static inline uint64_t
spl_rand_next(uint64_t *s)
{
- uint64_t s1 = s[0];
- const uint64_t s0 = s[1];
- s[0] = s0;
- s1 ^= s1 << 23; // a
- s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); // b, c
- return (s[1] + s0);
+ const uint64_t result = rotl(s[0] + s[3], 23) + s[0];
+
+ const uint64_t t = s[1] << 17;
+
+ s[2] ^= s[0];
+ s[3] ^= s[1];
+ s[1] ^= s[2];
+ s[0] ^= s[3];
+
+ s[2] ^= t;
+
+ s[3] = rotl(s[3], 45);
+
+ return (result);
}
static inline void
spl_rand_jump(uint64_t *s)
{
- static const uint64_t JUMP[] =
- { 0x8a5cd789635d2dff, 0x121fd2155c472f96 };
+ static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba,
+ 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
uint64_t s0 = 0;
uint64_t s1 = 0;
+ uint64_t s2 = 0;
+ uint64_t s3 = 0;
int i, b;
for (i = 0; i < sizeof (JUMP) / sizeof (*JUMP); i++)
for (b = 0; b < 64; b++) {
if (JUMP[i] & 1ULL << b) {
s0 ^= s[0];
s1 ^= s[1];
+ s2 ^= s[2];
+ s3 ^= s[3];
}
(void) spl_rand_next(s);
}
s[0] = s0;
s[1] = s1;
+ s[2] = s2;
+ s[3] = s3;
}
int
random_get_pseudo_bytes(uint8_t *ptr, size_t len)
{
- uint64_t *xp, s[2];
+ uint64_t *xp, s[4];
ASSERT(ptr);
@@ -141,6 +163,8 @@ random_get_pseudo_bytes(uint8_t *ptr, size_t len)
s[0] = xp[0];
s[1] = xp[1];
+ s[2] = xp[2];
+ s[3] = xp[3];
while (len) {
union {
@@ -152,12 +176,22 @@ random_get_pseudo_bytes(uint8_t *ptr, size_t len)
len -= i;
entropy.ui64 = spl_rand_next(s);
+ /*
+ * xoshiro256++ has low entropy lower bytes, so we copy the
+ * higher order bytes first.
+ */
while (i--)
+#ifdef _ZFS_BIG_ENDIAN
*ptr++ = entropy.byte[i];
+#else
+ *ptr++ = entropy.byte[7 - i];
+#endif
}
xp[0] = s[0];
xp[1] = s[1];
+ xp[2] = s[2];
+ xp[3] = s[3];
put_cpu_ptr(spl_pseudo_entropy);
@@ -220,8 +254,10 @@ __div_u64(uint64_t u, uint32_t v)
* replacements for libgcc-provided functions and will never be called
* directly.
*/
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+#endif
/*
* Implementation of 64-bit unsigned division for 32-bit machines.
@@ -415,7 +451,9 @@ __aeabi_ldivmod(int64_t u, int64_t v)
EXPORT_SYMBOL(__aeabi_ldivmod);
#endif /* __arm || __arm__ */
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
+#endif
#endif /* BITS_PER_LONG */
@@ -458,7 +496,7 @@ int ddi_strto##type(const char *str, char **endptr, \
if (tolower(str[1]) == 'x' && isxdigit(str[2])) { \
base = 16; /* hex */ \
ptr += 2; \
- } else if (str[1] >= '0' && str[1] < 8) { \
+ } else if (str[1] >= '0' && str[1] < '8') { \
base = 8; /* octal */ \
ptr += 1; \
} else { \
@@ -517,6 +555,61 @@ ddi_copyin(const void *from, void *to, size_t len, int flags)
}
EXPORT_SYMBOL(ddi_copyin);
+#define define_spl_param(type, fmt) \
+int \
+spl_param_get_##type(char *buf, zfs_kernel_param_t *kp) \
+{ \
+ return (scnprintf(buf, PAGE_SIZE, fmt "\n", \
+ *(type *)kp->arg)); \
+} \
+int \
+spl_param_set_##type(const char *buf, zfs_kernel_param_t *kp) \
+{ \
+ return (kstrto##type(buf, 0, (type *)kp->arg)); \
+} \
+const struct kernel_param_ops spl_param_ops_##type = { \
+ .set = spl_param_set_##type, \
+ .get = spl_param_get_##type, \
+}; \
+EXPORT_SYMBOL(spl_param_get_##type); \
+EXPORT_SYMBOL(spl_param_set_##type); \
+EXPORT_SYMBOL(spl_param_ops_##type);
+
+define_spl_param(s64, "%lld")
+define_spl_param(u64, "%llu")
+
+/*
+ * Post a uevent to userspace whenever a new vdev adds to the pool. It is
+ * necessary to sync blkid information with udev, which zed daemon uses
+ * during device hotplug to identify the vdev.
+ */
+void
+spl_signal_kobj_evt(struct block_device *bdev)
+{
+#if defined(HAVE_BDEV_KOBJ) || defined(HAVE_PART_TO_DEV)
+#ifdef HAVE_BDEV_KOBJ
+ struct kobject *disk_kobj = bdev_kobj(bdev);
+#else
+ struct kobject *disk_kobj = &part_to_dev(bdev->bd_part)->kobj;
+#endif
+ if (disk_kobj) {
+ int ret = kobject_uevent(disk_kobj, KOBJ_CHANGE);
+ if (ret) {
+ pr_warn("ZFS: Sending event '%d' to kobject: '%s'"
+ " (%p): failed(ret:%d)\n", KOBJ_CHANGE,
+ kobject_name(disk_kobj), disk_kobj, ret);
+ }
+ }
+#else
+/*
+ * This is encountered if neither bdev_kobj() nor part_to_dev() is available
+ * in the kernel - likely due to an API change that needs to be chased down.
+ */
+#error "Unsupported kernel: unable to get struct kobj from bdev"
+#endif
+}
+EXPORT_SYMBOL(spl_signal_kobj_evt);
+
int
ddi_copyout(const void *from, void *to, size_t len, int flags)
{
@@ -705,28 +798,33 @@ spl_kvmem_init(void)
* initialize each of the per-cpu seeds so that the sequences generated on each
* CPU are guaranteed to never overlap in practice.
*/
-static void __init
+static int __init
spl_random_init(void)
{
- uint64_t s[2];
+ uint64_t s[4];
int i = 0;
- spl_pseudo_entropy = __alloc_percpu(2 * sizeof (uint64_t),
+ spl_pseudo_entropy = __alloc_percpu(4 * sizeof (uint64_t),
sizeof (uint64_t));
+ if (!spl_pseudo_entropy)
+ return (-ENOMEM);
+
get_random_bytes(s, sizeof (s));
- if (s[0] == 0 && s[1] == 0) {
+ if (s[0] == 0 && s[1] == 0 && s[2] == 0 && s[3] == 0) {
if (jiffies != 0) {
s[0] = jiffies;
s[1] = ~0 - jiffies;
+ s[2] = ~jiffies;
+ s[3] = jiffies - ~0;
} else {
- (void) memcpy(s, "improbable seed", sizeof (s));
+ (void) memcpy(s, "improbable seed", 16);
}
printk("SPL: get_random_bytes() returned 0 "
"when generating random seed. Setting initial seed to "
- "0x%016llx%016llx.\n", cpu_to_be64(s[0]),
- cpu_to_be64(s[1]));
+ "0x%016llx%016llx%016llx%016llx.\n", cpu_to_be64(s[0]),
+ cpu_to_be64(s[1]), cpu_to_be64(s[2]), cpu_to_be64(s[3]));
}
for_each_possible_cpu(i) {
@@ -736,7 +834,11 @@ spl_random_init(void)
wordp[0] = s[0];
wordp[1] = s[1];
+ wordp[2] = s[2];
+ wordp[3] = s[3];
}
+
+ return (0);
}
static void
@@ -757,7 +859,8 @@ spl_init(void)
{
int rc = 0;
- spl_random_init();
+ if ((rc = spl_random_init()))
+ goto out0;
if ((rc = spl_kvmem_init()))
goto out1;
@@ -800,6 +903,8 @@ out3:
out2:
spl_kvmem_fini();
out1:
+ spl_random_fini();
+out0:
return (rc);
}
diff --git a/module/os/linux/spl/spl-kmem-cache.c b/module/os/linux/spl/spl-kmem-cache.c
index ba4ca49a2ac9..42821ad60256 100644
--- a/module/os/linux/spl/spl-kmem-cache.c
+++ b/module/os/linux/spl/spl-kmem-cache.c
@@ -28,6 +28,7 @@
#include <sys/timer.h>
#include <sys/vmem.h>
#include <sys/wait.h>
+#include <sys/string.h>
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/prefetch.h>
@@ -76,17 +77,6 @@ module_param(spl_kmem_cache_magazine_size, uint, 0444);
MODULE_PARM_DESC(spl_kmem_cache_magazine_size,
"Default magazine size (2-256), set automatically (0)");
-/*
- * The default behavior is to report the number of objects remaining in the
- * cache. This allows the Linux VM to repeatedly reclaim objects from the
- * cache when memory is low satisfy other memory allocations. Alternately,
- * setting this value to KMC_RECLAIM_ONCE limits how aggressively the cache
- * is reclaimed. This may increase the likelihood of out of memory events.
- */
-static unsigned int spl_kmem_cache_reclaim = 0 /* KMC_RECLAIM_ONCE */;
-module_param(spl_kmem_cache_reclaim, uint, 0644);
-MODULE_PARM_DESC(spl_kmem_cache_reclaim, "Single reclaim pass (0x1)");
-
static unsigned int spl_kmem_cache_obj_per_slab = SPL_KMEM_CACHE_OBJ_PER_SLAB;
module_param(spl_kmem_cache_obj_per_slab, uint, 0644);
MODULE_PARM_DESC(spl_kmem_cache_obj_per_slab, "Number of objects per slab");
@@ -102,7 +92,8 @@ MODULE_PARM_DESC(spl_kmem_cache_max_size, "Maximum size of slab in MB");
* of 16K was determined to be optimal for architectures using 4K pages and
* to also work well on architecutres using larger 64K page sizes.
*/
-static unsigned int spl_kmem_cache_slab_limit = 16384;
+static unsigned int spl_kmem_cache_slab_limit =
+ SPL_MAX_KMEM_ORDER_NR_PAGES * PAGE_SIZE;
module_param(spl_kmem_cache_slab_limit, uint, 0644);
MODULE_PARM_DESC(spl_kmem_cache_slab_limit,
"Objects less than N bytes use the Linux slab");
@@ -151,7 +142,7 @@ MODULE_PARM_DESC(spl_kmem_cache_kmem_threads,
struct list_head spl_kmem_cache_list; /* List of caches */
struct rw_semaphore spl_kmem_cache_sem; /* Cache list lock */
-taskq_t *spl_kmem_cache_taskq; /* Task queue for aging / reclaim */
+static taskq_t *spl_kmem_cache_taskq; /* Task queue for aging / reclaim */
static void spl_cache_shrink(spl_kmem_cache_t *skc, void *obj);
@@ -182,8 +173,11 @@ kv_free(spl_kmem_cache_t *skc, void *ptr, int size)
* of that infrastructure we are responsible for incrementing it.
*/
if (current->reclaim_state)
+#ifdef HAVE_RECLAIM_STATE_RECLAIMED
+ current->reclaim_state->reclaimed += size >> PAGE_SHIFT;
+#else
current->reclaim_state->reclaimed_slab += size >> PAGE_SHIFT;
-
+#endif
vfree(ptr);
}
@@ -701,12 +695,12 @@ spl_kmem_cache_create(const char *name, size_t size, size_t align,
skc->skc_magic = SKC_MAGIC;
skc->skc_name_size = strlen(name) + 1;
- skc->skc_name = (char *)kmalloc(skc->skc_name_size, lflags);
+ skc->skc_name = kmalloc(skc->skc_name_size, lflags);
if (skc->skc_name == NULL) {
kfree(skc);
return (NULL);
}
- strncpy(skc->skc_name, name, skc->skc_name_size);
+ strlcpy(skc->skc_name, name, skc->skc_name_size);
skc->skc_ctor = ctor;
skc->skc_dtor = dtor;
@@ -791,10 +785,8 @@ spl_kmem_cache_create(const char *name, size_t size, size_t align,
} else {
unsigned long slabflags = 0;
- if (size > (SPL_MAX_KMEM_ORDER_NR_PAGES * PAGE_SIZE)) {
- rc = EINVAL;
+ if (size > spl_kmem_cache_slab_limit)
goto out;
- }
#if defined(SLAB_USERCOPY)
/*
@@ -815,10 +807,8 @@ spl_kmem_cache_create(const char *name, size_t size, size_t align,
skc->skc_linux_cache = kmem_cache_create(
skc->skc_name, size, align, slabflags, NULL);
#endif
- if (skc->skc_linux_cache == NULL) {
- rc = ENOMEM;
+ if (skc->skc_linux_cache == NULL)
goto out;
- }
}
down_write(&spl_kmem_cache_sem);
@@ -1016,10 +1006,20 @@ spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj)
ASSERT0(flags & ~KM_PUBLIC_MASK);
ASSERT(skc->skc_magic == SKC_MAGIC);
ASSERT((skc->skc_flags & KMC_SLAB) == 0);
- might_sleep();
+
*obj = NULL;
/*
+ * Since we can't sleep attempt an emergency allocation to satisfy
+ * the request. The only alterative is to fail the allocation but
+ * it's preferable try. The use of KM_NOSLEEP is expected to be rare.
+ */
+ if (flags & KM_NOSLEEP)
+ return (spl_emergency_alloc(skc, flags, obj));
+
+ might_sleep();
+
+ /*
* Before allocating a new slab wait for any reaping to complete and
* then return so the local magazine can be rechecked for new objects.
*/
@@ -1452,6 +1452,9 @@ spl_kmem_cache_init(void)
spl_kmem_cache_kmem_threads * 8, INT_MAX,
TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
+ if (spl_kmem_cache_taskq == NULL)
+ return (-ENOMEM);
+
return (0);
}
diff --git a/module/os/linux/spl/spl-kstat.c b/module/os/linux/spl/spl-kstat.c
index c6d3c8f4413f..ad553a73a69e 100644
--- a/module/os/linux/spl/spl-kstat.c
+++ b/module/os/linux/spl/spl-kstat.c
@@ -32,6 +32,7 @@
#include <sys/vmem.h>
#include <sys/cmn_err.h>
#include <sys/sysmacros.h>
+#include <sys/string.h>
static kmutex_t kstat_module_lock;
static struct list_head kstat_module_list;
@@ -390,7 +391,7 @@ kstat_create_module(char *name)
module = kmem_alloc(sizeof (kstat_module_t), KM_SLEEP);
module->ksm_proc = pde;
- strlcpy(module->ksm_name, name, KSTAT_STRLEN+1);
+ strlcpy(module->ksm_name, name, KSTAT_STRLEN);
INIT_LIST_HEAD(&module->ksm_kstat_list);
list_add_tail(&module->ksm_module_list, &kstat_module_list);
@@ -479,8 +480,8 @@ kstat_proc_entry_init(kstat_proc_entry_t *kpep, const char *module,
kpep->kpe_owner = NULL;
kpep->kpe_proc = NULL;
INIT_LIST_HEAD(&kpep->kpe_list);
- strncpy(kpep->kpe_module, module, KSTAT_STRLEN);
- strncpy(kpep->kpe_name, name, KSTAT_STRLEN);
+ strlcpy(kpep->kpe_module, module, sizeof (kpep->kpe_module));
+ strlcpy(kpep->kpe_name, name, sizeof (kpep->kpe_name));
}
EXPORT_SYMBOL(kstat_proc_entry_init);
@@ -514,7 +515,7 @@ __kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
ksp->ks_crtime = gethrtime();
ksp->ks_snaptime = ksp->ks_crtime;
ksp->ks_instance = ks_instance;
- strncpy(ksp->ks_class, ks_class, KSTAT_STRLEN);
+ strlcpy(ksp->ks_class, ks_class, sizeof (ksp->ks_class));
ksp->ks_type = ks_type;
ksp->ks_flags = ks_flags;
ksp->ks_update = kstat_default_update;
diff --git a/module/os/linux/spl/spl-proc.c b/module/os/linux/spl/spl-proc.c
index 01f5619e1893..f0f929d3ce90 100644
--- a/module/os/linux/spl/spl-proc.c
+++ b/module/os/linux/spl/spl-proc.c
@@ -47,6 +47,10 @@ static unsigned long table_min = 0;
static unsigned long table_max = ~0;
static struct ctl_table_header *spl_header = NULL;
+#ifndef HAVE_REGISTER_SYSCTL_TABLE
+static struct ctl_table_header *spl_kmem = NULL;
+static struct ctl_table_header *spl_kstat = NULL;
+#endif
static struct proc_dir_entry *proc_spl = NULL;
static struct proc_dir_entry *proc_spl_kmem = NULL;
static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
@@ -624,6 +628,7 @@ static struct ctl_table spl_table[] = {
.mode = 0644,
.proc_handler = &proc_dohostid,
},
+#ifdef HAVE_REGISTER_SYSCTL_TABLE
{
.procname = "kmem",
.mode = 0555,
@@ -634,9 +639,11 @@ static struct ctl_table spl_table[] = {
.mode = 0555,
.child = spl_kstat_table,
},
+#endif
{},
};
+#ifdef HAVE_REGISTER_SYSCTL_TABLE
static struct ctl_table spl_dir[] = {
{
.procname = "spl",
@@ -648,21 +655,64 @@ static struct ctl_table spl_dir[] = {
static struct ctl_table spl_root[] = {
{
- .procname = "kernel",
- .mode = 0555,
- .child = spl_dir,
+ .procname = "kernel",
+ .mode = 0555,
+ .child = spl_dir,
},
{}
};
+#endif
+
+static void spl_proc_cleanup(void)
+{
+ remove_proc_entry("kstat", proc_spl);
+ remove_proc_entry("slab", proc_spl_kmem);
+ remove_proc_entry("kmem", proc_spl);
+ remove_proc_entry("taskq-all", proc_spl);
+ remove_proc_entry("taskq", proc_spl);
+ remove_proc_entry("spl", NULL);
+
+#ifndef HAVE_REGISTER_SYSCTL_TABLE
+ if (spl_kstat) {
+ unregister_sysctl_table(spl_kstat);
+ spl_kstat = NULL;
+ }
+ if (spl_kmem) {
+ unregister_sysctl_table(spl_kmem);
+ spl_kmem = NULL;
+ }
+#endif
+ if (spl_header) {
+ unregister_sysctl_table(spl_header);
+ spl_header = NULL;
+ }
+}
int
spl_proc_init(void)
{
int rc = 0;
+#ifdef HAVE_REGISTER_SYSCTL_TABLE
spl_header = register_sysctl_table(spl_root);
if (spl_header == NULL)
return (-EUNATCH);
+#else
+ spl_header = register_sysctl("kernel/spl", spl_table);
+ if (spl_header == NULL)
+ return (-EUNATCH);
+
+ spl_kmem = register_sysctl("kernel/spl/kmem", spl_kmem_table);
+ if (spl_kmem == NULL) {
+ rc = -EUNATCH;
+ goto out;
+ }
+ spl_kstat = register_sysctl("kernel/spl/kstat", spl_kstat_table);
+ if (spl_kstat == NULL) {
+ rc = -EUNATCH;
+ goto out;
+ }
+#endif
proc_spl = proc_mkdir("spl", NULL);
if (proc_spl == NULL) {
@@ -703,15 +753,8 @@ spl_proc_init(void)
goto out;
}
out:
- if (rc) {
- remove_proc_entry("kstat", proc_spl);
- remove_proc_entry("slab", proc_spl_kmem);
- remove_proc_entry("kmem", proc_spl);
- remove_proc_entry("taskq-all", proc_spl);
- remove_proc_entry("taskq", proc_spl);
- remove_proc_entry("spl", NULL);
- unregister_sysctl_table(spl_header);
- }
+ if (rc)
+ spl_proc_cleanup();
return (rc);
}
@@ -719,13 +762,5 @@ out:
void
spl_proc_fini(void)
{
- remove_proc_entry("kstat", proc_spl);
- remove_proc_entry("slab", proc_spl_kmem);
- remove_proc_entry("kmem", proc_spl);
- remove_proc_entry("taskq-all", proc_spl);
- remove_proc_entry("taskq", proc_spl);
- remove_proc_entry("spl", NULL);
-
- ASSERT(spl_header != NULL);
- unregister_sysctl_table(spl_header);
+ spl_proc_cleanup();
}
diff --git a/module/os/linux/spl/spl-procfs-list.c b/module/os/linux/spl/spl-procfs-list.c
index 81501460f04f..5e073950d61a 100644
--- a/module/os/linux/spl/spl-procfs-list.c
+++ b/module/os/linux/spl/spl-procfs-list.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,9 +23,9 @@
*/
#include <sys/list.h>
-#include <sys/mutex.h>
#include <sys/procfs_list.h>
#include <linux/proc_fs.h>
+#include <sys/mutex.h>
/*
* A procfs_list is a wrapper around a linked list which implements the seq_file
diff --git a/module/os/linux/spl/spl-shrinker.c b/module/os/linux/spl/spl-shrinker.c
new file mode 100644
index 000000000000..d5c8da471cbb
--- /dev/null
+++ b/module/os/linux/spl/spl-shrinker.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
+ * Copyright (C) 2007 The Regents of the University of California.
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
+ * UCRL-CODE-235197
+ *
+ * This file is part of the SPL, Solaris Porting Layer.
+ *
+ * The SPL is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The SPL is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the SPL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Solaris Porting Layer (SPL) Shrinker Implementation.
+ */
+
+#include <sys/kmem.h>
+#include <sys/shrinker.h>
+
+#ifdef HAVE_SINGLE_SHRINKER_CALLBACK
+/* 3.0-3.11: single shrink() callback, which we wrap to carry both functions */
+struct spl_shrinker_wrap {
+ struct shrinker shrinker;
+ spl_shrinker_cb countfunc;
+ spl_shrinker_cb scanfunc;
+};
+
+static int
+spl_shrinker_single_cb(struct shrinker *shrinker, struct shrink_control *sc)
+{
+ struct spl_shrinker_wrap *sw = (struct spl_shrinker_wrap *)shrinker;
+
+ if (sc->nr_to_scan != 0)
+ (void) sw->scanfunc(&sw->shrinker, sc);
+ return (sw->countfunc(&sw->shrinker, sc));
+}
+#endif
+
+struct shrinker *
+spl_register_shrinker(const char *name, spl_shrinker_cb countfunc,
+ spl_shrinker_cb scanfunc, int seek_cost)
+{
+ struct shrinker *shrinker;
+
+ /* allocate shrinker */
+#if defined(HAVE_SHRINKER_REGISTER)
+ /* 6.7: kernel will allocate the shrinker for us */
+ shrinker = shrinker_alloc(0, name);
+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
+ /* 3.12-6.6: we allocate the shrinker */
+ shrinker = kmem_zalloc(sizeof (struct shrinker), KM_SLEEP);
+#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK)
+ /* 3.0-3.11: allocate a wrapper */
+ struct spl_shrinker_wrap *sw =
+ kmem_zalloc(sizeof (struct spl_shrinker_wrap), KM_SLEEP);
+ shrinker = &sw->shrinker;
+#else
+ /* 2.x-2.6.22, or a newer shrinker API has been introduced. */
+#error "Unknown shrinker API"
+#endif
+
+ if (shrinker == NULL)
+ return (NULL);
+
+ /* set callbacks */
+#ifdef HAVE_SINGLE_SHRINKER_CALLBACK
+ sw->countfunc = countfunc;
+ sw->scanfunc = scanfunc;
+ shrinker->shrink = spl_shrinker_single_cb;
+#else
+ shrinker->count_objects = countfunc;
+ shrinker->scan_objects = scanfunc;
+#endif
+
+ /* set params */
+ shrinker->seeks = seek_cost;
+
+ /* register with kernel */
+#if defined(HAVE_SHRINKER_REGISTER)
+ shrinker_register(shrinker);
+#elif defined(HAVE_REGISTER_SHRINKER_VARARG)
+ register_shrinker(shrinker, name);
+#else
+ register_shrinker(shrinker);
+#endif
+
+ return (shrinker);
+}
+EXPORT_SYMBOL(spl_register_shrinker);
+
+void
+spl_unregister_shrinker(struct shrinker *shrinker)
+{
+#if defined(HAVE_SHRINKER_REGISTER)
+ shrinker_free(shrinker);
+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
+ unregister_shrinker(shrinker);
+ kmem_free(shrinker, sizeof (struct shrinker));
+#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK)
+ unregister_shrinker(shrinker);
+ kmem_free(shrinker, sizeof (struct spl_shrinker_wrap));
+#else
+#error "Unknown shrinker API"
+#endif
+}
+EXPORT_SYMBOL(spl_unregister_shrinker);
diff --git a/module/os/linux/spl/spl-taskq.c b/module/os/linux/spl/spl-taskq.c
index 0aab148975aa..c384b7b378c3 100644
--- a/module/os/linux/spl/spl-taskq.c
+++ b/module/os/linux/spl/spl-taskq.c
@@ -36,6 +36,12 @@ static int spl_taskq_thread_bind = 0;
module_param(spl_taskq_thread_bind, int, 0644);
MODULE_PARM_DESC(spl_taskq_thread_bind, "Bind taskq thread to CPU by default");
+static uint_t spl_taskq_thread_timeout_ms = 5000;
+/* BEGIN CSTYLED */
+module_param(spl_taskq_thread_timeout_ms, uint, 0644);
+/* END CSTYLED */
+MODULE_PARM_DESC(spl_taskq_thread_timeout_ms,
+ "Minimum idle threads exit interval for dynamic taskqs");
static int spl_taskq_thread_dynamic = 1;
module_param(spl_taskq_thread_dynamic, int, 0444);
@@ -46,8 +52,10 @@ module_param(spl_taskq_thread_priority, int, 0644);
MODULE_PARM_DESC(spl_taskq_thread_priority,
"Allow non-default priority for taskq threads");
-static int spl_taskq_thread_sequential = 4;
-module_param(spl_taskq_thread_sequential, int, 0644);
+static uint_t spl_taskq_thread_sequential = 4;
+/* BEGIN CSTYLED */
+module_param(spl_taskq_thread_sequential, uint, 0644);
+/* END CSTYLED */
MODULE_PARM_DESC(spl_taskq_thread_sequential,
"Create new taskq threads after N sequential tasks");
@@ -586,8 +594,7 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
ASSERT(tq->tq_nactive <= tq->tq_nthreads);
if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) {
/* Dynamic taskq may be able to spawn another thread */
- if (!(tq->tq_flags & TASKQ_DYNAMIC) ||
- taskq_thread_spawn(tq) == 0)
+ if (taskq_thread_spawn(tq) == 0)
goto out;
}
@@ -621,11 +628,11 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
spin_unlock(&t->tqent_lock);
wake_up(&tq->tq_work_waitq);
-out:
+
/* Spawn additional taskq threads if required. */
if (!(flags & TQ_NOQUEUE) && tq->tq_nactive == tq->tq_nthreads)
(void) taskq_thread_spawn(tq);
-
+out:
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
return (rc);
}
@@ -668,10 +675,11 @@ taskq_dispatch_delay(taskq_t *tq, task_func_t func, void *arg,
ASSERT(!(t->tqent_flags & TQENT_FLAG_PREALLOC));
spin_unlock(&t->tqent_lock);
-out:
+
/* Spawn additional taskq threads if required. */
if (tq->tq_nactive == tq->tq_nthreads)
(void) taskq_thread_spawn(tq);
+out:
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
return (rc);
}
@@ -696,9 +704,8 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
if ((flags & TQ_NOQUEUE) && (tq->tq_nactive == tq->tq_nthreads)) {
/* Dynamic taskq may be able to spawn another thread */
- if (!(tq->tq_flags & TASKQ_DYNAMIC) ||
- taskq_thread_spawn(tq) == 0)
- goto out2;
+ if (taskq_thread_spawn(tq) == 0)
+ goto out;
flags |= TQ_FRONT;
}
@@ -734,11 +741,11 @@ taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
spin_unlock(&t->tqent_lock);
wake_up(&tq->tq_work_waitq);
-out:
+
/* Spawn additional taskq threads if required. */
if (tq->tq_nactive == tq->tq_nthreads)
(void) taskq_thread_spawn(tq);
-out2:
+out:
spin_unlock_irqrestore(&tq->tq_lock, irqflags);
}
EXPORT_SYMBOL(taskq_dispatch_ent);
@@ -817,6 +824,7 @@ taskq_thread_spawn(taskq_t *tq)
if (!(tq->tq_flags & TASKQ_DYNAMIC))
return (0);
+ tq->lastspawnstop = jiffies;
if ((tq->tq_nthreads + tq->tq_nspawn < tq->tq_maxthreads) &&
(tq->tq_flags & TASKQ_ACTIVE)) {
spawning = (++tq->tq_nspawn);
@@ -828,9 +836,9 @@ taskq_thread_spawn(taskq_t *tq)
}
/*
- * Threads in a dynamic taskq should only exit once it has been completely
- * drained and no other threads are actively servicing tasks. This prevents
- * threads from being created and destroyed more than is required.
+ * Threads in a dynamic taskq may exit once there is no more work to do.
+ * To prevent threads from being created and destroyed too often limit
+ * the exit rate to one per spl_taskq_thread_timeout_ms.
*
* The first thread is the thread list is treated as the primary thread.
* There is nothing special about the primary thread but in order to avoid
@@ -839,19 +847,22 @@ taskq_thread_spawn(taskq_t *tq)
static int
taskq_thread_should_stop(taskq_t *tq, taskq_thread_t *tqt)
{
- if (!(tq->tq_flags & TASKQ_DYNAMIC))
+ ASSERT(!taskq_next_ent(tq));
+ if (!(tq->tq_flags & TASKQ_DYNAMIC) || !spl_taskq_thread_dynamic)
return (0);
-
+ if (!(tq->tq_flags & TASKQ_ACTIVE))
+ return (1);
if (list_first_entry(&(tq->tq_thread_list), taskq_thread_t,
tqt_thread_list) == tqt)
return (0);
-
- return
- ((tq->tq_nspawn == 0) && /* No threads are being spawned */
- (tq->tq_nactive == 0) && /* No threads are handling tasks */
- (tq->tq_nthreads > 1) && /* More than 1 thread is running */
- (!taskq_next_ent(tq)) && /* There are no pending tasks */
- (spl_taskq_thread_dynamic)); /* Dynamic taskqs are allowed */
+ ASSERT3U(tq->tq_nthreads, >, 1);
+ if (tq->tq_nspawn != 0)
+ return (0);
+ if (time_before(jiffies, tq->lastspawnstop +
+ msecs_to_jiffies(spl_taskq_thread_timeout_ms)))
+ return (0);
+ tq->lastspawnstop = jiffies;
+ return (1);
}
static int
@@ -902,10 +913,8 @@ taskq_thread(void *args)
if (list_empty(&tq->tq_pend_list) &&
list_empty(&tq->tq_prio_list)) {
- if (taskq_thread_should_stop(tq, tqt)) {
- wake_up_all(&tq->tq_wait_waitq);
+ if (taskq_thread_should_stop(tq, tqt))
break;
- }
add_wait_queue_exclusive(&tq->tq_work_waitq, &wait);
spin_unlock_irqrestore(&tq->tq_lock, flags);
@@ -980,9 +989,6 @@ taskq_thread(void *args)
tqt->tqt_id = TASKQID_INVALID;
tqt->tqt_flags = 0;
wake_up_all(&tq->tq_wait_waitq);
- } else {
- if (taskq_thread_should_stop(tq, tqt))
- break;
}
set_current_state(TASK_INTERRUPTIBLE);
@@ -1046,7 +1052,6 @@ taskq_create(const char *name, int threads_arg, pri_t pri,
ASSERT(name != NULL);
ASSERT(minalloc >= 0);
- ASSERT(maxalloc <= INT_MAX);
ASSERT(!(flags & (TASKQ_CPR_SAFE))); /* Unsupported */
/* Scale the number of threads using nthreads as a percentage */
@@ -1090,6 +1095,7 @@ taskq_create(const char *name, int threads_arg, pri_t pri,
tq->tq_flags = (flags | TASKQ_ACTIVE);
tq->tq_next_id = TASKQID_INITIAL;
tq->tq_lowest_id = TASKQID_INITIAL;
+ tq->lastspawnstop = jiffies;
INIT_LIST_HEAD(&tq->tq_free_list);
INIT_LIST_HEAD(&tq->tq_pend_list);
INIT_LIST_HEAD(&tq->tq_prio_list);
@@ -1229,6 +1235,42 @@ taskq_destroy(taskq_t *tq)
}
EXPORT_SYMBOL(taskq_destroy);
+/*
+ * Create a taskq with a specified number of pool threads. Allocate
+ * and return an array of nthreads kthread_t pointers, one for each
+ * thread in the pool. The array is not ordered and must be freed
+ * by the caller.
+ */
+taskq_t *
+taskq_create_synced(const char *name, int nthreads, pri_t pri,
+ int minalloc, int maxalloc, uint_t flags, kthread_t ***ktpp)
+{
+ taskq_t *tq;
+ taskq_thread_t *tqt;
+ int i = 0;
+ kthread_t **kthreads = kmem_zalloc(sizeof (*kthreads) * nthreads,
+ KM_SLEEP);
+
+ flags &= ~(TASKQ_DYNAMIC | TASKQ_THREADS_CPU_PCT | TASKQ_DC_BATCH);
+
+ /* taskq_create spawns all the threads before returning */
+ tq = taskq_create(name, nthreads, minclsyspri, nthreads, INT_MAX,
+ flags | TASKQ_PREPOPULATE);
+ VERIFY(tq != NULL);
+ VERIFY(tq->tq_nthreads == nthreads);
+
+ list_for_each_entry(tqt, &tq->tq_thread_list, tqt_thread_list) {
+ kthreads[i] = tqt->tqt_thread;
+ i++;
+ }
+
+ ASSERT3S(i, ==, nthreads);
+ *ktpp = kthreads;
+
+ return (tq);
+}
+EXPORT_SYMBOL(taskq_create_synced);
+
static unsigned int spl_taskq_kick = 0;
/*
@@ -1379,7 +1421,7 @@ spl_taskq_init(void)
system_taskq = taskq_create("spl_system_taskq", MAX(boot_ncpus, 64),
maxclsyspri, boot_ncpus, INT_MAX, TASKQ_PREPOPULATE|TASKQ_DYNAMIC);
if (system_taskq == NULL)
- return (1);
+ return (-ENOMEM);
system_delay_taskq = taskq_create("spl_delay_taskq", MAX(boot_ncpus, 4),
maxclsyspri, boot_ncpus, INT_MAX, TASKQ_PREPOPULATE|TASKQ_DYNAMIC);
@@ -1388,7 +1430,7 @@ spl_taskq_init(void)
cpuhp_remove_multi_state(spl_taskq_cpuhp_state);
#endif
taskq_destroy(system_taskq);
- return (1);
+ return (-ENOMEM);
}
dynamic_taskq = taskq_create("spl_dynamic_taskq", 1,
@@ -1399,7 +1441,7 @@ spl_taskq_init(void)
#endif
taskq_destroy(system_taskq);
taskq_destroy(system_delay_taskq);
- return (1);
+ return (-ENOMEM);
}
/*
diff --git a/module/os/linux/spl/spl-thread.c b/module/os/linux/spl/spl-thread.c
index 32a2d34b1d93..ee3eb4690c3a 100644
--- a/module/os/linux/spl/spl-thread.c
+++ b/module/os/linux/spl/spl-thread.c
@@ -26,6 +26,7 @@
#include <sys/thread.h>
#include <sys/kmem.h>
#include <sys/tsd.h>
+#include <sys/string.h>
/*
* Thread interfaces
@@ -92,7 +93,7 @@ __thread_create(caddr_t stk, size_t stksize, thread_func_t func,
return (NULL);
}
- strncpy(tp->tp_name, name, tp->tp_name_size);
+ strlcpy(tp->tp_name, name, tp->tp_name_size);
/*
* Strip trailing "_thread" from passed name which will be the func
@@ -178,12 +179,11 @@ issig(int why)
sigorsets(&set, &task->blocked, &set);
spin_lock_irq(&task->sighand->siglock);
- int ret;
#ifdef HAVE_DEQUEUE_SIGNAL_4ARG
enum pid_type __type;
- if ((ret = dequeue_signal(task, &set, &__info, &__type)) != 0) {
+ if (dequeue_signal(task, &set, &__info, &__type) != 0) {
#else
- if ((ret = dequeue_signal(task, &set, &__info)) != 0) {
+ if (dequeue_signal(task, &set, &__info) != 0) {
#endif
#ifdef HAVE_SIGNAL_STOP
spin_unlock_irq(&task->sighand->siglock);
diff --git a/module/os/linux/spl/spl-trace.c b/module/os/linux/spl/spl-trace.c
index 7912a381294d..d3e53e541b8b 100644
--- a/module/os/linux/spl/spl-trace.c
+++ b/module/os/linux/spl/spl-trace.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/linux/spl/spl-tsd.c b/module/os/linux/spl/spl-tsd.c
index 546db9ab8bd7..389c9d0d6df3 100644
--- a/module/os/linux/spl/spl-tsd.c
+++ b/module/os/linux/spl/spl-tsd.c
@@ -706,7 +706,7 @@ spl_tsd_init(void)
{
tsd_hash_table = tsd_hash_table_init(TSD_HASH_TABLE_BITS_DEFAULT);
if (tsd_hash_table == NULL)
- return (1);
+ return (-ENOMEM);
return (0);
}
diff --git a/module/os/linux/spl/spl-xdr.c b/module/os/linux/spl/spl-xdr.c
index 6b77524181db..e1773da5d173 100644
--- a/module/os/linux/spl/spl-xdr.c
+++ b/module/os/linux/spl/spl-xdr.c
@@ -25,6 +25,7 @@
#include <sys/debug.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
+#include <rpc/types.h>
#include <rpc/xdr.h>
/*
diff --git a/module/os/linux/spl/spl-zlib.c b/module/os/linux/spl/spl-zlib.c
index 589496da0c78..8c6282ee5d16 100644
--- a/module/os/linux/spl/spl-zlib.c
+++ b/module/os/linux/spl/spl-zlib.c
@@ -204,7 +204,7 @@ spl_zlib_init(void)
size, 0, NULL, NULL, NULL, NULL, NULL,
KMC_KVMEM);
if (!zlib_workspace_cache)
- return (1);
+ return (-ENOMEM);
return (0);
}
diff --git a/module/os/linux/spl/spl-zone.c b/module/os/linux/spl/spl-zone.c
index b8a8b7cd8cd8..d0d0cca154a7 100644
--- a/module/os/linux/spl/spl-zone.c
+++ b/module/os/linux/spl/spl-zone.c
@@ -25,18 +25,20 @@
*/
#include <sys/types.h>
-#include <sys/mutex.h>
#include <sys/sysmacros.h>
#include <sys/kmem.h>
#include <linux/file.h>
#include <linux/magic.h>
#include <sys/zone.h>
+#include <sys/string.h>
#if defined(CONFIG_USER_NS)
#include <linux/statfs.h>
#include <linux/proc_ns.h>
#endif
+#include <sys/mutex.h>
+
static kmutex_t zone_datasets_lock;
static struct list_head zone_datasets;
@@ -49,7 +51,7 @@ typedef struct zone_datasets {
typedef struct zone_dataset {
struct list_head zd_list; /* zone_dataset linkage */
size_t zd_dsnamelen; /* length of name */
- char zd_dsname[0]; /* name of the member dataset */
+ char zd_dsname[]; /* name of the member dataset */
} zone_dataset_t;
#if defined(CONFIG_USER_NS) && defined(HAVE_USER_NS_COMMON_INUM)
@@ -203,8 +205,7 @@ zone_dataset_attach(cred_t *cred, const char *dataset, int userns_fd)
zd = kmem_alloc(sizeof (zone_dataset_t) + dsnamelen + 1, KM_SLEEP);
zd->zd_dsnamelen = dsnamelen;
- strncpy(zd->zd_dsname, dataset, dsnamelen);
- zd->zd_dsname[dsnamelen] = '\0';
+ strlcpy(zd->zd_dsname, dataset, dsnamelen + 1);
INIT_LIST_HEAD(&zd->zd_list);
list_add_tail(&zd->zd_list, &zds->zds_datasets);
@@ -415,8 +416,8 @@ spl_zone_fini(void)
zone_dataset_t, zd_list);
list_del(&zd->zd_list);
kmem_free(zd, sizeof (*zd) + zd->zd_dsnamelen + 1);
- put_user_ns(zds->zds_userns);
}
+ put_user_ns(zds->zds_userns);
list_del(&zds->zds_list);
kmem_free(zds, sizeof (*zds));
}
diff --git a/module/os/linux/zfs/abd_os.c b/module/os/linux/zfs/abd_os.c
index 0cd4fa5213d4..cee7410c8833 100644
--- a/module/os/linux/zfs/abd_os.c
+++ b/module/os/linux/zfs/abd_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2014 by Chunwei Chen. All rights reserved.
* Copyright (c) 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2023, 2024, Klara Inc.
*/
/*
@@ -59,9 +60,19 @@
#include <sys/zfs_znode.h>
#ifdef _KERNEL
#include <linux/kmap_compat.h>
+#include <linux/mm_compat.h>
#include <linux/scatterlist.h>
+#include <linux/version.h>
+#endif
+
+#ifdef _KERNEL
+#if defined(MAX_ORDER)
+#define ABD_MAX_ORDER (MAX_ORDER)
+#elif defined(MAX_PAGE_ORDER)
+#define ABD_MAX_ORDER (MAX_PAGE_ORDER)
+#endif
#else
-#define MAX_ORDER 1
+#define ABD_MAX_ORDER (1)
#endif
typedef struct abd_stats {
@@ -71,7 +82,7 @@ typedef struct abd_stats {
kstat_named_t abdstat_scatter_cnt;
kstat_named_t abdstat_scatter_data_size;
kstat_named_t abdstat_scatter_chunk_waste;
- kstat_named_t abdstat_scatter_orders[MAX_ORDER];
+ kstat_named_t abdstat_scatter_orders[ABD_MAX_ORDER];
kstat_named_t abdstat_scatter_page_multi_chunk;
kstat_named_t abdstat_scatter_page_multi_zone;
kstat_named_t abdstat_scatter_page_alloc_retry;
@@ -132,14 +143,14 @@ static abd_stats_t abd_stats = {
{ "scatter_sg_table_retry", KSTAT_DATA_UINT64 },
};
-struct {
+static struct {
wmsum_t abdstat_struct_size;
wmsum_t abdstat_linear_cnt;
wmsum_t abdstat_linear_data_size;
wmsum_t abdstat_scatter_cnt;
wmsum_t abdstat_scatter_data_size;
wmsum_t abdstat_scatter_chunk_waste;
- wmsum_t abdstat_scatter_orders[MAX_ORDER];
+ wmsum_t abdstat_scatter_orders[ABD_MAX_ORDER];
wmsum_t abdstat_scatter_page_multi_chunk;
wmsum_t abdstat_scatter_page_multi_zone;
wmsum_t abdstat_scatter_page_alloc_retry;
@@ -222,7 +233,7 @@ abd_free_struct_impl(abd_t *abd)
}
#ifdef _KERNEL
-static unsigned zfs_abd_scatter_max_order = MAX_ORDER - 1;
+static unsigned zfs_abd_scatter_max_order = ABD_MAX_ORDER - 1;
/*
* Mark zfs data pages so they can be excluded from kernel crash dumps
@@ -272,18 +283,21 @@ abd_alloc_chunks(abd_t *abd, size_t size)
struct page *page, *tmp_page = NULL;
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
gfp_t gfp_comp = (gfp | __GFP_NORETRY | __GFP_COMP) & ~__GFP_RECLAIM;
- int max_order = MIN(zfs_abd_scatter_max_order, MAX_ORDER - 1);
- int nr_pages = abd_chunkcnt_for_bytes(size);
- int chunks = 0, zones = 0;
+ unsigned int max_order = MIN(zfs_abd_scatter_max_order,
+ ABD_MAX_ORDER - 1);
+ unsigned int nr_pages = abd_chunkcnt_for_bytes(size);
+ unsigned int chunks = 0, zones = 0;
size_t remaining_size;
int nid = NUMA_NO_NODE;
- int alloc_pages = 0;
+ unsigned int alloc_pages = 0;
INIT_LIST_HEAD(&pages);
+ ASSERT3U(alloc_pages, <, nr_pages);
+
while (alloc_pages < nr_pages) {
- unsigned chunk_pages;
- int order;
+ unsigned int chunk_pages;
+ unsigned int order;
order = MIN(highbit64(nr_pages - alloc_pages) - 1, max_order);
chunk_pages = (1U << order);
@@ -597,10 +611,8 @@ abd_free_chunks(abd_t *abd)
struct scatterlist *sg;
abd_for_each_sg(abd, sg, n, i) {
- for (int j = 0; j < sg->length; j += PAGESIZE) {
- struct page *p = nth_page(sg_page(sg), j >> PAGE_SHIFT);
- umem_free(p, PAGESIZE);
- }
+ struct page *p = nth_page(sg_page(sg), 0);
+ umem_free_aligned(p, PAGESIZE);
}
abd_free_sg_table(abd);
}
@@ -706,7 +718,7 @@ abd_free_zero_scatter(void)
__free_page(abd_zero_page);
#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
#else
- umem_free(abd_zero_page, PAGESIZE);
+ umem_free_aligned(abd_zero_page, PAGESIZE);
#endif /* _KERNEL */
}
@@ -729,7 +741,7 @@ abd_kstats_update(kstat_t *ksp, int rw)
wmsum_value(&abd_sums.abdstat_scatter_data_size);
as->abdstat_scatter_chunk_waste.value.ui64 =
wmsum_value(&abd_sums.abdstat_scatter_chunk_waste);
- for (int i = 0; i < MAX_ORDER; i++) {
+ for (int i = 0; i < ABD_MAX_ORDER; i++) {
as->abdstat_scatter_orders[i].value.ui64 =
wmsum_value(&abd_sums.abdstat_scatter_orders[i]);
}
@@ -758,7 +770,7 @@ abd_init(void)
wmsum_init(&abd_sums.abdstat_scatter_cnt, 0);
wmsum_init(&abd_sums.abdstat_scatter_data_size, 0);
wmsum_init(&abd_sums.abdstat_scatter_chunk_waste, 0);
- for (i = 0; i < MAX_ORDER; i++)
+ for (i = 0; i < ABD_MAX_ORDER; i++)
wmsum_init(&abd_sums.abdstat_scatter_orders[i], 0);
wmsum_init(&abd_sums.abdstat_scatter_page_multi_chunk, 0);
wmsum_init(&abd_sums.abdstat_scatter_page_multi_zone, 0);
@@ -768,7 +780,7 @@ abd_init(void)
abd_ksp = kstat_create("zfs", 0, "abdstats", "misc", KSTAT_TYPE_NAMED,
sizeof (abd_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
if (abd_ksp != NULL) {
- for (i = 0; i < MAX_ORDER; i++) {
+ for (i = 0; i < ABD_MAX_ORDER; i++) {
snprintf(abd_stats.abdstat_scatter_orders[i].name,
KSTAT_STRLEN, "scatter_order_%d", i);
abd_stats.abdstat_scatter_orders[i].data_type =
@@ -798,7 +810,7 @@ abd_fini(void)
wmsum_fini(&abd_sums.abdstat_scatter_cnt);
wmsum_fini(&abd_sums.abdstat_scatter_data_size);
wmsum_fini(&abd_sums.abdstat_scatter_chunk_waste);
- for (int i = 0; i < MAX_ORDER; i++)
+ for (int i = 0; i < ABD_MAX_ORDER; i++)
wmsum_fini(&abd_sums.abdstat_scatter_orders[i]);
wmsum_fini(&abd_sums.abdstat_scatter_page_multi_chunk);
wmsum_fini(&abd_sums.abdstat_scatter_page_multi_zone);
@@ -886,14 +898,9 @@ abd_iter_init(struct abd_iter *aiter, abd_t *abd)
{
ASSERT(!abd_is_gang(abd));
abd_verify(abd);
+ memset(aiter, 0, sizeof (struct abd_iter));
aiter->iter_abd = abd;
- aiter->iter_mapaddr = NULL;
- aiter->iter_mapsize = 0;
- aiter->iter_pos = 0;
- if (abd_is_linear(abd)) {
- aiter->iter_offset = 0;
- aiter->iter_sg = NULL;
- } else {
+ if (!abd_is_linear(abd)) {
aiter->iter_offset = ABD_SCATTER(abd).abd_offset;
aiter->iter_sg = ABD_SCATTER(abd).abd_sgl;
}
@@ -906,6 +913,7 @@ abd_iter_init(struct abd_iter *aiter, abd_t *abd)
boolean_t
abd_iter_at_end(struct abd_iter *aiter)
{
+ ASSERT3U(aiter->iter_pos, <=, aiter->iter_abd->abd_size);
return (aiter->iter_pos == aiter->iter_abd->abd_size);
}
@@ -917,8 +925,15 @@ abd_iter_at_end(struct abd_iter *aiter)
void
abd_iter_advance(struct abd_iter *aiter, size_t amount)
{
+ /*
+ * Ensure that last chunk is not in use. abd_iterate_*() must clear
+ * this state (directly or abd_iter_unmap()) before advancing.
+ */
ASSERT3P(aiter->iter_mapaddr, ==, NULL);
ASSERT0(aiter->iter_mapsize);
+ ASSERT3P(aiter->iter_page, ==, NULL);
+ ASSERT0(aiter->iter_page_doff);
+ ASSERT0(aiter->iter_page_dsize);
/* There's nothing left to advance to, so do nothing */
if (abd_iter_at_end(aiter))
@@ -1000,6 +1015,134 @@ abd_cache_reap_now(void)
}
#if defined(_KERNEL)
+
+/*
+ * This is abd_iter_page(), the function underneath abd_iterate_page_func().
+ * It yields the next page struct and data offset and size within it, without
+ * mapping it into the address space.
+ */
+
+/*
+ * "Compound pages" are a group of pages that can be referenced from a single
+ * struct page *. Its organised as a "head" page, followed by a series of
+ * "tail" pages.
+ *
+ * In OpenZFS, compound pages are allocated using the __GFP_COMP flag, which we
+ * get from scatter ABDs and SPL vmalloc slabs (ie >16K allocations). So a
+ * great many of the IO buffers we get are going to be of this type.
+ *
+ * The tail pages are just regular PAGESIZE pages, and can be safely used
+ * as-is. However, the head page has length covering itself and all the tail
+ * pages. If the ABD chunk spans multiple pages, then we can use the head page
+ * and a >PAGESIZE length, which is far more efficient.
+ *
+ * Before kernel 4.5 however, compound page heads were refcounted separately
+ * from tail pages, such that moving back to the head page would require us to
+ * take a reference to it and releasing it once we're completely finished with
+ * it. In practice, that means when our caller is done with the ABD, which we
+ * have no insight into from here. Rather than contort this API to track head
+ * page references on such ancient kernels, we disable this special compound
+ * page handling on 4.5, instead just using treating each page within it as a
+ * regular PAGESIZE page (which it is). This is slightly less efficient, but
+ * makes everything far simpler.
+ *
+ * The below test sets/clears ABD_ITER_COMPOUND_PAGES to enable/disable the
+ * special handling, and also defines the ABD_ITER_PAGE_SIZE(page) macro to
+ * understand compound pages, or not, as required.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+#define ABD_ITER_COMPOUND_PAGES 1
+#define ABD_ITER_PAGE_SIZE(page) \
+ (PageCompound(page) ? page_size(page) : PAGESIZE)
+#else
+#undef ABD_ITER_COMPOUND_PAGES
+#define ABD_ITER_PAGE_SIZE(page) (PAGESIZE)
+#endif
+
+void
+abd_iter_page(struct abd_iter *aiter)
+{
+ if (abd_iter_at_end(aiter)) {
+ aiter->iter_page = NULL;
+ aiter->iter_page_doff = 0;
+ aiter->iter_page_dsize = 0;
+ return;
+ }
+
+ struct page *page;
+ size_t doff, dsize;
+
+ /*
+ * Find the page, and the start of the data within it. This is computed
+ * differently for linear and scatter ABDs; linear is referenced by
+ * virtual memory location, while scatter is referenced by page
+ * pointer.
+ */
+ if (abd_is_linear(aiter->iter_abd)) {
+ ASSERT3U(aiter->iter_pos, ==, aiter->iter_offset);
+
+ /* memory address at iter_pos */
+ void *paddr = ABD_LINEAR_BUF(aiter->iter_abd) + aiter->iter_pos;
+
+ /* struct page for address */
+ page = is_vmalloc_addr(paddr) ?
+ vmalloc_to_page(paddr) : virt_to_page(paddr);
+
+ /* offset of address within the page */
+ doff = offset_in_page(paddr);
+ } else {
+ ASSERT(!abd_is_gang(aiter->iter_abd));
+
+ /* current scatter page */
+ page = nth_page(sg_page(aiter->iter_sg),
+ aiter->iter_offset >> PAGE_SHIFT);
+
+ /* position within page */
+ doff = aiter->iter_offset & (PAGESIZE - 1);
+ }
+
+#ifdef ABD_ITER_COMPOUND_PAGES
+ if (PageTail(page)) {
+ /*
+ * If this is a compound tail page, move back to the head, and
+ * adjust the offset to match. This may let us yield a much
+ * larger amount of data from a single logical page, and so
+ * leave our caller with fewer pages to process.
+ */
+ struct page *head = compound_head(page);
+ doff += ((page - head) * PAGESIZE);
+ page = head;
+ }
+#endif
+
+ ASSERT(page);
+
+ /*
+ * Compute the maximum amount of data we can take from this page. This
+ * is the smaller of:
+ * - the remaining space in the page
+ * - the remaining space in this scatterlist entry (which may not cover
+ * the entire page)
+ * - the remaining space in the abd (which may not cover the entire
+ * scatterlist entry)
+ */
+ dsize = MIN(ABD_ITER_PAGE_SIZE(page) - doff,
+ aiter->iter_abd->abd_size - aiter->iter_pos);
+ if (!abd_is_linear(aiter->iter_abd))
+ dsize = MIN(dsize, aiter->iter_sg->length - aiter->iter_offset);
+ ASSERT3U(dsize, >, 0);
+
+ /* final iterator outputs */
+ aiter->iter_page = page;
+ aiter->iter_page_doff = doff;
+ aiter->iter_page_dsize = dsize;
+}
+
+/*
+ * Note: ABD BIO functions only needed to support vdev_classic. See comments in
+ * vdev_disk.c.
+ */
+
/*
* bio_nr_pages for ABD.
* @off is the offset in @abd
@@ -1154,4 +1297,5 @@ MODULE_PARM_DESC(zfs_abd_scatter_min_size,
module_param(zfs_abd_scatter_max_order, uint, 0644);
MODULE_PARM_DESC(zfs_abd_scatter_max_order,
"Maximum order allocation used for a scatter ABD.");
-#endif
+
+#endif /* _KERNEL */
diff --git a/module/os/linux/zfs/arc_os.c b/module/os/linux/zfs/arc_os.c
index a95e9c334af9..02dd80c06062 100644
--- a/module/os/linux/zfs/arc_os.c
+++ b/module/os/linux/zfs/arc_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -80,12 +80,18 @@ static struct notifier_block arc_hotplug_callback_mem_nb;
/*
* Return a default max arc size based on the amount of physical memory.
+ * This may be overridden by tuning the zfs_arc_max module parameter.
*/
uint64_t
arc_default_max(uint64_t min, uint64_t allmem)
{
- /* Default to 1/2 of all memory. */
- return (MAX(allmem / 2, min));
+ uint64_t size;
+
+ if (allmem >= 1 << 30)
+ size = allmem - (1 << 30);
+ else
+ size = min;
+ return (MAX(allmem * 5 / 8, size));
}
#ifdef _KERNEL
@@ -219,7 +225,11 @@ arc_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
arc_reduce_target_size(ptob(sc->nr_to_scan));
arc_wait_for_eviction(ptob(sc->nr_to_scan), B_FALSE);
if (current->reclaim_state != NULL)
+#ifdef HAVE_RECLAIM_STATE_RECLAIMED
+ current->reclaim_state->reclaimed += sc->nr_to_scan;
+#else
current->reclaim_state->reclaimed_slab += sc->nr_to_scan;
+#endif
/*
* We are experiencing memory pressure which the arc_evict_zthr was
@@ -243,8 +253,7 @@ arc_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
return (sc->nr_to_scan);
}
-SPL_SHRINKER_DECLARE(arc_shrinker,
- arc_shrinker_count, arc_shrinker_scan, DEFAULT_SEEKS);
+static struct shrinker *arc_shrinker = NULL;
int
arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg)
@@ -347,22 +356,26 @@ arc_lowmem_init(void)
* reclaim from the arc. This is done to prevent kswapd from
* swapping out pages when it is preferable to shrink the arc.
*/
- spl_register_shrinker(&arc_shrinker);
+ arc_shrinker = spl_register_shrinker("zfs-arc-shrinker",
+ arc_shrinker_count, arc_shrinker_scan, DEFAULT_SEEKS);
+ VERIFY(arc_shrinker);
+
arc_set_sys_free(allmem);
}
void
arc_lowmem_fini(void)
{
- spl_unregister_shrinker(&arc_shrinker);
+ spl_unregister_shrinker(arc_shrinker);
+ arc_shrinker = NULL;
}
int
-param_set_arc_long(const char *buf, zfs_kernel_param_t *kp)
+param_set_arc_u64(const char *buf, zfs_kernel_param_t *kp)
{
int error;
- error = param_set_long(buf, kp);
+ error = spl_param_set_u64(buf, kp);
if (error < 0)
return (SET_ERROR(error));
@@ -374,13 +387,13 @@ param_set_arc_long(const char *buf, zfs_kernel_param_t *kp)
int
param_set_arc_min(const char *buf, zfs_kernel_param_t *kp)
{
- return (param_set_arc_long(buf, kp));
+ return (param_set_arc_u64(buf, kp));
}
int
param_set_arc_max(const char *buf, zfs_kernel_param_t *kp)
{
- return (param_set_arc_long(buf, kp));
+ return (param_set_arc_u64(buf, kp));
}
int
@@ -485,56 +498,5 @@ arc_unregister_hotplug(void)
}
#endif /* _KERNEL */
-/*
- * Helper function for arc_prune_async() it is responsible for safely
- * handling the execution of a registered arc_prune_func_t.
- */
-static void
-arc_prune_task(void *ptr)
-{
- arc_prune_t *ap = (arc_prune_t *)ptr;
- arc_prune_func_t *func = ap->p_pfunc;
-
- if (func != NULL)
- func(ap->p_adjust, ap->p_private);
-
- zfs_refcount_remove(&ap->p_refcnt, func);
-}
-
-/*
- * Notify registered consumers they must drop holds on a portion of the ARC
- * buffered they reference. This provides a mechanism to ensure the ARC can
- * honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This
- * is analogous to dnlc_reduce_cache() but more generic.
- *
- * This operation is performed asynchronously so it may be safely called
- * in the context of the arc_reclaim_thread(). A reference is taken here
- * for each registered arc_prune_t and the arc_prune_task() is responsible
- * for releasing it once the registered arc_prune_func_t has completed.
- */
-void
-arc_prune_async(int64_t adjust)
-{
- arc_prune_t *ap;
-
- mutex_enter(&arc_prune_mtx);
- for (ap = list_head(&arc_prune_list); ap != NULL;
- ap = list_next(&arc_prune_list, ap)) {
-
- if (zfs_refcount_count(&ap->p_refcnt) >= 2)
- continue;
-
- zfs_refcount_add(&ap->p_refcnt, ap->p_pfunc);
- ap->p_adjust = adjust;
- if (taskq_dispatch(arc_prune_taskq, arc_prune_task,
- ap, TQ_SLEEP) == TASKQID_INVALID) {
- zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
- continue;
- }
- ARCSTAT_BUMP(arcstat_prune);
- }
- mutex_exit(&arc_prune_mtx);
-}
-
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, shrinker_limit, INT, ZMOD_RW,
"Limit on number of pages that ARC shrinker can reclaim at once");
diff --git a/module/os/linux/zfs/mmp_os.c b/module/os/linux/zfs/mmp_os.c
index ff3ef1bf6ad9..7e5bd392437e 100644
--- a/module/os/linux/zfs/mmp_os.c
+++ b/module/os/linux/zfs/mmp_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -30,7 +30,7 @@ param_set_multihost_interval(const char *val, zfs_kernel_param_t *kp)
{
int ret;
- ret = param_set_ulong(val, kp);
+ ret = spl_param_set_u64(val, kp);
if (ret < 0)
return (ret);
diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c
index ab00d2ae14d2..5d1b4383412a 100644
--- a/module/os/linux/zfs/policy.c
+++ b/module/os/linux/zfs/policy.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -124,7 +124,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
if (crgetuid(cr) == owner)
return (0);
- if (zpl_inode_owner_or_capable(kcred->user_ns, ip))
+ if (zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (0);
#if defined(CONFIG_USER_NS)
@@ -214,8 +214,10 @@ secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr,
* Determine that subject can set the file setgid flag.
*/
int
-secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid)
+secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zidmap_t *mnt_ns,
+ struct user_namespace *fs_ns)
{
+ gid = zfs_gid_to_vfsgid(mnt_ns, fs_ns, gid);
#if defined(CONFIG_USER_NS)
if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid)))
return (EPERM);
@@ -284,8 +286,11 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr)
* Determine that subject can set the file setid flags.
*/
static int
-secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner)
+secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zidmap_t *mnt_ns,
+ struct user_namespace *fs_ns)
{
+ owner = zfs_uid_to_vfsuid(mnt_ns, fs_ns, owner);
+
if (crgetuid(cr) == owner)
return (0);
@@ -310,13 +315,14 @@ secpolicy_vnode_stky_modify(const cred_t *cr)
int
secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap,
- const vattr_t *ovap, cred_t *cr)
+ const vattr_t *ovap, cred_t *cr, zidmap_t *mnt_ns,
+ struct user_namespace *fs_ns)
{
int error;
if ((vap->va_mode & S_ISUID) != 0 &&
(error = secpolicy_vnode_setid_modify(cr,
- ovap->va_uid)) != 0) {
+ ovap->va_uid, mnt_ns, fs_ns)) != 0) {
return (error);
}
@@ -334,7 +340,8 @@ secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap,
* group-id bit.
*/
if ((vap->va_mode & S_ISGID) != 0 &&
- secpolicy_vnode_setids_setgids(cr, ovap->va_gid) != 0) {
+ secpolicy_vnode_setids_setgids(cr, ovap->va_gid,
+ mnt_ns, fs_ns) != 0) {
vap->va_mode &= ~S_ISGID;
}
diff --git a/module/os/linux/zfs/qat.c b/module/os/linux/zfs/qat.c
index 08613b3a2042..07e0cafabb0e 100644
--- a/module/os/linux/zfs/qat.c
+++ b/module/os/linux/zfs/qat.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/linux/zfs/qat_compress.c b/module/os/linux/zfs/qat_compress.c
index 1d099c95bc7c..6d0595dd5f76 100644
--- a/module/os/linux/zfs/qat_compress.c
+++ b/module/os/linux/zfs/qat_compress.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -193,7 +193,9 @@ qat_dc_init(void)
sd.huffType = CPA_DC_HT_FULL_DYNAMIC;
sd.sessDirection = CPA_DC_DIR_COMBINED;
sd.sessState = CPA_DC_STATELESS;
+#if (CPA_DC_API_VERSION_NUM_MAJOR == 1 && CPA_DC_API_VERSION_NUM_MINOR < 6)
sd.deflateWindowSize = 7;
+#endif
sd.checksum = CPA_DC_ADLER32;
status = cpaDcGetSessionSize(dc_inst_handles[i],
&sd, &sess_size, &ctx_size);
@@ -247,7 +249,7 @@ qat_compress_impl(qat_compress_dir_t dir, char *src, int src_len,
Cpa8U *buffer_meta_src = NULL;
Cpa8U *buffer_meta_dst = NULL;
Cpa32U buffer_meta_size = 0;
- CpaDcRqResults dc_results;
+ CpaDcRqResults dc_results = {.checksum = 1};
CpaStatus status = CPA_STATUS_FAIL;
Cpa32U hdr_sz = 0;
Cpa32U compressed_sz;
diff --git a/module/os/linux/zfs/qat_crypt.c b/module/os/linux/zfs/qat_crypt.c
index 18b6e38d1a6e..0523a23c61e1 100644
--- a/module/os/linux/zfs/qat_crypt.c
+++ b/module/os/linux/zfs/qat_crypt.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/linux/zfs/spa_misc_os.c b/module/os/linux/zfs/spa_misc_os.c
index cbdc0f350ad8..c8cbedcd5157 100644
--- a/module/os/linux/zfs/spa_misc_os.c
+++ b/module/os/linux/zfs/spa_misc_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -60,7 +60,7 @@ param_set_deadman_ziotime(const char *val, zfs_kernel_param_t *kp)
{
int error;
- error = param_set_ulong(val, kp);
+ error = spl_param_set_u64(val, kp);
if (error < 0)
return (SET_ERROR(error));
@@ -74,7 +74,7 @@ param_set_deadman_synctime(const char *val, zfs_kernel_param_t *kp)
{
int error;
- error = param_set_ulong(val, kp);
+ error = spl_param_set_u64(val, kp);
if (error < 0)
return (SET_ERROR(error));
@@ -103,6 +103,18 @@ param_set_slop_shift(const char *buf, zfs_kernel_param_t *kp)
return (0);
}
+int
+param_set_active_allocator(const char *val, zfs_kernel_param_t *kp)
+{
+ int error;
+
+ error = -param_set_active_allocator_common(val);
+ if (error == 0)
+ error = param_set_charp(val, kp);
+
+ return (error);
+}
+
const char *
spa_history_zone(void)
{
diff --git a/module/os/linux/zfs/trace.c b/module/os/linux/zfs/trace.c
index a690822ae14c..32a188d169e3 100644
--- a/module/os/linux/zfs/trace.c
+++ b/module/os/linux/zfs/trace.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c
index 9a382261df73..463c5f705102 100644
--- a/module/os/linux/zfs/vdev_disk.c
+++ b/module/os/linux/zfs/vdev_disk.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,6 +24,7 @@
* Rewritten for Linux by Brian Behlendorf <behlendorf1@llnl.gov>.
* LLNL-CODE-403049.
* Copyright (c) 2012, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2023, 2024, Klara Inc.
*/
#include <sys/zfs_context.h>
@@ -41,12 +42,49 @@
#include <linux/blk-cgroup.h>
#endif
+/*
+ * Linux 6.8.x uses a bdev_handle as an instance/refcount for an underlying
+ * block_device. Since it carries the block_device inside, its convenient to
+ * just use the handle as a proxy.
+ *
+ * Linux 6.9.x uses a file for the same purpose.
+ *
+ * For pre-6.8, we just emulate this with a cast, since we don't need any of
+ * the other fields inside the handle.
+ */
+#if defined(HAVE_BDEV_OPEN_BY_PATH)
+typedef struct bdev_handle zfs_bdev_handle_t;
+#define BDH_BDEV(bdh) ((bdh)->bdev)
+#define BDH_IS_ERR(bdh) (IS_ERR(bdh))
+#define BDH_PTR_ERR(bdh) (PTR_ERR(bdh))
+#define BDH_ERR_PTR(err) (ERR_PTR(err))
+#elif defined(HAVE_BDEV_FILE_OPEN_BY_PATH)
+typedef struct file zfs_bdev_handle_t;
+#define BDH_BDEV(bdh) (file_bdev(bdh))
+#define BDH_IS_ERR(bdh) (IS_ERR(bdh))
+#define BDH_PTR_ERR(bdh) (PTR_ERR(bdh))
+#define BDH_ERR_PTR(err) (ERR_PTR(err))
+#else
+typedef void zfs_bdev_handle_t;
+#define BDH_BDEV(bdh) ((struct block_device *)bdh)
+#define BDH_IS_ERR(bdh) (IS_ERR(BDH_BDEV(bdh)))
+#define BDH_PTR_ERR(bdh) (PTR_ERR(BDH_BDEV(bdh)))
+#define BDH_ERR_PTR(err) (ERR_PTR(err))
+#endif
+
typedef struct vdev_disk {
- struct block_device *vd_bdev;
+ zfs_bdev_handle_t *vd_bdh;
krwlock_t vd_lock;
} vdev_disk_t;
/*
+ * Maximum number of segments to add to a bio (min 4). If this is higher than
+ * the maximum allowed by the device queue or the kernel itself, it will be
+ * clamped. Setting it to zero will cause the kernel's ideal size to be used.
+ */
+uint_t zfs_vdev_disk_max_segs = 0;
+
+/*
* Unique identifier for the exclusive vdev holder.
*/
static void *zfs_vdev_holder = VDEV_HOLDER;
@@ -56,7 +94,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.
@@ -64,28 +102,46 @@ static unsigned zfs_vdev_open_timeout_ms = 1000;
#define EFI_MIN_RESV_SIZE (16 * 1024)
/*
- * Virtual device vector for disks.
+ * BIO request failfast mask.
*/
-typedef struct dio_request {
- zio_t *dr_zio; /* Parent ZIO */
- atomic_t dr_ref; /* References */
- int dr_error; /* Bio error */
- int dr_bio_count; /* Count of bio's */
- struct bio *dr_bio[0]; /* Attached bio's */
-} dio_request_t;
-static fmode_t
-vdev_bdev_mode(spa_mode_t spa_mode)
+static unsigned int zfs_vdev_failfast_mask = 1;
+
+/*
+ * Convert SPA mode flags into bdev open mode flags.
+ */
+#ifdef HAVE_BLK_MODE_T
+typedef blk_mode_t vdev_bdev_mode_t;
+#define VDEV_BDEV_MODE_READ BLK_OPEN_READ
+#define VDEV_BDEV_MODE_WRITE BLK_OPEN_WRITE
+#define VDEV_BDEV_MODE_EXCL BLK_OPEN_EXCL
+#define VDEV_BDEV_MODE_MASK (BLK_OPEN_READ|BLK_OPEN_WRITE|BLK_OPEN_EXCL)
+#else
+typedef fmode_t vdev_bdev_mode_t;
+#define VDEV_BDEV_MODE_READ FMODE_READ
+#define VDEV_BDEV_MODE_WRITE FMODE_WRITE
+#define VDEV_BDEV_MODE_EXCL FMODE_EXCL
+#define VDEV_BDEV_MODE_MASK (FMODE_READ|FMODE_WRITE|FMODE_EXCL)
+#endif
+
+static vdev_bdev_mode_t
+vdev_bdev_mode(spa_mode_t smode)
{
- fmode_t mode = 0;
+ ASSERT3U(smode, !=, SPA_MODE_UNINIT);
+ ASSERT0(smode & ~(SPA_MODE_READ|SPA_MODE_WRITE));
- if (spa_mode & SPA_MODE_READ)
- mode |= FMODE_READ;
+ vdev_bdev_mode_t bmode = VDEV_BDEV_MODE_EXCL;
- if (spa_mode & SPA_MODE_WRITE)
- mode |= FMODE_WRITE;
+ if (smode & SPA_MODE_READ)
+ bmode |= VDEV_BDEV_MODE_READ;
- return (mode);
+ if (smode & SPA_MODE_WRITE)
+ bmode |= VDEV_BDEV_MODE_WRITE;
+
+ ASSERT(bmode & VDEV_BDEV_MODE_MASK);
+ ASSERT0(bmode & ~VDEV_BDEV_MODE_MASK);
+
+ return (bmode);
}
/*
@@ -105,6 +161,16 @@ bdev_whole(struct block_device *bdev)
}
#endif
+#if defined(HAVE_BDEVNAME)
+#define vdev_bdevname(bdev, name) bdevname(bdev, name)
+#else
+static inline void
+vdev_bdevname(struct block_device *bdev, char *name)
+{
+ snprintf(name, BDEVNAME_SIZE, "%pg", bdev);
+}
+#endif
+
/*
* Returns the maximum expansion capacity of the block device (in bytes).
*
@@ -163,18 +229,60 @@ vdev_disk_error(zio_t *zio)
* which is safe from any context.
*/
printk(KERN_WARNING "zio pool=%s vdev=%s error=%d type=%d "
- "offset=%llu size=%llu flags=%x\n", spa_name(zio->io_spa),
+ "offset=%llu size=%llu flags=%llu\n", spa_name(zio->io_spa),
zio->io_vd->vdev_path, zio->io_error, zio->io_type,
(u_longlong_t)zio->io_offset, (u_longlong_t)zio->io_size,
zio->io_flags);
}
+static void
+vdev_disk_kobj_evt_post(vdev_t *v)
+{
+ vdev_disk_t *vd = v->vdev_tsd;
+ if (vd && vd->vd_bdh) {
+ spl_signal_kobj_evt(BDH_BDEV(vd->vd_bdh));
+ } else {
+ vdev_dbgmsg(v, "vdev_disk_t is NULL for VDEV:%s\n",
+ v->vdev_path);
+ }
+}
+
+static zfs_bdev_handle_t *
+vdev_blkdev_get_by_path(const char *path, spa_mode_t smode, void *holder)
+{
+ vdev_bdev_mode_t bmode = vdev_bdev_mode(smode);
+
+#if defined(HAVE_BDEV_FILE_OPEN_BY_PATH)
+ return (bdev_file_open_by_path(path, bmode, holder, NULL));
+#elif defined(HAVE_BDEV_OPEN_BY_PATH)
+ return (bdev_open_by_path(path, bmode, holder, NULL));
+#elif defined(HAVE_BLKDEV_GET_BY_PATH_4ARG)
+ return (blkdev_get_by_path(path, bmode, holder, NULL));
+#else
+ return (blkdev_get_by_path(path, bmode, holder));
+#endif
+}
+
+static void
+vdev_blkdev_put(zfs_bdev_handle_t *bdh, spa_mode_t smode, void *holder)
+{
+#if defined(HAVE_BDEV_RELEASE)
+ return (bdev_release(bdh));
+#elif defined(HAVE_BLKDEV_PUT_HOLDER)
+ return (blkdev_put(BDH_BDEV(bdh), holder));
+#elif defined(HAVE_BLKDEV_PUT)
+ return (blkdev_put(BDH_BDEV(bdh), vdev_bdev_mode(smode)));
+#else
+ fput(bdh);
+#endif
+}
+
static int
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
uint64_t *logical_ashift, uint64_t *physical_ashift)
{
- struct block_device *bdev;
- fmode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
+ zfs_bdev_handle_t *bdh;
+ spa_mode_t smode = spa_mode(v->vdev_spa);
hrtime_t timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms);
vdev_disk_t *vd;
@@ -199,12 +307,13 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
boolean_t reread_part = B_FALSE;
rw_enter(&vd->vd_lock, RW_WRITER);
- bdev = vd->vd_bdev;
- vd->vd_bdev = NULL;
+ bdh = vd->vd_bdh;
+ vd->vd_bdh = NULL;
- if (bdev) {
+ if (bdh) {
+ struct block_device *bdev = BDH_BDEV(bdh);
if (v->vdev_expanding && bdev != bdev_whole(bdev)) {
- bdevname(bdev_whole(bdev), disk_name + 5);
+ vdev_bdevname(bdev_whole(bdev), disk_name + 5);
/*
* If userland has BLKPG_RESIZE_PARTITION,
* then it should have updated the partition
@@ -224,15 +333,16 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
reread_part = B_TRUE;
}
- blkdev_put(bdev, mode | FMODE_EXCL);
+ vdev_blkdev_put(bdh, smode, zfs_vdev_holder);
}
if (reread_part) {
- bdev = blkdev_get_by_path(disk_name, mode | FMODE_EXCL,
+ bdh = vdev_blkdev_get_by_path(disk_name, smode,
zfs_vdev_holder);
- if (!IS_ERR(bdev)) {
- int error = vdev_bdev_reread_part(bdev);
- blkdev_put(bdev, mode | FMODE_EXCL);
+ if (!BDH_IS_ERR(bdh)) {
+ int error =
+ vdev_bdev_reread_part(BDH_BDEV(bdh));
+ vdev_blkdev_put(bdh, smode, zfs_vdev_holder);
if (error == 0) {
timeout = MSEC2NSEC(
zfs_vdev_open_timeout_ms * 2);
@@ -275,58 +385,70 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
* subsequent attempts are expected to eventually succeed.
*/
hrtime_t start = gethrtime();
- bdev = ERR_PTR(-ENXIO);
- while (IS_ERR(bdev) && ((gethrtime() - start) < timeout)) {
- bdev = blkdev_get_by_path(v->vdev_path, mode | FMODE_EXCL,
+ bdh = BDH_ERR_PTR(-ENXIO);
+ while (BDH_IS_ERR(bdh) && ((gethrtime() - start) < timeout)) {
+ bdh = vdev_blkdev_get_by_path(v->vdev_path, smode,
zfs_vdev_holder);
- if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
+ if (unlikely(BDH_PTR_ERR(bdh) == -ENOENT)) {
+ /*
+ * There is no point of waiting since device is removed
+ * explicitly
+ */
+ if (v->vdev_removed)
+ break;
+
schedule_timeout(MSEC_TO_TICK(10));
- } else if (unlikely(PTR_ERR(bdev) == -ERESTARTSYS)) {
+ } else if (unlikely(BDH_PTR_ERR(bdh) == -ERESTARTSYS)) {
timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms * 10);
continue;
- } else if (IS_ERR(bdev)) {
+ } else if (BDH_IS_ERR(bdh)) {
break;
}
}
- if (IS_ERR(bdev)) {
- int error = -PTR_ERR(bdev);
+ if (BDH_IS_ERR(bdh)) {
+ int error = -BDH_PTR_ERR(bdh);
vdev_dbgmsg(v, "open error=%d timeout=%llu/%llu", error,
(u_longlong_t)(gethrtime() - start),
(u_longlong_t)timeout);
- vd->vd_bdev = NULL;
+ vd->vd_bdh = NULL;
v->vdev_tsd = vd;
rw_exit(&vd->vd_lock);
return (SET_ERROR(error));
} else {
- vd->vd_bdev = bdev;
+ vd->vd_bdh = bdh;
v->vdev_tsd = vd;
rw_exit(&vd->vd_lock);
}
+ struct block_device *bdev = BDH_BDEV(vd->vd_bdh);
+
/* Determine the physical block size */
- int physical_block_size = bdev_physical_block_size(vd->vd_bdev);
+ int physical_block_size = bdev_physical_block_size(bdev);
/* Determine the logical block size */
- int logical_block_size = bdev_logical_block_size(vd->vd_bdev);
+ int logical_block_size = bdev_logical_block_size(bdev);
- /* Clear the nowritecache bit, causes vdev_reopen() to try again. */
- v->vdev_nowritecache = B_FALSE;
+ /*
+ * If the device has a write cache, clear the nowritecache flag,
+ * so that we start issuing flush requests again.
+ */
+ v->vdev_nowritecache = !zfs_bdev_has_write_cache(bdev);
/* Set when device reports it supports TRIM. */
- v->vdev_has_trim = bdev_discard_supported(vd->vd_bdev);
+ v->vdev_has_trim = bdev_discard_supported(bdev);
/* Set when device reports it supports secure TRIM. */
- v->vdev_has_securetrim = bdev_secure_discard_supported(vd->vd_bdev);
+ v->vdev_has_securetrim = bdev_secure_discard_supported(bdev);
/* Inform the ZIO pipeline that we are non-rotational */
- v->vdev_nonrot = blk_queue_nonrot(bdev_get_queue(vd->vd_bdev));
+ v->vdev_nonrot = blk_queue_nonrot(bdev_get_queue(bdev));
/* Physical volume size in bytes for the partition */
- *psize = bdev_capacity(vd->vd_bdev);
+ *psize = bdev_capacity(bdev);
/* Physical volume size in bytes including possible expansion space */
- *max_psize = bdev_max_capacity(vd->vd_bdev, v->vdev_wholedisk);
+ *max_psize = bdev_max_capacity(bdev, v->vdev_wholedisk);
/* Based on the minimum sector size set the block size */
*physical_ashift = highbit64(MAX(physical_block_size,
@@ -346,98 +468,15 @@ vdev_disk_close(vdev_t *v)
if (v->vdev_reopening || vd == NULL)
return;
- if (vd->vd_bdev != NULL) {
- blkdev_put(vd->vd_bdev,
- vdev_bdev_mode(spa_mode(v->vdev_spa)) | FMODE_EXCL);
- }
+ if (vd->vd_bdh != NULL)
+ vdev_blkdev_put(vd->vd_bdh, spa_mode(v->vdev_spa),
+ zfs_vdev_holder);
rw_destroy(&vd->vd_lock);
kmem_free(vd, sizeof (vdev_disk_t));
v->vdev_tsd = NULL;
}
-static dio_request_t *
-vdev_disk_dio_alloc(int bio_count)
-{
- dio_request_t *dr = kmem_zalloc(sizeof (dio_request_t) +
- sizeof (struct bio *) * bio_count, KM_SLEEP);
- atomic_set(&dr->dr_ref, 0);
- dr->dr_bio_count = bio_count;
- dr->dr_error = 0;
-
- for (int i = 0; i < dr->dr_bio_count; i++)
- dr->dr_bio[i] = NULL;
-
- return (dr);
-}
-
-static void
-vdev_disk_dio_free(dio_request_t *dr)
-{
- int i;
-
- for (i = 0; i < dr->dr_bio_count; i++)
- if (dr->dr_bio[i])
- bio_put(dr->dr_bio[i]);
-
- kmem_free(dr, sizeof (dio_request_t) +
- sizeof (struct bio *) * dr->dr_bio_count);
-}
-
-static void
-vdev_disk_dio_get(dio_request_t *dr)
-{
- atomic_inc(&dr->dr_ref);
-}
-
-static int
-vdev_disk_dio_put(dio_request_t *dr)
-{
- int rc = atomic_dec_return(&dr->dr_ref);
-
- /*
- * Free the dio_request when the last reference is dropped and
- * ensure zio_interpret is called only once with the correct zio
- */
- if (rc == 0) {
- zio_t *zio = dr->dr_zio;
- int error = dr->dr_error;
-
- vdev_disk_dio_free(dr);
-
- if (zio) {
- zio->io_error = error;
- ASSERT3S(zio->io_error, >=, 0);
- if (zio->io_error)
- vdev_disk_error(zio);
-
- zio_delay_interrupt(zio);
- }
- }
-
- return (rc);
-}
-
-BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, error)
-{
- dio_request_t *dr = bio->bi_private;
- int rc;
-
- if (dr->dr_error == 0) {
-#ifdef HAVE_1ARG_BIO_END_IO_T
- dr->dr_error = BIO_END_IO_ERROR(bio);
-#else
- if (error)
- dr->dr_error = -(error);
- else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
- dr->dr_error = EIO;
-#endif
- }
-
- /* Drop reference acquired by __vdev_disk_physio */
- rc = vdev_disk_dio_put(dr);
-}
-
static inline void
vdev_submit_bio_impl(struct bio *bio)
{
@@ -589,8 +628,467 @@ vdev_bio_alloc(struct block_device *bdev, gfp_t gfp_mask,
return (bio);
}
+static inline uint_t
+vdev_bio_max_segs(struct block_device *bdev)
+{
+ /*
+ * Smallest of the device max segs and the tuneable max segs. Minimum
+ * 4, so there's room to finish split pages if they come up.
+ */
+ const uint_t dev_max_segs = queue_max_segments(bdev_get_queue(bdev));
+ const uint_t tune_max_segs = (zfs_vdev_disk_max_segs > 0) ?
+ MAX(4, zfs_vdev_disk_max_segs) : dev_max_segs;
+ const uint_t max_segs = MIN(tune_max_segs, dev_max_segs);
+
+#ifdef HAVE_BIO_MAX_SEGS
+ return (bio_max_segs(max_segs));
+#else
+ return (MIN(max_segs, BIO_MAX_PAGES));
+#endif
+}
+
+static inline uint_t
+vdev_bio_max_bytes(struct block_device *bdev)
+{
+ return (queue_max_sectors(bdev_get_queue(bdev)) << 9);
+}
+
+
+/*
+ * Virtual block IO object (VBIO)
+ *
+ * Linux block IO (BIO) objects have a limit on how many data segments (pages)
+ * they can hold. Depending on how they're allocated and structured, a large
+ * ZIO can require more than one BIO to be submitted to the kernel, which then
+ * all have to complete before we can return the completed ZIO back to ZFS.
+ *
+ * A VBIO is a wrapper around multiple BIOs, carrying everything needed to
+ * translate a ZIO down into the kernel block layer and back again.
+ *
+ * Note that these are only used for data ZIOs (read/write). Meta-operations
+ * (flush/trim) don't need multiple BIOs and so can just make the call
+ * directly.
+ */
+typedef struct {
+ zio_t *vbio_zio; /* parent zio */
+
+ struct block_device *vbio_bdev; /* blockdev to submit bios to */
+
+ abd_t *vbio_abd; /* abd carrying borrowed linear buf */
+
+ uint_t vbio_max_segs; /* max segs per bio */
+
+ uint_t vbio_max_bytes; /* max bytes per bio */
+ uint_t vbio_lbs_mask; /* logical block size mask */
+
+ uint64_t vbio_offset; /* start offset of next bio */
+
+ struct bio *vbio_bio; /* pointer to the current bio */
+ int vbio_flags; /* bio flags */
+} vbio_t;
+
+static vbio_t *
+vbio_alloc(zio_t *zio, struct block_device *bdev, int flags)
+{
+ vbio_t *vbio = kmem_zalloc(sizeof (vbio_t), KM_SLEEP);
+
+ vbio->vbio_zio = zio;
+ vbio->vbio_bdev = bdev;
+ vbio->vbio_abd = NULL;
+ vbio->vbio_max_segs = vdev_bio_max_segs(bdev);
+ vbio->vbio_max_bytes = vdev_bio_max_bytes(bdev);
+ vbio->vbio_lbs_mask = ~(bdev_logical_block_size(bdev)-1);
+ vbio->vbio_offset = zio->io_offset;
+ vbio->vbio_bio = NULL;
+ vbio->vbio_flags = flags;
+
+ return (vbio);
+}
+
+BIO_END_IO_PROTO(vbio_completion, bio, error);
+
+static int
+vbio_add_page(vbio_t *vbio, struct page *page, uint_t size, uint_t offset)
+{
+ struct bio *bio = vbio->vbio_bio;
+ uint_t ssize;
+
+ while (size > 0) {
+ if (bio == NULL) {
+ /* New BIO, allocate and set up */
+ bio = vdev_bio_alloc(vbio->vbio_bdev, GFP_NOIO,
+ vbio->vbio_max_segs);
+ VERIFY(bio);
+
+ BIO_BI_SECTOR(bio) = vbio->vbio_offset >> 9;
+ bio_set_op_attrs(bio,
+ vbio->vbio_zio->io_type == ZIO_TYPE_WRITE ?
+ WRITE : READ, vbio->vbio_flags);
+
+ if (vbio->vbio_bio) {
+ bio_chain(vbio->vbio_bio, bio);
+ vdev_submit_bio(vbio->vbio_bio);
+ }
+ vbio->vbio_bio = bio;
+ }
+
+ /*
+ * Only load as much of the current page data as will fit in
+ * the space left in the BIO, respecting lbs alignment. Older
+ * kernels will error if we try to overfill the BIO, while
+ * newer ones will accept it and split the BIO. This ensures
+ * everything works on older kernels, and avoids an additional
+ * overhead on the new.
+ */
+ ssize = MIN(size, (vbio->vbio_max_bytes - BIO_BI_SIZE(bio)) &
+ vbio->vbio_lbs_mask);
+ if (ssize > 0 &&
+ bio_add_page(bio, page, ssize, offset) == ssize) {
+ /* Accepted, adjust and load any remaining. */
+ size -= ssize;
+ offset += ssize;
+ continue;
+ }
+
+ /* No room, set up for a new BIO and loop */
+ vbio->vbio_offset += BIO_BI_SIZE(bio);
+
+ /* Signal new BIO allocation wanted */
+ bio = NULL;
+ }
+
+ return (0);
+}
+
+/* Iterator callback to submit ABD pages to the vbio. */
+static int
+vbio_fill_cb(struct page *page, size_t off, size_t len, void *priv)
+{
+ vbio_t *vbio = priv;
+ return (vbio_add_page(vbio, page, len, off));
+}
+
+/* Create some BIOs, fill them with data and submit them */
+static void
+vbio_submit(vbio_t *vbio, abd_t *abd, uint64_t size)
+{
+ /*
+ * We plug so we can submit the BIOs as we go and only unplug them when
+ * they are fully created and submitted. This is important; if we don't
+ * plug, then the kernel may start executing earlier BIOs while we're
+ * still creating and executing later ones, and if the device goes
+ * away while that's happening, older kernels can get confused and
+ * trample memory.
+ */
+ struct blk_plug plug;
+ blk_start_plug(&plug);
+
+ (void) abd_iterate_page_func(abd, 0, size, vbio_fill_cb, vbio);
+ ASSERT(vbio->vbio_bio);
+
+ vbio->vbio_bio->bi_end_io = vbio_completion;
+ vbio->vbio_bio->bi_private = vbio;
+
+ /*
+ * Once submitted, vbio_bio now owns vbio (through bi_private) and we
+ * can't touch it again. The bio may complete and vbio_completion() be
+ * called and free the vbio before this task is run again, so we must
+ * consider it invalid from this point.
+ */
+ vdev_submit_bio(vbio->vbio_bio);
+
+ blk_finish_plug(&plug);
+}
+
+/* IO completion callback */
+BIO_END_IO_PROTO(vbio_completion, bio, error)
+{
+ vbio_t *vbio = bio->bi_private;
+ zio_t *zio = vbio->vbio_zio;
+
+ ASSERT(zio);
+
+ /* Capture and log any errors */
+#ifdef HAVE_1ARG_BIO_END_IO_T
+ zio->io_error = BIO_END_IO_ERROR(bio);
+#else
+ zio->io_error = 0;
+ if (error)
+ zio->io_error = -(error);
+ else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+ zio->io_error = EIO;
+#endif
+ ASSERT3U(zio->io_error, >=, 0);
+
+ if (zio->io_error)
+ vdev_disk_error(zio);
+
+ /* Return the BIO to the kernel */
+ bio_put(bio);
+
+ /*
+ * If we copied the ABD before issuing it, clean up and return the copy
+ * to the ADB, with changes if appropriate.
+ */
+ if (vbio->vbio_abd != NULL) {
+ void *buf = abd_to_buf(vbio->vbio_abd);
+ abd_free(vbio->vbio_abd);
+ vbio->vbio_abd = NULL;
+
+ if (zio->io_type == ZIO_TYPE_READ)
+ abd_return_buf_copy(zio->io_abd, buf, zio->io_size);
+ else
+ abd_return_buf(zio->io_abd, buf, zio->io_size);
+ }
+
+ /* Final cleanup */
+ kmem_free(vbio, sizeof (vbio_t));
+
+ /* All done, submit for processing */
+ zio_delay_interrupt(zio);
+}
+
+/*
+ * Iterator callback to count ABD pages and check their size & alignment.
+ *
+ * On Linux, each BIO segment can take a page pointer, and an offset+length of
+ * the data within that page. A page can be arbitrarily large ("compound"
+ * pages) but we still have to ensure the data portion is correctly sized and
+ * aligned to the logical block size, to ensure that if the kernel wants to
+ * split the BIO, the two halves will still be properly aligned.
+ *
+ * NOTE: if you change this function, change the copy in
+ * tests/zfs-tests/tests/functional/vdev_disk/page_alignment.c, and add test
+ * data there to validate the change you're making.
+ *
+ */
+typedef struct {
+ uint_t bmask;
+ uint_t npages;
+ uint_t end;
+} vdev_disk_check_pages_t;
+
+static int
+vdev_disk_check_pages_cb(struct page *page, size_t off, size_t len, void *priv)
+{
+ (void) page;
+ vdev_disk_check_pages_t *s = priv;
+
+ /*
+ * If we didn't finish on a block size boundary last time, then there
+ * would be a gap if we tried to use this ABD as-is, so abort.
+ */
+ if (s->end != 0)
+ return (1);
+
+ /*
+ * Note if we're taking less than a full block, so we can check it
+ * above on the next call.
+ */
+ s->end = (off+len) & s->bmask;
+
+ /* All blocks after the first must start on a block size boundary. */
+ if (s->npages != 0 && (off & s->bmask) != 0)
+ return (1);
+
+ s->npages++;
+ return (0);
+}
+
+/*
+ * Check if we can submit the pages in this ABD to the kernel as-is. Returns
+ * the number of pages, or 0 if it can't be submitted like this.
+ */
+static boolean_t
+vdev_disk_check_pages(abd_t *abd, uint64_t size, struct block_device *bdev)
+{
+ vdev_disk_check_pages_t s = {
+ .bmask = bdev_logical_block_size(bdev)-1,
+ .npages = 0,
+ .end = 0,
+ };
+
+ if (abd_iterate_page_func(abd, 0, size, vdev_disk_check_pages_cb, &s))
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+static int
+vdev_disk_io_rw(zio_t *zio)
+{
+ vdev_t *v = zio->io_vd;
+ vdev_disk_t *vd = v->vdev_tsd;
+ struct block_device *bdev = BDH_BDEV(vd->vd_bdh);
+ int flags = 0;
+
+ /*
+ * Accessing outside the block device is never allowed.
+ */
+ if (zio->io_offset + zio->io_size > bdev->bd_inode->i_size) {
+ vdev_dbgmsg(zio->io_vd,
+ "Illegal access %llu size %llu, device size %llu",
+ (u_longlong_t)zio->io_offset,
+ (u_longlong_t)zio->io_size,
+ (u_longlong_t)i_size_read(bdev->bd_inode));
+ return (SET_ERROR(EIO));
+ }
+
+ if (!(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)) &&
+ v->vdev_failfast == B_TRUE) {
+ bio_set_flags_failfast(bdev, &flags, zfs_vdev_failfast_mask & 1,
+ zfs_vdev_failfast_mask & 2, zfs_vdev_failfast_mask & 4);
+ }
+
+ /*
+ * Check alignment of the incoming ABD. If any part of it would require
+ * submitting a page that is not aligned to the logical block size,
+ * then we take a copy into a linear buffer and submit that instead.
+ * This should be impossible on a 512b LBS, and fairly rare on 4K,
+ * usually requiring abnormally-small data blocks (eg gang blocks)
+ * mixed into the same ABD as larger ones (eg aggregated).
+ */
+ abd_t *abd = zio->io_abd;
+ if (!vdev_disk_check_pages(abd, zio->io_size, bdev)) {
+ void *buf;
+ if (zio->io_type == ZIO_TYPE_READ)
+ buf = abd_borrow_buf(zio->io_abd, zio->io_size);
+ else
+ buf = abd_borrow_buf_copy(zio->io_abd, zio->io_size);
+
+ /*
+ * Wrap the copy in an abd_t, so we can use the same iterators
+ * to count and fill the vbio later.
+ */
+ abd = abd_get_from_buf(buf, zio->io_size);
+
+ /*
+ * False here would mean the borrowed copy has an invalid
+ * alignment too, which would mean we've somehow been passed a
+ * linear ABD with an interior page that has a non-zero offset
+ * or a size not a multiple of PAGE_SIZE. This is not possible.
+ * It would mean either zio_buf_alloc() or its underlying
+ * allocators have done something extremely strange, or our
+ * math in vdev_disk_check_pages() is wrong. In either case,
+ * something in seriously wrong and its not safe to continue.
+ */
+ VERIFY(vdev_disk_check_pages(abd, zio->io_size, bdev));
+ }
+
+ /* Allocate vbio, with a pointer to the borrowed ABD if necessary */
+ vbio_t *vbio = vbio_alloc(zio, bdev, flags);
+ if (abd != zio->io_abd)
+ vbio->vbio_abd = abd;
+
+ /* Fill it with data pages and submit it to the kernel */
+ vbio_submit(vbio, abd, zio->io_size);
+ return (0);
+}
+
+/* ========== */
+
+/*
+ * This is the classic, battle-tested BIO submission code. Until we're totally
+ * sure that the new code is safe and correct in all cases, this will remain
+ * available and can be enabled by setting zfs_vdev_disk_classic=1 at module
+ * load time.
+ *
+ * These functions have been renamed to vdev_classic_* to make it clear what
+ * they belong to, but their implementations are unchanged.
+ */
+
+/*
+ * Virtual device vector for disks.
+ */
+typedef struct dio_request {
+ zio_t *dr_zio; /* Parent ZIO */
+ atomic_t dr_ref; /* References */
+ int dr_error; /* Bio error */
+ int dr_bio_count; /* Count of bio's */
+ struct bio *dr_bio[]; /* Attached bio's */
+} dio_request_t;
+
+static dio_request_t *
+vdev_classic_dio_alloc(int bio_count)
+{
+ dio_request_t *dr = kmem_zalloc(sizeof (dio_request_t) +
+ sizeof (struct bio *) * bio_count, KM_SLEEP);
+ atomic_set(&dr->dr_ref, 0);
+ dr->dr_bio_count = bio_count;
+ dr->dr_error = 0;
+
+ for (int i = 0; i < dr->dr_bio_count; i++)
+ dr->dr_bio[i] = NULL;
+
+ return (dr);
+}
+
+static void
+vdev_classic_dio_free(dio_request_t *dr)
+{
+ int i;
+
+ for (i = 0; i < dr->dr_bio_count; i++)
+ if (dr->dr_bio[i])
+ bio_put(dr->dr_bio[i]);
+
+ kmem_free(dr, sizeof (dio_request_t) +
+ sizeof (struct bio *) * dr->dr_bio_count);
+}
+
+static void
+vdev_classic_dio_get(dio_request_t *dr)
+{
+ atomic_inc(&dr->dr_ref);
+}
+
+static void
+vdev_classic_dio_put(dio_request_t *dr)
+{
+ int rc = atomic_dec_return(&dr->dr_ref);
+
+ /*
+ * Free the dio_request when the last reference is dropped and
+ * ensure zio_interpret is called only once with the correct zio
+ */
+ if (rc == 0) {
+ zio_t *zio = dr->dr_zio;
+ int error = dr->dr_error;
+
+ vdev_classic_dio_free(dr);
+
+ if (zio) {
+ zio->io_error = error;
+ ASSERT3S(zio->io_error, >=, 0);
+ if (zio->io_error)
+ vdev_disk_error(zio);
+
+ zio_delay_interrupt(zio);
+ }
+ }
+}
+
+BIO_END_IO_PROTO(vdev_classic_physio_completion, bio, error)
+{
+ dio_request_t *dr = bio->bi_private;
+
+ if (dr->dr_error == 0) {
+#ifdef HAVE_1ARG_BIO_END_IO_T
+ dr->dr_error = BIO_END_IO_ERROR(bio);
+#else
+ if (error)
+ dr->dr_error = -(error);
+ else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+ dr->dr_error = EIO;
+#endif
+ }
+
+ /* Drop reference acquired by vdev_classic_physio */
+ vdev_classic_dio_put(dr);
+}
+
static inline unsigned int
-vdev_bio_max_segs(zio_t *zio, int bio_size, uint64_t abd_offset)
+vdev_classic_bio_max_segs(zio_t *zio, int bio_size, uint64_t abd_offset)
{
unsigned long nr_segs = abd_nr_pages_off(zio->io_abd,
bio_size, abd_offset);
@@ -603,9 +1101,16 @@ vdev_bio_max_segs(zio_t *zio, int bio_size, uint64_t abd_offset)
}
static int
-__vdev_disk_physio(struct block_device *bdev, zio_t *zio,
- size_t io_size, uint64_t io_offset, int rw, int flags)
+vdev_classic_physio(zio_t *zio)
{
+ vdev_t *v = zio->io_vd;
+ vdev_disk_t *vd = v->vdev_tsd;
+ struct block_device *bdev = BDH_BDEV(vd->vd_bdh);
+ size_t io_size = zio->io_size;
+ uint64_t io_offset = zio->io_offset;
+ int rw = zio->io_type == ZIO_TYPE_READ ? READ : WRITE;
+ int flags = 0;
+
dio_request_t *dr;
uint64_t abd_offset;
uint64_t bio_offset;
@@ -628,10 +1133,13 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
}
retry:
- dr = vdev_disk_dio_alloc(bio_count);
+ dr = vdev_classic_dio_alloc(bio_count);
- if (zio && !(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))
- bio_set_flags_failfast(bdev, &flags);
+ if (!(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)) &&
+ zio->io_vd->vdev_failfast == B_TRUE) {
+ bio_set_flags_failfast(bdev, &flags, zfs_vdev_failfast_mask & 1,
+ zfs_vdev_failfast_mask & 2, zfs_vdev_failfast_mask & 4);
+ }
dr->dr_zio = zio;
@@ -660,23 +1168,23 @@ retry:
* this should be rare - see the comment above.
*/
if (dr->dr_bio_count == i) {
- vdev_disk_dio_free(dr);
+ vdev_classic_dio_free(dr);
bio_count *= 2;
goto retry;
}
- nr_vecs = vdev_bio_max_segs(zio, bio_size, abd_offset);
+ nr_vecs = vdev_classic_bio_max_segs(zio, bio_size, abd_offset);
dr->dr_bio[i] = vdev_bio_alloc(bdev, GFP_NOIO, nr_vecs);
if (unlikely(dr->dr_bio[i] == NULL)) {
- vdev_disk_dio_free(dr);
+ vdev_classic_dio_free(dr);
return (SET_ERROR(ENOMEM));
}
- /* Matching put called by vdev_disk_physio_completion */
- vdev_disk_dio_get(dr);
+ /* Matching put called by vdev_classic_physio_completion */
+ vdev_classic_dio_get(dr);
BIO_BI_SECTOR(dr->dr_bio[i]) = bio_offset >> 9;
- dr->dr_bio[i]->bi_end_io = vdev_disk_physio_completion;
+ dr->dr_bio[i]->bi_end_io = vdev_classic_physio_completion;
dr->dr_bio[i]->bi_private = dr;
bio_set_op_attrs(dr->dr_bio[i], rw, flags);
@@ -690,7 +1198,7 @@ retry:
}
/* Extra reference to protect dio_request during vdev_submit_bio */
- vdev_disk_dio_get(dr);
+ vdev_classic_dio_get(dr);
if (dr->dr_bio_count > 1)
blk_start_plug(&plug);
@@ -704,11 +1212,13 @@ retry:
if (dr->dr_bio_count > 1)
blk_finish_plug(&plug);
- (void) vdev_disk_dio_put(dr);
+ vdev_classic_dio_put(dr);
return (error);
}
+/* ========== */
+
BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, error)
{
zio_t *zio = bio->bi_private;
@@ -751,39 +1261,123 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio)
return (0);
}
+BIO_END_IO_PROTO(vdev_disk_discard_end_io, bio, error)
+{
+ zio_t *zio = bio->bi_private;
+#ifdef HAVE_1ARG_BIO_END_IO_T
+ zio->io_error = BIO_END_IO_ERROR(bio);
+#else
+ zio->io_error = -error;
+#endif
+ bio_put(bio);
+ if (zio->io_error)
+ vdev_disk_error(zio);
+ zio_interrupt(zio);
+}
+
+/*
+ * Wrappers for the different secure erase and discard APIs. We use async
+ * when available; in this case, *biop is set to the last bio in the chain.
+ */
static int
-vdev_disk_io_trim(zio_t *zio)
+vdev_bdev_issue_secure_erase(zfs_bdev_handle_t *bdh, sector_t sector,
+ sector_t nsect, struct bio **biop)
{
- vdev_t *v = zio->io_vd;
- vdev_disk_t *vd = v->vdev_tsd;
+ *biop = NULL;
+ int error;
#if defined(HAVE_BLKDEV_ISSUE_SECURE_ERASE)
- if (zio->io_trim_flags & ZIO_TRIM_SECURE) {
- return (-blkdev_issue_secure_erase(vd->vd_bdev,
- zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS));
- } else {
- return (-blkdev_issue_discard(vd->vd_bdev,
- zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS));
- }
-#elif defined(HAVE_BLKDEV_ISSUE_DISCARD)
- unsigned long trim_flags = 0;
-#if defined(BLKDEV_DISCARD_SECURE)
- if (zio->io_trim_flags & ZIO_TRIM_SECURE)
- trim_flags |= BLKDEV_DISCARD_SECURE;
+ error = blkdev_issue_secure_erase(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS);
+#elif defined(HAVE_BLKDEV_ISSUE_DISCARD_ASYNC_FLAGS)
+ error = __blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS, BLKDEV_DISCARD_SECURE, biop);
+#elif defined(HAVE_BLKDEV_ISSUE_DISCARD_FLAGS)
+ error = blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS, BLKDEV_DISCARD_SECURE);
+#else
+#error "unsupported kernel"
#endif
- return (-blkdev_issue_discard(vd->vd_bdev,
- zio->io_offset >> 9, zio->io_size >> 9, GFP_NOFS, trim_flags));
+
+ return (error);
+}
+
+static int
+vdev_bdev_issue_discard(zfs_bdev_handle_t *bdh, sector_t sector,
+ sector_t nsect, struct bio **biop)
+{
+ *biop = NULL;
+ int error;
+
+#if defined(HAVE_BLKDEV_ISSUE_DISCARD_ASYNC_FLAGS)
+ error = __blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS, 0, biop);
+#elif defined(HAVE_BLKDEV_ISSUE_DISCARD_ASYNC_NOFLAGS)
+ error = __blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS, biop);
+#elif defined(HAVE_BLKDEV_ISSUE_DISCARD_FLAGS)
+ error = blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS, 0);
+#elif defined(HAVE_BLKDEV_ISSUE_DISCARD_NOFLAGS)
+ error = blkdev_issue_discard(BDH_BDEV(bdh),
+ sector, nsect, GFP_NOFS);
#else
-#error "Unsupported kernel"
+#error "unsupported kernel"
#endif
+
+ return (error);
+}
+
+/*
+ * Entry point for TRIM ops. This calls the right wrapper for secure erase or
+ * discard, and then does the appropriate finishing work for error vs success
+ * and async vs sync.
+ */
+static int
+vdev_disk_io_trim(zio_t *zio)
+{
+ int error;
+ struct bio *bio;
+
+ zfs_bdev_handle_t *bdh = ((vdev_disk_t *)zio->io_vd->vdev_tsd)->vd_bdh;
+ sector_t sector = zio->io_offset >> 9;
+ sector_t nsects = zio->io_size >> 9;
+
+ if (zio->io_trim_flags & ZIO_TRIM_SECURE)
+ error = vdev_bdev_issue_secure_erase(bdh, sector, nsects, &bio);
+ else
+ error = vdev_bdev_issue_discard(bdh, sector, nsects, &bio);
+
+ if (error != 0)
+ return (SET_ERROR(-error));
+
+ if (bio == NULL) {
+ /*
+ * This was a synchronous op that completed successfully, so
+ * return it to ZFS immediately.
+ */
+ zio_interrupt(zio);
+ } else {
+ /*
+ * This was an asynchronous op; set up completion callback and
+ * issue it.
+ */
+ bio->bi_private = zio;
+ bio->bi_end_io = vdev_disk_discard_end_io;
+ vdev_submit_bio(bio);
+ }
+
+ return (0);
}
+int (*vdev_disk_io_rw_fn)(zio_t *zio) = NULL;
+
static void
vdev_disk_io_start(zio_t *zio)
{
vdev_t *v = zio->io_vd;
vdev_disk_t *vd = v->vdev_tsd;
- int rw, error;
+ int error;
/*
* If the vdev is closed, it's likely in the REMOVED or FAULTED state.
@@ -801,7 +1395,7 @@ vdev_disk_io_start(zio_t *zio)
* If the vdev is closed, it's likely due to a failed reopen and is
* in the UNAVAIL state. Nothing to be done here but return failure.
*/
- if (vd->vd_bdev == NULL) {
+ if (vd->vd_bdh == NULL) {
rw_exit(&vd->vd_lock);
zio->io_error = ENXIO;
zio_interrupt(zio);
@@ -809,74 +1403,72 @@ vdev_disk_io_start(zio_t *zio)
}
switch (zio->io_type) {
- case ZIO_TYPE_IOCTL:
+ case ZIO_TYPE_FLUSH:
if (!vdev_readable(v)) {
- rw_exit(&vd->vd_lock);
- zio->io_error = SET_ERROR(ENXIO);
- zio_interrupt(zio);
- return;
- }
-
- switch (zio->io_cmd) {
- case DKIOCFLUSHWRITECACHE:
-
- if (zfs_nocacheflush)
- break;
-
- if (v->vdev_nowritecache) {
- zio->io_error = SET_ERROR(ENOTSUP);
- break;
- }
-
- error = vdev_disk_io_flush(vd->vd_bdev, zio);
+ /* Drive not there, can't flush */
+ error = SET_ERROR(ENXIO);
+ } else if (zfs_nocacheflush) {
+ /* Flushing disabled by operator, declare success */
+ error = 0;
+ } else if (v->vdev_nowritecache) {
+ /* This vdev not capable of flushing */
+ error = SET_ERROR(ENOTSUP);
+ } else {
+ /*
+ * Issue the flush. If successful, the response will
+ * be handled in the completion callback, so we're done.
+ */
+ error = vdev_disk_io_flush(BDH_BDEV(vd->vd_bdh), zio);
if (error == 0) {
rw_exit(&vd->vd_lock);
return;
}
-
- zio->io_error = error;
-
- break;
-
- default:
- zio->io_error = SET_ERROR(ENOTSUP);
}
+ /* Couldn't issue the flush, so set the error and return it */
rw_exit(&vd->vd_lock);
+ zio->io_error = error;
zio_execute(zio);
return;
- case ZIO_TYPE_WRITE:
- rw = WRITE;
- break;
-
- case ZIO_TYPE_READ:
- rw = READ;
- break;
case ZIO_TYPE_TRIM:
- zio->io_error = vdev_disk_io_trim(zio);
+ error = vdev_disk_io_trim(zio);
rw_exit(&vd->vd_lock);
- zio_interrupt(zio);
+ if (error) {
+ zio->io_error = error;
+ zio_execute(zio);
+ }
return;
- default:
+ case ZIO_TYPE_READ:
+ case ZIO_TYPE_WRITE:
+ zio->io_target_timestamp = zio_handle_io_delay(zio);
+ error = vdev_disk_io_rw_fn(zio);
rw_exit(&vd->vd_lock);
- zio->io_error = SET_ERROR(ENOTSUP);
- zio_interrupt(zio);
+ if (error) {
+ zio->io_error = error;
+ zio_interrupt(zio);
+ }
return;
- }
- zio->io_target_timestamp = zio_handle_io_delay(zio);
- error = __vdev_disk_physio(vd->vd_bdev, zio,
- zio->io_size, zio->io_offset, rw, 0);
- rw_exit(&vd->vd_lock);
+ default:
+ /*
+ * Getting here means our parent vdev has made a very strange
+ * request of us, and shouldn't happen. Assert here to force a
+ * crash in dev builds, but in production return the IO
+ * unhandled. The pool will likely suspend anyway but that's
+ * nicer than crashing the kernel.
+ */
+ ASSERT3S(zio->io_type, ==, -1);
- if (error) {
- zio->io_error = error;
+ rw_exit(&vd->vd_lock);
+ zio->io_error = SET_ERROR(ENOTSUP);
zio_interrupt(zio);
return;
}
+
+ __builtin_unreachable();
}
static void
@@ -891,8 +1483,8 @@ vdev_disk_io_done(zio_t *zio)
vdev_t *v = zio->io_vd;
vdev_disk_t *vd = v->vdev_tsd;
- if (zfs_check_media_change(vd->vd_bdev)) {
- invalidate_bdev(vd->vd_bdev);
+ if (!zfs_check_disk_status(BDH_BDEV(vd->vd_bdh))) {
+ invalidate_bdev(BDH_BDEV(vd->vd_bdh));
v->vdev_remove_wanted = B_TRUE;
spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE);
}
@@ -925,8 +1517,49 @@ vdev_disk_rele(vdev_t *vd)
/* XXX: Implement me as a vnode rele for the device */
}
+/*
+ * BIO submission method. See comment above about vdev_classic.
+ * Set zfs_vdev_disk_classic=0 for new, =1 for classic
+ */
+static uint_t zfs_vdev_disk_classic = 0; /* default new */
+
+/* Set submission function from module parameter */
+static int
+vdev_disk_param_set_classic(const char *buf, zfs_kernel_param_t *kp)
+{
+ int err = param_set_uint(buf, kp);
+ if (err < 0)
+ return (SET_ERROR(err));
+
+ vdev_disk_io_rw_fn =
+ zfs_vdev_disk_classic ? vdev_classic_physio : vdev_disk_io_rw;
+
+ printk(KERN_INFO "ZFS: forcing %s BIO submission\n",
+ zfs_vdev_disk_classic ? "classic" : "new");
+
+ return (0);
+}
+
+/*
+ * At first use vdev use, set the submission function from the default value if
+ * it hasn't been set already.
+ */
+static int
+vdev_disk_init(spa_t *spa, nvlist_t *nv, void **tsd)
+{
+ (void) spa;
+ (void) nv;
+ (void) tsd;
+
+ if (vdev_disk_io_rw_fn == NULL)
+ vdev_disk_io_rw_fn = zfs_vdev_disk_classic ?
+ vdev_classic_physio : vdev_disk_io_rw;
+
+ return (0);
+}
+
vdev_ops_t vdev_disk_ops = {
- .vdev_op_init = NULL,
+ .vdev_op_init = vdev_disk_init,
.vdev_op_fini = NULL,
.vdev_op_open = vdev_disk_open,
.vdev_op_close = vdev_disk_close,
@@ -947,7 +1580,8 @@ vdev_ops_t vdev_disk_ops = {
.vdev_op_nparity = NULL,
.vdev_op_ndisks = NULL,
.vdev_op_type = VDEV_TYPE_DISK, /* name of this vdev type */
- .vdev_op_leaf = B_TRUE /* leaf vdev */
+ .vdev_op_leaf = B_TRUE, /* leaf vdev */
+ .vdev_op_kobj_evt_post = vdev_disk_kobj_evt_post
};
/*
@@ -976,17 +1610,17 @@ MODULE_PARM_DESC(zfs_vdev_scheduler, "I/O scheduler");
int
param_set_min_auto_ashift(const char *buf, zfs_kernel_param_t *kp)
{
- uint64_t val;
+ uint_t val;
int error;
- error = kstrtoull(buf, 0, &val);
+ error = kstrtouint(buf, 0, &val);
if (error < 0)
return (SET_ERROR(error));
if (val < ASHIFT_MIN || val > zfs_vdev_max_auto_ashift)
return (SET_ERROR(-EINVAL));
- error = param_set_ulong(buf, kp);
+ error = param_set_uint(buf, kp);
if (error < 0)
return (SET_ERROR(error));
@@ -996,19 +1630,32 @@ param_set_min_auto_ashift(const char *buf, zfs_kernel_param_t *kp)
int
param_set_max_auto_ashift(const char *buf, zfs_kernel_param_t *kp)
{
- uint64_t val;
+ uint_t val;
int error;
- error = kstrtoull(buf, 0, &val);
+ error = kstrtouint(buf, 0, &val);
if (error < 0)
return (SET_ERROR(error));
if (val > ASHIFT_MAX || val < zfs_vdev_min_auto_ashift)
return (SET_ERROR(-EINVAL));
- error = param_set_ulong(buf, kp);
+ error = param_set_uint(buf, kp);
if (error < 0)
return (SET_ERROR(error));
return (0);
}
+
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, open_timeout_ms, UINT, ZMOD_RW,
+ "Timeout before determining that a device is missing");
+
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, failfast_mask, UINT, ZMOD_RW,
+ "Defines failfast mask: 1 - device, 2 - transport, 4 - driver");
+
+ZFS_MODULE_PARAM(zfs_vdev_disk, zfs_vdev_disk_, max_segs, UINT, ZMOD_RW,
+ "Maximum number of data segments to add to an IO request (min 4)");
+
+ZFS_MODULE_PARAM_CALL(zfs_vdev_disk, zfs_vdev_disk_, classic,
+ vdev_disk_param_set_classic, param_get_uint, ZMOD_RD,
+ "Use classic BIO submission method");
diff --git a/module/os/linux/zfs/vdev_file.c b/module/os/linux/zfs/vdev_file.c
index f073145326e3..ac41a2615f16 100644
--- a/module/os/linux/zfs/vdev_file.c
+++ b/module/os/linux/zfs/vdev_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -53,8 +53,8 @@ static taskq_t *vdev_file_taskq;
* impact the vdev_ashift setting which can only be set at vdev creation
* time.
*/
-static unsigned long vdev_file_logical_ashift = SPA_MINBLOCKSHIFT;
-static unsigned long vdev_file_physical_ashift = SPA_MINBLOCKSHIFT;
+static uint_t vdev_file_logical_ashift = SPA_MINBLOCKSHIFT;
+static uint_t vdev_file_physical_ashift = SPA_MINBLOCKSHIFT;
static void
vdev_file_hold(vdev_t *vd)
@@ -242,7 +242,7 @@ vdev_file_io_start(zio_t *zio)
vdev_t *vd = zio->io_vd;
vdev_file_t *vf = vd->vdev_tsd;
- if (zio->io_type == ZIO_TYPE_IOCTL) {
+ if (zio->io_type == ZIO_TYPE_FLUSH) {
/* XXPOLICY */
if (!vdev_readable(vd)) {
zio->io_error = SET_ERROR(ENXIO);
@@ -250,33 +250,27 @@ vdev_file_io_start(zio_t *zio)
return;
}
- switch (zio->io_cmd) {
- case DKIOCFLUSHWRITECACHE:
-
- if (zfs_nocacheflush)
- break;
-
- /*
- * We cannot safely call vfs_fsync() when PF_FSTRANS
- * is set in the current context. Filesystems like
- * XFS include sanity checks to verify it is not
- * already set, see xfs_vm_writepage(). Therefore
- * the sync must be dispatched to a different context.
- */
- if (__spl_pf_fstrans_check()) {
- VERIFY3U(taskq_dispatch(vdev_file_taskq,
- vdev_file_io_fsync, zio, TQ_SLEEP), !=,
- TASKQID_INVALID);
- return;
- }
-
- zio->io_error = zfs_file_fsync(vf->vf_file,
- O_SYNC | O_DSYNC);
- break;
- default:
- zio->io_error = SET_ERROR(ENOTSUP);
+ if (zfs_nocacheflush) {
+ zio_execute(zio);
+ return;
}
+ /*
+ * We cannot safely call vfs_fsync() when PF_FSTRANS
+ * is set in the current context. Filesystems like
+ * XFS include sanity checks to verify it is not
+ * already set, see xfs_vm_writepage(). Therefore
+ * the sync must be dispatched to a different context.
+ */
+ if (__spl_pf_fstrans_check()) {
+ VERIFY3U(taskq_dispatch(vdev_file_taskq,
+ vdev_file_io_fsync, zio, TQ_SLEEP), !=,
+ TASKQID_INVALID);
+ return;
+ }
+
+ zio->io_error = zfs_file_fsync(vf->vf_file, O_SYNC | O_DSYNC);
+
zio_execute(zio);
return;
} else if (zio->io_type == ZIO_TYPE_TRIM) {
@@ -376,7 +370,7 @@ vdev_ops_t vdev_disk_ops = {
#endif
-ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, logical_ashift, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, logical_ashift, UINT, ZMOD_RW,
"Logical ashift for file-based devices");
-ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, physical_ashift, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, physical_ashift, UINT, ZMOD_RW,
"Physical ashift for file-based devices");
diff --git a/module/zfs/spa_boot.c b/module/os/linux/zfs/vdev_label_os.c
index 674394650f82..3d965b89a962 100644
--- a/module/zfs/spa_boot.c
+++ b/module/os/linux/zfs/vdev_label_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,31 +20,26 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2023 by iXsystems, Inc.
*/
-#ifdef _KERNEL
+#include <sys/zfs_context.h>
+#include <sys/spa.h>
+#include <sys/spa_impl.h>
+#include <sys/vdev.h>
+#include <sys/vdev_impl.h>
-#include <sys/zio.h>
-#include <sys/spa_boot.h>
-#include <sys/sunddi.h>
-
-char *
-spa_get_bootprop(char *propname)
+/*
+ * Check if the reserved boot area is in-use.
+ *
+ * This function always returns 0, as there are no known external uses
+ * of the reserved area on Linux.
+ */
+int
+vdev_check_boot_reserve(spa_t *spa, vdev_t *childvd)
{
- char *value;
+ (void) spa;
+ (void) childvd;
- if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
- DDI_PROP_DONTPASS, propname, &value) != DDI_SUCCESS)
- return (NULL);
- return (value);
+ return (0);
}
-
-void
-spa_free_bootprop(char *value)
-{
- ddi_prop_free(value);
-}
-
-#endif /* _KERNEL */
diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c
index b70691ab31c1..48abbc010917 100644
--- a/module/os/linux/zfs/zfs_acl.c
+++ b/module/os/linux/zfs/zfs_acl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -493,10 +493,8 @@ zfs_acl_release_nodes(zfs_acl_t *aclp)
{
zfs_acl_node_t *aclnode;
- while ((aclnode = list_head(&aclp->z_acl))) {
- list_remove(&aclp->z_acl, aclnode);
+ while ((aclnode = list_remove_head(&aclp->z_acl)))
zfs_acl_node_free(aclnode);
- }
aclp->z_acl_count = 0;
aclp->z_acl_bytes = 0;
}
@@ -525,7 +523,7 @@ zfs_acl_valid_ace_type(uint_t type, uint_t flags)
entry_type == ACE_EVERYONE || entry_type == 0 ||
entry_type == ACE_IDENTIFIER_GROUP);
default:
- if (type >= MIN_ACE_TYPE && type <= MAX_ACE_TYPE)
+ if (type <= MAX_ACE_TYPE)
return (B_TRUE);
}
return (B_FALSE);
@@ -629,18 +627,18 @@ zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who,
return (NULL);
}
-static uint64_t
-zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
+static uintptr_t
+zfs_ace_walk(void *datap, uintptr_t cookie, int aclcnt,
uint16_t *flags, uint16_t *type, uint32_t *mask)
{
(void) aclcnt;
zfs_acl_t *aclp = datap;
- zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)(uintptr_t)cookie;
+ zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)cookie;
uint64_t who;
acep = zfs_acl_next_ace(aclp, acep, &who, mask,
flags, type);
- return ((uint64_t)(uintptr_t)acep);
+ return ((uintptr_t)acep);
}
/*
@@ -1163,6 +1161,7 @@ zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen,
cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl,
cb->cb_acl_node);
}
+ ASSERT3P(cb->cb_acl_node, !=, NULL);
*dataptr = cb->cb_acl_node->z_acldata;
*length = cb->cb_acl_node->z_size;
}
@@ -1284,7 +1283,7 @@ acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)
*/
static int
ace_trivial_common(void *acep, int aclcnt,
- uint64_t (*walk)(void *, uint64_t, int aclcnt,
+ uintptr_t (*walk)(void *, uintptr_t, int,
uint16_t *, uint16_t *, uint32_t *))
{
uint16_t flags;
@@ -1801,7 +1800,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp,
*/
int
zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
- vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids)
+ vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns)
{
int error;
zfsvfs_t *zfsvfs = ZTOZSB(dzp);
@@ -1888,8 +1887,10 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
acl_ids->z_mode |= S_ISGID;
} else {
if ((acl_ids->z_mode & S_ISGID) &&
- secpolicy_vnode_setids_setgids(cr, gid) != 0)
+ secpolicy_vnode_setids_setgids(cr, gid, mnt_ns,
+ zfs_i_user_ns(ZTOI(dzp))) != 0) {
acl_ids->z_mode &= ~S_ISGID;
+ }
}
if (acl_ids->z_aclp == NULL) {
@@ -1920,8 +1921,8 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH &&
zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X)
trim = B_TRUE;
- zfs_acl_chmod(vap->va_mode, acl_ids->z_mode, B_FALSE,
- trim, acl_ids->z_aclp);
+ zfs_acl_chmod(S_ISDIR(vap->va_mode), acl_ids->z_mode,
+ B_FALSE, trim, acl_ids->z_aclp);
}
}
@@ -1977,7 +1978,8 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
if (mask == 0)
return (SET_ERROR(ENOSYS));
- if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)))
+ if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr,
+ zfs_init_idmap)))
return (error);
mutex_enter(&zp->z_acl_lock);
@@ -2136,7 +2138,8 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
if (zp->z_pflags & ZFS_IMMUTABLE)
return (SET_ERROR(EPERM));
- if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)))
+ if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr,
+ zfs_init_idmap)))
return (error);
error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp,
@@ -2228,8 +2231,7 @@ static int
zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
{
if ((v4_mode & WRITE_MASK) && (zfs_is_readonly(ZTOZSB(zp))) &&
- (!Z_ISDEV(ZTOI(zp)->i_mode) ||
- (Z_ISDEV(ZTOI(zp)->i_mode) && (v4_mode & WRITE_MASK_ATTRS)))) {
+ (!Z_ISDEV(ZTOI(zp)->i_mode) || (v4_mode & WRITE_MASK_ATTRS))) {
return (SET_ERROR(EROFS));
}
@@ -2282,7 +2284,7 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
*/
static int
zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
- boolean_t anyaccess, cred_t *cr)
+ boolean_t anyaccess, cred_t *cr, zidmap_t *mnt_ns)
{
zfsvfs_t *zfsvfs = ZTOZSB(zp);
zfs_acl_t *aclp;
@@ -2298,7 +2300,13 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
uid_t gowner;
uid_t fowner;
- zfs_fuid_map_ids(zp, cr, &fowner, &gowner);
+ if (mnt_ns) {
+ fowner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),
+ KUID_TO_SUID(ZTOI(zp)->i_uid));
+ gowner = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),
+ KGID_TO_SGID(ZTOI(zp)->i_gid));
+ } else
+ zfs_fuid_map_ids(zp, cr, &fowner, &gowner);
mutex_enter(&zp->z_acl_lock);
@@ -2409,7 +2417,8 @@ zfs_has_access(znode_t *zp, cred_t *cr)
{
uint32_t have = ACE_ALL_PERMS;
- if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) {
+ if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr,
+ zfs_init_idmap) != 0) {
uid_t owner;
owner = zfs_fuid_map_id(ZTOZSB(zp),
@@ -2439,7 +2448,8 @@ zfs_has_access(znode_t *zp, cred_t *cr)
* we want to avoid that here.
*/
static int
-zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr)
+zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr,
+ zidmap_t *mnt_ns)
{
int err, mask;
int unmapped = 0;
@@ -2452,8 +2462,9 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr)
return (unmapped ? SET_ERROR(EPERM) : 0);
}
-#if defined(HAVE_IOPS_PERMISSION_USERNS)
- err = generic_permission(cr->user_ns, ZTOI(zp), mask);
+#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
+ defined(HAVE_IOPS_PERMISSION_IDMAP))
+ err = generic_permission(mnt_ns, ZTOI(zp), mask);
#else
err = generic_permission(ZTOI(zp), mask);
#endif
@@ -2468,7 +2479,7 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr)
static int
zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
- boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr)
+ boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zidmap_t *mnt_ns)
{
zfsvfs_t *zfsvfs = ZTOZSB(zp);
int err;
@@ -2518,20 +2529,20 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
}
if (zp->z_pflags & ZFS_ACL_TRIVIAL)
- return (zfs_zaccess_trivial(zp, working_mode, cr));
+ return (zfs_zaccess_trivial(zp, working_mode, cr, mnt_ns));
- return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
+ return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr, mnt_ns));
}
static int
zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs,
- cred_t *cr)
+ cred_t *cr, zidmap_t *mnt_ns)
{
if (*working_mode != ACE_WRITE_DATA)
return (SET_ERROR(EACCES));
return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode,
- check_privs, B_FALSE, cr));
+ check_privs, B_FALSE, cr, mnt_ns));
}
int
@@ -2566,7 +2577,6 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
}
if (uid == KUID_TO_SUID(ZTOI(zdp)->i_uid)) {
- owner = B_TRUE;
if (zdp->z_mode & S_IXUSR) {
mutex_exit(&zdp->z_acl_lock);
return (0);
@@ -2576,7 +2586,6 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
}
}
if (groupmember(KGID_TO_SGID(ZTOI(zdp)->i_gid), cr)) {
- groupmbr = B_TRUE;
if (zdp->z_mode & S_IXGRP) {
mutex_exit(&zdp->z_acl_lock);
return (0);
@@ -2596,9 +2605,11 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
slow:
DTRACE_PROBE(zfs__fastpath__execute__access__miss);
- ZFS_ENTER(ZTOZSB(zdp));
- error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr);
- ZFS_EXIT(ZTOZSB(zdp));
+ if ((error = zfs_enter(ZTOZSB(zdp), FTAG)) != 0)
+ return (error);
+ error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr,
+ zfs_init_idmap);
+ zfs_exit(ZTOZSB(zdp), FTAG);
return (error);
}
@@ -2609,7 +2620,8 @@ slow:
* can define any form of access.
*/
int
-zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
+zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,
+ zidmap_t *mnt_ns)
{
uint32_t working_mode;
int error;
@@ -2648,8 +2660,10 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
}
}
- owner = zfs_fuid_map_id(ZTOZSB(zp), KUID_TO_SUID(ZTOI(zp)->i_uid),
- cr, ZFS_OWNER);
+ owner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),
+ KUID_TO_SUID(ZTOI(zp)->i_uid));
+ owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER);
+
/*
* Map the bits required to the standard inode flags
* S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits. Map the bits
@@ -2674,7 +2688,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
needed_bits |= S_IXUSR;
if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,
- &check_privs, skipaclchk, cr)) == 0) {
+ &check_privs, skipaclchk, cr, mnt_ns)) == 0) {
if (is_attr)
zrele(xzp);
return (secpolicy_vnode_access2(cr, ZTOI(zp), owner,
@@ -2688,7 +2702,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
}
if (error && (flags & V_APPEND)) {
- error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr);
+ error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr,
+ mnt_ns);
}
if (error && check_privs) {
@@ -2699,7 +2714,6 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
* read_acl/read_attributes
*/
- error = 0;
ASSERT(working_mode != 0);
if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&
@@ -2755,20 +2769,22 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
* NFSv4-style ZFS ACL format and call zfs_zaccess()
*/
int
-zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr)
+zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr,
+ zidmap_t *mnt_ns)
{
- return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr));
+ return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr,
+ mnt_ns));
}
/*
* Access function for secpolicy_vnode_setattr
*/
int
-zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr)
+zfs_zaccess_unix(void *zp, int mode, cred_t *cr)
{
int v4_mode = zfs_unix_to_v4(mode >> 6);
- return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr));
+ return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_idmap));
}
/* See zfs_zaccess_delete() */
@@ -2845,7 +2861,7 @@ static const boolean_t zfs_write_implies_delete_child = B_TRUE;
* zfs_write_implies_delete_child
*/
int
-zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
+zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns)
{
uint32_t wanted_dirperms;
uint32_t dzp_working_mode = 0;
@@ -2872,7 +2888,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
* (This is part of why we're checking the target first.)
*/
zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode,
- &zpcheck_privs, B_FALSE, cr);
+ &zpcheck_privs, B_FALSE, cr, mnt_ns);
if (zp_error == EACCES) {
/* We hit a DENY ACE. */
if (!zpcheck_privs)
@@ -2894,7 +2910,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
if (zfs_write_implies_delete_child)
wanted_dirperms |= ACE_WRITE_DATA;
dzp_error = zfs_zaccess_common(dzp, wanted_dirperms,
- &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr);
+ &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr, mnt_ns);
if (dzp_error == EACCES) {
/* We hit a DENY ACE. */
if (!dzpcheck_privs)
@@ -2976,7 +2992,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
int
zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
- znode_t *tzp, cred_t *cr)
+ znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns)
{
int add_perm;
int error;
@@ -2998,21 +3014,21 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
* If that succeeds then check for add_file/add_subdir permissions
*/
- if ((error = zfs_zaccess_delete(sdzp, szp, cr)))
+ if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns)))
return (error);
/*
* If we have a tzp, see if we can delete it?
*/
if (tzp) {
- if ((error = zfs_zaccess_delete(tdzp, tzp, cr)))
+ if ((error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns)))
return (error);
}
/*
* Now check for add permissions
*/
- error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr);
+ error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns);
return (error);
}
diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c
index aae19f6346fd..54ed70d0394f 100644
--- a/module/os/linux/zfs/zfs_ctldir.c
+++ b/module/os/linux/zfs/zfs_ctldir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -392,7 +392,20 @@ zfsctl_snapshot_unmount_delay_impl(zfs_snapentry_t *se, int delay)
zfsctl_snapshot_hold(se);
rw_enter(&se->se_taskqid_lock, RW_WRITER);
- ASSERT3S(se->se_taskqid, ==, TASKQID_INVALID);
+ /*
+ * If this condition happens, we managed to:
+ * - dispatch once
+ * - want to dispatch _again_ before it returned
+ *
+ * So let's just return - if that task fails at unmounting,
+ * we'll eventually dispatch again, and if it succeeds,
+ * no problem.
+ */
+ if (se->se_taskqid != TASKQID_INVALID) {
+ rw_exit(&se->se_taskqid_lock);
+ zfsctl_snapshot_rele(se);
+ return;
+ }
se->se_taskqid = taskq_dispatch_delay(system_delay_taskq,
snapentry_expire, se, TQ_SLEEP, ddi_get_lbolt() + delay * HZ);
rw_exit(&se->se_taskqid_lock);
@@ -465,17 +478,19 @@ zfsctl_is_snapdir(struct inode *ip)
*/
static struct inode *
zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
- const struct file_operations *fops, const struct inode_operations *ops)
+ const struct file_operations *fops, const struct inode_operations *ops,
+ uint64_t creation)
{
- inode_timespec_t now;
struct inode *ip;
znode_t *zp;
+ inode_timespec_t now = {.tv_sec = creation};
ip = new_inode(zfsvfs->z_sb);
if (ip == NULL)
return (NULL);
- now = current_time(ip);
+ if (!creation)
+ now = current_time(ip);
zp = ITOZ(ip);
ASSERT3P(zp->z_dirlocks, ==, NULL);
ASSERT3P(zp->z_acl_cached, ==, NULL);
@@ -485,9 +500,10 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
zp->z_atime_dirty = B_FALSE;
zp->z_zn_prefetch = B_FALSE;
zp->z_is_sa = B_FALSE;
+#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
zp->z_is_mapped = B_FALSE;
+#endif
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;
@@ -504,9 +520,9 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
ip->i_uid = SUID_TO_KUID(0);
ip->i_gid = SGID_TO_KGID(0);
ip->i_blkbits = SPA_MINBLOCKSHIFT;
- ip->i_atime = now;
- ip->i_mtime = now;
- ip->i_ctime = now;
+ zpl_inode_set_atime_to_ts(ip, now);
+ zpl_inode_set_mtime_to_ts(ip, now);
+ zpl_inode_set_ctime_to_ts(ip, now);
ip->i_fop = fops;
ip->i_op = ops;
#if defined(IOP_XATTR)
@@ -521,7 +537,6 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp);
- zfsvfs->z_nr_znodes++;
membar_producer();
mutex_exit(&zfsvfs->z_znodes_lock);
@@ -538,14 +553,28 @@ zfsctl_inode_lookup(zfsvfs_t *zfsvfs, uint64_t id,
const struct file_operations *fops, const struct inode_operations *ops)
{
struct inode *ip = NULL;
+ uint64_t creation = 0;
+ dsl_dataset_t *snap_ds;
+ dsl_pool_t *pool;
while (ip == NULL) {
ip = ilookup(zfsvfs->z_sb, (unsigned long)id);
if (ip)
break;
+ if (id <= ZFSCTL_INO_SNAPDIRS && !creation) {
+ pool = dmu_objset_pool(zfsvfs->z_os);
+ dsl_pool_config_enter(pool, FTAG);
+ if (!dsl_dataset_hold_obj(pool,
+ ZFSCTL_INO_SNAPDIRS - id, FTAG, &snap_ds)) {
+ creation = dsl_get_creation(snap_ds);
+ dsl_dataset_rele(snap_ds, FTAG);
+ }
+ dsl_pool_config_exit(pool, FTAG);
+ }
+
/* May fail due to concurrent zfsctl_inode_alloc() */
- ip = zfsctl_inode_alloc(zfsvfs, id, fops, ops);
+ ip = zfsctl_inode_alloc(zfsvfs, id, fops, ops, creation);
}
return (ip);
@@ -567,7 +596,7 @@ zfsctl_create(zfsvfs_t *zfsvfs)
ASSERT(zfsvfs->z_ctldir == NULL);
zfsvfs->z_ctldir = zfsctl_inode_alloc(zfsvfs, ZFSCTL_INO_ROOT,
- &zpl_fops_root, &zpl_ops_root);
+ &zpl_fops_root, &zpl_ops_root, 0);
if (zfsvfs->z_ctldir == NULL)
return (SET_ERROR(ENOENT));
@@ -673,17 +702,19 @@ zfsctl_fid(struct inode *ip, fid_t *fidp)
uint64_t object = zp->z_id;
zfid_short_t *zfid;
int i;
+ int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (zfsctl_is_snapdir(ip)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (zfsctl_snapdir_fid(ip, fidp));
}
if (fidp->fid_len < SHORT_FID_LEN) {
fidp->fid_len = SHORT_FID_LEN;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOSPC));
}
@@ -698,7 +729,7 @@ zfsctl_fid(struct inode *ip, fid_t *fidp)
for (i = 0; i < sizeof (zfid->zf_gen); i++)
zfid->zf_gen[i] = 0;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -776,7 +807,8 @@ zfsctl_root_lookup(struct inode *dip, const char *name, struct inode **ipp,
zfsvfs_t *zfsvfs = ITOZSB(dip);
int error = 0;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (strcmp(name, "..") == 0) {
*ipp = dip->i_sb->s_root->d_inode;
@@ -793,7 +825,7 @@ zfsctl_root_lookup(struct inode *dip, const char *name, struct inode **ipp,
if (*ipp == NULL)
error = SET_ERROR(ENOENT);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -810,11 +842,12 @@ zfsctl_snapdir_lookup(struct inode *dip, const char *name, struct inode **ipp,
uint64_t id;
int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
error = dmu_snapshot_lookup(zfsvfs->z_os, name, &id);
if (error) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -823,7 +856,7 @@ zfsctl_snapdir_lookup(struct inode *dip, const char *name, struct inode **ipp,
if (*ipp == NULL)
error = SET_ERROR(ENOENT);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -844,7 +877,8 @@ zfsctl_snapdir_rename(struct inode *sdip, const char *snm,
if (!zfs_admin_snapshot)
return (SET_ERROR(EACCES));
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
to = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
from = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
@@ -902,7 +936,7 @@ out:
kmem_free(real, ZFS_MAX_DATASET_NAME_LEN);
kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -922,7 +956,8 @@ zfsctl_snapdir_remove(struct inode *dip, const char *name, cred_t *cr,
if (!zfs_admin_snapshot)
return (SET_ERROR(EACCES));
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
snapname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
real = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
@@ -951,7 +986,7 @@ out:
kmem_free(snapname, ZFS_MAX_DATASET_NAME_LEN);
kmem_free(real, ZFS_MAX_DATASET_NAME_LEN);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1076,7 +1111,8 @@ zfsctl_snapshot_mount(struct path *path, int flags)
return (SET_ERROR(EISDIR));
zfsvfs = ITOZSB(ip);
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
full_name = kmem_zalloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
full_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
@@ -1164,7 +1200,7 @@ error:
kmem_free(full_name, ZFS_MAX_DATASET_NAME_LEN);
kmem_free(full_path, MAXPATHLEN);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1228,10 +1264,11 @@ zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
znode_t *dzp;
int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (zfsvfs->z_shares_dir == 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOTSUP));
}
@@ -1240,7 +1277,7 @@ zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
zrele(dzp);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
diff --git a/module/os/linux/zfs/zfs_debug.c b/module/os/linux/zfs/zfs_debug.c
index be65f0a2e245..f707959c9445 100644
--- a/module/os/linux/zfs/zfs_debug.c
+++ b/module/os/linux/zfs/zfs_debug.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -29,13 +29,13 @@
typedef struct zfs_dbgmsg {
procfs_list_node_t zdm_node;
uint64_t zdm_timestamp;
- int zdm_size;
- char zdm_msg[1]; /* variable length allocation */
+ uint_t zdm_size;
+ char zdm_msg[]; /* variable length allocation */
} zfs_dbgmsg_t;
static procfs_list_t zfs_dbgmsgs;
-static int zfs_dbgmsg_size = 0;
-int zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
+static uint_t zfs_dbgmsg_size = 0;
+static uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */
/*
* Internal ZFS debug messages are enabled by default.
@@ -68,14 +68,14 @@ zfs_dbgmsg_show(struct seq_file *f, void *p)
}
static void
-zfs_dbgmsg_purge(int max_size)
+zfs_dbgmsg_purge(uint_t max_size)
{
while (zfs_dbgmsg_size > max_size) {
zfs_dbgmsg_t *zdm = list_remove_head(&zfs_dbgmsgs.pl_list);
if (zdm == NULL)
return;
- int size = zdm->zdm_size;
+ uint_t size = zdm->zdm_size;
kmem_free(zdm, size);
zfs_dbgmsg_size -= size;
}
@@ -135,7 +135,7 @@ __set_error(const char *file, const char *func, int line, int err)
void
__zfs_dbgmsg(char *buf)
{
- int size = sizeof (zfs_dbgmsg_t) + strlen(buf);
+ uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
zfs_dbgmsg_t *zdm = kmem_zalloc(size, KM_SLEEP);
zdm->zdm_size = size;
zdm->zdm_timestamp = gethrestime_sec();
@@ -144,7 +144,7 @@ __zfs_dbgmsg(char *buf)
mutex_enter(&zfs_dbgmsgs.pl_lock);
procfs_list_add(&zfs_dbgmsgs, zdm);
zfs_dbgmsg_size += size;
- zfs_dbgmsg_purge(MAX(zfs_dbgmsg_maxsize, 0));
+ zfs_dbgmsg_purge(zfs_dbgmsg_maxsize);
mutex_exit(&zfs_dbgmsgs.pl_lock);
}
@@ -175,7 +175,8 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
newfile = file;
}
- i = snprintf(buf, size, "%s%s:%d:%s(): ", prefix, newfile, line, func);
+ i = snprintf(buf, size, "%px %s%s:%d:%s(): ",
+ curthread, prefix, newfile, line, func);
if (i < size) {
va_start(adx, fmt);
@@ -252,6 +253,8 @@ zfs_dbgmsg_print(const char *tag)
module_param(zfs_dbgmsg_enable, int, 0644);
MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log");
-module_param(zfs_dbgmsg_maxsize, int, 0644);
+/* BEGIN CSTYLED */
+module_param(zfs_dbgmsg_maxsize, uint, 0644);
+/* END CSTYLED */
MODULE_PARM_DESC(zfs_dbgmsg_maxsize, "Maximum ZFS debug log size");
#endif
diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c
index c5b3b5ce7fc0..1eeabe53d23c 100644
--- a/module/os/linux/zfs/zfs_dir.c
+++ b/module/os/linux/zfs/zfs_dir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -649,6 +649,8 @@ zfs_rmnode(znode_t *zp)
objset_t *os = zfsvfs->z_os;
znode_t *xzp = NULL;
dmu_tx_t *tx;
+ znode_hold_t *zh;
+ uint64_t z_id = zp->z_id;
uint64_t acl_obj;
uint64_t xattr_obj;
uint64_t links;
@@ -666,8 +668,9 @@ zfs_rmnode(znode_t *zp)
* Not enough space to delete some xattrs.
* Leave it in the unlinked set.
*/
+ zh = zfs_znode_hold_enter(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
-
+ zfs_znode_hold_exit(zfsvfs, zh);
return;
}
}
@@ -686,7 +689,9 @@ zfs_rmnode(znode_t *zp)
* Not enough space or we were interrupted by unmount.
* Leave the file in the unlinked set.
*/
+ zh = zfs_znode_hold_enter(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
+ zfs_znode_hold_exit(zfsvfs, zh);
return;
}
}
@@ -726,7 +731,9 @@ zfs_rmnode(znode_t *zp)
* which point we'll call zfs_unlinked_drain() to process it).
*/
dmu_tx_abort(tx);
+ zh = zfs_znode_hold_enter(zfsvfs, z_id);
zfs_znode_dmu_fini(zp);
+ zfs_znode_hold_exit(zfsvfs, zh);
goto out;
}
@@ -926,6 +933,74 @@ zfs_dropname(zfs_dirlock_t *dl, znode_t *zp, znode_t *dzp, dmu_tx_t *tx,
return (error);
}
+static int
+zfs_drop_nlink_locked(znode_t *zp, dmu_tx_t *tx, boolean_t *unlinkedp)
+{
+ zfsvfs_t *zfsvfs = ZTOZSB(zp);
+ int zp_is_dir = S_ISDIR(ZTOI(zp)->i_mode);
+ boolean_t unlinked = B_FALSE;
+ sa_bulk_attr_t bulk[3];
+ uint64_t mtime[2], ctime[2];
+ uint64_t links;
+ int count = 0;
+ int error;
+
+ if (zp_is_dir && !zfs_dirempty(zp))
+ return (SET_ERROR(ENOTEMPTY));
+
+ if (ZTOI(zp)->i_nlink <= zp_is_dir) {
+ zfs_panic_recover("zfs: link count on %lu is %u, "
+ "should be at least %u", zp->z_id,
+ (int)ZTOI(zp)->i_nlink, zp_is_dir + 1);
+ set_nlink(ZTOI(zp), zp_is_dir + 1);
+ }
+ drop_nlink(ZTOI(zp));
+ if (ZTOI(zp)->i_nlink == zp_is_dir) {
+ zp->z_unlinked = B_TRUE;
+ clear_nlink(ZTOI(zp));
+ unlinked = B_TRUE;
+ } else {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs),
+ NULL, &ctime, sizeof (ctime));
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+ NULL, &zp->z_pflags, sizeof (zp->z_pflags));
+ zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime,
+ ctime);
+ }
+ links = ZTOI(zp)->i_nlink;
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs),
+ NULL, &links, sizeof (links));
+ error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
+ ASSERT3U(error, ==, 0);
+
+ if (unlinkedp != NULL)
+ *unlinkedp = unlinked;
+ else if (unlinked)
+ zfs_unlinked_add(zp, tx);
+
+ return (0);
+}
+
+/*
+ * Forcefully drop an nlink reference from (zp) and mark it for deletion if it
+ * was the last link. This *must* only be done to znodes which have already
+ * been zfs_link_destroy()'d with ZRENAMING. This is explicitly only used in
+ * the error path of zfs_rename(), where we have to correct the nlink count if
+ * we failed to link the target as well as failing to re-link the original
+ * znodes.
+ */
+int
+zfs_drop_nlink(znode_t *zp, dmu_tx_t *tx, boolean_t *unlinkedp)
+{
+ int error;
+
+ mutex_enter(&zp->z_lock);
+ error = zfs_drop_nlink_locked(zp, tx, unlinkedp);
+ mutex_exit(&zp->z_lock);
+
+ return (error);
+}
+
/*
* Unlink zp from dl, and mark zp for deletion if this was the last link. Can
* fail if zp is a mount point (EBUSY) or a non-empty directory (ENOTEMPTY).
@@ -966,31 +1041,9 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
return (error);
}
- if (ZTOI(zp)->i_nlink <= zp_is_dir) {
- zfs_panic_recover("zfs: link count on %lu is %u, "
- "should be at least %u", zp->z_id,
- (int)ZTOI(zp)->i_nlink, zp_is_dir + 1);
- set_nlink(ZTOI(zp), zp_is_dir + 1);
- }
- drop_nlink(ZTOI(zp));
- if (ZTOI(zp)->i_nlink == zp_is_dir) {
- zp->z_unlinked = B_TRUE;
- clear_nlink(ZTOI(zp));
- unlinked = B_TRUE;
- } else {
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs),
- NULL, &ctime, sizeof (ctime));
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
- NULL, &zp->z_pflags, sizeof (zp->z_pflags));
- zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime,
- ctime);
- }
- links = ZTOI(zp)->i_nlink;
- SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs),
- NULL, &links, sizeof (links));
- error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
- count = 0;
- ASSERT(error == 0);
+ /* The only error is !zfs_dirempty() and we checked earlier. */
+ error = zfs_drop_nlink_locked(zp, tx, &unlinked);
+ ASSERT3U(error, ==, 0);
mutex_exit(&zp->z_lock);
} else {
error = zfs_dropname(dl, zp, dzp, tx, flag);
@@ -1066,11 +1119,8 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr)
*xzpp = NULL;
- if ((error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr)))
- return (error);
-
if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL,
- &acl_ids)) != 0)
+ &acl_ids, zfs_init_idmap)) != 0)
return (error);
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) {
zfs_acl_ids_free(&acl_ids);
@@ -1218,7 +1268,8 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
cr, ZFS_OWNER);
if ((uid = crgetuid(cr)) == downer || uid == fowner ||
- zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0)
+ zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr,
+ zfs_init_idmap) == 0)
return (0);
else
return (secpolicy_vnode_remove(cr));
diff --git a/module/os/linux/zfs/zfs_file_os.c b/module/os/linux/zfs/zfs_file_os.c
index e12f7c3ced43..bc753614be27 100644
--- a/module/os/linux/zfs/zfs_file_os.c
+++ b/module/os/linux/zfs/zfs_file_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -246,7 +246,7 @@ zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
{
loff_t rc;
- if (*offp < 0 || *offp > MAXOFFSET_T)
+ if (*offp < 0)
return (EINVAL);
rc = vfs_llseek(fp, *offp, whence);
diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c
index 67b864aa77a9..663474ea49ab 100644
--- a/module/os/linux/zfs/zfs_ioctl_os.c
+++ b/module/os/linux/zfs/zfs_ioctl_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -135,7 +135,7 @@ zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
vecnum = cmd - ZFS_IOC_FIRST;
- zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
+ zc = vmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
if (ddi_copyin((void *)(uintptr_t)arg, zc, sizeof (zfs_cmd_t), 0)) {
error = -SET_ERROR(EFAULT);
@@ -146,7 +146,7 @@ zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
if (error == 0 && rc != 0)
error = -SET_ERROR(EFAULT);
out:
- kmem_free(zc, sizeof (zfs_cmd_t));
+ vmem_free(zc, sizeof (zfs_cmd_t));
return (error);
}
@@ -282,6 +282,8 @@ zfsdev_detach(void)
#define ZFS_DEBUG_STR ""
#endif
+zidmap_t *zfs_init_idmap;
+
static int
openzfs_init_os(void)
{
@@ -305,6 +307,8 @@ openzfs_init_os(void)
printk(KERN_NOTICE "ZFS: Posix ACLs disabled by kernel\n");
#endif /* CONFIG_FS_POSIX_ACL */
+ zfs_init_idmap = (zidmap_t *)zfs_get_init_idmap();
+
return (0);
}
@@ -369,8 +373,7 @@ MODULE_ALIAS("zcommon");
MODULE_ALIAS("zzstd");
MODULE_DESCRIPTION("ZFS");
MODULE_AUTHOR(ZFS_META_AUTHOR);
-MODULE_LICENSE("Lua: MIT");
-MODULE_LICENSE("zstd: Dual BSD/GPL");
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_LICENSE("Dual MIT/GPL"); /* lua */
+MODULE_LICENSE("Dual BSD/GPL"); /* zstd / misc */
MODULE_LICENSE(ZFS_META_LICENSE);
MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE);
diff --git a/module/os/linux/zfs/zfs_sysfs.c b/module/os/linux/zfs/zfs_sysfs.c
index eb7c5f6166d2..e2431fe8a803 100644
--- a/module/os/linux/zfs/zfs_sysfs.c
+++ b/module/os/linux/zfs/zfs_sysfs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -279,11 +279,11 @@ zprop_sysfs_show(const char *attr_name, const zprop_desc_t *property,
for (int i = 0; i < ARRAY_SIZE(type_map); i++) {
if (type_map[i].ztm_type & property->pd_types) {
- len += snprintf(buf + len, buflen - len, "%s ",
- type_map[i].ztm_name);
+ len += kmem_scnprintf(buf + len, buflen - len,
+ "%s ", type_map[i].ztm_name);
}
}
- len += snprintf(buf + len, buflen - len, "\n");
+ len += kmem_scnprintf(buf + len, buflen - len, "\n");
return (len);
}
diff --git a/module/os/linux/zfs/zfs_uio.c b/module/os/linux/zfs/zfs_uio.c
index abb6dbe67cdf..c2ed67c438c6 100644
--- a/module/os/linux/zfs/zfs_uio.c
+++ b/module/os/linux/zfs/zfs_uio.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -204,22 +204,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
this_seg_start = orig_loffset;
rq_for_each_segment(bv, rq, iter) {
- if (uio->iter.bio) {
- /*
- * If uio->iter.bio is present, then we know we've saved
- * uio->iter from a previous call to this function, and
- * we can skip ahead in this rq_for_each_segment() loop
- * to where we last left off. That way, we don't need
- * to iterate over tons of segments we've already
- * processed - we can just restore the "saved state".
- */
- iter = uio->iter;
- bv = uio->bv;
- this_seg_start = uio->uio_loffset;
- memset(&uio->iter, 0, sizeof (uio->iter));
- continue;
- }
-
/*
* Lookup what the logical offset of the last byte of this
* segment is.
@@ -260,19 +244,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
copied = 1; /* We copied some data */
}
- if (n == 0) {
- /*
- * All done copying. Save our 'iter' value to the uio.
- * This allows us to "save our state" and skip ahead in
- * the rq_for_each_segment() loop the next time we call
- * call zfs_uiomove_bvec_rq() on this uio (which we
- * will be doing for any remaining data in the uio).
- */
- uio->iter = iter; /* make a copy of the struct data */
- uio->bv = bv;
- return (0);
- }
-
this_seg_start = this_seg_end + 1;
}
diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c
index a67ba821d06f..2015c20d7340 100644
--- a/module/os/linux/zfs/zfs_vfsops.c
+++ b/module/os/linux/zfs/zfs_vfsops.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -56,7 +56,6 @@
#include <sys/sunddi.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_dir.h>
-#include <sys/spa_boot.h>
#include <sys/objlist.h>
#include <sys/zpl.h>
#include <linux/vfs_compat.h>
@@ -274,8 +273,10 @@ zfs_sync(struct super_block *sb, int wait, cred_t *cr)
* Sync a specific filesystem.
*/
dsl_pool_t *dp;
+ int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
dp = dmu_objset_pool(zfsvfs->z_os);
/*
@@ -283,14 +284,14 @@ zfs_sync(struct super_block *sb, int wait, cred_t *cr)
* filesystems which may exist on a suspended pool.
*/
if (spa_suspended(dp->dp_spa)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
if (zfsvfs->z_log != NULL)
zil_commit(zfsvfs->z_log, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
} else {
/*
* Sync all ZFS filesystems. This is what happens when you
@@ -607,7 +608,8 @@ zfs_get_temporary_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, uint64_t *val,
}
if (tmp != *val) {
- (void) strcpy(setpoint, "temporary");
+ if (setpoint)
+ (void) strcpy(setpoint, "temporary");
*val = tmp;
}
return (0);
@@ -783,9 +785,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);
}
@@ -825,6 +825,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);
@@ -848,8 +849,6 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
if (error)
return (error);
- zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
-
/*
* If we are not mounting (ie: online recv), then we don't
* have to worry about replaying the log as we blocked all
@@ -857,7 +856,11 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
*/
if (mounting) {
ASSERT3P(zfsvfs->z_kstat.dk_kstats, ==, NULL);
- dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os);
+ error = dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os);
+ if (error)
+ return (error);
+ zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data,
+ &zfsvfs->z_kstat.dk_zil_sums);
/*
* During replay we remove the read only flag to
@@ -921,6 +924,10 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
/* restore readonly bit */
if (readonly != 0)
readonly_changed_cb(zfsvfs, B_TRUE);
+ } else {
+ ASSERT3P(zfsvfs->z_kstat.dk_kstats, !=, NULL);
+ zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data,
+ &zfsvfs->z_kstat.dk_zil_sums);
}
/*
@@ -1087,7 +1094,8 @@ zfs_statvfs(struct inode *ip, struct kstatfs *statp)
uint64_t refdbytes, availbytes, usedobjs, availobjs;
int err = 0;
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
dmu_objset_space(zfsvfs->z_os,
&refdbytes, &availbytes, &usedobjs, &availobjs);
@@ -1148,7 +1156,7 @@ zfs_statvfs(struct inode *ip, struct kstatfs *statp)
err = zfs_statfs_project(zfsvfs, zp, statp, bshift);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -1158,13 +1166,14 @@ zfs_root(zfsvfs_t *zfsvfs, struct inode **ipp)
znode_t *rootzp;
int error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
if (error == 0)
*ipp = ZTOI(rootzp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1185,7 +1194,7 @@ zfs_prune_aliases(zfsvfs_t *zfsvfs, unsigned long nr_to_scan)
int objects = 0;
int i = 0, j = 0;
- zp_array = kmem_zalloc(max_array * sizeof (znode_t *), KM_SLEEP);
+ zp_array = vmem_zalloc(max_array * sizeof (znode_t *), KM_SLEEP);
mutex_enter(&zfsvfs->z_znodes_lock);
while ((zp = list_head(&zfsvfs->z_all_znodes)) != NULL) {
@@ -1221,7 +1230,7 @@ zfs_prune_aliases(zfsvfs_t *zfsvfs, unsigned long nr_to_scan)
zrele(zp);
}
- kmem_free(zp_array, max_array * sizeof (znode_t *));
+ vmem_free(zp_array, max_array * sizeof (znode_t *));
return (objects);
}
@@ -1231,23 +1240,30 @@ zfs_prune_aliases(zfsvfs_t *zfsvfs, unsigned long nr_to_scan)
* and inode caches. This can occur when the ARC needs to free meta data
* blocks but can't because they are all pinned by entries in these caches.
*/
+#if defined(HAVE_SUPER_BLOCK_S_SHRINK)
+#define S_SHRINK(sb) (&(sb)->s_shrink)
+#elif defined(HAVE_SUPER_BLOCK_S_SHRINK_PTR)
+#define S_SHRINK(sb) ((sb)->s_shrink)
+#endif
+
int
zfs_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
{
zfsvfs_t *zfsvfs = sb->s_fs_info;
int error = 0;
- struct shrinker *shrinker = &sb->s_shrink;
+ struct shrinker *shrinker = S_SHRINK(sb);
struct shrink_control sc = {
.nr_to_scan = nr_to_scan,
.gfp_mask = GFP_KERNEL,
};
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
#if defined(HAVE_SPLIT_SHRINKER_CALLBACK) && \
defined(SHRINK_CONTROL_HAS_NID) && \
defined(SHRINKER_NUMA_AWARE)
- if (sb->s_shrink.flags & SHRINKER_NUMA_AWARE) {
+ if (shrinker->flags & SHRINKER_NUMA_AWARE) {
*objects = 0;
for_each_online_node(sc.nid) {
*objects += (*shrinker->scan_objects)(shrinker, &sc);
@@ -1283,7 +1299,7 @@ zfs_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
*objects = zfs_prune_aliases(zfsvfs, nr_to_scan);
#endif
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
dprintf_ds(zfsvfs->z_os->os_dsl_dataset,
"pruning, nr_to_scan=%lu objects=%d error=%d\n",
@@ -1320,12 +1336,11 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
* may add the parents of dir-based xattrs to the taskq
* so we want to wait for these.
*
- * We can safely read z_nr_znodes without locking because the
- * VFS has already blocked operations which add to the
- * z_all_znodes list and thus increment z_nr_znodes.
+ * We can safely check z_all_znodes for being empty because the
+ * VFS has already blocked operations which add to it.
*/
int round = 0;
- while (zfsvfs->z_nr_znodes > 0) {
+ while (!list_is_empty(&zfsvfs->z_all_znodes)) {
taskq_wait_outstanding(dsl_pool_zrele_taskq(
dmu_objset_pool(zfsvfs->z_os)), 0);
if (++round > 1 && !unmounting)
@@ -1479,7 +1494,7 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
* read-only flag, pretend it was set, as done for snapshots.
*/
if (!canwrite)
- vfs->vfs_readonly = true;
+ vfs->vfs_readonly = B_TRUE;
error = zfsvfs_create(osname, vfs->vfs_readonly, &zfsvfs);
if (error) {
@@ -1513,7 +1528,6 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
sb->s_op = &zpl_super_operations;
sb->s_xattr = zpl_xattr_handlers;
sb->s_export_op = &zpl_export_operations;
- sb->s_d_op = &zpl_dentry_operations;
/* Set features for file system. */
zfs_set_fuid_feature(zfsvfs);
@@ -1547,6 +1561,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;
}
@@ -1554,6 +1569,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;
}
@@ -1651,6 +1667,7 @@ zfs_umount(struct super_block *sb)
}
zfsvfs_free(zfsvfs);
+ sb->s_fs_info = NULL;
return (0);
}
@@ -1740,7 +1757,8 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
return (zfsctl_snapdir_vget(sb, objsetid, fid_gen, ipp));
}
- ZFS_ENTER(zfsvfs);
+ if ((err = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (err);
/* A zero fid_gen means we are in the .zfs control directories */
if (fid_gen == 0 &&
(object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) {
@@ -1756,7 +1774,7 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
*/
VERIFY3P(igrab(*ipp), !=, NULL);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1764,14 +1782,14 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
dprintf("getting %llu [%llu mask %llx]\n", object, fid_gen, gen_mask);
if ((err = zfs_zget(zfsvfs, object, &zp))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
/* Don't export xattr stuff */
if (zp->z_pflags & ZFS_XATTR) {
zrele(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOENT));
}
@@ -1786,7 +1804,7 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
dprintf("znode gen (%llu) != fid gen (%llu)\n", zp_gen,
fid_gen);
zrele(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOENT));
}
@@ -1794,7 +1812,7 @@ zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp)
if (*ipp)
zfs_znode_update_vfs(ITOZ(*ipp));
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1869,8 +1887,8 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
zp = list_next(&zfsvfs->z_all_znodes, zp)) {
err2 = zfs_rezget(zp);
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() */
@@ -2041,91 +2059,6 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
}
/*
- * Read a property stored within the master node.
- */
-int
-zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
-{
- uint64_t *cached_copy = NULL;
-
- /*
- * Figure out where in the objset_t the cached copy would live, if it
- * is available for the requested property.
- */
- if (os != NULL) {
- switch (prop) {
- case ZFS_PROP_VERSION:
- cached_copy = &os->os_version;
- break;
- case ZFS_PROP_NORMALIZE:
- cached_copy = &os->os_normalization;
- break;
- case ZFS_PROP_UTF8ONLY:
- cached_copy = &os->os_utf8only;
- break;
- case ZFS_PROP_CASE:
- cached_copy = &os->os_casesensitivity;
- break;
- default:
- break;
- }
- }
- if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
- *value = *cached_copy;
- return (0);
- }
-
- /*
- * If the property wasn't cached, look up the file system's value for
- * the property. For the version property, we look up a slightly
- * different string.
- */
- const char *pname;
- int error = ENOENT;
- if (prop == ZFS_PROP_VERSION)
- pname = ZPL_VERSION_STR;
- else
- pname = zfs_prop_to_name(prop);
-
- if (os != NULL) {
- ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
- error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
- }
-
- if (error == ENOENT) {
- /* No value set, use the default value */
- switch (prop) {
- case ZFS_PROP_VERSION:
- *value = ZPL_VERSION;
- break;
- case ZFS_PROP_NORMALIZE:
- case ZFS_PROP_UTF8ONLY:
- *value = 0;
- break;
- case ZFS_PROP_CASE:
- *value = ZFS_CASE_SENSITIVE;
- break;
- case ZFS_PROP_ACLTYPE:
- *value = ZFS_ACLTYPE_OFF;
- break;
- default:
- return (error);
- }
- error = 0;
- }
-
- /*
- * If one of the methods for getting the property value above worked,
- * copy it into the objset_t's cache.
- */
- if (error == 0 && cached_copy != NULL) {
- *cached_copy = *value;
- }
-
- return (error);
-}
-
-/*
* Return true if the corresponding vfs's unmounted flag is set.
* Otherwise return false.
* If this function returns true we know VFS unmount has been initiated.
@@ -2164,6 +2097,9 @@ zfs_init(void)
zfs_znode_init();
dmu_objset_register_type(DMU_OST_ZFS, zpl_get_file_info);
register_filesystem(&zpl_fs_type);
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+ register_fo_extend(&zpl_file_operations);
+#endif
}
void
@@ -2174,6 +2110,9 @@ zfs_fini(void)
*/
taskq_wait(system_delay_taskq);
taskq_wait(system_taskq);
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+ unregister_fo_extend(&zpl_file_operations);
+#endif
unregister_filesystem(&zpl_fs_type);
zfs_znode_fini();
zfsctl_fini();
diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
index d6ff838806eb..1cecad9f7755 100644
--- a/module/os/linux/zfs/zfs_vnops_os.c
+++ b/module/os/linux/zfs/zfs_vnops_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -82,13 +82,13 @@
* to freed memory. The example below illustrates the following Big Rules:
*
* (1) A check must be made in each zfs thread for a mounted file system.
- * This is done avoiding races using ZFS_ENTER(zfsvfs).
- * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes
- * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros
+ * This is done avoiding races using zfs_enter(zfsvfs).
+ * A zfs_exit(zfsvfs) is needed before all returns. Any znodes
+ * must be checked with zfs_verify_zp(zp). Both of these macros
* can return EIO from the calling function.
*
* (2) zrele() should always be the last thing except for zil_commit() (if
- * necessary) and ZFS_EXIT(). This is for 3 reasons: First, if it's the
+ * necessary) and zfs_exit(). This is for 3 reasons: First, if it's the
* last reference, the vnode/znode can be freed, so the zp may point to
* freed memory. Second, the last reference will call zfs_zinactive(),
* which may induce a lot of work -- pushing cached pages (which acquires
@@ -107,7 +107,7 @@
* dmu_tx_assign(). This is critical because we don't want to block
* while holding locks.
*
- * If no ZPL locks are held (aside from ZFS_ENTER()), use TXG_WAIT. This
+ * If no ZPL locks are held (aside from zfs_enter()), use TXG_WAIT. This
* reduces lock contention and CPU usage when we must wait (note that if
* throughput is constrained by the storage, nearly every transaction
* must wait).
@@ -142,7 +142,7 @@
*
* In general, this is how things should be ordered in each vnode op:
*
- * ZFS_ENTER(zfsvfs); // exit if unmounted
+ * zfs_enter(zfsvfs); // exit if unmounted
* top:
* zfs_dirent_lock(&dl, ...) // lock directory entry (may igrab())
* rw_enter(...); // grab any other locks you need
@@ -160,7 +160,7 @@
* goto top;
* }
* dmu_tx_abort(tx); // abort DMU tx
- * ZFS_EXIT(zfsvfs); // finished in zfs
+ * zfs_exit(zfsvfs); // finished in zfs
* return (error); // really out of space
* }
* error = do_real_work(); // do whatever this VOP does
@@ -171,7 +171,7 @@
* zfs_dirent_unlock(dl); // unlock directory entry
* zrele(...); // release held znodes
* zil_commit(zilog, foid); // synchronous when necessary
- * ZFS_EXIT(zfsvfs); // finished in zfs
+ * zfs_exit(zfsvfs); // finished in zfs
* return (error); // done, report error
*/
int
@@ -180,22 +180,29 @@ zfs_open(struct inode *ip, int mode, int flag, cred_t *cr)
(void) cr;
znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
/* Honor ZFS_APPENDONLY file attribute */
- if ((mode & FMODE_WRITE) && (zp->z_pflags & ZFS_APPENDONLY) &&
+ if (blk_mode_is_open_write(mode) && (zp->z_pflags & ZFS_APPENDONLY) &&
((flag & O_APPEND) == 0)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- /* Keep a count of the synchronous opens in the znode */
- if (flag & O_SYNC)
- atomic_inc_32(&zp->z_sync_cnt);
+ /*
+ * Keep a count of the synchronous opens in the znode. On first
+ * synchronous open we must convert all previous async transactions
+ * into sync to keep correct ordering.
+ */
+ if (flag & O_SYNC) {
+ if (atomic_inc_32_nv(&zp->z_sync_cnt) == 1)
+ zil_async_to_sync(zfsvfs->z_log, zp->z_id);
+ }
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -205,56 +212,60 @@ zfs_close(struct inode *ip, int flag, cred_t *cr)
(void) cr;
znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
/* Decrement the synchronous opens in the znode */
if (flag & O_SYNC)
atomic_dec_32(&zp->z_sync_cnt);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
#if defined(_KERNEL)
+
+static int zfs_fillpage(struct inode *ip, struct page *pp);
+
/*
* When a file is memory mapped, we must keep the IO data synchronized
- * between the DMU cache and the memory mapped pages. What this means:
- *
- * On Write: If we find a memory mapped page, we write to *both*
- * the page and the dmu buffer.
+ * between the DMU cache and the memory mapped pages. Update all mapped
+ * pages with the contents of the coresponding dmu buffer.
*/
void
update_pages(znode_t *zp, int64_t start, int len, objset_t *os)
{
- struct inode *ip = ZTOI(zp);
- struct address_space *mp = ip->i_mapping;
- struct page *pp;
- uint64_t nbytes;
- int64_t off;
- void *pb;
+ struct address_space *mp = ZTOI(zp)->i_mapping;
+ int64_t off = start & (PAGE_SIZE - 1);
- off = start & (PAGE_SIZE-1);
for (start &= PAGE_MASK; len > 0; start += PAGE_SIZE) {
- nbytes = MIN(PAGE_SIZE - off, len);
+ uint64_t nbytes = MIN(PAGE_SIZE - off, len);
- pp = find_lock_page(mp, start >> PAGE_SHIFT);
+ struct page *pp = find_lock_page(mp, start >> PAGE_SHIFT);
if (pp) {
if (mapping_writably_mapped(mp))
flush_dcache_page(pp);
- pb = kmap(pp);
- (void) dmu_read(os, zp->z_id, start + off, nbytes,
- pb + off, DMU_READ_PREFETCH);
+ void *pb = kmap(pp);
+ int error = dmu_read(os, zp->z_id, start + off,
+ nbytes, pb + off, DMU_READ_PREFETCH);
kunmap(pp);
- if (mapping_writably_mapped(mp))
- flush_dcache_page(pp);
+ if (error) {
+ SetPageError(pp);
+ ClearPageUptodate(pp);
+ } else {
+ ClearPageError(pp);
+ SetPageUptodate(pp);
+
+ if (mapping_writably_mapped(mp))
+ flush_dcache_page(pp);
+
+ mark_page_accessed(pp);
+ }
- mark_page_accessed(pp);
- SetPageUptodate(pp);
- ClearPageError(pp);
unlock_page(pp);
put_page(pp);
}
@@ -265,38 +276,44 @@ update_pages(znode_t *zp, int64_t start, int len, objset_t *os)
}
/*
- * When a file is memory mapped, we must keep the IO data synchronized
- * between the DMU cache and the memory mapped pages. What this means:
- *
- * On Read: We "read" preferentially from memory mapped pages,
- * else we default from the dmu buffer.
- *
- * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
- * the file is memory mapped.
+ * When a file is memory mapped, we must keep the I/O data synchronized
+ * between the DMU cache and the memory mapped pages. Preferentially read
+ * from memory mapped pages, otherwise fallback to reading through the dmu.
*/
int
mappedread(znode_t *zp, int nbytes, zfs_uio_t *uio)
{
struct inode *ip = ZTOI(zp);
struct address_space *mp = ip->i_mapping;
- struct page *pp;
- int64_t start, off;
- uint64_t bytes;
+ int64_t start = uio->uio_loffset;
+ int64_t off = start & (PAGE_SIZE - 1);
int len = nbytes;
int error = 0;
- void *pb;
- start = uio->uio_loffset;
- off = start & (PAGE_SIZE-1);
for (start &= PAGE_MASK; len > 0; start += PAGE_SIZE) {
- bytes = MIN(PAGE_SIZE - off, len);
+ uint64_t bytes = MIN(PAGE_SIZE - off, len);
- pp = find_lock_page(mp, start >> PAGE_SHIFT);
+ struct page *pp = find_lock_page(mp, start >> PAGE_SHIFT);
if (pp) {
- ASSERT(PageUptodate(pp));
+ /*
+ * If filemap_fault() retries there exists a window
+ * where the page will be unlocked and not up to date.
+ * In this case we must try and fill the page.
+ */
+ if (unlikely(!PageUptodate(pp))) {
+ error = zfs_fillpage(ip, pp);
+ if (error) {
+ unlock_page(pp);
+ put_page(pp);
+ return (error);
+ }
+ }
+
+ ASSERT(PageUptodate(pp) || PageDirty(pp));
+
unlock_page(pp);
- pb = kmap(pp);
+ void *pb = kmap(pp);
error = zfs_uiomove(pb + off, bytes, UIO_READ, uio);
kunmap(pp);
@@ -312,9 +329,11 @@ mappedread(znode_t *zp, int nbytes, zfs_uio_t *uio)
len -= bytes;
off = 0;
+
if (error)
break;
}
+
return (error);
}
#endif /* _KERNEL */
@@ -449,8 +468,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
}
}
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zdp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zdp, FTAG)) != 0)
+ return (error);
*zpp = NULL;
@@ -460,12 +479,12 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
* Maybe someday we will.
*/
if (zdp->z_pflags & ZFS_XATTR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if ((error = zfs_get_xattrdir(zdp, zpp, cr, flags))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -474,17 +493,17 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
*/
if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0,
- B_TRUE, cr))) {
+ B_TRUE, cr, zfs_init_idmap))) {
zrele(*zpp);
*zpp = NULL;
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (!S_ISDIR(ZTOI(zdp)->i_mode)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOTDIR));
}
@@ -492,14 +511,15 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
* Check accessibility of directory.
*/
- if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr,
+ zfs_init_idmap))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
@@ -507,7 +527,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
if ((error == 0) && (*zpp))
zfs_znode_update_vfs(*zpp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -524,6 +544,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
* cr - credentials of caller.
* flag - file flag.
* vsecp - ACL to be set
+ * mnt_ns - user namespace of the mount
*
* OUT: zpp - znode of created or trunc'd entry.
*
@@ -535,7 +556,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr,
*/
int
zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
- int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp)
+ int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp,
+ zidmap_t *mnt_ns)
{
znode_t *zp;
zfsvfs_t *zfsvfs = ZTOZSB(dzp);
@@ -550,6 +572,7 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
boolean_t fuid_dirtied;
boolean_t have_acl = B_FALSE;
boolean_t waited = B_FALSE;
+ boolean_t skip_acl = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
/*
* If we have an ephemeral id, ACL, or XVATTR then
@@ -566,21 +589,21 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
if (name == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (vap->va_mask & ATTR_XVATTR) {
if ((error = secpolicy_xvattr((xvattr_t *)vap,
crgetuid(cr), cr, vap->va_mode)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
@@ -609,7 +632,7 @@ top:
zfs_acl_ids_free(&acl_ids);
if (strcmp(name, "..") == 0)
error = SET_ERROR(EISDIR);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
@@ -622,7 +645,8 @@ top:
* Create a new file object and update the directory
* to reference it.
*/
- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, skip_acl, cr,
+ mnt_ns))) {
if (have_acl)
zfs_acl_ids_free(&acl_ids);
goto out;
@@ -641,7 +665,7 @@ top:
}
if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap,
- cr, vsecp, &acl_ids)) != 0)
+ cr, vsecp, &acl_ids, mnt_ns)) != 0)
goto out;
have_acl = B_TRUE;
@@ -681,7 +705,7 @@ top:
}
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
@@ -714,7 +738,6 @@ top:
if (have_acl)
zfs_acl_ids_free(&acl_ids);
- have_acl = B_FALSE;
/*
* A directory entry already exists for this name.
@@ -736,7 +759,8 @@ top:
/*
* Verify requested access to file.
*/
- if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr))) {
+ if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr,
+ mnt_ns))) {
goto out;
}
@@ -774,13 +798,14 @@ out:
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
int
zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl,
- int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp)
+ int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp,
+ zidmap_t *mnt_ns)
{
(void) excl, (void) mode, (void) flag;
znode_t *zp = NULL, *dzp = ITOZ(dip);
@@ -808,14 +833,14 @@ zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl,
(vsecp || IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
os = zfsvfs->z_os;
if (vap->va_mask & ATTR_XVATTR) {
if ((error = secpolicy_xvattr((xvattr_t *)vap,
crgetuid(cr), cr, vap->va_mode)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
@@ -827,14 +852,14 @@ top:
* Create a new file object and update the directory
* to reference it.
*/
- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) {
if (have_acl)
zfs_acl_ids_free(&acl_ids);
goto out;
}
if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap,
- cr, vsecp, &acl_ids)) != 0)
+ cr, vsecp, &acl_ids, mnt_ns)) != 0)
goto out;
have_acl = B_TRUE;
@@ -870,7 +895,7 @@ top:
}
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
zfs_mknode(dzp, vap, tx, cr, IS_TMPFILE, &zp, &acl_ids);
@@ -894,7 +919,7 @@ out:
*ipp = ZTOI(zp);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -941,8 +966,8 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags)
if (name == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (flags & FIGNORECASE) {
@@ -961,11 +986,11 @@ top:
NULL, realnmp))) {
if (realnmp)
pn_free(realnmp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_idmap))) {
goto out;
}
@@ -979,7 +1004,7 @@ top:
mutex_enter(&zp->z_lock);
may_delete_now = atomic_read(&ZTOI(zp)->i_count) == 1 &&
- !(zp->z_is_mapped);
+ !zn_has_cached_data(zp, 0, LLONG_MAX);
mutex_exit(&zp->z_lock);
/*
@@ -1042,7 +1067,7 @@ top:
zrele(zp);
if (xzp)
zrele(xzp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1067,8 +1092,10 @@ top:
&xattr_obj_unlinked, sizeof (xattr_obj_unlinked));
delete_now = may_delete_now && !toobig &&
atomic_read(&ZTOI(zp)->i_count) == 1 &&
- !(zp->z_is_mapped) && xattr_obj == xattr_obj_unlinked &&
+ !zn_has_cached_data(zp, 0, LLONG_MAX) &&
+ xattr_obj == xattr_obj_unlinked &&
zfs_external_acl(zp) == acl_obj;
+ VERIFY_IMPLY(xattr_obj_unlinked, xzp);
}
if (delete_now) {
@@ -1131,7 +1158,7 @@ out:
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1145,6 +1172,7 @@ out:
* cr - credentials of caller.
* flags - case flags.
* vsecp - ACL to be set
+ * mnt_ns - user namespace of the mount
*
* OUT: zpp - znode of created directory.
*
@@ -1157,7 +1185,7 @@ out:
*/
int
zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp,
- cred_t *cr, int flags, vsecattr_t *vsecp)
+ cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_t *mnt_ns)
{
znode_t *zp;
zfsvfs_t *zfsvfs = ZTOZSB(dzp);
@@ -1188,18 +1216,18 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp,
if (dirname == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (dzp->z_pflags & ZFS_XATTR) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if (zfsvfs->z_utf8 && u8_validate(dirname,
strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (flags & FIGNORECASE)
@@ -1208,14 +1236,14 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp,
if (vap->va_mask & ATTR_XVATTR) {
if ((error = secpolicy_xvattr((xvattr_t *)vap,
crgetuid(cr), cr, vap->va_mode)) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
}
if ((error = zfs_acl_ids_create(dzp, 0, vap, cr,
- vsecp, &acl_ids)) != 0) {
- ZFS_EXIT(zfsvfs);
+ vsecp, &acl_ids, mnt_ns)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
/*
@@ -1231,21 +1259,22 @@ top:
if ((error = zfs_dirent_lock(&dl, dzp, dirname, &zp, zf,
NULL, NULL))) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr,
+ mnt_ns))) {
zfs_acl_ids_free(&acl_ids);
zfs_dirent_unlock(dl);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zfs_inherit_projid(dzp))) {
zfs_acl_ids_free(&acl_ids);
zfs_dirent_unlock(dl);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EDQUOT));
}
@@ -1277,7 +1306,7 @@ top:
}
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1323,7 +1352,7 @@ out:
zfs_znode_update_vfs(dzp);
zfs_znode_update_vfs(zp);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1359,8 +1388,8 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr,
if (name == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (flags & FIGNORECASE)
@@ -1373,11 +1402,11 @@ top:
*/
if ((error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
NULL, NULL))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
+ if ((error = zfs_zaccess_delete(dzp, zp, cr, zfs_init_idmap))) {
goto out;
}
@@ -1424,7 +1453,7 @@ top:
}
dmu_tx_abort(tx);
zrele(zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1452,7 +1481,7 @@ out:
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1491,8 +1520,8 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
uint64_t parent;
uint64_t offset; /* must be unsigned; checks for < 1 */
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
&parent, sizeof (parent))) != 0)
@@ -1587,11 +1616,8 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
if (done)
break;
- /* Prefetch znode */
- if (prefetch) {
- dmu_prefetch(os, objnum, 0, 0, 0,
- ZIO_PRIORITY_SYNC_READ);
- }
+ if (prefetch)
+ dmu_prefetch_dnode(os, objnum, ZIO_PRIORITY_SYNC_READ);
/*
* Move to the next entry, fill in the previous offset.
@@ -1611,7 +1637,7 @@ update:
if (error == ENOENT)
error = 0;
out:
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -1629,20 +1655,29 @@ out:
* RETURN: 0 (always succeeds)
*/
int
-zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip,
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK
+zfs_getattr_fast(zidmap_t *user_ns, u32 request_mask, struct inode *ip,
struct kstat *sp)
+#else
+zfs_getattr_fast(zidmap_t *user_ns, struct inode *ip, struct kstat *sp)
+#endif
{
znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
uint32_t blksize;
u_longlong_t nblocks;
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
mutex_enter(&zp->z_lock);
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK
+ zpl_generic_fillattr(user_ns, request_mask, ip, sp);
+#else
zpl_generic_fillattr(user_ns, ip, sp);
+#endif
/*
* +1 link count for root inode with visible '.zfs' directory.
*/
@@ -1673,7 +1708,7 @@ zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip,
dmu_objset_id(zfsvfs->z_os);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -1808,6 +1843,7 @@ next:
* flags - ATTR_UTIME set if non-default time values provided.
* - ATTR_NOACLCHECK (CIFS context only).
* cr - credentials of caller.
+ * mnt_ns - user namespace of the mount
*
* RETURN: 0 if success
* error code if failure
@@ -1816,11 +1852,11 @@ next:
* ip - ctime updated, mtime updated if size changed.
*/
int
-zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
+zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
{
struct inode *ip;
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- objset_t *os = zfsvfs->z_os;
+ objset_t *os;
zilog_t *zilog;
dmu_tx_t *tx;
vattr_t oldva;
@@ -1849,9 +1885,10 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
if (mask == 0)
return (0);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((err = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (err);
ip = ZTOI(zp);
+ os = zfsvfs->z_os;
/*
* If this is a xvattr_t, then get a pointer to the structure of
@@ -1862,13 +1899,13 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
if (XVA_ISSET_REQ(xvap, XAT_PROJID)) {
if (!dmu_objset_projectquota_enabled(os) ||
(!S_ISREG(ip->i_mode) && !S_ISDIR(ip->i_mode))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOTSUP));
}
projid = xoap->xoa_projid;
if (unlikely(projid == ZFS_INVALID_PROJID)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -1883,7 +1920,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
((zp->z_pflags & ZFS_PROJINHERIT) != 0)) &&
(!dmu_objset_projectquota_enabled(os) ||
(!S_ISREG(ip->i_mode) && !S_ISDIR(ip->i_mode)))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOTSUP));
}
}
@@ -1899,17 +1936,17 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
(((mask & ATTR_UID) && IS_EPHEMERAL(vap->va_uid)) ||
((mask & ATTR_GID) && IS_EPHEMERAL(vap->va_gid)) ||
(mask & ATTR_XVATTR))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
if (mask & ATTR_SIZE && S_ISDIR(ip->i_mode)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EISDIR));
}
if (mask & ATTR_SIZE && !S_ISREG(ip->i_mode) && !S_ISFIFO(ip->i_mode)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -1965,7 +2002,8 @@ top:
*/
if (mask & ATTR_SIZE) {
- err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr);
+ err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr,
+ mnt_ns);
if (err)
goto out3;
@@ -1990,13 +2028,15 @@ top:
XVA_ISSET_REQ(xvap, XAT_CREATETIME) ||
XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) {
need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0,
- skipaclchk, cr);
+ skipaclchk, cr, mnt_ns);
}
if (mask & (ATTR_UID|ATTR_GID)) {
int idmask = (mask & (ATTR_UID|ATTR_GID));
int take_owner;
int take_group;
+ uid_t uid;
+ gid_t gid;
/*
* NOTE: even if a new mode is being set,
@@ -2010,9 +2050,13 @@ top:
* Take ownership or chgrp to group we are a member of
*/
- take_owner = (mask & ATTR_UID) && (vap->va_uid == crgetuid(cr));
+ uid = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ip),
+ vap->va_uid);
+ gid = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ip),
+ vap->va_gid);
+ take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr));
take_group = (mask & ATTR_GID) &&
- zfs_groupmember(zfsvfs, vap->va_gid, cr);
+ zfs_groupmember(zfsvfs, gid, cr);
/*
* If both ATTR_UID and ATTR_GID are set then take_owner and
@@ -2028,7 +2072,7 @@ top:
((idmask == ATTR_UID) && take_owner) ||
((idmask == ATTR_GID) && take_group)) {
if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0,
- skipaclchk, cr) == 0) {
+ skipaclchk, cr, mnt_ns) == 0) {
/*
* Remove setuid/setgid for non-privileged users
*/
@@ -2141,12 +2185,12 @@ top:
mutex_exit(&zp->z_lock);
if (mask & ATTR_MODE) {
- if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) {
+ if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr,
+ mnt_ns) == 0) {
err = secpolicy_setid_setsticky_clear(ip, vap,
- &oldva, cr);
+ &oldva, cr, mnt_ns, zfs_i_user_ns(ip));
if (err)
goto out3;
-
trim_mask |= ATTR_MODE;
} else {
need_policy = TRUE;
@@ -2167,7 +2211,7 @@ top:
vap->va_mask &= ~trim_mask;
}
err = secpolicy_vnode_setattr(cr, ip, vap, &oldva, flags,
- (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp);
+ zfs_zaccess_unix, zp);
if (err)
goto out3;
@@ -2395,15 +2439,16 @@ top:
if ((mask & ATTR_ATIME) || zp->z_atime_dirty) {
zp->z_atime_dirty = B_FALSE;
- ZFS_TIME_ENCODE(&ip->i_atime, atime);
+ inode_timespec_t tmp_atime = zpl_inode_get_atime(ip);
+ ZFS_TIME_ENCODE(&tmp_atime, atime);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
&atime, sizeof (atime));
}
if (mask & (ATTR_MTIME | ATTR_SIZE)) {
ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
- ZTOI(zp)->i_mtime = zpl_inode_timestamp_truncate(
- vap->va_mtime, ZTOI(zp));
+ zpl_inode_set_mtime_to_ts(ZTOI(zp),
+ zpl_inode_timestamp_truncate(vap->va_mtime, ZTOI(zp)));
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
mtime, sizeof (mtime));
@@ -2411,8 +2456,8 @@ top:
if (mask & (ATTR_CTIME | ATTR_SIZE)) {
ZFS_TIME_ENCODE(&vap->va_ctime, ctime);
- ZTOI(zp)->i_ctime = zpl_inode_timestamp_truncate(vap->va_ctime,
- ZTOI(zp));
+ zpl_inode_set_ctime_to_ts(ZTOI(zp),
+ zpl_inode_timestamp_truncate(vap->va_ctime, ZTOI(zp)));
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
ctime, sizeof (ctime));
}
@@ -2512,7 +2557,7 @@ out:
dmu_tx_commit(tx);
if (attrzp) {
if (err2 == 0 && handle_eadir)
- err2 = zfs_setattr_dir(attrzp);
+ err = zfs_setattr_dir(attrzp);
zrele(attrzp);
}
zfs_znode_update_vfs(zp);
@@ -2526,7 +2571,7 @@ out3:
kmem_free(xattr_bulk, sizeof (sa_bulk_attr_t) * bulks);
kmem_free(bulk, sizeof (sa_bulk_attr_t) * bulks);
kmem_free(tmpxvattr, sizeof (xvattr_t));
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -2637,6 +2682,9 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
* tnm - New entry name.
* cr - credentials of caller.
* flags - case flags
+ * rflags - RENAME_* flags
+ * wa_vap - attributes for RENAME_WHITEOUT (must be a char 0:0).
+ * mnt_ns - user namespace of the mount
*
* RETURN: 0 on success, error code on failure.
*
@@ -2645,7 +2693,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
*/
int
zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm,
- cred_t *cr, int flags)
+ cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap, zidmap_t *mnt_ns)
{
znode_t *szp, *tzp;
zfsvfs_t *zfsvfs = ZTOZSB(sdzp);
@@ -2657,15 +2705,41 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm,
int error = 0;
int zflg = 0;
boolean_t waited = B_FALSE;
+ /* Needed for whiteout inode creation. */
+ boolean_t fuid_dirtied;
+ zfs_acl_ids_t acl_ids;
+ boolean_t have_acl = B_FALSE;
+ znode_t *wzp = NULL;
+
if (snm == NULL || tnm == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(sdzp);
+ if (rflags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
+ return (SET_ERROR(EINVAL));
+
+ /* Already checked by Linux VFS, but just to make sure. */
+ if (rflags & RENAME_EXCHANGE &&
+ (rflags & (RENAME_NOREPLACE | RENAME_WHITEOUT)))
+ return (SET_ERROR(EINVAL));
+
+ /*
+ * Make sure we only get wo_vap iff. RENAME_WHITEOUT and that it's the
+ * right kind of vattr_t for the whiteout file. These are set
+ * internally by ZFS so should never be incorrect.
+ */
+ VERIFY_EQUIV(rflags & RENAME_WHITEOUT, wo_vap != NULL);
+ VERIFY_IMPLY(wo_vap, wo_vap->va_mode == S_IFCHR);
+ VERIFY_IMPLY(wo_vap, wo_vap->va_rdev == makedevice(0, 0));
+
+ if ((error = zfs_enter_verify_zp(zfsvfs, sdzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
- ZFS_VERIFY_ZP(tdzp);
+ if ((error = zfs_verify_zp(tdzp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
/*
* We check i_sb because snapshots and the ctldir must have different
@@ -2673,13 +2747,13 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm,
*/
if (ZTOI(tdzp)->i_sb != ZTOI(sdzp)->i_sb ||
zfsctl_is_node(ZTOI(tdzp))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EXDEV));
}
if (zfsvfs->z_utf8 && u8_validate(tnm,
strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
@@ -2697,7 +2771,7 @@ top:
* See the comment in zfs_link() for why this is considered bad.
*/
if ((tdzp->z_pflags & ZFS_XATTR) != (sdzp->z_pflags & ZFS_XATTR)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -2727,7 +2801,7 @@ top:
* the rename() function shall return successfully
* and perform no other action."
*/
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
/*
@@ -2799,7 +2873,7 @@ top:
if (strcmp(snm, "..") == 0)
serr = EINVAL;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (serr);
}
if (terr) {
@@ -2811,7 +2885,7 @@ top:
if (strcmp(tnm, "..") == 0)
terr = EINVAL;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (terr);
}
@@ -2834,8 +2908,7 @@ top:
* Note that if target and source are the same, this can be
* done in a single check.
*/
-
- if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)))
+ if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, mnt_ns)))
goto out;
if (S_ISDIR(ZTOI(szp)->i_mode)) {
@@ -2851,17 +2924,19 @@ top:
* Does target exist?
*/
if (tzp) {
+ if (rflags & RENAME_NOREPLACE) {
+ error = SET_ERROR(EEXIST);
+ goto out;
+ }
/*
- * Source and target must be the same type.
+ * Source and target must be the same type (unless exchanging).
*/
- if (S_ISDIR(ZTOI(szp)->i_mode)) {
- if (!S_ISDIR(ZTOI(tzp)->i_mode)) {
- error = SET_ERROR(ENOTDIR);
- goto out;
- }
- } else {
- if (S_ISDIR(ZTOI(tzp)->i_mode)) {
- error = SET_ERROR(EISDIR);
+ if (!(rflags & RENAME_EXCHANGE)) {
+ boolean_t s_is_dir = S_ISDIR(ZTOI(szp)->i_mode) != 0;
+ boolean_t t_is_dir = S_ISDIR(ZTOI(tzp)->i_mode) != 0;
+
+ if (s_is_dir != t_is_dir) {
+ error = SET_ERROR(s_is_dir ? ENOTDIR : EISDIR);
goto out;
}
}
@@ -2874,12 +2949,43 @@ top:
error = 0;
goto out;
}
+ } else if (rflags & RENAME_EXCHANGE) {
+ /* Target must exist for RENAME_EXCHANGE. */
+ error = SET_ERROR(ENOENT);
+ goto out;
+ }
+
+ /* Set up inode creation for RENAME_WHITEOUT. */
+ if (rflags & RENAME_WHITEOUT) {
+ /*
+ * Whiteout files are not regular files or directories, so to
+ * match zfs_create() we do not inherit the project id.
+ */
+ uint64_t wo_projid = ZFS_DEFAULT_PROJID;
+
+ error = zfs_zaccess(sdzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns);
+ if (error)
+ goto out;
+
+ if (!have_acl) {
+ error = zfs_acl_ids_create(sdzp, 0, wo_vap, cr, NULL,
+ &acl_ids, mnt_ns);
+ if (error)
+ goto out;
+ have_acl = B_TRUE;
+ }
+
+ if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, wo_projid)) {
+ error = SET_ERROR(EDQUOT);
+ goto out;
+ }
}
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_sa(tx, szp->z_sa_hdl, B_FALSE);
dmu_tx_hold_sa(tx, sdzp->z_sa_hdl, B_FALSE);
- dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm);
+ dmu_tx_hold_zap(tx, sdzp->z_id,
+ (rflags & RENAME_EXCHANGE) ? TRUE : FALSE, snm);
dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm);
if (sdzp != tdzp) {
dmu_tx_hold_sa(tx, tdzp->z_sa_hdl, B_FALSE);
@@ -2889,7 +2995,21 @@ top:
dmu_tx_hold_sa(tx, tzp->z_sa_hdl, B_FALSE);
zfs_sa_upgrade_txholds(tx, tzp);
}
+ if (rflags & RENAME_WHITEOUT) {
+ dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes +
+ ZFS_SA_BASE_ATTR_SIZE);
+ dmu_tx_hold_zap(tx, sdzp->z_id, TRUE, snm);
+ dmu_tx_hold_sa(tx, sdzp->z_sa_hdl, B_FALSE);
+ if (!zfsvfs->z_use_sa &&
+ acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
+ dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
+ 0, acl_ids.z_aclp->z_acl_bytes);
+ }
+ }
+ fuid_dirtied = zfsvfs->z_fuid_dirty;
+ if (fuid_dirtied)
+ zfs_fuid_txhold(zfsvfs, tx);
zfs_sa_upgrade_txholds(tx, szp);
dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
error = dmu_tx_assign(tx, (waited ? TXG_NOTHROTTLE : 0) | TXG_NOWAIT);
@@ -2915,62 +3035,114 @@ top:
zrele(szp);
if (tzp)
zrele(tzp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if (tzp) /* Attempt to remove the existing target */
- error = zfs_link_destroy(tdl, tzp, tx, zflg, NULL);
+ /*
+ * Unlink the source.
+ */
+ szp->z_pflags |= ZFS_AV_MODIFIED;
+ if (tdzp->z_pflags & ZFS_PROJINHERIT)
+ szp->z_pflags |= ZFS_PROJINHERIT;
- if (error == 0) {
- error = zfs_link_create(tdl, szp, tx, ZRENAMING);
- if (error == 0) {
- szp->z_pflags |= ZFS_AV_MODIFIED;
- if (tdzp->z_pflags & ZFS_PROJINHERIT)
- szp->z_pflags |= ZFS_PROJINHERIT;
-
- error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
- (void *)&szp->z_pflags, sizeof (uint64_t), tx);
+ error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
+ (void *)&szp->z_pflags, sizeof (uint64_t), tx);
+ VERIFY0(error);
+
+ error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
+ if (error)
+ goto commit;
+
+ /*
+ * Unlink the target.
+ */
+ if (tzp) {
+ int tzflg = zflg;
+
+ if (rflags & RENAME_EXCHANGE) {
+ /* This inode will be re-linked soon. */
+ tzflg |= ZRENAMING;
+
+ tzp->z_pflags |= ZFS_AV_MODIFIED;
+ if (sdzp->z_pflags & ZFS_PROJINHERIT)
+ tzp->z_pflags |= ZFS_PROJINHERIT;
+
+ error = sa_update(tzp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
+ (void *)&tzp->z_pflags, sizeof (uint64_t), tx);
ASSERT0(error);
+ }
+ error = zfs_link_destroy(tdl, tzp, tx, tzflg, NULL);
+ if (error)
+ goto commit_link_szp;
+ }
- error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
- if (error == 0) {
- zfs_log_rename(zilog, tx, TX_RENAME |
- (flags & FIGNORECASE ? TX_CI : 0), sdzp,
- sdl->dl_name, tdzp, tdl->dl_name, szp);
- } else {
- /*
- * At this point, we have successfully created
- * the target name, but have failed to remove
- * the source name. Since the create was done
- * with the ZRENAMING flag, there are
- * complications; for one, the link count is
- * wrong. The easiest way to deal with this
- * is to remove the newly created target, and
- * return the original error. This must
- * succeed; fortunately, it is very unlikely to
- * fail, since we just created it.
- */
- VERIFY3U(zfs_link_destroy(tdl, szp, tx,
- ZRENAMING, NULL), ==, 0);
- }
- } else {
- /*
- * If we had removed the existing target, subsequent
- * call to zfs_link_create() to add back the same entry
- * but, the new dnode (szp) should not fail.
- */
- ASSERT(tzp == NULL);
+ /*
+ * Create the new target links:
+ * * We always link the target.
+ * * RENAME_EXCHANGE: Link the old target to the source.
+ * * RENAME_WHITEOUT: Create a whiteout inode in-place of the source.
+ */
+ error = zfs_link_create(tdl, szp, tx, ZRENAMING);
+ if (error) {
+ /*
+ * If we have removed the existing target, a subsequent call to
+ * zfs_link_create() to add back the same entry, but with a new
+ * dnode (szp), should not fail.
+ */
+ ASSERT3P(tzp, ==, NULL);
+ goto commit_link_tzp;
+ }
+
+ switch (rflags & (RENAME_EXCHANGE | RENAME_WHITEOUT)) {
+ case RENAME_EXCHANGE:
+ error = zfs_link_create(sdl, tzp, tx, ZRENAMING);
+ /*
+ * The same argument as zfs_link_create() failing for
+ * szp applies here, since the source directory must
+ * have had an entry we are replacing.
+ */
+ ASSERT0(error);
+ if (error)
+ goto commit_unlink_td_szp;
+ break;
+ case RENAME_WHITEOUT:
+ zfs_mknode(sdzp, wo_vap, tx, cr, 0, &wzp, &acl_ids);
+ error = zfs_link_create(sdl, wzp, tx, ZNEW);
+ if (error) {
+ zfs_znode_delete(wzp, tx);
+ remove_inode_hash(ZTOI(wzp));
+ goto commit_unlink_td_szp;
}
+ break;
}
+ if (fuid_dirtied)
+ zfs_fuid_sync(zfsvfs, tx);
+
+ switch (rflags & (RENAME_EXCHANGE | RENAME_WHITEOUT)) {
+ case RENAME_EXCHANGE:
+ zfs_log_rename_exchange(zilog, tx,
+ (flags & FIGNORECASE ? TX_CI : 0), sdzp, sdl->dl_name,
+ tdzp, tdl->dl_name, szp);
+ break;
+ case RENAME_WHITEOUT:
+ zfs_log_rename_whiteout(zilog, tx,
+ (flags & FIGNORECASE ? TX_CI : 0), sdzp, sdl->dl_name,
+ tdzp, tdl->dl_name, szp, wzp);
+ break;
+ default:
+ ASSERT0(rflags & ~RENAME_NOREPLACE);
+ zfs_log_rename(zilog, tx, (flags & FIGNORECASE ? TX_CI : 0),
+ sdzp, sdl->dl_name, tdzp, tdl->dl_name, szp);
+ break;
+ }
+
+commit:
dmu_tx_commit(tx);
out:
- if (zl != NULL)
- zfs_rename_unlock(&zl);
-
- zfs_dirent_unlock(sdl);
- zfs_dirent_unlock(tdl);
+ if (have_acl)
+ zfs_acl_ids_free(&acl_ids);
zfs_znode_update_vfs(sdzp);
if (sdzp == tdzp)
@@ -2981,16 +3153,57 @@ out:
zfs_znode_update_vfs(szp);
zrele(szp);
+ if (wzp) {
+ zfs_znode_update_vfs(wzp);
+ zrele(wzp);
+ }
if (tzp) {
zfs_znode_update_vfs(tzp);
zrele(tzp);
}
+ if (zl != NULL)
+ zfs_rename_unlock(&zl);
+
+ zfs_dirent_unlock(sdl);
+ zfs_dirent_unlock(tdl);
+
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
+
+ /*
+ * Clean-up path for broken link state.
+ *
+ * At this point we are in a (very) bad state, so we need to do our
+ * best to correct the state. In particular, all of the nlinks are
+ * wrong because we were destroying and creating links with ZRENAMING.
+ *
+ * In some form, all of these operations have to resolve the state:
+ *
+ * * link_destroy() *must* succeed. Fortunately, this is very likely
+ * since we only just created it.
+ *
+ * * link_create()s are allowed to fail (though they shouldn't because
+ * we only just unlinked them and are putting the entries back
+ * during clean-up). But if they fail, we can just forcefully drop
+ * the nlink value to (at the very least) avoid broken nlink values
+ * -- though in the case of non-empty directories we will have to
+ * panic (otherwise we'd have a leaked directory with a broken ..).
+ */
+commit_unlink_td_szp:
+ VERIFY0(zfs_link_destroy(tdl, szp, tx, ZRENAMING, NULL));
+commit_link_tzp:
+ if (tzp) {
+ if (zfs_link_create(tdl, tzp, tx, ZRENAMING))
+ VERIFY0(zfs_drop_nlink(tzp, tx, NULL));
+ }
+commit_link_szp:
+ if (zfs_link_create(sdl, szp, tx, ZRENAMING))
+ VERIFY0(zfs_drop_nlink(szp, tx, NULL));
+ goto commit;
}
/*
@@ -3002,6 +3215,7 @@ out:
* link - Name for new symlink entry.
* cr - credentials of caller.
* flags - case flags
+ * mnt_ns - user namespace of the mount
*
* OUT: zpp - Znode for new symbolic link.
*
@@ -3012,7 +3226,7 @@ out:
*/
int
zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link,
- znode_t **zpp, cred_t *cr, int flags)
+ znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns)
{
znode_t *zp;
zfs_dirlock_t *dl;
@@ -3032,26 +3246,26 @@ zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link,
if (name == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(dzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, dzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (flags & FIGNORECASE)
zflg |= ZCILOOK;
if (len > MAXPATHLEN) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENAMETOOLONG));
}
if ((error = zfs_acl_ids_create(dzp, 0,
- vap, cr, NULL, &acl_ids)) != 0) {
- ZFS_EXIT(zfsvfs);
+ vap, cr, NULL, &acl_ids, mnt_ns)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
top:
@@ -3063,21 +3277,21 @@ top:
error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL);
if (error) {
zfs_acl_ids_free(&acl_ids);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+ if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) {
zfs_acl_ids_free(&acl_ids);
zfs_dirent_unlock(dl);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, ZFS_DEFAULT_PROJID)) {
zfs_acl_ids_free(&acl_ids);
zfs_dirent_unlock(dl);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EDQUOT));
}
tx = dmu_tx_create(zfsvfs->z_os);
@@ -3104,7 +3318,7 @@ top:
}
zfs_acl_ids_free(&acl_ids);
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3159,7 +3373,7 @@ top:
zrele(zp);
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3185,8 +3399,8 @@ zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr)
zfsvfs_t *zfsvfs = ITOZSB(ip);
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
mutex_enter(&zp->z_lock);
if (zp->z_is_sa)
@@ -3196,7 +3410,7 @@ zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr)
error = zfs_sa_readlink(zp, uio);
mutex_exit(&zp->z_lock);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3241,8 +3455,8 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
if (name == NULL)
return (SET_ERROR(EINVAL));
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(tdzp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, tdzp, FTAG)) != 0)
+ return (error);
zilog = zfsvfs->z_log;
/*
@@ -3250,11 +3464,14 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
* Better choices include ENOTSUP or EISDIR.
*/
if (S_ISDIR(sip->i_mode)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- ZFS_VERIFY_ZP(szp);
+ if ((error = zfs_verify_zp(szp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
/*
* If we are using project inheritance, means if the directory has
@@ -3265,7 +3482,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
*/
if (tdzp->z_pflags & ZFS_PROJINHERIT &&
tdzp->z_projid != szp->z_projid) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EXDEV));
}
@@ -3274,7 +3491,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
* super blocks.
*/
if (sip->i_sb != ZTOI(tdzp)->i_sb || zfsctl_is_node(sip)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EXDEV));
}
@@ -3282,17 +3499,17 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
if ((error = sa_lookup(szp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
&parent, sizeof (uint64_t))) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
if (parent == zfsvfs->z_shares_dir) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
if (zfsvfs->z_utf8 && u8_validate(name,
strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EILSEQ));
}
if (flags & FIGNORECASE)
@@ -3305,19 +3522,20 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr,
* imposed in attribute space.
*/
if ((szp->z_pflags & ZFS_XATTR) != (tdzp->z_pflags & ZFS_XATTR)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
owner = zfs_fuid_map_id(zfsvfs, KUID_TO_SUID(sip->i_uid),
cr, ZFS_OWNER);
if (owner != crgetuid(cr) && secpolicy_basic_link(cr) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
- if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr,
+ zfs_init_idmap))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3327,7 +3545,7 @@ top:
*/
error = zfs_dirent_lock(&dl, tdzp, name, &tzp, zf, NULL, NULL);
if (error) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3349,7 +3567,7 @@ top:
goto top;
}
dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
/* unmark z_unlinked so zfs_link_create will not reject */
@@ -3391,7 +3609,7 @@ top:
zfs_znode_update_vfs(tdzp);
zfs_znode_update_vfs(szp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3444,12 +3662,13 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
caddr_t va;
int err = 0;
uint64_t mtime[2], ctime[2];
+ inode_timespec_t tmp_ts;
sa_bulk_attr_t bulk[3];
int cnt = 0;
struct address_space *mapping;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((err = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (err);
ASSERT(PageLocked(pp));
@@ -3461,7 +3680,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
/* Page is beyond end of file */
if (pgoff >= offset) {
unlock_page(pp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3521,7 +3740,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
if (unlikely((mapping != pp->mapping) || !PageDirty(pp))) {
unlock_page(pp);
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3549,7 +3768,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
#endif
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3557,7 +3776,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
if (!clear_page_dirty_for_io(pp)) {
unlock_page(pp);
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3576,11 +3795,8 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
zfs_sa_upgrade_txholds(tx, zp);
- err = dmu_tx_assign(tx, TXG_NOWAIT);
+ err = dmu_tx_assign(tx, TXG_WAIT);
if (err != 0) {
- if (err == ERESTART)
- dmu_tx_wait(tx);
-
dmu_tx_abort(tx);
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
filemap_dirty_folio(page_mapping(pp), page_folio(pp));
@@ -3592,7 +3808,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
if (!for_sync)
atomic_dec_32(&zp->z_async_writes_cnt);
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -3607,28 +3823,23 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
&zp->z_pflags, 8);
/* Preserve the mtime and ctime provided by the inode */
- ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
- ZFS_TIME_ENCODE(&ip->i_ctime, ctime);
+ tmp_ts = zpl_inode_get_mtime(ip);
+ ZFS_TIME_ENCODE(&tmp_ts, mtime);
+ tmp_ts = zpl_inode_get_ctime(ip);
+ ZFS_TIME_ENCODE(&tmp_ts, ctime);
zp->z_atime_dirty = B_FALSE;
zp->z_seq++;
err = sa_bulk_update(zp->z_sa_hdl, bulk, cnt, tx);
- zfs_log_write(zfsvfs->z_log, tx, TX_WRITE, zp, pgoff, pglen, 0,
- for_sync ? zfs_putpage_sync_commit_cb :
- zfs_putpage_async_commit_cb, pp);
-
- dmu_tx_commit(tx);
-
- zfs_rangelock_exit(lr);
-
+ boolean_t commit = B_FALSE;
if (wbc->sync_mode != WB_SYNC_NONE) {
/*
* Note that this is rarely called under writepages(), because
* writepages() normally handles the entire commit for
* performance reasons.
*/
- zil_commit(zfsvfs->z_log, zp->z_id);
+ commit = B_TRUE;
} else if (!for_sync && atomic_load_32(&zp->z_sync_writes_cnt) > 0) {
/*
* If the caller does not intend to wait synchronously
@@ -3638,12 +3849,23 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc,
* our writeback to complete. Refer to the comment in
* zpl_fsync() (when HAVE_FSYNC_RANGE is defined) for details.
*/
- zil_commit(zfsvfs->z_log, zp->z_id);
+ commit = B_TRUE;
}
+ zfs_log_write(zfsvfs->z_log, tx, TX_WRITE, zp, pgoff, pglen, commit,
+ for_sync ? zfs_putpage_sync_commit_cb :
+ zfs_putpage_async_commit_cb, pp);
+
+ dmu_tx_commit(tx);
+
+ zfs_rangelock_exit(lr);
+
+ if (commit)
+ zil_commit(zfsvfs->z_log, zp->z_id);
+
dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, pglen);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (err);
}
@@ -3658,6 +3880,7 @@ zfs_dirty_inode(struct inode *ip, int flags)
zfsvfs_t *zfsvfs = ITOZSB(ip);
dmu_tx_t *tx;
uint64_t mode, atime[2], mtime[2], ctime[2];
+ inode_timespec_t tmp_ts;
sa_bulk_attr_t bulk[4];
int error = 0;
int cnt = 0;
@@ -3665,8 +3888,8 @@ zfs_dirty_inode(struct inode *ip, int flags)
if (zfs_is_readonly(zfsvfs) || dmu_objset_is_snapshot(zfsvfs->z_os))
return (0);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
#ifdef I_DIRTY_TIME
/*
@@ -3702,9 +3925,12 @@ zfs_dirty_inode(struct inode *ip, int flags)
SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
/* Preserve the mode, mtime and ctime provided by the inode */
- ZFS_TIME_ENCODE(&ip->i_atime, atime);
- ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
- ZFS_TIME_ENCODE(&ip->i_ctime, ctime);
+ tmp_ts = zpl_inode_get_atime(ip);
+ ZFS_TIME_ENCODE(&tmp_ts, atime);
+ tmp_ts = zpl_inode_get_mtime(ip);
+ ZFS_TIME_ENCODE(&tmp_ts, mtime);
+ tmp_ts = zpl_inode_get_ctime(ip);
+ ZFS_TIME_ENCODE(&tmp_ts, ctime);
mode = ip->i_mode;
zp->z_mode = mode;
@@ -3714,7 +3940,7 @@ zfs_dirty_inode(struct inode *ip, int flags)
dmu_tx_commit(tx);
out:
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3747,7 +3973,9 @@ zfs_inactive(struct inode *ip)
if (error) {
dmu_tx_abort(tx);
} else {
- ZFS_TIME_ENCODE(&ip->i_atime, atime);
+ inode_timespec_t tmp_atime;
+ tmp_atime = zpl_inode_get_atime(ip);
+ ZFS_TIME_ENCODE(&tmp_atime, atime);
mutex_enter(&zp->z_lock);
(void) sa_update(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs),
(void *)&atime, sizeof (atime), tx);
@@ -3766,55 +3994,45 @@ zfs_inactive(struct inode *ip)
* Fill pages with data from the disk.
*/
static int
-zfs_fillpage(struct inode *ip, struct page *pl[], int nr_pages)
+zfs_fillpage(struct inode *ip, struct page *pp)
{
- znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
- objset_t *os;
- struct page *cur_pp;
- u_offset_t io_off, total;
- size_t io_len;
- loff_t i_size;
- unsigned page_idx;
- int err;
+ loff_t i_size = i_size_read(ip);
+ u_offset_t io_off = page_offset(pp);
+ size_t io_len = PAGE_SIZE;
- os = zfsvfs->z_os;
- io_len = nr_pages << PAGE_SHIFT;
- i_size = i_size_read(ip);
- io_off = page_offset(pl[0]);
+ ASSERT3U(io_off, <, i_size);
if (io_off + io_len > i_size)
io_len = i_size - io_off;
- /*
- * Iterate over list of pages and read each page individually.
- */
- page_idx = 0;
- for (total = io_off + io_len; io_off < total; io_off += PAGESIZE) {
- caddr_t va;
+ void *va = kmap(pp);
+ int error = dmu_read(zfsvfs->z_os, ITOZ(ip)->z_id, io_off,
+ io_len, va, DMU_READ_PREFETCH);
+ if (io_len != PAGE_SIZE)
+ memset((char *)va + io_len, 0, PAGE_SIZE - io_len);
+ kunmap(pp);
- cur_pp = pl[page_idx++];
- va = kmap(cur_pp);
- err = dmu_read(os, zp->z_id, io_off, PAGESIZE, va,
- DMU_READ_PREFETCH);
- kunmap(cur_pp);
- if (err) {
- /* convert checksum errors into IO errors */
- if (err == ECKSUM)
- err = SET_ERROR(EIO);
- return (err);
- }
+ if (error) {
+ /* convert checksum errors into IO errors */
+ if (error == ECKSUM)
+ error = SET_ERROR(EIO);
+
+ SetPageError(pp);
+ ClearPageUptodate(pp);
+ } else {
+ ClearPageError(pp);
+ SetPageUptodate(pp);
}
- return (0);
+ return (error);
}
/*
- * Uses zfs_fillpage to read data from the file and fill the pages.
+ * Uses zfs_fillpage to read data from the file and fill the page.
*
* IN: ip - inode of file to get data from.
- * pl - list of pages to read
- * nr_pages - number of pages to read
+ * pp - page to read
*
* RETURN: 0 on success, error code on failure.
*
@@ -3822,24 +4040,22 @@ zfs_fillpage(struct inode *ip, struct page *pl[], int nr_pages)
* vp - atime updated
*/
int
-zfs_getpage(struct inode *ip, struct page *pl[], int nr_pages)
+zfs_getpage(struct inode *ip, struct page *pp)
{
- znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
- int err;
-
- if (pl == NULL)
- return (0);
+ znode_t *zp = ITOZ(ip);
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
- err = zfs_fillpage(ip, pl, nr_pages);
+ error = zfs_fillpage(ip, pp);
+ if (error == 0)
+ dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, PAGE_SIZE);
- dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, nr_pages*PAGESIZE);
+ zfs_exit(zfsvfs, FTAG);
- ZFS_EXIT(zfsvfs);
- return (err);
+ return (error);
}
/*
@@ -3861,28 +4077,29 @@ zfs_map(struct inode *ip, offset_t off, caddr_t *addrp, size_t len,
(void) addrp;
znode_t *zp = ITOZ(ip);
zfsvfs_t *zfsvfs = ITOZSB(ip);
+ int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
- if ((vm_flags & VM_WRITE) && (zp->z_pflags &
- (ZFS_IMMUTABLE | ZFS_READONLY | ZFS_APPENDONLY))) {
- ZFS_EXIT(zfsvfs);
+ if ((vm_flags & VM_WRITE) && (vm_flags & VM_SHARED) &&
+ (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY | ZFS_APPENDONLY))) {
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
if ((vm_flags & (VM_READ | VM_EXEC)) &&
(zp->z_pflags & ZFS_AV_QUARANTINED)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EACCES));
}
if (off < 0 || len > MAXOFFSET_T - off) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENXIO));
}
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -3913,11 +4130,11 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
uint64_t off, len;
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if (cmd != F_FREESP) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -3926,12 +4143,12 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
* so check it explicitly here.
*/
if (zfs_is_readonly(zfsvfs)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EROFS));
}
if (bfp->l_len < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -3941,8 +4158,9 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
* On Linux we can get here through truncate_range() which
* operates directly on inodes, so we need to check access rights.
*/
- if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr))) {
- ZFS_EXIT(zfsvfs);
+ if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr,
+ zfs_init_idmap))) {
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3951,7 +4169,7 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag,
error = zfs_freesp(zp, off, len, flag, TRUE);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3966,19 +4184,23 @@ zfs_fid(struct inode *ip, fid_t *fidp)
zfid_short_t *zfid;
int size, i, error;
- ZFS_ENTER(zfsvfs);
+ if ((error = zfs_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (fidp->fid_len < SHORT_FID_LEN) {
fidp->fid_len = SHORT_FID_LEN;
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(ENOSPC));
}
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_verify_zp(zp)) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
&gen64, sizeof (uint64_t))) != 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -3999,7 +4221,7 @@ zfs_fid(struct inode *ip, fid_t *fidp)
for (i = 0; i < sizeof (zfid->zf_gen); i++)
zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -4030,5 +4252,4 @@ EXPORT_SYMBOL(zfs_map);
/* CSTYLED */
module_param(zfs_delete_blocks, ulong, 0644);
MODULE_PARM_DESC(zfs_delete_blocks, "Delete files larger than N blocks async");
-
#endif
diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c
index dc504b1a120b..b99df188c64b 100644
--- a/module/os/linux/zfs/zfs_znode.c
+++ b/module/os/linux/zfs/zfs_znode.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -169,8 +169,7 @@ zfs_znode_hold_cache_constructor(void *buf, void *arg, int kmflags)
znode_hold_t *zh = buf;
mutex_init(&zh->zh_lock, NULL, MUTEX_DEFAULT, NULL);
- zfs_refcount_create(&zh->zh_refcount);
- zh->zh_obj = ZFS_NO_OBJECT;
+ zh->zh_refcount = 0;
return (0);
}
@@ -182,7 +181,6 @@ zfs_znode_hold_cache_destructor(void *buf, void *arg)
znode_hold_t *zh = buf;
mutex_destroy(&zh->zh_lock);
- zfs_refcount_destroy(&zh->zh_refcount);
}
void
@@ -273,7 +271,7 @@ zfs_znode_held(zfsvfs_t *zfsvfs, uint64_t obj)
return (held);
}
-static znode_hold_t *
+znode_hold_t *
zfs_znode_hold_enter(zfsvfs_t *zfsvfs, uint64_t obj)
{
znode_hold_t *zh, *zh_new, search;
@@ -281,43 +279,43 @@ zfs_znode_hold_enter(zfsvfs_t *zfsvfs, uint64_t obj)
boolean_t found = B_FALSE;
zh_new = kmem_cache_alloc(znode_hold_cache, KM_SLEEP);
- zh_new->zh_obj = obj;
search.zh_obj = obj;
mutex_enter(&zfsvfs->z_hold_locks[i]);
zh = avl_find(&zfsvfs->z_hold_trees[i], &search, NULL);
if (likely(zh == NULL)) {
zh = zh_new;
+ zh->zh_obj = obj;
avl_add(&zfsvfs->z_hold_trees[i], zh);
} else {
ASSERT3U(zh->zh_obj, ==, obj);
found = B_TRUE;
}
- zfs_refcount_add(&zh->zh_refcount, NULL);
+ zh->zh_refcount++;
+ ASSERT3S(zh->zh_refcount, >, 0);
mutex_exit(&zfsvfs->z_hold_locks[i]);
if (found == B_TRUE)
kmem_cache_free(znode_hold_cache, zh_new);
ASSERT(MUTEX_NOT_HELD(&zh->zh_lock));
- ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
mutex_enter(&zh->zh_lock);
return (zh);
}
-static void
+void
zfs_znode_hold_exit(zfsvfs_t *zfsvfs, znode_hold_t *zh)
{
int i = ZFS_OBJ_HASH(zfsvfs, zh->zh_obj);
boolean_t remove = B_FALSE;
ASSERT(zfs_znode_held(zfsvfs, zh->zh_obj));
- ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
mutex_exit(&zh->zh_lock);
mutex_enter(&zfsvfs->z_hold_locks[i]);
- if (zfs_refcount_remove(&zh->zh_refcount, NULL) == 0) {
+ ASSERT3S(zh->zh_refcount, >, 0);
+ if (--zh->zh_refcount == 0) {
avl_remove(&zfsvfs->z_hold_trees[i], zh);
remove = B_TRUE;
}
@@ -359,7 +357,7 @@ zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
void
zfs_znode_dmu_fini(znode_t *zp)
{
- ASSERT(zfs_znode_held(ZTOZSB(zp), zp->z_id) || zp->z_unlinked ||
+ ASSERT(zfs_znode_held(ZTOZSB(zp), zp->z_id) ||
RW_WRITE_HELD(&ZTOZSB(zp)->z_teardown_inactive_lock));
sa_handle_destroy(zp->z_sa_hdl);
@@ -392,7 +390,6 @@ zfs_inode_destroy(struct inode *ip)
mutex_enter(&zfsvfs->z_znodes_lock);
if (list_link_active(&zp->z_link_node)) {
list_remove(&zfsvfs->z_all_znodes, zp);
- zfsvfs->z_nr_znodes--;
}
mutex_exit(&zfsvfs->z_znodes_lock);
@@ -417,12 +414,21 @@ zfs_inode_set_ops(zfsvfs_t *zfsvfs, struct inode *ip)
switch (ip->i_mode & S_IFMT) {
case S_IFREG:
ip->i_op = &zpl_inode_operations;
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+ ip->i_fop = &zpl_file_operations.kabi_fops;
+#else
ip->i_fop = &zpl_file_operations;
+#endif
ip->i_mapping->a_ops = &zpl_address_space_operations;
break;
case S_IFDIR:
+#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
+ ip->i_flags |= S_IOPS_WRAPPER;
+ ip->i_op = &zpl_dir_inode_operations.ops;
+#else
ip->i_op = &zpl_dir_inode_operations;
+#endif
ip->i_fop = &zpl_dir_file_operations;
ITOZ(ip)->z_zn_prefetch = B_TRUE;
break;
@@ -452,7 +458,11 @@ zfs_inode_set_ops(zfsvfs_t *zfsvfs, struct inode *ip)
/* Assume the inode is a file and attempt to continue */
ip->i_mode = S_IFREG | 0644;
ip->i_op = &zpl_inode_operations;
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+ ip->i_fop = &zpl_file_operations.kabi_fops;
+#else
ip->i_fop = &zpl_file_operations;
+#endif
ip->i_mapping->a_ops = &zpl_address_space_operations;
break;
}
@@ -492,13 +502,11 @@ zfs_set_inode_flags(znode_t *zp, struct inode *ip)
void
zfs_znode_update_vfs(znode_t *zp)
{
- zfsvfs_t *zfsvfs;
struct inode *ip;
uint32_t blksize;
u_longlong_t i_blocks;
ASSERT(zp != NULL);
- zfsvfs = ZTOZSB(zp);
ip = ZTOI(zp);
/* Skip .zfs control nodes which do not exist on disk. */
@@ -534,6 +542,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
uint64_t links;
uint64_t z_uid, z_gid;
uint64_t atime[2], mtime[2], ctime[2], btime[2];
+ inode_timespec_t tmp_ts;
uint64_t projid = ZFS_DEFAULT_PROJID;
sa_bulk_attr_t bulk[12];
int count = 0;
@@ -550,9 +559,10 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
ASSERT3P(zp->z_xattr_cached, ==, NULL);
zp->z_unlinked = B_FALSE;
zp->z_atime_dirty = B_FALSE;
+#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
zp->z_is_mapped = B_FALSE;
+#endif
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;
@@ -604,9 +614,12 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
if (zp->z_pflags & ZFS_XATTR)
zp->z_xattr_parent = parent;
- ZFS_TIME_DECODE(&ip->i_atime, atime);
- ZFS_TIME_DECODE(&ip->i_mtime, mtime);
- ZFS_TIME_DECODE(&ip->i_ctime, ctime);
+ ZFS_TIME_DECODE(&tmp_ts, atime);
+ zpl_inode_set_atime_to_ts(ip, tmp_ts);
+ ZFS_TIME_DECODE(&tmp_ts, mtime);
+ zpl_inode_set_mtime_to_ts(ip, tmp_ts);
+ ZFS_TIME_DECODE(&tmp_ts, ctime);
+ zpl_inode_set_ctime_to_ts(ip, tmp_ts);
ZFS_TIME_DECODE(&zp->z_btime, btime);
ip->i_ino = zp->z_id;
@@ -631,7 +644,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp);
- zfsvfs->z_nr_znodes++;
mutex_exit(&zfsvfs->z_znodes_lock);
if (links > 0)
@@ -1187,6 +1199,7 @@ zfs_rezget(znode_t *zp)
uint64_t gen;
uint64_t z_uid, z_gid;
uint64_t atime[2], mtime[2], ctime[2], btime[2];
+ inode_timespec_t tmp_ts;
uint64_t projid = ZFS_DEFAULT_PROJID;
znode_hold_t *zh;
@@ -1279,9 +1292,12 @@ zfs_rezget(znode_t *zp)
zfs_uid_write(ZTOI(zp), z_uid);
zfs_gid_write(ZTOI(zp), z_gid);
- ZFS_TIME_DECODE(&ZTOI(zp)->i_atime, atime);
- ZFS_TIME_DECODE(&ZTOI(zp)->i_mtime, mtime);
- ZFS_TIME_DECODE(&ZTOI(zp)->i_ctime, ctime);
+ ZFS_TIME_DECODE(&tmp_ts, atime);
+ zpl_inode_set_atime_to_ts(ZTOI(zp), tmp_ts);
+ ZFS_TIME_DECODE(&tmp_ts, mtime);
+ zpl_inode_set_mtime_to_ts(ZTOI(zp), tmp_ts);
+ ZFS_TIME_DECODE(&tmp_ts, ctime);
+ zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ts);
ZFS_TIME_DECODE(&zp->z_btime, btime);
if ((uint32_t)gen != ZTOI(zp)->i_generation) {
@@ -1389,21 +1405,24 @@ zfs_zinactive(znode_t *zp)
boolean_t
zfs_relatime_need_update(const struct inode *ip)
{
- inode_timespec_t now;
+ inode_timespec_t now, tmp_atime, tmp_ts;
gethrestime(&now);
+ tmp_atime = zpl_inode_get_atime(ip);
/*
* In relatime mode, only update the atime if the previous atime
* is earlier than either the ctime or mtime or if at least a day
* has passed since the last update of atime.
*/
- if (zfs_compare_timespec(&ip->i_mtime, &ip->i_atime) >= 0)
+ tmp_ts = zpl_inode_get_mtime(ip);
+ if (zfs_compare_timespec(&tmp_ts, &tmp_atime) >= 0)
return (B_TRUE);
- if (zfs_compare_timespec(&ip->i_ctime, &ip->i_atime) >= 0)
+ tmp_ts = zpl_inode_get_ctime(ip);
+ if (zfs_compare_timespec(&tmp_ts, &tmp_atime) >= 0)
return (B_TRUE);
- if ((hrtime_t)now.tv_sec - (hrtime_t)ip->i_atime.tv_sec >= 24*60*60)
+ if ((hrtime_t)now.tv_sec - (hrtime_t)tmp_atime.tv_sec >= 24*60*60)
return (B_TRUE);
return (B_FALSE);
@@ -1426,7 +1445,7 @@ void
zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
uint64_t ctime[2])
{
- inode_timespec_t now;
+ inode_timespec_t now, tmp_ts;
gethrestime(&now);
@@ -1434,7 +1453,8 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
if (flag & ATTR_MTIME) {
ZFS_TIME_ENCODE(&now, mtime);
- ZFS_TIME_DECODE(&(ZTOI(zp)->i_mtime), mtime);
+ ZFS_TIME_DECODE(&tmp_ts, mtime);
+ zpl_inode_set_mtime_to_ts(ZTOI(zp), tmp_ts);
if (ZTOZSB(zp)->z_use_fuids) {
zp->z_pflags |= (ZFS_ARCHIVE |
ZFS_AV_MODIFIED);
@@ -1443,7 +1463,8 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
if (flag & ATTR_CTIME) {
ZFS_TIME_ENCODE(&now, ctime);
- ZFS_TIME_DECODE(&(ZTOI(zp)->i_ctime), ctime);
+ ZFS_TIME_DECODE(&tmp_ts, ctime);
+ zpl_inode_set_ctime_to_ts(ZTOI(zp), tmp_ts);
if (ZTOZSB(zp)->z_use_fuids)
zp->z_pflags |= ZFS_ARCHIVE;
}
@@ -1641,7 +1662,7 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
* Zero partial page cache entries. This must be done under a
* range lock in order to keep the ARC and page cache in sync.
*/
- if (zp->z_is_mapped) {
+ if (zn_has_cached_data(zp, off, off + len - 1)) {
loff_t first_page, last_page, page_len;
loff_t first_page_offset, last_page_offset;
@@ -1864,7 +1885,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
/* For the moment we expect all zpl props to be uint64_ts */
uint64_t val;
- char *name;
+ const char *name;
ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64);
VERIFY(nvpair_value_uint64(elem, &val) == 0);
@@ -1883,6 +1904,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
}
ASSERT(version != 0);
error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
+ ASSERT(error == 0);
/*
* Create zap object used for SA attribute registration
@@ -1960,7 +1982,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
}
VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
- cr, NULL, &acl_ids));
+ cr, NULL, &acl_ids, zfs_init_idmap));
zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
ASSERT3P(zp, ==, rootzp);
error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
@@ -2136,7 +2158,6 @@ zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
} else if (error != ENOENT) {
return (error);
}
- error = 0;
for (;;) {
uint64_t pobj = 0;
@@ -2252,6 +2273,91 @@ zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
return (error);
}
+/*
+ * Read a property stored within the master node.
+ */
+int
+zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
+{
+ uint64_t *cached_copy = NULL;
+
+ /*
+ * Figure out where in the objset_t the cached copy would live, if it
+ * is available for the requested property.
+ */
+ if (os != NULL) {
+ switch (prop) {
+ case ZFS_PROP_VERSION:
+ cached_copy = &os->os_version;
+ break;
+ case ZFS_PROP_NORMALIZE:
+ cached_copy = &os->os_normalization;
+ break;
+ case ZFS_PROP_UTF8ONLY:
+ cached_copy = &os->os_utf8only;
+ break;
+ case ZFS_PROP_CASE:
+ cached_copy = &os->os_casesensitivity;
+ break;
+ default:
+ break;
+ }
+ }
+ if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
+ *value = *cached_copy;
+ return (0);
+ }
+
+ /*
+ * If the property wasn't cached, look up the file system's value for
+ * the property. For the version property, we look up a slightly
+ * different string.
+ */
+ const char *pname;
+ int error = ENOENT;
+ if (prop == ZFS_PROP_VERSION)
+ pname = ZPL_VERSION_STR;
+ else
+ pname = zfs_prop_to_name(prop);
+
+ if (os != NULL) {
+ ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
+ error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
+ }
+
+ if (error == ENOENT) {
+ /* No value set, use the default value */
+ switch (prop) {
+ case ZFS_PROP_VERSION:
+ *value = ZPL_VERSION;
+ break;
+ case ZFS_PROP_NORMALIZE:
+ case ZFS_PROP_UTF8ONLY:
+ *value = 0;
+ break;
+ case ZFS_PROP_CASE:
+ *value = ZFS_CASE_SENSITIVE;
+ break;
+ case ZFS_PROP_ACLTYPE:
+ *value = ZFS_ACLTYPE_OFF;
+ break;
+ default:
+ return (error);
+ }
+ error = 0;
+ }
+
+ /*
+ * If one of the methods for getting the property value above worked,
+ * copy it into the objset_t's cache.
+ */
+ if (error == 0 && cached_copy != NULL) {
+ *cached_copy = *value;
+ }
+
+ return (error);
+}
+
#if defined(_KERNEL)
EXPORT_SYMBOL(zfs_create_fs);
EXPORT_SYMBOL(zfs_obj_to_path);
diff --git a/module/os/linux/zfs/zio_crypt.c b/module/os/linux/zfs/zio_crypt.c
index dcab02b07894..21f3740f6fe6 100644
--- a/module/os/linux/zfs/zio_crypt.c
+++ b/module/os/linux/zfs/zio_crypt.c
@@ -223,14 +223,32 @@ int
zio_crypt_key_init(uint64_t crypt, zio_crypt_key_t *key)
{
int ret;
- crypto_mechanism_t mech;
+ crypto_mechanism_t mech = {0};
uint_t keydata_len;
ASSERT(key != NULL);
ASSERT3U(crypt, <, ZIO_CRYPT_FUNCTIONS);
+/*
+ * Workaround for GCC 12+ with UBSan enabled deficencies.
+ *
+ * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
+ * below as violating -Warray-bounds
+ */
+#if defined(__GNUC__) && !defined(__clang__) && \
+ ((!defined(_KERNEL) && defined(ZFS_UBSAN_ENABLED)) || \
+ defined(CONFIG_UBSAN))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
keydata_len = zio_crypt_table[crypt].ci_keylen;
+#if defined(__GNUC__) && !defined(__clang__) && \
+ ((!defined(_KERNEL) && defined(ZFS_UBSAN_ENABLED)) || \
+ defined(CONFIG_UBSAN))
+#pragma GCC diagnostic pop
+#endif
memset(key, 0, sizeof (zio_crypt_key_t));
+ rw_init(&key->zk_salt_lock, NULL, RW_DEFAULT, NULL);
/* fill keydata buffers and salt with random data */
ret = random_get_bytes((uint8_t *)&key->zk_guid, sizeof (uint64_t));
@@ -282,7 +300,6 @@ zio_crypt_key_init(uint64_t crypt, zio_crypt_key_t *key)
key->zk_crypt = crypt;
key->zk_version = ZIO_CRYPT_KEY_CURRENT_VERSION;
key->zk_salt_count = 0;
- rw_init(&key->zk_salt_lock, NULL, RW_DEFAULT, NULL);
return (0);
@@ -1388,7 +1405,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
boolean_t *no_crypt)
{
int ret;
- uint64_t txtype, lr_len;
+ uint64_t txtype, lr_len, nused;
uint_t nr_src, nr_dst, crypt_len;
uint_t aad_len = 0, nr_iovecs = 0, total_len = 0;
iovec_t *src_iovecs = NULL, *dst_iovecs = NULL;
@@ -1415,7 +1432,10 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
zilc = (zil_chain_t *)src;
slrp = src + sizeof (zil_chain_t);
aadp = aadbuf;
- blkend = src + ((byteswap) ? BSWAP_64(zilc->zc_nused) : zilc->zc_nused);
+ nused = ((byteswap) ? BSWAP_64(zilc->zc_nused) : zilc->zc_nused);
+ ASSERT3U(nused, >=, sizeof (zil_chain_t));
+ ASSERT3U(nused, <=, datalen);
+ blkend = src + nused;
/* calculate the number of encrypted iovecs we will need */
for (; slrp < blkend; slrp += lr_len) {
@@ -1428,6 +1448,8 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
txtype = BSWAP_64(lr->lrc_txtype);
lr_len = BSWAP_64(lr->lrc_reclen);
}
+ ASSERT3U(lr_len, >=, sizeof (lr_t));
+ ASSERT3U(lr_len, <=, blkend - slrp);
nr_iovecs++;
if (txtype == TX_WRITE && lr_len != sizeof (lr_write_t))
@@ -1496,20 +1518,16 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
* authenticate it.
*/
if (txtype == TX_WRITE) {
- crypt_len = sizeof (lr_write_t) -
- sizeof (lr_t) - sizeof (blkptr_t);
+ const size_t o = offsetof(lr_write_t, lr_blkptr);
+ crypt_len = o - sizeof (lr_t);
src_iovecs[nr_iovecs].iov_base = slrp + sizeof (lr_t);
src_iovecs[nr_iovecs].iov_len = crypt_len;
dst_iovecs[nr_iovecs].iov_base = dlrp + sizeof (lr_t);
dst_iovecs[nr_iovecs].iov_len = crypt_len;
/* copy the bp now since it will not be encrypted */
- memcpy(dlrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- slrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- sizeof (blkptr_t));
- memcpy(aadp,
- slrp + sizeof (lr_write_t) - sizeof (blkptr_t),
- sizeof (blkptr_t));
+ memcpy(dlrp + o, slrp + o, sizeof (blkptr_t));
+ memcpy(aadp, slrp + o, sizeof (blkptr_t));
aadp += sizeof (blkptr_t);
aad_len += sizeof (blkptr_t);
nr_iovecs++;
@@ -1526,6 +1544,21 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
nr_iovecs++;
total_len += crypt_len;
}
+ } else if (txtype == TX_CLONE_RANGE) {
+ const size_t o = offsetof(lr_clone_range_t, lr_nbps);
+ crypt_len = o - sizeof (lr_t);
+ src_iovecs[nr_iovecs].iov_base = slrp + sizeof (lr_t);
+ src_iovecs[nr_iovecs].iov_len = crypt_len;
+ dst_iovecs[nr_iovecs].iov_base = dlrp + sizeof (lr_t);
+ dst_iovecs[nr_iovecs].iov_len = crypt_len;
+
+ /* copy the bps now since they will not be encrypted */
+ memcpy(dlrp + o, slrp + o, lr_len - o);
+ memcpy(aadp, slrp + o, lr_len - o);
+ aadp += lr_len - o;
+ aad_len += lr_len - o;
+ nr_iovecs++;
+ total_len += crypt_len;
} else {
crypt_len = lr_len - sizeof (lr_t);
src_iovecs[nr_iovecs].iov_base = slrp + sizeof (lr_t);
@@ -1891,6 +1924,9 @@ zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key,
crypto_ctx_template_t tmpl;
uint8_t *authbuf = NULL;
+ memset(&puio, 0, sizeof (puio));
+ memset(&cuio, 0, sizeof (cuio));
+
/*
* If the needed key is the current one, just use it. Otherwise we
* need to generate a temporary one from the given salt + master key.
@@ -1950,9 +1986,6 @@ zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key,
/* If the hardware implementation fails fall back to software */
}
- memset(&puio, 0, sizeof (puio));
- memset(&cuio, 0, sizeof (cuio));
-
/* create uios for encryption */
ret = zio_crypt_init_uios(encrypt, key->zk_version, ot, plainbuf,
cipherbuf, datalen, byteswap, mac, &puio, &cuio, &enc_len,
@@ -1968,7 +2001,6 @@ zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key,
if (locked) {
rw_exit(&key->zk_salt_lock);
- locked = B_FALSE;
}
if (authbuf != NULL)
diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c
index d5c222120a9d..8ee7fcecc7b7 100644
--- a/module/os/linux/zfs/zpl_ctldir.c
+++ b/module/os/linux/zfs/zpl_ctldir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -42,7 +42,7 @@
static int
zpl_common_open(struct inode *ip, struct file *filp)
{
- if (filp->f_mode & FMODE_WRITE)
+ if (blk_mode_is_open_write(filp->f_mode))
return (-EACCES);
return (generic_file_open(ip, filp));
@@ -57,7 +57,8 @@ zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx)
zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
int error = 0;
- ZPL_ENTER(zfsvfs);
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (!zpl_dir_emit_dots(filp, ctx))
goto out;
@@ -78,7 +79,7 @@ zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx)
ctx->pos++;
}
out:
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
return (error);
}
@@ -102,7 +103,11 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
* Get root directory attributes.
*/
static int
-#ifdef HAVE_USERNS_IOPS_GETATTR
+#ifdef HAVE_IDMAP_IOPS_GETATTR
+zpl_root_getattr_impl(struct mnt_idmap *user_ns,
+ const struct path *path, struct kstat *stat, u32 request_mask,
+ unsigned int query_flags)
+#elif defined(HAVE_USERNS_IOPS_GETATTR)
zpl_root_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags)
@@ -114,9 +119,13 @@ zpl_root_getattr_impl(const struct path *path, struct kstat *stat,
(void) request_mask, (void) query_flags;
struct inode *ip = path->dentry->d_inode;
-#ifdef HAVE_USERNS_IOPS_GETATTR
+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
#ifdef HAVE_GENERIC_FILLATTR_USERNS
generic_fillattr(user_ns, ip, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
+ generic_fillattr(user_ns, ip, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP_REQMASK)
+ generic_fillattr(user_ns, request_mask, ip, stat);
#else
(void) user_ns;
#endif
@@ -207,7 +216,7 @@ zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
return (!!dentry->d_inode);
}
-static const dentry_operations_t zpl_dops_snapdirs = {
+static dentry_operations_t zpl_dops_snapdirs = {
/*
* Auto mounting of snapshots is only supported for 2.6.37 and
* newer kernels. Prior to this kernel the ops->follow_link()
@@ -258,7 +267,8 @@ zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx)
uint64_t id, pos;
int error = 0;
- ZPL_ENTER(zfsvfs);
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
cookie = spl_fstrans_mark();
if (!zpl_dir_emit_dots(filp, ctx))
@@ -282,7 +292,7 @@ zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx)
}
out:
spl_fstrans_unmark(cookie);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
if (error == -ENOENT)
return (0);
@@ -310,6 +320,10 @@ static int
zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip,
struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
unsigned int flags)
+#elif defined(HAVE_IOPS_RENAME_IDMAP)
+zpl_snapdir_rename2(struct mnt_idmap *user_ns, struct inode *sdip,
+ struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
+ unsigned int flags)
#else
zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry, unsigned int flags)
@@ -331,7 +345,9 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
return (error);
}
-#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS)
+#if (!defined(HAVE_RENAME_WANTS_FLAGS) && \
+ !defined(HAVE_IOPS_RENAME_USERNS) && \
+ !defined(HAVE_IOPS_RENAME_IDMAP))
static int
zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry)
@@ -358,6 +374,9 @@ static int
#ifdef HAVE_IOPS_MKDIR_USERNS
zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip,
struct dentry *dentry, umode_t mode)
+#elif defined(HAVE_IOPS_MKDIR_IDMAP)
+zpl_snapdir_mkdir(struct mnt_idmap *user_ns, struct inode *dip,
+ struct dentry *dentry, umode_t mode)
#else
zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
#endif
@@ -369,7 +388,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
- zpl_vap_init(vap, dip, mode | S_IFDIR, cr);
+#if (defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP))
+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns);
+#else
+ zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_idmap);
+#endif
error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0);
if (error == 0) {
@@ -389,7 +412,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
* Get snapshot directory attributes.
*/
static int
-#ifdef HAVE_USERNS_IOPS_GETATTR
+#ifdef HAVE_IDMAP_IOPS_GETATTR
+zpl_snapdir_getattr_impl(struct mnt_idmap *user_ns,
+ const struct path *path, struct kstat *stat, u32 request_mask,
+ unsigned int query_flags)
+#elif defined(HAVE_USERNS_IOPS_GETATTR)
zpl_snapdir_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags)
@@ -401,11 +428,17 @@ zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
(void) request_mask, (void) query_flags;
struct inode *ip = path->dentry->d_inode;
zfsvfs_t *zfsvfs = ITOZSB(ip);
+ int error;
- ZPL_ENTER(zfsvfs);
-#ifdef HAVE_USERNS_IOPS_GETATTR
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
#ifdef HAVE_GENERIC_FILLATTR_USERNS
generic_fillattr(user_ns, ip, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
+ generic_fillattr(user_ns, ip, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP_REQMASK)
+ generic_fillattr(user_ns, request_mask, ip, stat);
#else
(void) user_ns;
#endif
@@ -422,7 +455,7 @@ zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
dmu_objset_pool(ds->ds_objset)->dp_meta_objset,
dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
if (err != 0) {
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
return (-err);
}
stat->nlink += snap_count;
@@ -430,7 +463,7 @@ zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
stat->atime = current_time(ip);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
return (0);
}
@@ -463,7 +496,9 @@ const struct file_operations zpl_fops_snapdir = {
const struct inode_operations zpl_ops_snapdir = {
.lookup = zpl_snapdir_lookup,
.getattr = zpl_snapdir_getattr,
-#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
+#if (defined(HAVE_RENAME_WANTS_FLAGS) || \
+ defined(HAVE_IOPS_RENAME_USERNS) || \
+ defined(HAVE_IOPS_RENAME_IDMAP))
.rename = zpl_snapdir_rename2,
#else
.rename = zpl_snapdir_rename,
@@ -508,7 +543,8 @@ zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx)
znode_t *dzp;
int error = 0;
- ZPL_ENTER(zfsvfs);
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
cookie = spl_fstrans_mark();
if (zfsvfs->z_shares_dir == 0) {
@@ -527,7 +563,7 @@ zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx)
iput(ZTOI(dzp));
out:
spl_fstrans_unmark(cookie);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
ASSERT3S(error, <=, 0);
return (error);
@@ -553,6 +589,10 @@ static int
zpl_shares_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags)
+#elif defined(HAVE_IDMAP_IOPS_GETATTR)
+zpl_shares_getattr_impl(struct mnt_idmap *user_ns,
+ const struct path *path, struct kstat *stat, u32 request_mask,
+ unsigned int query_flags)
#else
zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int query_flags)
@@ -564,12 +604,17 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
znode_t *dzp;
int error;
- ZPL_ENTER(zfsvfs);
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
if (zfsvfs->z_shares_dir == 0) {
-#ifdef HAVE_USERNS_IOPS_GETATTR
+#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
#ifdef HAVE_GENERIC_FILLATTR_USERNS
generic_fillattr(user_ns, path->dentry->d_inode, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
+ generic_fillattr(user_ns, path->dentry->d_inode, stat);
+#elif defined(HAVE_GENERIC_FILLATTR_IDMAP_REQMASK)
+ generic_fillattr(user_ns, request_mask, ip, stat);
#else
(void) user_ns;
#endif
@@ -578,25 +623,24 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
#endif
stat->nlink = stat->size = 2;
stat->atime = current_time(ip);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
return (0);
}
error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
if (error == 0) {
-#ifdef HAVE_USERNS_IOPS_GETATTR
-#ifdef HAVE_GENERIC_FILLATTR_USERNS
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK
+ error = -zfs_getattr_fast(user_ns, request_mask, ZTOI(dzp),
+ stat);
+#elif (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat);
#else
- (void) user_ns;
-#endif
-#else
error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat);
#endif
iput(ZTOI(dzp));
}
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
ASSERT3S(error, <=, 0);
return (error);
diff --git a/module/os/linux/zfs/zpl_export.c b/module/os/linux/zfs/zpl_export.c
index 5be63532d329..aa80b72e2d7a 100644
--- a/module/os/linux/zfs/zpl_export.c
+++ b/module/os/linux/zfs/zpl_export.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c
index 9a640fb40b67..9dec52215c7c 100644
--- a/module/os/linux/zfs/zpl_file.c
+++ b/module/os/linux/zfs/zpl_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,6 +27,7 @@
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif
+#include <linux/fs.h>
#include <sys/file.h>
#include <sys/dmu_objset.h>
#include <sys/zfs_znode.h>
@@ -37,6 +38,9 @@
defined(HAVE_VFS_FILEMAP_DIRTY_FOLIO)
#include <linux/pagemap.h>
#endif
+#ifdef HAVE_FILE_FADVISE
+#include <linux/fadvise.h>
+#endif
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
#include <linux/writeback.h>
#endif
@@ -191,9 +195,12 @@ zpl_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
* zfs_putpage() respectively.
*/
if (atomic_load_32(&zp->z_async_writes_cnt) > 0) {
- ZPL_ENTER(zfsvfs);
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0) {
+ atomic_dec_32(&zp->z_sync_writes_cnt);
+ return (error);
+ }
zil_commit(zfsvfs->z_log, zp->z_id);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
}
error = filemap_write_and_wait_range(inode->i_mapping, start, end);
@@ -294,16 +301,11 @@ zpl_uio_init(zfs_uio_t *uio, struct kiocb *kiocb, struct iov_iter *to,
#if defined(HAVE_VFS_IOV_ITER)
zfs_uio_iov_iter_init(uio, to, pos, count, skip);
#else
-#ifdef HAVE_IOV_ITER_TYPE
- zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
- iov_iter_type(to) & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
- count, skip);
-#else
- zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
- to->type & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
+ zfs_uio_iovec_init(uio, zfs_uio_iter_iov(to), to->nr_segs, pos,
+ zfs_uio_iov_iter_type(to) & ITER_KVEC ?
+ UIO_SYSSPACE : UIO_USERSPACE,
count, skip);
#endif
-#endif
}
static ssize_t
@@ -618,7 +620,6 @@ static int
zpl_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct inode *ip = filp->f_mapping->host;
- znode_t *zp = ITOZ(ip);
int error;
fstrans_cookie_t cookie;
@@ -633,9 +634,12 @@ zpl_mmap(struct file *filp, struct vm_area_struct *vma)
if (error)
return (error);
+#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
+ znode_t *zp = ITOZ(ip);
mutex_enter(&zp->z_lock);
zp->z_is_mapped = B_TRUE;
mutex_exit(&zp->z_lock);
+#endif
return (error);
}
@@ -648,29 +652,16 @@ zpl_mmap(struct file *filp, struct vm_area_struct *vma)
static inline int
zpl_readpage_common(struct page *pp)
{
- struct inode *ip;
- struct page *pl[1];
- int error = 0;
fstrans_cookie_t cookie;
ASSERT(PageLocked(pp));
- ip = pp->mapping->host;
- pl[0] = pp;
cookie = spl_fstrans_mark();
- error = -zfs_getpage(ip, pl, 1);
+ int error = -zfs_getpage(pp->mapping->host, pp);
spl_fstrans_unmark(cookie);
- if (error) {
- SetPageError(pp);
- ClearPageUptodate(pp);
- } else {
- ClearPageError(pp);
- SetPageUptodate(pp);
- flush_dcache_page(pp);
- }
-
unlock_page(pp);
+
return (error);
}
@@ -729,15 +720,38 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
{
boolean_t *for_sync = data;
fstrans_cookie_t cookie;
+ int ret;
ASSERT(PageLocked(pp));
ASSERT(!PageWriteback(pp));
cookie = spl_fstrans_mark();
- (void) zfs_putpage(pp->mapping->host, pp, wbc, *for_sync);
+ ret = zfs_putpage(pp->mapping->host, pp, wbc, *for_sync);
spl_fstrans_unmark(cookie);
- return (0);
+ return (ret);
+}
+
+#ifdef HAVE_WRITEPAGE_T_FOLIO
+static int
+zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data)
+{
+ return (zpl_putpage(&pp->page, wbc, data));
+}
+#endif
+
+static inline int
+zpl_write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc, void *data)
+{
+ int result;
+
+#ifdef HAVE_WRITEPAGE_T_FOLIO
+ result = write_cache_pages(mapping, wbc, zpl_putfolio, data);
+#else
+ result = write_cache_pages(mapping, wbc, zpl_putpage, data);
+#endif
+ return (result);
}
static int
@@ -748,10 +762,11 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
enum writeback_sync_modes sync_mode;
int result;
- ZPL_ENTER(zfsvfs);
+ if ((result = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (result);
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
wbc->sync_mode = WB_SYNC_ALL;
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
sync_mode = wbc->sync_mode;
/*
@@ -763,13 +778,13 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
*/
boolean_t for_sync = (sync_mode == WB_SYNC_ALL);
wbc->sync_mode = WB_SYNC_NONE;
- result = write_cache_pages(mapping, wbc, zpl_putpage, &for_sync);
+ result = zpl_write_cache_pages(mapping, wbc, &for_sync);
if (sync_mode != wbc->sync_mode) {
- ZPL_ENTER(zfsvfs);
- ZPL_VERIFY_ZP(zp);
+ if ((result = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (result);
if (zfsvfs->z_log != NULL)
zil_commit(zfsvfs->z_log, zp->z_id);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
/*
* We need to call write_cache_pages() again (we can't just
@@ -779,8 +794,7 @@ zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
* details). That being said, this is a no-op in most cases.
*/
wbc->sync_mode = sync_mode;
- result = write_cache_pages(mapping, wbc, zpl_putpage,
- &for_sync);
+ result = zpl_write_cache_pages(mapping, wbc, &for_sync);
}
return (result);
}
@@ -906,6 +920,61 @@ zpl_ioctl_getversion(struct file *filp, void __user *arg)
return (copy_to_user(arg, &generation, sizeof (generation)));
}
+#ifdef HAVE_FILE_FADVISE
+static int
+zpl_fadvise(struct file *filp, loff_t offset, loff_t len, int advice)
+{
+ struct inode *ip = file_inode(filp);
+ znode_t *zp = ITOZ(ip);
+ zfsvfs_t *zfsvfs = ITOZSB(ip);
+ objset_t *os = zfsvfs->z_os;
+ int error = 0;
+
+ if (S_ISFIFO(ip->i_mode))
+ return (-ESPIPE);
+
+ if (offset < 0 || len < 0)
+ return (-EINVAL);
+
+ if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
+
+ switch (advice) {
+ case POSIX_FADV_SEQUENTIAL:
+ case POSIX_FADV_WILLNEED:
+#ifdef HAVE_GENERIC_FADVISE
+ if (zn_has_cached_data(zp, offset, offset + len - 1))
+ error = generic_fadvise(filp, offset, len, advice);
+#endif
+ /*
+ * Pass on the caller's size directly, but note that
+ * dmu_prefetch_max will effectively cap it. If there
+ * really is a larger sequential access pattern, perhaps
+ * dmu_zfetch will detect it.
+ */
+ if (len == 0)
+ len = i_size_read(ip) - offset;
+
+ dmu_prefetch(os, zp->z_id, 0, offset, len,
+ ZIO_PRIORITY_ASYNC_READ);
+ break;
+ case POSIX_FADV_NORMAL:
+ case POSIX_FADV_RANDOM:
+ case POSIX_FADV_DONTNEED:
+ case POSIX_FADV_NOREUSE:
+ /* ignored for now */
+ break;
+ default:
+ error = -EINVAL;
+ break;
+ }
+
+ zfs_exit(zfsvfs, FTAG);
+
+ return (error);
+}
+#endif /* HAVE_FILE_FADVISE */
+
#define ZFS_FL_USER_VISIBLE (FS_FL_USER_VISIBLE | ZFS_PROJINHERIT_FL)
#define ZFS_FL_USER_MODIFIABLE (FS_FL_USER_MODIFIABLE | ZFS_PROJINHERIT_FL)
@@ -975,7 +1044,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva)
!capable(CAP_LINUX_IMMUTABLE))
return (-EPERM);
- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EACCES);
xva_init(xva);
@@ -1022,7 +1091,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg)
crhold(cr);
cookie = spl_fstrans_mark();
- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr);
+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap);
spl_fstrans_unmark(cookie);
crfree(cr);
@@ -1070,7 +1139,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg)
crhold(cr);
cookie = spl_fstrans_mark();
- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr);
+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap);
spl_fstrans_unmark(cookie);
crfree(cr);
@@ -1105,7 +1174,7 @@ __zpl_ioctl_setdosflags(struct inode *ip, uint64_t ioctl_flags, xvattr_t *xva)
!capable(CAP_LINUX_IMMUTABLE))
return (-EPERM);
- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
return (-EACCES);
xva_init(xva);
@@ -1158,7 +1227,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg)
crhold(cr);
cookie = spl_fstrans_mark();
- err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr);
+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, zfs_init_idmap);
spl_fstrans_unmark(cookie);
crfree(cr);
@@ -1183,6 +1252,12 @@ zpl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return (zpl_ioctl_getdosflags(filp, (void *)arg));
case ZFS_IOC_SETDOSFLAGS:
return (zpl_ioctl_setdosflags(filp, (void *)arg));
+ case ZFS_IOC_COMPAT_FICLONE:
+ return (zpl_ioctl_ficlone(filp, (void *)arg));
+ case ZFS_IOC_COMPAT_FICLONERANGE:
+ return (zpl_ioctl_ficlonerange(filp, (void *)arg));
+ case ZFS_IOC_COMPAT_FIDEDUPERANGE:
+ return (zpl_ioctl_fideduperange(filp, (void *)arg));
default:
return (-ENOTTY);
}
@@ -1209,7 +1284,6 @@ zpl_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
#endif /* CONFIG_COMPAT */
-
const struct address_space_operations zpl_address_space_operations = {
#ifdef HAVE_VFS_READPAGES
.readpages = zpl_readpages,
@@ -1232,7 +1306,12 @@ const struct address_space_operations zpl_address_space_operations = {
#endif
};
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+const struct file_operations_extend zpl_file_operations = {
+ .kabi_fops = {
+#else
const struct file_operations zpl_file_operations = {
+#endif
.open = zpl_open,
.release = zpl_release,
.llseek = zpl_llseek,
@@ -1244,7 +1323,11 @@ const struct file_operations zpl_file_operations = {
.read_iter = zpl_iter_read,
.write_iter = zpl_iter_write,
#ifdef HAVE_VFS_IOV_ITER
+#ifdef HAVE_COPY_SPLICE_READ
+ .splice_read = copy_splice_read,
+#else
.splice_read = generic_file_splice_read,
+#endif
.splice_write = iter_file_splice_write,
#endif
#else
@@ -1259,10 +1342,30 @@ const struct file_operations zpl_file_operations = {
.aio_fsync = zpl_aio_fsync,
#endif
.fallocate = zpl_fallocate,
+#ifdef HAVE_VFS_COPY_FILE_RANGE
+ .copy_file_range = zpl_copy_file_range,
+#endif
+#ifdef HAVE_VFS_CLONE_FILE_RANGE
+ .clone_file_range = zpl_clone_file_range,
+#endif
+#ifdef HAVE_VFS_REMAP_FILE_RANGE
+ .remap_file_range = zpl_remap_file_range,
+#endif
+#ifdef HAVE_VFS_DEDUPE_FILE_RANGE
+ .dedupe_file_range = zpl_dedupe_file_range,
+#endif
+#ifdef HAVE_FILE_FADVISE
+ .fadvise = zpl_fadvise,
+#endif
.unlocked_ioctl = zpl_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = zpl_compat_ioctl,
#endif
+#ifdef HAVE_VFS_FILE_OPERATIONS_EXTEND
+ }, /* kabi_fops */
+ .copy_file_range = zpl_copy_file_range,
+ .clone_file_range = zpl_clone_file_range,
+#endif
};
const struct file_operations zpl_dir_file_operations = {
diff --git a/module/os/linux/zfs/zpl_file_range.c b/module/os/linux/zfs/zpl_file_range.c
new file mode 100644
index 000000000000..64728fdb1187
--- /dev/null
+++ b/module/os/linux/zfs/zpl_file_range.c
@@ -0,0 +1,299 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2023, Klara Inc.
+ */
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+#include <linux/fs.h>
+#ifdef HAVE_VFS_SPLICE_COPY_FILE_RANGE
+#include <linux/splice.h>
+#endif
+#include <sys/file.h>
+#include <sys/zfs_znode.h>
+#include <sys/zfs_vnops.h>
+#include <sys/zfeature.h>
+
+/*
+ * Clone part of a file via block cloning.
+ *
+ * Note that we are not required to update file offsets; the kernel will take
+ * care of that depending on how it was called.
+ */
+static ssize_t
+zpl_clone_file_range_impl(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, size_t len)
+{
+ struct inode *src_i = file_inode(src_file);
+ struct inode *dst_i = file_inode(dst_file);
+ uint64_t src_off_o = (uint64_t)src_off;
+ uint64_t dst_off_o = (uint64_t)dst_off;
+ uint64_t len_o = (uint64_t)len;
+ cred_t *cr = CRED();
+ fstrans_cookie_t cookie;
+ int err;
+
+ if (!zfs_bclone_enabled)
+ return (-EOPNOTSUPP);
+
+ if (!spa_feature_is_enabled(
+ dmu_objset_spa(ITOZSB(dst_i)->z_os), SPA_FEATURE_BLOCK_CLONING))
+ return (-EOPNOTSUPP);
+
+ if (src_i != dst_i)
+ spl_inode_lock_shared(src_i);
+ spl_inode_lock(dst_i);
+
+ crhold(cr);
+ cookie = spl_fstrans_mark();
+
+ err = -zfs_clone_range(ITOZ(src_i), &src_off_o, ITOZ(dst_i),
+ &dst_off_o, &len_o, cr);
+
+ spl_fstrans_unmark(cookie);
+ crfree(cr);
+
+ spl_inode_unlock(dst_i);
+ if (src_i != dst_i)
+ spl_inode_unlock_shared(src_i);
+
+ if (err < 0)
+ return (err);
+
+ return ((ssize_t)len_o);
+}
+
+#if defined(HAVE_VFS_COPY_FILE_RANGE) || \
+ defined(HAVE_VFS_FILE_OPERATIONS_EXTEND)
+/*
+ * Entry point for copy_file_range(). Copy len bytes from src_off in src_file
+ * to dst_off in dst_file. We are permitted to do this however we like, so we
+ * try to just clone the blocks, and if we can't support it, fall back to the
+ * kernel's generic byte copy function.
+ */
+ssize_t
+zpl_copy_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, size_t len, unsigned int flags)
+{
+ ssize_t ret;
+
+ /* Flags is reserved for future extensions and must be zero. */
+ if (flags != 0)
+ return (-EINVAL);
+
+ /* Try to do it via zfs_clone_range() and allow shortening. */
+ ret = zpl_clone_file_range_impl(src_file, src_off,
+ dst_file, dst_off, len);
+
+#if defined(HAVE_VFS_GENERIC_COPY_FILE_RANGE)
+ /*
+ * Since Linux 5.3 the filesystem driver is responsible for executing
+ * an appropriate fallback, and a generic fallback function is provided.
+ */
+ if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV ||
+ ret == -EAGAIN)
+ ret = generic_copy_file_range(src_file, src_off, dst_file,
+ dst_off, len, flags);
+#elif defined(HAVE_VFS_SPLICE_COPY_FILE_RANGE)
+ /*
+ * Since 6.8 the fallback function is called splice_copy_file_range
+ * and has a slightly different signature.
+ */
+ if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV ||
+ ret == -EAGAIN)
+ ret = splice_copy_file_range(src_file, src_off, dst_file,
+ dst_off, len);
+#else
+ /*
+ * Before Linux 5.3 the filesystem has to return -EOPNOTSUPP to signal
+ * to the kernel that it should fallback to a content copy.
+ */
+ if (ret == -EINVAL || ret == -EXDEV || ret == -EAGAIN)
+ ret = -EOPNOTSUPP;
+#endif /* HAVE_VFS_GENERIC_COPY_FILE_RANGE || HAVE_VFS_SPLICE_COPY_FILE_RANGE */
+
+ return (ret);
+}
+#endif /* HAVE_VFS_COPY_FILE_RANGE || HAVE_VFS_FILE_OPERATIONS_EXTEND */
+
+#ifdef HAVE_VFS_REMAP_FILE_RANGE
+/*
+ * Entry point for FICLONE/FICLONERANGE/FIDEDUPERANGE.
+ *
+ * FICLONE and FICLONERANGE are basically the same as copy_file_range(), except
+ * that they must clone - they cannot fall back to copying. FICLONE is exactly
+ * FICLONERANGE, for the entire file. We don't need to try to tell them apart;
+ * the kernel will sort that out for us.
+ *
+ * FIDEDUPERANGE is for turning a non-clone into a clone, that is, compare the
+ * range in both files and if they're the same, arrange for them to be backed
+ * by the same storage.
+ *
+ * REMAP_FILE_CAN_SHORTEN lets us know we can clone less than the given range
+ * if we want. It's designed for filesystems that may need to shorten the
+ * length for alignment, EOF, or any other requirement. ZFS may shorten the
+ * request when there is outstanding dirty data which hasn't been written.
+ */
+loff_t
+zpl_remap_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, loff_t len, unsigned int flags)
+{
+ if (flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_CAN_SHORTEN))
+ return (-EINVAL);
+
+ /* No support for dedup yet */
+ if (flags & REMAP_FILE_DEDUP)
+ return (-EOPNOTSUPP);
+
+ /* Zero length means to clone everything to the end of the file */
+ if (len == 0)
+ len = i_size_read(file_inode(src_file)) - src_off;
+
+ ssize_t ret = zpl_clone_file_range_impl(src_file, src_off,
+ dst_file, dst_off, len);
+
+ if (!(flags & REMAP_FILE_CAN_SHORTEN) && ret >= 0 && ret != len)
+ ret = -EINVAL;
+
+ return (ret);
+}
+#endif /* HAVE_VFS_REMAP_FILE_RANGE */
+
+#if defined(HAVE_VFS_CLONE_FILE_RANGE) || \
+ defined(HAVE_VFS_FILE_OPERATIONS_EXTEND)
+/*
+ * Entry point for FICLONE and FICLONERANGE, before Linux 4.20.
+ */
+int
+zpl_clone_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, uint64_t len)
+{
+ /* Zero length means to clone everything to the end of the file */
+ if (len == 0)
+ len = i_size_read(file_inode(src_file)) - src_off;
+
+ /* The entire length must be cloned or this is an error. */
+ ssize_t ret = zpl_clone_file_range_impl(src_file, src_off,
+ dst_file, dst_off, len);
+
+ if (ret >= 0 && ret != len)
+ ret = -EINVAL;
+
+ return (ret);
+}
+#endif /* HAVE_VFS_CLONE_FILE_RANGE || HAVE_VFS_FILE_OPERATIONS_EXTEND */
+
+#ifdef HAVE_VFS_DEDUPE_FILE_RANGE
+/*
+ * Entry point for FIDEDUPERANGE, before Linux 4.20.
+ */
+int
+zpl_dedupe_file_range(struct file *src_file, loff_t src_off,
+ struct file *dst_file, loff_t dst_off, uint64_t len)
+{
+ /* No support for dedup yet */
+ return (-EOPNOTSUPP);
+}
+#endif /* HAVE_VFS_DEDUPE_FILE_RANGE */
+
+/* Entry point for FICLONE, before Linux 4.5. */
+long
+zpl_ioctl_ficlone(struct file *dst_file, void *arg)
+{
+ unsigned long sfd = (unsigned long)arg;
+
+ struct file *src_file = fget(sfd);
+ if (src_file == NULL)
+ return (-EBADF);
+
+ if (dst_file->f_op != src_file->f_op) {
+ fput(src_file);
+ return (-EXDEV);
+ }
+
+ size_t len = i_size_read(file_inode(src_file));
+
+ ssize_t ret = zpl_clone_file_range_impl(src_file, 0, dst_file, 0, len);
+
+ fput(src_file);
+
+ if (ret < 0) {
+ if (ret == -EOPNOTSUPP)
+ return (-ENOTTY);
+ return (ret);
+ }
+
+ if (ret != len)
+ return (-EINVAL);
+
+ return (0);
+}
+
+/* Entry point for FICLONERANGE, before Linux 4.5. */
+long
+zpl_ioctl_ficlonerange(struct file *dst_file, void __user *arg)
+{
+ zfs_ioc_compat_file_clone_range_t fcr;
+
+ if (copy_from_user(&fcr, arg, sizeof (fcr)))
+ return (-EFAULT);
+
+ struct file *src_file = fget(fcr.fcr_src_fd);
+ if (src_file == NULL)
+ return (-EBADF);
+
+ if (dst_file->f_op != src_file->f_op) {
+ fput(src_file);
+ return (-EXDEV);
+ }
+
+ size_t len = fcr.fcr_src_length;
+ if (len == 0)
+ len = i_size_read(file_inode(src_file)) - fcr.fcr_src_offset;
+
+ ssize_t ret = zpl_clone_file_range_impl(src_file, fcr.fcr_src_offset,
+ dst_file, fcr.fcr_dest_offset, len);
+
+ fput(src_file);
+
+ if (ret < 0) {
+ if (ret == -EOPNOTSUPP)
+ return (-ENOTTY);
+ return (ret);
+ }
+
+ if (ret != len)
+ return (-EINVAL);
+
+ return (0);
+}
+
+/* Entry point for FIDEDUPERANGE, before Linux 4.5. */
+long
+zpl_ioctl_fideduperange(struct file *filp, void *arg)
+{
+ (void) arg;
+
+ /* No support for dedup yet */
+ return (-ENOTTY);
+}
diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c
index 4f79265a0856..ad1753f7a071 100644
--- a/module/os/linux/zfs/zpl_inode.c
+++ b/module/os/linux/zfs/zpl_inode.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,6 +24,7 @@
*/
+#include <sys/sysmacros.h>
#include <sys/zfs_ctldir.h>
#include <sys/zfs_vfsops.h>
#include <sys/zfs_vnops.h>
@@ -33,7 +34,6 @@
#include <sys/zpl.h>
#include <sys/file.h>
-
static struct dentry *
zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
{
@@ -112,18 +112,22 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
}
void
-zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr)
+zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr,
+ zidmap_t *mnt_ns)
{
vap->va_mask = ATTR_MODE;
vap->va_mode = mode;
- vap->va_uid = crgetuid(cr);
- if (dir && dir->i_mode & S_ISGID) {
+ vap->va_uid = zfs_vfsuid_to_uid(mnt_ns,
+ zfs_i_user_ns(dir), crgetuid(cr));
+
+ if (dir->i_mode & S_ISGID) {
vap->va_gid = KGID_TO_SGID(dir->i_gid);
if (S_ISDIR(mode))
vap->va_mode |= S_ISGID;
} else {
- vap->va_gid = crgetgid(cr);
+ vap->va_gid = zfs_vfsgid_to_gid(mnt_ns,
+ zfs_i_user_ns(dir), crgetgid(cr));
}
}
@@ -131,6 +135,9 @@ static int
#ifdef HAVE_IOPS_CREATE_USERNS
zpl_create(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool flag)
+#elif defined(HAVE_IOPS_CREATE_IDMAP)
+zpl_create(struct mnt_idmap *user_ns, struct inode *dir,
+ struct dentry *dentry, umode_t mode, bool flag)
#else
zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)
#endif
@@ -140,14 +147,17 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)
vattr_t *vap;
int error;
fstrans_cookie_t cookie;
+#if !(defined(HAVE_IOPS_CREATE_USERNS) || defined(HAVE_IOPS_CREATE_IDMAP))
+ zidmap_t *user_ns = kcred->user_ns;
+#endif
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
- zpl_vap_init(vap, dir, mode, cr);
+ zpl_vap_init(vap, dir, mode, cr, user_ns);
cookie = spl_fstrans_mark();
error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0,
- mode, &zp, cr, 0, NULL);
+ mode, &zp, cr, 0, NULL, user_ns);
if (error == 0) {
error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);
if (error == 0)
@@ -174,6 +184,9 @@ static int
#ifdef HAVE_IOPS_MKNOD_USERNS
zpl_mknod(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode,
+#elif defined(HAVE_IOPS_MKNOD_IDMAP)
+zpl_mknod(struct mnt_idmap *user_ns, struct inode *dir,
+ struct dentry *dentry, umode_t mode,
#else
zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
#endif
@@ -184,6 +197,9 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
vattr_t *vap;
int error;
fstrans_cookie_t cookie;
+#if !(defined(HAVE_IOPS_MKNOD_USERNS) || defined(HAVE_IOPS_MKNOD_IDMAP))
+ zidmap_t *user_ns = kcred->user_ns;
+#endif
/*
* We currently expect Linux to supply rdev=0 for all sockets
@@ -194,12 +210,12 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
- zpl_vap_init(vap, dir, mode, cr);
+ zpl_vap_init(vap, dir, mode, cr, user_ns);
vap->va_rdev = rdev;
cookie = spl_fstrans_mark();
error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0,
- mode, &zp, cr, 0, NULL);
+ mode, &zp, cr, 0, NULL, user_ns);
if (error == 0) {
error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);
if (error == 0)
@@ -224,18 +240,29 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
#ifdef HAVE_TMPFILE
static int
+#ifdef HAVE_TMPFILE_IDMAP
+zpl_tmpfile(struct mnt_idmap *userns, struct inode *dir,
+ struct file *file, umode_t mode)
+#elif !defined(HAVE_TMPFILE_DENTRY)
+zpl_tmpfile(struct user_namespace *userns, struct inode *dir,
+ struct file *file, umode_t mode)
+#else
#ifdef HAVE_TMPFILE_USERNS
zpl_tmpfile(struct user_namespace *userns, struct inode *dir,
struct dentry *dentry, umode_t mode)
#else
zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
#endif
+#endif
{
cred_t *cr = CRED();
struct inode *ip;
vattr_t *vap;
int error;
fstrans_cookie_t cookie;
+#if !(defined(HAVE_TMPFILE_USERNS) || defined(HAVE_TMPFILE_IDMAP))
+ zidmap_t *userns = kcred->user_ns;
+#endif
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
@@ -245,18 +272,28 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
*/
if (!IS_POSIXACL(dir))
mode &= ~current_umask();
- zpl_vap_init(vap, dir, mode, cr);
+ zpl_vap_init(vap, dir, mode, cr, userns);
cookie = spl_fstrans_mark();
- error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL);
+ error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns);
if (error == 0) {
/* d_tmpfile will do drop_nlink, so we should set it first */
set_nlink(ip, 1);
+#ifndef HAVE_TMPFILE_DENTRY
+ d_tmpfile(file, ip);
+
+ error = zpl_xattr_security_init(ip, dir,
+ &file->f_path.dentry->d_name);
+#else
d_tmpfile(dentry, ip);
error = zpl_xattr_security_init(ip, dir, &dentry->d_name);
+#endif
if (error == 0)
error = zpl_init_acl(ip, dir);
+#ifndef HAVE_TMPFILE_DENTRY
+ error = finish_open_simple(file, error);
+#endif
/*
* don't need to handle error here, file is already in
* unlinked set.
@@ -302,6 +339,9 @@ static int
#ifdef HAVE_IOPS_MKDIR_USERNS
zpl_mkdir(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, umode_t mode)
+#elif defined(HAVE_IOPS_MKDIR_IDMAP)
+zpl_mkdir(struct mnt_idmap *user_ns, struct inode *dir,
+ struct dentry *dentry, umode_t mode)
#else
zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
#endif
@@ -311,13 +351,17 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
znode_t *zp;
int error;
fstrans_cookie_t cookie;
+#if !(defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP))
+ zidmap_t *user_ns = kcred->user_ns;
+#endif
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
- zpl_vap_init(vap, dir, mode | S_IFDIR, cr);
+ zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns);
cookie = spl_fstrans_mark();
- error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL);
+ error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL,
+ user_ns);
if (error == 0) {
error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);
if (error == 0)
@@ -371,6 +415,10 @@ static int
zpl_getattr_impl(struct user_namespace *user_ns,
const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags)
+#elif defined(HAVE_IDMAP_IOPS_GETATTR)
+zpl_getattr_impl(struct mnt_idmap *user_ns,
+ const struct path *path, struct kstat *stat, u32 request_mask,
+ unsigned int query_flags)
#else
zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
unsigned int query_flags)
@@ -387,7 +435,9 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
* XXX query_flags currently ignored.
*/
-#ifdef HAVE_USERNS_IOPS_GETATTR
+#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK
+ error = -zfs_getattr_fast(user_ns, request_mask, ip, stat);
+#elif (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
error = -zfs_getattr_fast(user_ns, ip, stat);
#else
error = -zfs_getattr_fast(kcred->user_ns, ip, stat);
@@ -426,9 +476,12 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
ZPL_GETATTR_WRAPPER(zpl_getattr);
static int
-#ifdef HAVE_SETATTR_PREPARE_USERNS
+#ifdef HAVE_USERNS_IOPS_SETATTR
zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry,
struct iattr *ia)
+#elif defined(HAVE_IDMAP_IOPS_SETATTR)
+zpl_setattr(struct mnt_idmap *user_ns, struct dentry *dentry,
+ struct iattr *ia)
#else
zpl_setattr(struct dentry *dentry, struct iattr *ia)
#endif
@@ -439,7 +492,13 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
int error;
fstrans_cookie_t cookie;
- error = zpl_setattr_prepare(kcred->user_ns, dentry, ia);
+#ifdef HAVE_SETATTR_PREPARE_USERNS
+ error = zpl_setattr_prepare(user_ns, dentry, ia);
+#elif defined(HAVE_SETATTR_PREPARE_IDMAP)
+ error = zpl_setattr_prepare(user_ns, dentry, ia);
+#else
+ error = zpl_setattr_prepare(zfs_init_idmap, dentry, ia);
+#endif
if (error)
return (error);
@@ -447,18 +506,37 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK;
vap->va_mode = ia->ia_mode;
- vap->va_uid = KUID_TO_SUID(ia->ia_uid);
- vap->va_gid = KGID_TO_SGID(ia->ia_gid);
+ if (ia->ia_valid & ATTR_UID)
+#ifdef HAVE_IATTR_VFSID
+ vap->va_uid = zfs_vfsuid_to_uid(user_ns, zfs_i_user_ns(ip),
+ __vfsuid_val(ia->ia_vfsuid));
+#else
+ vap->va_uid = KUID_TO_SUID(ia->ia_uid);
+#endif
+ if (ia->ia_valid & ATTR_GID)
+#ifdef HAVE_IATTR_VFSID
+ vap->va_gid = zfs_vfsgid_to_gid(user_ns, zfs_i_user_ns(ip),
+ __vfsgid_val(ia->ia_vfsgid));
+#else
+ vap->va_gid = KGID_TO_SGID(ia->ia_gid);
+#endif
vap->va_size = ia->ia_size;
vap->va_atime = ia->ia_atime;
vap->va_mtime = ia->ia_mtime;
vap->va_ctime = ia->ia_ctime;
if (vap->va_mask & ATTR_ATIME)
- ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip);
+ zpl_inode_set_atime_to_ts(ip,
+ zpl_inode_timestamp_truncate(ia->ia_atime, ip));
cookie = spl_fstrans_mark();
- error = -zfs_setattr(ITOZ(ip), vap, 0, cr);
+#ifdef HAVE_USERNS_IOPS_SETATTR
+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns);
+#elif defined(HAVE_IDMAP_IOPS_SETATTR)
+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns);
+#else
+ error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_idmap);
+#endif
if (!error && (ia->ia_valid & ATTR_MODE))
error = zpl_chmod_acl(ip);
@@ -474,32 +552,47 @@ static int
#ifdef HAVE_IOPS_RENAME_USERNS
zpl_rename2(struct user_namespace *user_ns, struct inode *sdip,
struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
- unsigned int flags)
+ unsigned int rflags)
+#elif defined(HAVE_IOPS_RENAME_IDMAP)
+zpl_rename2(struct mnt_idmap *user_ns, struct inode *sdip,
+ struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
+ unsigned int rflags)
#else
zpl_rename2(struct inode *sdip, struct dentry *sdentry,
- struct inode *tdip, struct dentry *tdentry, unsigned int flags)
+ struct inode *tdip, struct dentry *tdentry, unsigned int rflags)
#endif
{
cred_t *cr = CRED();
+ vattr_t *wo_vap = NULL;
int error;
fstrans_cookie_t cookie;
-
- /* We don't have renameat2(2) support */
- if (flags)
- return (-EINVAL);
+#if !(defined(HAVE_IOPS_RENAME_USERNS) || defined(HAVE_IOPS_RENAME_IDMAP))
+ zidmap_t *user_ns = kcred->user_ns;
+#endif
crhold(cr);
+ if (rflags & RENAME_WHITEOUT) {
+ wo_vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
+ zpl_vap_init(wo_vap, sdip, S_IFCHR, cr, user_ns);
+ wo_vap->va_rdev = makedevice(0, 0);
+ }
+
cookie = spl_fstrans_mark();
error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip),
- dname(tdentry), cr, 0);
+ dname(tdentry), cr, 0, rflags, wo_vap, user_ns);
spl_fstrans_unmark(cookie);
+ if (wo_vap)
+ kmem_free(wo_vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
return (error);
}
-#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS)
+#if !defined(HAVE_IOPS_RENAME_USERNS) && \
+ !defined(HAVE_RENAME_WANTS_FLAGS) && \
+ !defined(HAVE_RENAME2) && \
+ !defined(HAVE_IOPS_RENAME_IDMAP)
static int
zpl_rename(struct inode *sdip, struct dentry *sdentry,
struct inode *tdip, struct dentry *tdentry)
@@ -512,6 +605,9 @@ static int
#ifdef HAVE_IOPS_SYMLINK_USERNS
zpl_symlink(struct user_namespace *user_ns, struct inode *dir,
struct dentry *dentry, const char *name)
+#elif defined(HAVE_IOPS_SYMLINK_IDMAP)
+zpl_symlink(struct mnt_idmap *user_ns, struct inode *dir,
+ struct dentry *dentry, const char *name)
#else
zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
#endif
@@ -521,14 +617,17 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
znode_t *zp;
int error;
fstrans_cookie_t cookie;
+#if !(defined(HAVE_IOPS_SYMLINK_USERNS) || defined(HAVE_IOPS_SYMLINK_IDMAP))
+ zidmap_t *user_ns = kcred->user_ns;
+#endif
crhold(cr);
vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
- zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr);
+ zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns);
cookie = spl_fstrans_mark();
error = -zfs_symlink(ITOZ(dir), dname(dentry), vap,
- (char *)name, &zp, cr, 0);
+ (char *)name, &zp, cr, 0, user_ns);
if (error == 0) {
error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);
if (error) {
@@ -678,7 +777,7 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
return (-EMLINK);
crhold(cr);
- ip->i_ctime = current_time(ip);
+ zpl_inode_set_ctime_to_ts(ip, current_time(ip));
/* Must have an existing ref, so igrab() cannot return NULL */
VERIFY3P(igrab(ip), !=, NULL);
@@ -698,46 +797,6 @@ out:
return (error);
}
-static int
-#ifdef HAVE_D_REVALIDATE_NAMEIDATA
-zpl_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
- unsigned int flags = (nd ? nd->flags : 0);
-#else
-zpl_revalidate(struct dentry *dentry, unsigned int flags)
-{
-#endif /* HAVE_D_REVALIDATE_NAMEIDATA */
- /* CSTYLED */
- zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;
- int error;
-
- if (flags & LOOKUP_RCU)
- return (-ECHILD);
-
- /*
- * After a rollback negative dentries created before the rollback
- * time must be invalidated. Otherwise they can obscure files which
- * are only present in the rolled back dataset.
- */
- if (dentry->d_inode == NULL) {
- spin_lock(&dentry->d_lock);
- error = time_before(dentry->d_time, zfsvfs->z_rollback_time);
- spin_unlock(&dentry->d_lock);
-
- if (error)
- return (0);
- }
-
- /*
- * The dentry may reference a stale inode if a mounted file system
- * was rolled back to a point in time where the object didn't exist.
- */
- if (dentry->d_inode && ITOZ(dentry->d_inode)->z_is_stale)
- return (0);
-
- return (1);
-}
-
const struct inode_operations zpl_inode_operations = {
.setattr = zpl_setattr,
.getattr = zpl_getattr,
@@ -751,11 +810,20 @@ const struct inode_operations zpl_inode_operations = {
#if defined(HAVE_SET_ACL)
.set_acl = zpl_set_acl,
#endif /* HAVE_SET_ACL */
+#if defined(HAVE_GET_INODE_ACL)
+ .get_inode_acl = zpl_get_acl,
+#else
.get_acl = zpl_get_acl,
+#endif /* HAVE_GET_INODE_ACL */
#endif /* CONFIG_FS_POSIX_ACL */
};
+#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
+const struct inode_operations_wrapper zpl_dir_inode_operations = {
+ .ops = {
+#else
const struct inode_operations zpl_dir_inode_operations = {
+#endif
.create = zpl_create,
.lookup = zpl_lookup,
.link = zpl_link,
@@ -764,7 +832,11 @@ const struct inode_operations zpl_dir_inode_operations = {
.mkdir = zpl_mkdir,
.rmdir = zpl_rmdir,
.mknod = zpl_mknod,
-#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
+#ifdef HAVE_RENAME2
+ .rename2 = zpl_rename2,
+#elif defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)
+ .rename = zpl_rename2,
+#elif defined(HAVE_IOPS_RENAME_IDMAP)
.rename = zpl_rename2,
#else
.rename = zpl_rename,
@@ -784,8 +856,16 @@ const struct inode_operations zpl_dir_inode_operations = {
#if defined(HAVE_SET_ACL)
.set_acl = zpl_set_acl,
#endif /* HAVE_SET_ACL */
+#if defined(HAVE_GET_INODE_ACL)
+ .get_inode_acl = zpl_get_acl,
+#else
.get_acl = zpl_get_acl,
+#endif /* HAVE_GET_INODE_ACL */
#endif /* CONFIG_FS_POSIX_ACL */
+#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
+ },
+ .rename2 = zpl_rename2,
+#endif
};
const struct inode_operations zpl_symlink_inode_operations = {
@@ -823,10 +903,10 @@ const struct inode_operations zpl_special_inode_operations = {
#if defined(HAVE_SET_ACL)
.set_acl = zpl_set_acl,
#endif /* HAVE_SET_ACL */
+#if defined(HAVE_GET_INODE_ACL)
+ .get_inode_acl = zpl_get_acl,
+#else
.get_acl = zpl_get_acl,
+#endif /* HAVE_GET_INODE_ACL */
#endif /* CONFIG_FS_POSIX_ACL */
};
-
-dentry_operations_t zpl_dentry_operations = {
- .d_revalidate = zpl_revalidate,
-};
diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c
index b18efde9b18a..d98d32c1f9fb 100644
--- a/module/os/linux/zfs/zpl_super.c
+++ b/module/os/linux/zfs/zpl_super.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2011, Lawrence Livermore National Security, LLC.
+ * Copyright (c) 2023, Datto Inc. All rights reserved.
*/
@@ -185,7 +186,9 @@ zpl_remount_fs(struct super_block *sb, int *flags, char *data)
static int
__zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs)
{
- ZPL_ENTER(zfsvfs);
+ int error;
+ if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
+ return (error);
char *fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
dmu_objset_name(zfsvfs->z_os, fsname);
@@ -205,7 +208,7 @@ __zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs)
kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
return (0);
}
@@ -233,6 +236,18 @@ __zpl_show_options(struct seq_file *seq, zfsvfs_t *zfsvfs)
}
#endif /* CONFIG_FS_POSIX_ACL */
+ switch (zfsvfs->z_case) {
+ case ZFS_CASE_SENSITIVE:
+ seq_puts(seq, ",casesensitive");
+ break;
+ case ZFS_CASE_INSENSITIVE:
+ seq_puts(seq, ",caseinsensitive");
+ break;
+ default:
+ seq_puts(seq, ",casemixed");
+ break;
+ }
+
return (0);
}
@@ -262,11 +277,14 @@ zpl_test_super(struct super_block *s, void *data)
{
zfsvfs_t *zfsvfs = s->s_fs_info;
objset_t *os = data;
-
- if (zfsvfs == NULL)
- return (0);
-
- return (os == zfsvfs->z_os);
+ /*
+ * If the os doesn't match the z_os in the super_block, assume it is
+ * not a match. Matching would imply a multimount of a dataset. It is
+ * possible that during a multimount, there is a simultaneous operation
+ * that changes the z_os, e.g., rollback, where the match will be
+ * missed, but in that case the user will get an EBUSY.
+ */
+ return (zfsvfs != NULL && os == zfsvfs->z_os);
}
static struct super_block *
@@ -292,12 +310,35 @@ zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
s = sget(fs_type, zpl_test_super, set_anon_super, flags, os);
+ /*
+ * Recheck with the lock held to prevent mounting the wrong dataset
+ * since z_os can be stale when the teardown lock is held.
+ *
+ * We can't do this in zpl_test_super in since it's under spinlock and
+ * also s_umount lock is not held there so it would race with
+ * zfs_umount and zfsvfs can be freed.
+ */
+ if (!IS_ERR(s) && s->s_fs_info != NULL) {
+ zfsvfs_t *zfsvfs = s->s_fs_info;
+ if (zpl_enter(zfsvfs, FTAG) == 0) {
+ if (os != zfsvfs->z_os)
+ err = -SET_ERROR(EBUSY);
+ zpl_exit(zfsvfs, FTAG);
+ } else {
+ err = -SET_ERROR(EBUSY);
+ }
+ }
dsl_dataset_long_rele(dmu_objset_ds(os), FTAG);
dsl_dataset_rele(dmu_objset_ds(os), FTAG);
if (IS_ERR(s))
return (ERR_CAST(s));
+ if (err) {
+ deactivate_locked_super(s);
+ return (ERR_PTR(err));
+ }
+
if (s->s_root == NULL) {
err = zpl_fill_super(s, zm, flags & SB_SILENT ? 1 : 0);
if (err) {
@@ -334,7 +375,7 @@ zpl_kill_sb(struct super_block *sb)
}
void
-zpl_prune_sb(int64_t nr_to_scan, void *arg)
+zpl_prune_sb(uint64_t nr_to_scan, void *arg)
{
struct super_block *sb = (struct super_block *)arg;
int objects = 0;
@@ -360,7 +401,11 @@ const struct super_operations zpl_super_operations = {
struct file_system_type zpl_fs_type = {
.owner = THIS_MODULE,
.name = ZFS_DRIVER,
+#if defined(HAVE_IDMAP_MNT_API)
+ .fs_flags = FS_USERNS_MOUNT | FS_ALLOW_IDMAP,
+#else
.fs_flags = FS_USERNS_MOUNT,
+#endif
.mount = zpl_mount,
.kill_sb = zpl_kill_sb,
};
diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c
index 98378109cb9a..4e4f5210f85d 100644
--- a/module/os/linux/zfs/zpl_xattr.c
+++ b/module/os/linux/zfs/zpl_xattr.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -246,8 +246,8 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
crhold(cr);
cookie = spl_fstrans_mark();
- ZPL_ENTER(zfsvfs);
- ZPL_VERIFY_ZP(zp);
+ if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ goto out1;
rw_enter(&zp->z_xattr_lock, RW_READER);
if (zfsvfs->z_use_sa && zp->z_is_sa) {
@@ -264,7 +264,8 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
out:
rw_exit(&zp->z_xattr_lock);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
+out1:
spl_fstrans_unmark(cookie);
crfree(cr);
@@ -435,12 +436,13 @@ zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size)
crhold(cr);
cookie = spl_fstrans_mark();
- ZPL_ENTER(zfsvfs);
- ZPL_VERIFY_ZP(zp);
+ if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ goto out;
rw_enter(&zp->z_xattr_lock, RW_READER);
error = __zpl_xattr_get(ip, name, value, size, cr);
rw_exit(&zp->z_xattr_lock);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
+out:
spl_fstrans_unmark(cookie);
crfree(cr);
@@ -497,7 +499,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
vap->va_gid = crgetgid(cr);
error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp,
- cr, 0, NULL);
+ cr, ATTR_NOACLCHECK, NULL, zfs_init_idmap);
if (error)
goto out;
}
@@ -511,7 +513,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
error = -zfs_write_simple(xzp, value, size, pos, NULL);
out:
if (error == 0) {
- ip->i_ctime = current_time(ip);
+ zpl_inode_set_ctime_to_ts(ip, current_time(ip));
zfs_mark_inode_dirty(ip);
}
@@ -604,8 +606,8 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
crhold(cr);
cookie = spl_fstrans_mark();
- ZPL_ENTER(zfsvfs);
- ZPL_VERIFY_ZP(zp);
+ if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ goto out1;
rw_enter(&zp->z_xattr_lock, RW_WRITER);
/*
@@ -658,7 +660,8 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
zpl_xattr_set_sa(ip, name, NULL, 0, 0, cr);
out:
rw_exit(&zp->z_xattr_lock);
- ZPL_EXIT(zfsvfs);
+ zpl_exit(zfsvfs, FTAG);
+out1:
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);
@@ -735,9 +738,11 @@ __zpl_xattr_user_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
static int
-__zpl_xattr_user_set(struct inode *ip, const char *name,
+__zpl_xattr_user_set(zidmap_t *user_ns,
+ struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
+ (void) user_ns;
int error = 0;
/* xattr_resolve_name will do this for us if this is defined */
#ifndef HAVE_XATTR_HANDLER_NAME
@@ -843,9 +848,11 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
static int
-__zpl_xattr_trusted_set(struct inode *ip, const char *name,
+__zpl_xattr_trusted_set(zidmap_t *user_ns,
+ struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
+ (void) user_ns;
char *xattr_name;
int error;
@@ -911,9 +918,11 @@ __zpl_xattr_security_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
static int
-__zpl_xattr_security_set(struct inode *ip, const char *name,
+__zpl_xattr_security_set(zidmap_t *user_ns,
+ struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
+ (void) user_ns;
char *xattr_name;
int error;
/* xattr_resolve_name will do this for us if this is defined */
@@ -937,7 +946,7 @@ zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs,
int error = 0;
for (xattr = xattrs; xattr->name != NULL; xattr++) {
- error = __zpl_xattr_security_set(ip,
+ error = __zpl_xattr_security_set(NULL, ip,
xattr->name, xattr->value, xattr->value_len, 0);
if (error < 0)
@@ -1002,7 +1011,8 @@ zpl_set_acl_impl(struct inode *ip, struct posix_acl *acl, int type)
*/
if (ip->i_mode != mode) {
ip->i_mode = ITOZ(ip)->z_mode = mode;
- ip->i_ctime = current_time(ip);
+ zpl_inode_set_ctime_to_ts(ip,
+ current_time(ip));
zfs_mark_inode_dirty(ip);
}
@@ -1052,11 +1062,23 @@ int
#ifdef HAVE_SET_ACL_USERNS
zpl_set_acl(struct user_namespace *userns, struct inode *ip,
struct posix_acl *acl, int type)
+#elif defined(HAVE_SET_ACL_IDMAP_DENTRY)
+zpl_set_acl(struct mnt_idmap *userns, struct dentry *dentry,
+ struct posix_acl *acl, int type)
+#elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2)
+zpl_set_acl(struct user_namespace *userns, struct dentry *dentry,
+ struct posix_acl *acl, int type)
#else
zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type)
#endif /* HAVE_SET_ACL_USERNS */
{
+#ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2
+ return (zpl_set_acl_impl(d_inode(dentry), acl, type));
+#elif defined(HAVE_SET_ACL_IDMAP_DENTRY)
+ return (zpl_set_acl_impl(d_inode(dentry), acl, type));
+#else
return (zpl_set_acl_impl(ip, acl, type));
+#endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */
}
#endif /* HAVE_SET_ACL */
@@ -1115,7 +1137,7 @@ zpl_get_acl_impl(struct inode *ip, int type)
return (acl);
}
-#if defined(HAVE_GET_ACL_RCU)
+#if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL)
struct posix_acl *
zpl_get_acl(struct inode *ip, int type, bool rcu)
{
@@ -1149,7 +1171,7 @@ zpl_init_acl(struct inode *ip, struct inode *dir)
return (PTR_ERR(acl));
if (!acl) {
ITOZ(ip)->z_mode = (ip->i_mode &= ~current_umask());
- ip->i_ctime = current_time(ip);
+ zpl_inode_set_ctime_to_ts(ip, current_time(ip));
zfs_mark_inode_dirty(ip);
return (0);
}
@@ -1297,7 +1319,8 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default);
static int
-__zpl_xattr_acl_set_access(struct inode *ip, const char *name,
+__zpl_xattr_acl_set_access(zidmap_t *mnt_ns,
+ struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
struct posix_acl *acl;
@@ -1311,8 +1334,14 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP);
- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
+#if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
+ if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM);
+#else
+ (void) mnt_ns;
+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
+ return (-EPERM);
+#endif
if (value) {
acl = zpl_acl_from_xattr(value, size);
@@ -1336,7 +1365,8 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access);
static int
-__zpl_xattr_acl_set_default(struct inode *ip, const char *name,
+__zpl_xattr_acl_set_default(zidmap_t *mnt_ns,
+ struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
struct posix_acl *acl;
@@ -1350,8 +1380,14 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP);
- if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
+#if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP)
+ if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM);
+#else
+ (void) mnt_ns;
+ if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip))
+ return (-EPERM);
+#endif
if (value) {
acl = zpl_acl_from_xattr(value, size);
diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c
index acbab55d03ef..2a036dc5136b 100644
--- a/module/os/linux/zfs/zvol_os.c
+++ b/module/os/linux/zfs/zvol_os.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -37,6 +37,7 @@
#include <sys/spa_impl.h>
#include <sys/zvol.h>
#include <sys/zvol_impl.h>
+#include <cityhash.h>
#include <linux/blkdev_compat.h>
#include <linux/task_io_accounting_ops.h>
@@ -53,8 +54,14 @@ static unsigned int zvol_request_sync = 0;
static unsigned int zvol_prefetch_bytes = (128 * 1024);
static unsigned long zvol_max_discard_blocks = 16384;
+/*
+ * Switch taskq at multiple of 512 MB offset. This can be set to a lower value
+ * to utilize more threads for small files but may affect prefetch hits.
+ */
+#define ZVOL_TASKQ_OFFSET_SHIFT 29
+
#ifndef HAVE_BLKDEV_GET_ERESTARTSYS
-static const unsigned int zvol_open_timeout_ms = 1000;
+static unsigned int zvol_open_timeout_ms = 1000;
#endif
static unsigned int zvol_threads = 0;
@@ -76,6 +83,8 @@ static boolean_t zvol_use_blk_mq = B_FALSE;
static unsigned int zvol_blk_mq_blocks_per_thread = 8;
#endif
+static unsigned int zvol_num_taskqs = 0;
+
#ifndef BLKDEV_DEFAULT_RQ
/* BLKDEV_MAX_RQ was renamed to BLKDEV_DEFAULT_RQ in the 5.16 kernel */
#define BLKDEV_DEFAULT_RQ BLKDEV_MAX_RQ
@@ -114,7 +123,11 @@ struct zvol_state_os {
boolean_t use_blk_mq;
};
-taskq_t *zvol_taskq;
+typedef struct zv_taskq {
+ uint_t tqs_cnt;
+ taskq_t **tqs_taskq;
+} zv_taskq_t;
+static zv_taskq_t zvol_taskqs;
static struct ida zvol_ida;
typedef struct zv_request_stack {
@@ -342,8 +355,7 @@ zvol_discard(zv_request_t *zvr)
struct request_queue *q = zv->zv_zso->zvo_queue;
struct gendisk *disk = zv->zv_zso->zvo_disk;
unsigned long start_time = 0;
-
- boolean_t acct = blk_queue_io_stat(q);
+ boolean_t acct = B_FALSE;
ASSERT3P(zv, !=, NULL);
ASSERT3U(zv->zv_open_count, >, 0);
@@ -388,7 +400,7 @@ zvol_discard(zv_request_t *zvr)
if (error != 0) {
dmu_tx_abort(tx);
} else {
- zvol_log_truncate(zv, tx, start, size, B_TRUE);
+ zvol_log_truncate(zv, tx, start, size);
dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset,
ZVOL_OBJ, start, size);
@@ -513,7 +525,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
uint64_t size = io_size(bio, rq);
int rw = io_data_dir(bio, rq);
- if (zvol_request_sync)
+ if (zvol_request_sync || zv->zv_threading == B_FALSE)
force_sync = 1;
zv_request_t zvr = {
@@ -533,6 +545,22 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
}
zv_request_task_t *task;
+ zv_taskq_t *ztqs = &zvol_taskqs;
+ uint_t blk_mq_hw_queue = 0;
+ uint_t tq_idx;
+ uint_t taskq_hash;
+#ifdef HAVE_BLK_MQ
+ if (rq)
+#ifdef HAVE_BLK_MQ_RQ_HCTX
+ blk_mq_hw_queue = rq->mq_hctx->queue_num;
+#else
+ blk_mq_hw_queue =
+ rq->q->queue_hw_ctx[rq->q->mq_map[rq->cpu]]->queue_num;
+#endif
+#endif
+ taskq_hash = cityhash4((uintptr_t)zv, offset >> ZVOL_TASKQ_OFFSET_SHIFT,
+ blk_mq_hw_queue, 0);
+ tq_idx = taskq_hash % ztqs->tqs_cnt;
if (rw == WRITE) {
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
@@ -558,7 +586,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
rw_enter(&zv->zv_suspend_lock, RW_WRITER);
if (zv->zv_zilog == NULL) {
zv->zv_zilog = zil_open(zv->zv_objset,
- zvol_get_data);
+ zvol_get_data, &zv->zv_kstat.dk_zil_sums);
zv->zv_flags |= ZVOL_WRITTEN_TO;
/* replay / destroy done in zvol_create_minor */
VERIFY0((zv->zv_zilog->zl_header->zh_flags &
@@ -602,7 +630,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
zvol_discard(&zvr);
} else {
task = zv_request_task_create(zvr);
- taskq_dispatch_ent(zvol_taskq,
+ taskq_dispatch_ent(ztqs->tqs_taskq[tq_idx],
zvol_discard_task, task, 0, &task->ent);
}
} else {
@@ -610,7 +638,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
zvol_write(&zvr);
} else {
task = zv_request_task_create(zvr);
- taskq_dispatch_ent(zvol_taskq,
+ taskq_dispatch_ent(ztqs->tqs_taskq[tq_idx],
zvol_write_task, task, 0, &task->ent);
}
}
@@ -632,7 +660,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
zvol_read(&zvr);
} else {
task = zv_request_task_create(zvr);
- taskq_dispatch_ent(zvol_taskq,
+ taskq_dispatch_ent(ztqs->tqs_taskq[tq_idx],
zvol_read_task, task, 0, &task->ent);
}
}
@@ -672,7 +700,11 @@ zvol_request(struct request_queue *q, struct bio *bio)
}
static int
+#ifdef HAVE_BLK_MODE_T
+zvol_open(struct gendisk *disk, blk_mode_t flag)
+#else
zvol_open(struct block_device *bdev, fmode_t flag)
+#endif
{
zvol_state_t *zv;
int error = 0;
@@ -687,10 +719,14 @@ retry:
/*
* Obtain a copy of private_data under the zvol_state_lock to make
* sure that either the result of zvol free code path setting
- * bdev->bd_disk->private_data to NULL is observed, or zvol_os_free()
+ * disk->private_data to NULL is observed, or zvol_os_free()
* is not called on this zv because of the positive zv_open_count.
*/
+#ifdef HAVE_BLK_MODE_T
+ zv = disk->private_data;
+#else
zv = bdev->bd_disk->private_data;
+#endif
if (zv == NULL) {
rw_exit(&zvol_state_lock);
return (SET_ERROR(-ENXIO));
@@ -770,14 +806,15 @@ retry:
}
}
- error = -zvol_first_open(zv, !(flag & FMODE_WRITE));
+ error = -zvol_first_open(zv, !(blk_mode_is_open_write(flag)));
if (drop_namespace)
mutex_exit(&spa_namespace_lock);
}
if (error == 0) {
- if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
+ if ((blk_mode_is_open_write(flag)) &&
+ (zv->zv_flags & ZVOL_RDONLY)) {
if (zv->zv_open_count == 0)
zvol_last_close(zv);
@@ -792,14 +829,25 @@ retry:
rw_exit(&zv->zv_suspend_lock);
if (error == 0)
+#ifdef HAVE_BLK_MODE_T
+ disk_check_media_change(disk);
+#else
zfs_check_media_change(bdev);
+#endif
return (error);
}
static void
-zvol_release(struct gendisk *disk, fmode_t mode)
+#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
+zvol_release(struct gendisk *disk)
+#else
+zvol_release(struct gendisk *disk, fmode_t unused)
+#endif
{
+#if !defined(HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG)
+ (void) unused;
+#endif
zvol_state_t *zv;
boolean_t drop_suspend = B_TRUE;
@@ -854,7 +902,13 @@ zvol_ioctl(struct block_device *bdev, fmode_t mode,
switch (cmd) {
case BLKFLSBUF:
+#ifdef HAVE_FSYNC_BDEV
fsync_bdev(bdev);
+#elif defined(HAVE_SYNC_BLOCKDEV)
+ sync_blockdev(bdev);
+#else
+#error "Neither fsync_bdev() nor sync_blockdev() found"
+#endif
invalidate_bdev(bdev);
rw_enter(&zv->zv_suspend_lock, RW_READER);
@@ -1030,6 +1084,16 @@ zvol_alloc_non_blk_mq(struct zvol_state_os *zso)
zso->zvo_disk->minors = ZVOL_MINORS;
zso->zvo_queue = zso->zvo_disk->queue;
+#elif defined(HAVE_BLK_ALLOC_DISK_2ARG)
+ struct gendisk *disk = blk_alloc_disk(NULL, NUMA_NO_NODE);
+ if (IS_ERR(disk)) {
+ zso->zvo_disk = NULL;
+ return (1);
+ }
+
+ zso->zvo_disk = disk;
+ zso->zvo_disk->minors = ZVOL_MINORS;
+ zso->zvo_queue = zso->zvo_disk->queue;
#else
zso->zvo_queue = blk_alloc_queue(NUMA_NO_NODE);
if (zso->zvo_queue == NULL)
@@ -1078,6 +1142,17 @@ zvol_alloc_blk_mq(zvol_state_t *zv)
}
zso->zvo_queue = zso->zvo_disk->queue;
zso->zvo_disk->minors = ZVOL_MINORS;
+#elif defined(HAVE_BLK_ALLOC_DISK_2ARG)
+ struct gendisk *disk = blk_mq_alloc_disk(&zso->tag_set, NULL, zv);
+ if (IS_ERR(disk)) {
+ zso->zvo_disk = NULL;
+ blk_mq_free_tag_set(&zso->tag_set);
+ return (1);
+ }
+
+ zso->zvo_disk = disk;
+ zso->zvo_queue = zso->zvo_disk->queue;
+ zso->zvo_disk->minors = ZVOL_MINORS;
#else
zso->zvo_disk = alloc_disk(ZVOL_MINORS);
if (zso->zvo_disk == NULL) {
@@ -1174,7 +1249,7 @@ zvol_alloc(dev_t dev, const char *name)
zso->zvo_queue->queuedata = zv;
zso->zvo_dev = dev;
zv->zv_open_count = 0;
- strlcpy(zv->zv_name, name, MAXNAMELEN);
+ strlcpy(zv->zv_name, name, sizeof (zv->zv_name));
zfs_rangelock_init(&zv->zv_rangelock, NULL, NULL);
rw_init(&zv->zv_suspend_lock, NULL, RW_DEFAULT, NULL);
@@ -1231,9 +1306,13 @@ zvol_os_free(zvol_state_t *zv)
del_gendisk(zv->zv_zso->zvo_disk);
#if defined(HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS) && \
- defined(HAVE_BLK_ALLOC_DISK)
+ (defined(HAVE_BLK_ALLOC_DISK) || defined(HAVE_BLK_ALLOC_DISK_2ARG))
+#if defined(HAVE_BLK_CLEANUP_DISK)
blk_cleanup_disk(zv->zv_zso->zvo_disk);
#else
+ put_disk(zv->zv_zso->zvo_disk);
+#endif
+#else
blk_cleanup_queue(zv->zv_zso->zvo_queue);
put_disk(zv->zv_zso->zvo_disk);
#endif
@@ -1275,6 +1354,8 @@ zvol_os_create_minor(const char *name)
int error = 0;
int idx;
uint64_t hash = zvol_name_hash(name);
+ uint64_t volthreading;
+ bool replayed_zil = B_FALSE;
if (zvol_inhibit_dev)
return (0);
@@ -1283,6 +1364,13 @@ zvol_os_create_minor(const char *name)
if (idx < 0)
return (SET_ERROR(-idx));
minor = idx << ZVOL_MINOR_BITS;
+ if (MINOR(minor) != minor) {
+ /* too many partitions can cause an overflow */
+ zfs_dbgmsg("zvol: create minor overflow: %s, minor %u/%u",
+ name, minor, MINOR(minor));
+ ida_simple_remove(&zvol_ida, idx);
+ return (SET_ERROR(EINVAL));
+ }
zv = zvol_find_by_name_hash(name, hash, RW_NONE);
if (zv) {
@@ -1320,6 +1408,12 @@ zvol_os_create_minor(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;
+ /* Default */
+ zv->zv_threading = B_TRUE;
+ if (dsl_prop_get_integer(name, "volthreading", &volthreading, NULL)
+ == 0)
+ zv->zv_threading = volthreading;
+
set_capacity(zv->zv_zso->zvo_disk, zv->zv_volsize >> 9);
blk_queue_max_hw_sectors(zv->zv_zso->zvo_queue,
@@ -1408,18 +1502,21 @@ zvol_os_create_minor(const char *name)
blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, zv->zv_zso->zvo_queue);
#endif
+ ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
+ error = dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
+ if (error)
+ goto out_dmu_objset_disown;
ASSERT3P(zv->zv_zilog, ==, NULL);
- zv->zv_zilog = zil_open(os, zvol_get_data);
+ zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(zv->zv_zilog, B_FALSE);
+ replayed_zil = zil_destroy(zv->zv_zilog, B_FALSE);
else
- zil_replay(os, zv, zvol_replay_vector);
+ replayed_zil = zil_replay(os, zv, zvol_replay_vector);
}
- zil_close(zv->zv_zilog);
+ if (replayed_zil)
+ 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);
/*
* When udev detects the addition of the device it will immediately
@@ -1427,7 +1524,7 @@ zvol_os_create_minor(const char *name)
* Prefetching the blocks commonly scanned by blkid(8) will speed
* up this process.
*/
- len = MIN(MAX(zvol_prefetch_bytes, 0), SPA_MAXBLOCKSIZE);
+ len = MIN(zvol_prefetch_bytes, SPA_MAXBLOCKSIZE);
if (len > 0) {
dmu_prefetch(os, ZVOL_OBJ, 0, 0, len, ZIO_PRIORITY_SYNC_READ);
dmu_prefetch(os, ZVOL_OBJ, 0, volsize - len, len,
@@ -1474,7 +1571,7 @@ zvol_os_rename_minor(zvol_state_t *zv, const char *newname)
strlcpy(zv->zv_name, newname, sizeof (zv->zv_name));
/* move to new hashtable entry */
- zv->zv_hash = zvol_name_hash(zv->zv_name);
+ zv->zv_hash = zvol_name_hash(newname);
hlist_del(&zv->zv_hlink);
hlist_add_head(&zv->zv_hlink, ZVOL_HT_HEAD(zv->zv_hash));
@@ -1488,6 +1585,8 @@ zvol_os_rename_minor(zvol_state_t *zv, const char *newname)
*/
set_disk_ro(zv->zv_zso->zvo_disk, !readonly);
set_disk_ro(zv->zv_zso->zvo_disk, readonly);
+
+ dataset_kstats_rename(&zv->zv_kstat, newname);
}
void
@@ -1528,8 +1627,40 @@ zvol_init(void)
zvol_actual_threads = MIN(MAX(zvol_threads, 1), 1024);
}
+ /*
+ * Use atleast 32 zvol_threads but for many core system,
+ * prefer 6 threads per taskq, but no more taskqs
+ * than threads in them on large systems.
+ *
+ * taskq total
+ * cpus taskqs threads threads
+ * ------- ------- ------- -------
+ * 1 1 32 32
+ * 2 1 32 32
+ * 4 1 32 32
+ * 8 2 16 32
+ * 16 3 11 33
+ * 32 5 7 35
+ * 64 8 8 64
+ * 128 11 12 132
+ * 256 16 16 256
+ */
+ zv_taskq_t *ztqs = &zvol_taskqs;
+ uint_t num_tqs = MIN(num_online_cpus(), zvol_num_taskqs);
+ if (num_tqs == 0) {
+ num_tqs = 1 + num_online_cpus() / 6;
+ while (num_tqs * num_tqs > zvol_actual_threads)
+ num_tqs--;
+ }
+ uint_t per_tq_thread = zvol_actual_threads / num_tqs;
+ if (per_tq_thread * num_tqs < zvol_actual_threads)
+ per_tq_thread++;
+ ztqs->tqs_cnt = num_tqs;
+ ztqs->tqs_taskq = kmem_alloc(num_tqs * sizeof (taskq_t *), KM_SLEEP);
error = register_blkdev(zvol_major, ZVOL_DRIVER);
if (error) {
+ kmem_free(ztqs->tqs_taskq, ztqs->tqs_cnt * sizeof (taskq_t *));
+ ztqs->tqs_taskq = NULL;
printk(KERN_INFO "ZFS: register_blkdev() failed %d\n", error);
return (error);
}
@@ -1549,11 +1680,22 @@ zvol_init(void)
1024);
}
#endif
- zvol_taskq = taskq_create(ZVOL_DRIVER, zvol_actual_threads, maxclsyspri,
- zvol_actual_threads, INT_MAX, TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
- if (zvol_taskq == NULL) {
- unregister_blkdev(zvol_major, ZVOL_DRIVER);
- return (-ENOMEM);
+ for (uint_t i = 0; i < num_tqs; i++) {
+ char name[32];
+ (void) snprintf(name, sizeof (name), "%s_tq-%u",
+ ZVOL_DRIVER, i);
+ ztqs->tqs_taskq[i] = taskq_create(name, per_tq_thread,
+ maxclsyspri, per_tq_thread, INT_MAX,
+ TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
+ if (ztqs->tqs_taskq[i] == NULL) {
+ for (int j = i - 1; j >= 0; j--)
+ taskq_destroy(ztqs->tqs_taskq[j]);
+ unregister_blkdev(zvol_major, ZVOL_DRIVER);
+ kmem_free(ztqs->tqs_taskq, ztqs->tqs_cnt *
+ sizeof (taskq_t *));
+ ztqs->tqs_taskq = NULL;
+ return (-ENOMEM);
+ }
}
zvol_init_impl();
@@ -1564,9 +1706,22 @@ zvol_init(void)
void
zvol_fini(void)
{
+ zv_taskq_t *ztqs = &zvol_taskqs;
zvol_fini_impl();
unregister_blkdev(zvol_major, ZVOL_DRIVER);
- taskq_destroy(zvol_taskq);
+
+ if (ztqs->tqs_taskq == NULL) {
+ ASSERT3U(ztqs->tqs_cnt, ==, 0);
+ } else {
+ for (uint_t i = 0; i < ztqs->tqs_cnt; i++) {
+ ASSERT3P(ztqs->tqs_taskq[i], !=, NULL);
+ taskq_destroy(ztqs->tqs_taskq[i]);
+ }
+ kmem_free(ztqs->tqs_taskq, ztqs->tqs_cnt *
+ sizeof (taskq_t *));
+ ztqs->tqs_taskq = NULL;
+ }
+
ida_destroy(&zvol_ida);
}
@@ -1587,6 +1742,9 @@ MODULE_PARM_DESC(zvol_request_sync, "Synchronously handle bio requests");
module_param(zvol_max_discard_blocks, ulong, 0444);
MODULE_PARM_DESC(zvol_max_discard_blocks, "Max number of blocks to discard");
+module_param(zvol_num_taskqs, uint, 0444);
+MODULE_PARM_DESC(zvol_num_taskqs, "Number of zvol taskqs");
+
module_param(zvol_prefetch_bytes, uint, 0644);
MODULE_PARM_DESC(zvol_prefetch_bytes, "Prefetch N bytes at zvol start+end");
@@ -1605,4 +1763,9 @@ MODULE_PARM_DESC(zvol_blk_mq_blocks_per_thread,
"Process volblocksize blocks per thread");
#endif
+#ifndef HAVE_BLKDEV_GET_ERESTARTSYS
+module_param(zvol_open_timeout_ms, uint, 0644);
+MODULE_PARM_DESC(zvol_open_timeout_ms, "Timeout for ZVOL open retries");
+#endif
+
/* END CSTYLED */
diff --git a/module/unicode/u8_textprep.c b/module/unicode/u8_textprep.c
index 37d648b2172d..49e22c88cde7 100644
--- a/module/unicode/u8_textprep.c
+++ b/module/unicode/u8_textprep.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,6 +23,9 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2022 MNX Cloud, Inc.
+ */
@@ -213,10 +216,10 @@ static const int8_t u8_number_of_bytes[0x100] = {
/* 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F */
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
-/* 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F */
+/* 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F */
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
-/* A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF */
+/* A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF */
I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
/* B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF */
@@ -1286,8 +1289,12 @@ TRY_THE_NEXT_MARK:
saved_l = l - disp[last];
while (p < oslast) {
- size = u8_number_of_bytes[*p];
- if (size <= 1 || (p + size) > oslast)
+ int8_t number_of_bytes = u8_number_of_bytes[*p];
+
+ if (number_of_bytes <= 1)
+ break;
+ size = number_of_bytes;
+ if ((p + size) > oslast)
break;
saved_p = p;
@@ -1378,8 +1385,10 @@ SAFE_RETURN:
*/
static size_t
collect_a_seq(size_t uv, uchar_t *u8s, uchar_t **source, uchar_t *slast,
- boolean_t is_it_toupper, boolean_t is_it_tolower,
- boolean_t canonical_decomposition, boolean_t compatibility_decomposition,
+ boolean_t is_it_toupper,
+ boolean_t is_it_tolower,
+ boolean_t canonical_decomposition,
+ boolean_t compatibility_decomposition,
boolean_t canonical_composition,
int *errnum, u8_normalization_states_t *state)
{
diff --git a/module/unicode/uconv.c b/module/unicode/uconv.c
index 6854aeab277f..4bd19ebdd242 100644
--- a/module/unicode/uconv.c
+++ b/module/unicode/uconv.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c
index 4df09884aa91..309d9bf14cd4 100644
--- a/module/zcommon/zfeature_common.c
+++ b/module/zcommon/zfeature_common.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -725,6 +725,35 @@ zpool_feature_init(void)
blake3_deps, sfeatures);
}
+ zfeature_register(SPA_FEATURE_BLOCK_CLONING,
+ "com.fudosecurity:block_cloning", "block_cloning",
+ "Support for block cloning via Block Reference Table.",
+ ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
+ sfeatures);
+
+ zfeature_register(SPA_FEATURE_AVZ_V2,
+ "com.klarasystems:vdev_zaps_v2", "vdev_zaps_v2",
+ "Support for root vdev ZAP.",
+ ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL,
+ sfeatures);
+
+ {
+ static const spa_feature_t redact_list_spill_deps[] = {
+ SPA_FEATURE_REDACTION_BOOKMARKS,
+ SPA_FEATURE_NONE
+ };
+ zfeature_register(SPA_FEATURE_REDACTION_LIST_SPILL,
+ "com.delphix:redaction_list_spill", "redaction_list_spill",
+ "Support for increased number of redaction_snapshot "
+ "arguments in zfs redact.", 0, ZFEATURE_TYPE_BOOLEAN,
+ redact_list_spill_deps, sfeatures);
+ }
+
+ zfeature_register(SPA_FEATURE_RAIDZ_EXPANSION,
+ "org.openzfs:raidz_expansion", "raidz_expansion",
+ "Support for raidz expansion",
+ ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
+
zfs_mod_list_supported_free(sfeatures);
}
diff --git a/module/zcommon/zfs_comutil.c b/module/zcommon/zfs_comutil.c
index c8f4dccd30d5..384746bd4a02 100644
--- a/module/zcommon/zfs_comutil.c
+++ b/module/zcommon/zfs_comutil.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -70,7 +70,7 @@ zfs_allocatable_devs(nvlist_t *nv)
boolean_t
zfs_special_devs(nvlist_t *nv, const char *type)
{
- char *bias;
+ const char *bias;
uint_t c;
nvlist_t **child;
uint_t children;
@@ -98,7 +98,7 @@ zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp)
{
nvlist_t *policy;
nvpair_t *elem;
- char *nm;
+ const char *nm;
/* Defaults */
zlpp->zlp_rewind = ZPOOL_NO_REWIND;
diff --git a/module/zcommon/zfs_deleg.c b/module/zcommon/zfs_deleg.c
index acd2feca38e0..f977c761147d 100644
--- a/module/zcommon/zfs_deleg.c
+++ b/module/zcommon/zfs_deleg.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -102,9 +102,9 @@ zfs_deleg_canonicalize_perm(const char *perm)
}
static int
-zfs_validate_who(char *who)
+zfs_validate_who(const char *who)
{
- char *p;
+ const char *p;
if (who[2] != ZFS_DELEG_FIELD_SEP_CHR)
return (-1);
diff --git a/module/zcommon/zfs_fletcher.c b/module/zcommon/zfs_fletcher.c
index 4606b5491daa..619ddef0243a 100644
--- a/module/zcommon/zfs_fletcher.c
+++ b/module/zcommon/zfs_fletcher.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -136,8 +136,8 @@
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/byteorder.h>
-#include <sys/spa.h>
#include <sys/simd.h>
+#include <sys/spa.h>
#include <sys/zio_checksum.h>
#include <sys/zfs_context.h>
#include <zfs_fletcher.h>
@@ -160,6 +160,7 @@ static const fletcher_4_ops_t fletcher_4_scalar_ops = {
.fini_byteswap = fletcher_4_scalar_fini,
.compute_byteswap = fletcher_4_scalar_byteswap,
.valid = fletcher_4_scalar_valid,
+ .uses_fpu = B_FALSE,
.name = "scalar"
};
@@ -300,21 +301,18 @@ fletcher_2_byteswap(const void *buf, uint64_t size,
(void) fletcher_2_incremental_byteswap((void *) buf, size, zcp);
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_init(fletcher_4_ctx_t *ctx)
{
ZIO_SET_CHECKSUM(&ctx->scalar, 0, 0, 0, 0);
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
memcpy(zcp, &ctx->scalar, sizeof (zio_cksum_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_native(fletcher_4_ctx_t *ctx, const void *buf,
uint64_t size)
@@ -338,7 +336,6 @@ fletcher_4_scalar_native(fletcher_4_ctx_t *ctx, const void *buf,
ZIO_SET_CHECKSUM(&ctx->scalar, a, b, c, d);
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
uint64_t size)
@@ -458,9 +455,15 @@ fletcher_4_native_impl(const void *buf, uint64_t size, zio_cksum_t *zcp)
fletcher_4_ctx_t ctx;
const fletcher_4_ops_t *ops = fletcher_4_impl_get();
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_begin();
+ }
ops->init_native(&ctx);
ops->compute_native(&ctx, buf, size);
ops->fini_native(&ctx, zcp);
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_end();
+ }
}
void
@@ -500,9 +503,15 @@ fletcher_4_byteswap_impl(const void *buf, uint64_t size, zio_cksum_t *zcp)
fletcher_4_ctx_t ctx;
const fletcher_4_ops_t *ops = fletcher_4_impl_get();
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_begin();
+ }
ops->init_byteswap(&ctx);
ops->compute_byteswap(&ctx, buf, size);
ops->fini_byteswap(&ctx, zcp);
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_end();
+ }
}
void
@@ -628,7 +637,7 @@ fletcher_4_kstat_data(char *buf, size_t size, void *data)
off += snprintf(buf + off, size - off, "%-17s", "fastest");
off += snprintf(buf + off, size - off, "%-15s",
fletcher_4_supp_impls[fastest_stat->native]->name);
- off += snprintf(buf + off, size - off, "%-15s\n",
+ (void) snprintf(buf + off, size - off, "%-15s\n",
fletcher_4_supp_impls[fastest_stat->byteswap]->name);
} else {
ptrdiff_t id = curr_stat - fletcher_4_stat_data;
@@ -637,7 +646,7 @@ fletcher_4_kstat_data(char *buf, size_t size, void *data)
fletcher_4_supp_impls[id]->name);
off += snprintf(buf + off, size - off, "%-15llu",
(u_longlong_t)curr_stat->native);
- off += snprintf(buf + off, size - off, "%-15llu\n",
+ (void) snprintf(buf + off, size - off, "%-15llu\n",
(u_longlong_t)curr_stat->byteswap);
}
@@ -661,6 +670,7 @@ fletcher_4_kstat_addr(kstat_t *ksp, loff_t n)
fletcher_4_fastest_impl.init_ ## type = src->init_ ## type; \
fletcher_4_fastest_impl.fini_ ## type = src->fini_ ## type; \
fletcher_4_fastest_impl.compute_ ## type = src->compute_ ## type; \
+ fletcher_4_fastest_impl.uses_fpu = src->uses_fpu; \
}
#define FLETCHER_4_BENCH_NS (MSEC2NSEC(1)) /* 1ms */
@@ -816,10 +826,14 @@ abd_fletcher_4_init(zio_abd_checksum_data_t *cdp)
const fletcher_4_ops_t *ops = fletcher_4_impl_get();
cdp->acd_private = (void *) ops;
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_begin();
+ }
if (cdp->acd_byteorder == ZIO_CHECKSUM_NATIVE)
ops->init_native(cdp->acd_ctx);
else
ops->init_byteswap(cdp->acd_ctx);
+
}
static void
@@ -833,8 +847,13 @@ abd_fletcher_4_fini(zio_abd_checksum_data_t *cdp)
ops->fini_native(cdp->acd_ctx, cdp->acd_zcp);
else
ops->fini_byteswap(cdp->acd_ctx, cdp->acd_zcp);
+
+ if (ops->uses_fpu == B_TRUE) {
+ kfpu_end();
+ }
}
+
static void
abd_fletcher_4_simd2scalar(boolean_t native, void *data, size_t size,
zio_abd_checksum_data_t *cdp)
@@ -903,12 +922,12 @@ fletcher_4_param_get(char *buffer, zfs_kernel_param_t *unused)
/* list fastest */
fmt = IMPL_FMT(impl, IMPL_FASTEST);
- cnt += sprintf(buffer + cnt, fmt, "fastest");
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, "fastest");
/* list all supported implementations */
for (uint32_t i = 0; i < fletcher_4_supp_impls_cnt; ++i) {
fmt = IMPL_FMT(impl, i);
- cnt += sprintf(buffer + cnt, fmt,
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
fletcher_4_supp_impls[i]->name);
}
diff --git a/module/zcommon/zfs_fletcher_aarch64_neon.c b/module/zcommon/zfs_fletcher_aarch64_neon.c
index 3e14875d6c8c..26f2115c44bf 100644
--- a/module/zcommon/zfs_fletcher_aarch64_neon.c
+++ b/module/zcommon/zfs_fletcher_aarch64_neon.c
@@ -48,14 +48,12 @@
#include <sys/string.h>
#include <zfs_fletcher.h>
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_aarch64_neon_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->aarch64_neon, 0, 4 * sizeof (zfs_fletcher_aarch64_neon_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_aarch64_neon_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -146,17 +144,13 @@ unsigned char TMP2 __attribute__((vector_size(16)));
unsigned char SRC __attribute__((vector_size(16)));
#endif
- kfpu_begin();
-
NEON_INIT_LOOP();
- for (; ip < ipend; ip += 2) {
+ do {
NEON_MAIN_LOOP(NEON_DONT_REVERSE);
- }
+ } while ((ip += 2) < ipend);
NEON_FINI_LOOP();
-
- kfpu_end();
}
static void
@@ -185,17 +179,13 @@ unsigned char TMP2 __attribute__((vector_size(16)));
unsigned char SRC __attribute__((vector_size(16)));
#endif
- kfpu_begin();
-
NEON_INIT_LOOP();
- for (; ip < ipend; ip += 2) {
+ do {
NEON_MAIN_LOOP(NEON_DO_REVERSE);
- }
+ } while ((ip += 2) < ipend);
NEON_FINI_LOOP();
-
- kfpu_end();
}
static boolean_t fletcher_4_aarch64_neon_valid(void)
@@ -211,6 +201,7 @@ const fletcher_4_ops_t fletcher_4_aarch64_neon_ops = {
.compute_byteswap = fletcher_4_aarch64_neon_byteswap,
.fini_byteswap = fletcher_4_aarch64_neon_fini,
.valid = fletcher_4_aarch64_neon_valid,
+ .uses_fpu = B_TRUE,
.name = "aarch64_neon"
};
diff --git a/module/zcommon/zfs_fletcher_avx512.c b/module/zcommon/zfs_fletcher_avx512.c
index 713806d28259..95fc2b151a7d 100644
--- a/module/zcommon/zfs_fletcher_avx512.c
+++ b/module/zcommon/zfs_fletcher_avx512.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -35,14 +35,12 @@
#define __asm __asm__ __volatile__
#endif
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx512f_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->avx512, 0, 4 * sizeof (zfs_fletcher_avx512_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx512f_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -96,21 +94,17 @@ fletcher_4_avx512f_native(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint32_t *ip = buf;
const uint32_t *ipend = (uint32_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_AVX512_RESTORE_CTX(ctx);
- for (; ip < ipend; ip += 8) {
+ do {
__asm("vpmovzxdq %0, %%zmm4"::"m" (*ip));
__asm("vpaddq %zmm4, %zmm0, %zmm0");
__asm("vpaddq %zmm0, %zmm1, %zmm1");
__asm("vpaddq %zmm1, %zmm2, %zmm2");
__asm("vpaddq %zmm2, %zmm3, %zmm3");
- }
+ } while ((ip += 8) < ipend);
FLETCHER_4_AVX512_SAVE_CTX(ctx);
-
- kfpu_end();
}
STACK_FRAME_NON_STANDARD(fletcher_4_avx512f_native);
@@ -122,8 +116,6 @@ fletcher_4_avx512f_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
const uint32_t *ip = buf;
const uint32_t *ipend = (uint32_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_AVX512_RESTORE_CTX(ctx);
__asm("vpbroadcastq %0, %%zmm8" :: "r" (byteswap_mask));
@@ -131,7 +123,7 @@ fletcher_4_avx512f_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
__asm("vpsllq $16, %zmm8, %zmm10");
__asm("vpsllq $24, %zmm8, %zmm11");
- for (; ip < ipend; ip += 8) {
+ do {
__asm("vpmovzxdq %0, %%zmm5"::"m" (*ip));
__asm("vpsrlq $24, %zmm5, %zmm6");
@@ -150,11 +142,9 @@ fletcher_4_avx512f_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
__asm("vpaddq %zmm0, %zmm1, %zmm1");
__asm("vpaddq %zmm1, %zmm2, %zmm2");
__asm("vpaddq %zmm2, %zmm3, %zmm3");
- }
+ } while ((ip += 8) < ipend);
FLETCHER_4_AVX512_SAVE_CTX(ctx)
-
- kfpu_end();
}
STACK_FRAME_NON_STANDARD(fletcher_4_avx512f_byteswap);
@@ -172,6 +162,7 @@ const fletcher_4_ops_t fletcher_4_avx512f_ops = {
.fini_byteswap = fletcher_4_avx512f_fini,
.compute_byteswap = fletcher_4_avx512f_byteswap,
.valid = fletcher_4_avx512f_valid,
+ .uses_fpu = B_TRUE,
.name = "avx512f"
};
@@ -189,13 +180,11 @@ fletcher_4_avx512bw_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
const uint32_t *ip = buf;
const uint32_t *ipend = (uint32_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_AVX512_RESTORE_CTX(ctx);
__asm("vmovdqu64 %0, %%zmm5" :: "m" (mask));
- for (; ip < ipend; ip += 8) {
+ do {
__asm("vpmovzxdq %0, %%zmm4"::"m" (*ip));
__asm("vpshufb %zmm5, %zmm4, %zmm4");
@@ -204,11 +193,9 @@ fletcher_4_avx512bw_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
__asm("vpaddq %zmm0, %zmm1, %zmm1");
__asm("vpaddq %zmm1, %zmm2, %zmm2");
__asm("vpaddq %zmm2, %zmm3, %zmm3");
- }
+ } while ((ip += 8) < ipend);
FLETCHER_4_AVX512_SAVE_CTX(ctx)
-
- kfpu_end();
}
STACK_FRAME_NON_STANDARD(fletcher_4_avx512bw_byteswap);
@@ -226,6 +213,7 @@ const fletcher_4_ops_t fletcher_4_avx512bw_ops = {
.fini_byteswap = fletcher_4_avx512f_fini,
.compute_byteswap = fletcher_4_avx512bw_byteswap,
.valid = fletcher_4_avx512bw_valid,
+ .uses_fpu = B_TRUE,
.name = "avx512bw"
};
#endif
diff --git a/module/zcommon/zfs_fletcher_intel.c b/module/zcommon/zfs_fletcher_intel.c
index 42b6309d3609..34590a15572d 100644
--- a/module/zcommon/zfs_fletcher_intel.c
+++ b/module/zcommon/zfs_fletcher_intel.c
@@ -47,14 +47,12 @@
#include <sys/simd.h>
#include <zfs_fletcher.h>
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx2_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->avx, 0, 4 * sizeof (zfs_fletcher_avx_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx2_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -106,22 +104,18 @@ fletcher_4_avx2_native(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint64_t *ip = buf;
const uint64_t *ipend = (uint64_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_AVX2_RESTORE_CTX(ctx);
- for (; ip < ipend; ip += 2) {
+ do {
asm volatile("vpmovzxdq %0, %%ymm4"::"m" (*ip));
asm volatile("vpaddq %ymm4, %ymm0, %ymm0");
asm volatile("vpaddq %ymm0, %ymm1, %ymm1");
asm volatile("vpaddq %ymm1, %ymm2, %ymm2");
asm volatile("vpaddq %ymm2, %ymm3, %ymm3");
- }
+ } while ((ip += 2) < ipend);
FLETCHER_4_AVX2_SAVE_CTX(ctx);
asm volatile("vzeroupper");
-
- kfpu_end();
}
static void
@@ -134,13 +128,11 @@ fletcher_4_avx2_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint64_t *ip = buf;
const uint64_t *ipend = (uint64_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_AVX2_RESTORE_CTX(ctx);
asm volatile("vmovdqu %0, %%ymm5" :: "m" (mask));
- for (; ip < ipend; ip += 2) {
+ do {
asm volatile("vpmovzxdq %0, %%ymm4"::"m" (*ip));
asm volatile("vpshufb %ymm5, %ymm4, %ymm4");
@@ -148,12 +140,10 @@ fletcher_4_avx2_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
asm volatile("vpaddq %ymm0, %ymm1, %ymm1");
asm volatile("vpaddq %ymm1, %ymm2, %ymm2");
asm volatile("vpaddq %ymm2, %ymm3, %ymm3");
- }
+ } while ((ip += 2) < ipend);
FLETCHER_4_AVX2_SAVE_CTX(ctx);
asm volatile("vzeroupper");
-
- kfpu_end();
}
static boolean_t fletcher_4_avx2_valid(void)
@@ -169,6 +159,7 @@ const fletcher_4_ops_t fletcher_4_avx2_ops = {
.fini_byteswap = fletcher_4_avx2_fini,
.compute_byteswap = fletcher_4_avx2_byteswap,
.valid = fletcher_4_avx2_valid,
+ .uses_fpu = B_TRUE,
.name = "avx2"
};
diff --git a/module/zcommon/zfs_fletcher_sse.c b/module/zcommon/zfs_fletcher_sse.c
index 791bbd49f68f..8ab9b9acb83b 100644
--- a/module/zcommon/zfs_fletcher_sse.c
+++ b/module/zcommon/zfs_fletcher_sse.c
@@ -49,14 +49,12 @@
#include <sys/byteorder.h>
#include <zfs_fletcher.h>
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_sse2_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->sse, 0, 4 * sizeof (zfs_fletcher_sse_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_sse2_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -104,13 +102,11 @@ fletcher_4_sse2_native(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint64_t *ip = buf;
const uint64_t *ipend = (uint64_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_SSE_RESTORE_CTX(ctx);
asm volatile("pxor %xmm4, %xmm4");
- for (; ip < ipend; ip += 2) {
+ do {
asm volatile("movdqu %0, %%xmm5" :: "m"(*ip));
asm volatile("movdqa %xmm5, %xmm6");
asm volatile("punpckldq %xmm4, %xmm5");
@@ -123,11 +119,9 @@ fletcher_4_sse2_native(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
asm volatile("paddq %xmm0, %xmm1");
asm volatile("paddq %xmm1, %xmm2");
asm volatile("paddq %xmm2, %xmm3");
- }
+ } while ((ip += 2) < ipend);
FLETCHER_4_SSE_SAVE_CTX(ctx);
-
- kfpu_end();
}
static void
@@ -136,11 +130,9 @@ fletcher_4_sse2_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint32_t *ip = buf;
const uint32_t *ipend = (uint32_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_SSE_RESTORE_CTX(ctx);
- for (; ip < ipend; ip += 2) {
+ do {
uint32_t scratch1 = BSWAP_32(ip[0]);
uint32_t scratch2 = BSWAP_32(ip[1]);
asm volatile("movd %0, %%xmm5" :: "r"(scratch1));
@@ -150,11 +142,9 @@ fletcher_4_sse2_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
asm volatile("paddq %xmm0, %xmm1");
asm volatile("paddq %xmm1, %xmm2");
asm volatile("paddq %xmm2, %xmm3");
- }
+ } while ((ip += 2) < ipend);
FLETCHER_4_SSE_SAVE_CTX(ctx);
-
- kfpu_end();
}
static boolean_t fletcher_4_sse2_valid(void)
@@ -170,6 +160,7 @@ const fletcher_4_ops_t fletcher_4_sse2_ops = {
.fini_byteswap = fletcher_4_sse2_fini,
.compute_byteswap = fletcher_4_sse2_byteswap,
.valid = fletcher_4_sse2_valid,
+ .uses_fpu = B_TRUE,
.name = "sse2"
};
@@ -186,14 +177,12 @@ fletcher_4_ssse3_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
const uint64_t *ip = buf;
const uint64_t *ipend = (uint64_t *)((uint8_t *)ip + size);
- kfpu_begin();
-
FLETCHER_4_SSE_RESTORE_CTX(ctx);
asm volatile("movdqu %0, %%xmm7"::"m" (mask));
asm volatile("pxor %xmm4, %xmm4");
- for (; ip < ipend; ip += 2) {
+ do {
asm volatile("movdqu %0, %%xmm5"::"m" (*ip));
asm volatile("pshufb %xmm7, %xmm5");
asm volatile("movdqa %xmm5, %xmm6");
@@ -207,11 +196,9 @@ fletcher_4_ssse3_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size)
asm volatile("paddq %xmm0, %xmm1");
asm volatile("paddq %xmm1, %xmm2");
asm volatile("paddq %xmm2, %xmm3");
- }
+ } while ((ip += 2) < ipend);
FLETCHER_4_SSE_SAVE_CTX(ctx);
-
- kfpu_end();
}
static boolean_t fletcher_4_ssse3_valid(void)
@@ -228,6 +215,7 @@ const fletcher_4_ops_t fletcher_4_ssse3_ops = {
.fini_byteswap = fletcher_4_sse2_fini,
.compute_byteswap = fletcher_4_ssse3_byteswap,
.valid = fletcher_4_ssse3_valid,
+ .uses_fpu = B_TRUE,
.name = "ssse3"
};
diff --git a/module/zcommon/zfs_fletcher_superscalar.c b/module/zcommon/zfs_fletcher_superscalar.c
index ba3fb54cbcff..2a80816ff3ec 100644
--- a/module/zcommon/zfs_fletcher_superscalar.c
+++ b/module/zcommon/zfs_fletcher_superscalar.c
@@ -47,14 +47,12 @@
#include <sys/string.h>
#include <zfs_fletcher.h>
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->superscalar, 0, 4 * sizeof (zfs_fletcher_superscalar_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -70,7 +68,6 @@ fletcher_4_superscalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
ZIO_SET_CHECKSUM(zcp, A, B, C, D);
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@@ -89,7 +86,7 @@ fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
c2 = ctx->superscalar[2].v[1];
d2 = ctx->superscalar[3].v[1];
- for (; ip < ipend; ip += 2) {
+ do {
a += ip[0];
a2 += ip[1];
b += a;
@@ -98,7 +95,7 @@ fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
c2 += b2;
d += c;
d2 += c2;
- }
+ } while ((ip += 2) < ipend);
ctx->superscalar[0].v[0] = a;
ctx->superscalar[1].v[0] = b;
@@ -110,7 +107,6 @@ fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
ctx->superscalar[3].v[1] = d2;
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_byteswap(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@@ -129,7 +125,7 @@ fletcher_4_superscalar_byteswap(fletcher_4_ctx_t *ctx,
c2 = ctx->superscalar[2].v[1];
d2 = ctx->superscalar[3].v[1];
- for (; ip < ipend; ip += 2) {
+ do {
a += BSWAP_32(ip[0]);
a2 += BSWAP_32(ip[1]);
b += a;
@@ -138,7 +134,7 @@ fletcher_4_superscalar_byteswap(fletcher_4_ctx_t *ctx,
c2 += b2;
d += c;
d2 += c2;
- }
+ } while ((ip += 2) < ipend);
ctx->superscalar[0].v[0] = a;
ctx->superscalar[1].v[0] = b;
@@ -163,5 +159,6 @@ const fletcher_4_ops_t fletcher_4_superscalar_ops = {
.compute_byteswap = fletcher_4_superscalar_byteswap,
.fini_byteswap = fletcher_4_superscalar_fini,
.valid = fletcher_4_superscalar_valid,
+ .uses_fpu = B_FALSE,
.name = "superscalar"
};
diff --git a/module/zcommon/zfs_fletcher_superscalar4.c b/module/zcommon/zfs_fletcher_superscalar4.c
index e3eda029590a..0b52bb63d003 100644
--- a/module/zcommon/zfs_fletcher_superscalar4.c
+++ b/module/zcommon/zfs_fletcher_superscalar4.c
@@ -47,14 +47,12 @@
#include <sys/string.h>
#include <zfs_fletcher.h>
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_init(fletcher_4_ctx_t *ctx)
{
memset(ctx->superscalar, 0, 4 * sizeof (zfs_fletcher_superscalar_t));
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@@ -84,7 +82,6 @@ fletcher_4_superscalar4_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
ZIO_SET_CHECKSUM(zcp, A, B, C, D);
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@@ -113,7 +110,7 @@ fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
c4 = ctx->superscalar[2].v[3];
d4 = ctx->superscalar[3].v[3];
- for (; ip < ipend; ip += 4) {
+ do {
a += ip[0];
a2 += ip[1];
a3 += ip[2];
@@ -130,7 +127,7 @@ fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
d2 += c2;
d3 += c3;
d4 += c4;
- }
+ } while ((ip += 4) < ipend);
ctx->superscalar[0].v[0] = a;
ctx->superscalar[1].v[0] = b;
@@ -150,7 +147,6 @@ fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
ctx->superscalar[3].v[3] = d4;
}
-ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_byteswap(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@@ -179,7 +175,7 @@ fletcher_4_superscalar4_byteswap(fletcher_4_ctx_t *ctx,
c4 = ctx->superscalar[2].v[3];
d4 = ctx->superscalar[3].v[3];
- for (; ip < ipend; ip += 4) {
+ do {
a += BSWAP_32(ip[0]);
a2 += BSWAP_32(ip[1]);
a3 += BSWAP_32(ip[2]);
@@ -196,7 +192,7 @@ fletcher_4_superscalar4_byteswap(fletcher_4_ctx_t *ctx,
d2 += c2;
d3 += c3;
d4 += c4;
- }
+ } while ((ip += 4) < ipend);
ctx->superscalar[0].v[0] = a;
ctx->superscalar[1].v[0] = b;
@@ -229,5 +225,6 @@ const fletcher_4_ops_t fletcher_4_superscalar4_ops = {
.compute_byteswap = fletcher_4_superscalar4_byteswap,
.fini_byteswap = fletcher_4_superscalar4_fini,
.valid = fletcher_4_superscalar4_valid,
+ .uses_fpu = B_FALSE,
.name = "superscalar4"
};
diff --git a/module/zcommon/zfs_namecheck.c b/module/zcommon/zfs_namecheck.c
index 7ecce451b42d..273b219a9794 100644
--- a/module/zcommon/zfs_namecheck.c
+++ b/module/zcommon/zfs_namecheck.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c
index 32475611e11f..764993b45e7c 100644
--- a/module/zcommon/zfs_prop.c
+++ b/module/zcommon/zfs_prop.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -25,10 +25,15 @@
* 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 */
+#if defined(_KERNEL)
+#include <sys/simd.h>
+#endif
+
#include <sys/zio.h>
#include <sys/spa.h>
#include <sys/u8_textprep.h>
@@ -340,6 +345,13 @@ zfs_prop_init(void)
{ NULL }
};
+ static const zprop_index_t prefetch_table[] = {
+ { "none", ZFS_PREFETCH_NONE },
+ { "metadata", ZFS_PREFETCH_METADATA },
+ { "all", ZFS_PREFETCH_ALL },
+ { NULL }
+ };
+
static const zprop_index_t sync_table[] = {
{ "standard", ZFS_SYNC_STANDARD },
{ "always", ZFS_SYNC_ALWAYS },
@@ -369,6 +381,8 @@ zfs_prop_init(void)
static const 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 }
};
@@ -388,7 +402,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, sfeatures);
zprop_register_index(ZFS_PROP_SYNC, "sync", ZFS_SYNC_STANDARD,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
@@ -446,6 +460,10 @@ zfs_prop_init(void)
ZFS_CACHE_ALL, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME,
"all | none | metadata", "SECONDARYCACHE", cache_table, sfeatures);
+ zprop_register_index(ZFS_PROP_PREFETCH, "prefetch",
+ ZFS_PREFETCH_ALL, PROP_INHERIT,
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME,
+ "none | metadata | all", "PREFETCH", prefetch_table, sfeatures);
zprop_register_index(ZFS_PROP_LOGBIAS, "logbias", ZFS_LOGBIAS_LATENCY,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"latency | throughput", "LOGBIAS", logbias_table, sfeatures);
@@ -465,7 +483,7 @@ zfs_prop_init(void)
/* inherit index (boolean) properties */
zprop_register_index(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off", "ATIME", boolean_table, sfeatures);
- zprop_register_index(ZFS_PROP_RELATIME, "relatime", 0, PROP_INHERIT,
+ zprop_register_index(ZFS_PROP_RELATIME, "relatime", 1, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off", "RELATIME", boolean_table,
sfeatures);
zprop_register_index(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT,
@@ -610,6 +628,9 @@ zfs_prop_init(void)
ZVOL_DEFAULT_BLOCKSIZE, PROP_ONETIME,
ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", B_FALSE,
sfeatures);
+ zprop_register_index(ZFS_PROP_VOLTHREADING, "volthreading",
+ 1, PROP_DEFAULT, ZFS_TYPE_VOLUME, "on | off", "zvol threading",
+ boolean_table, sfeatures);
zprop_register_number(ZFS_PROP_USEDSNAP, "usedbysnapshots", 0,
PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>",
"USEDSNAP", B_FALSE, sfeatures);
@@ -734,12 +755,19 @@ zfs_prop_init(void)
NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK,
"<date>", "CREATION", B_FALSE, B_TRUE, B_TRUE, NULL, sfeatures);
+ zprop_register_impl(ZFS_PROP_SNAPSHOTS_CHANGED, "snapshots_changed",
+ PROP_TYPE_NUMBER, 0, NULL, PROP_READONLY, ZFS_TYPE_FILESYSTEM |
+ ZFS_TYPE_VOLUME, "<date>", "SNAPSHOTS_CHANGED", B_FALSE, B_TRUE,
+ B_TRUE, NULL, sfeatures);
+
zfs_mod_list_supported_free(sfeatures);
}
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. */
@@ -850,6 +878,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);
}
@@ -859,6 +889,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);
@@ -870,6 +902,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);
}
@@ -880,6 +914,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);
}
@@ -887,12 +923,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);
}
@@ -903,6 +943,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);
}
@@ -912,6 +954,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);
}
@@ -964,6 +1008,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);
}
@@ -975,6 +1021,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);
}
@@ -986,6 +1034,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);
}
@@ -996,6 +1046,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);
}
@@ -1003,8 +1055,6 @@ zfs_prop_align_right(zfs_prop_t prop)
#if defined(_KERNEL)
-#include <sys/simd.h>
-
#if defined(HAVE_KERNEL_FPU_INTERNAL)
uint8_t **zfs_kfpu_fpregs;
EXPORT_SYMBOL(zfs_kfpu_fpregs);
diff --git a/module/zcommon/zpool_prop.c b/module/zcommon/zpool_prop.c
index 853476a1fc16..e2e3bf5be69e 100644
--- a/module/zcommon/zpool_prop.c
+++ b/module/zcommon/zpool_prop.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -116,6 +116,15 @@ zpool_prop_init(void)
zprop_register_number(ZPOOL_PROP_DEDUPRATIO, "dedupratio", 0,
PROP_READONLY, ZFS_TYPE_POOL, "<1.00x or higher if deduped>",
"DEDUP", B_FALSE, sfeatures);
+ zprop_register_number(ZPOOL_PROP_BCLONEUSED, "bcloneused", 0,
+ PROP_READONLY, ZFS_TYPE_POOL, "<size>",
+ "BCLONE_USED", B_FALSE, sfeatures);
+ zprop_register_number(ZPOOL_PROP_BCLONESAVED, "bclonesaved", 0,
+ PROP_READONLY, ZFS_TYPE_POOL, "<size>",
+ "BCLONE_SAVED", B_FALSE, sfeatures);
+ zprop_register_number(ZPOOL_PROP_BCLONERATIO, "bcloneratio", 0,
+ PROP_READONLY, ZFS_TYPE_POOL, "<1.00x or higher if cloned>",
+ "BCLONE_RATIO", B_FALSE, sfeatures);
/* default number properties */
zprop_register_number(ZPOOL_PROP_VERSION, "version", SPA_VERSION,
@@ -151,7 +160,7 @@ zpool_prop_init(void)
"wait | continue | panic", "FAILMODE", failuremode_table,
sfeatures);
zprop_register_index(ZPOOL_PROP_AUTOTRIM, "autotrim",
- SPA_AUTOTRIM_DEFAULT, PROP_DEFAULT, ZFS_TYPE_POOL,
+ SPA_AUTOTRIM_OFF, PROP_DEFAULT, ZFS_TYPE_POOL,
"on | off", "AUTOTRIM", boolean_table, sfeatures);
/* hidden properties */
@@ -410,6 +419,24 @@ vdev_prop_init(void)
sfeatures);
/* default numeric properties */
+ zprop_register_number(VDEV_PROP_CHECKSUM_N, "checksum_n", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<events>", "CKSUM_N", B_FALSE,
+ sfeatures);
+ zprop_register_number(VDEV_PROP_CHECKSUM_T, "checksum_t", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<seconds>", "CKSUM_T", B_FALSE,
+ sfeatures);
+ zprop_register_number(VDEV_PROP_IO_N, "io_n", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<events>", "IO_N", B_FALSE,
+ sfeatures);
+ zprop_register_number(VDEV_PROP_IO_T, "io_t", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<seconds>", "IO_T", B_FALSE,
+ sfeatures);
+ zprop_register_number(VDEV_PROP_SLOW_IO_N, "slow_io_n", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<events>", "SLOW_IO_N", B_FALSE,
+ sfeatures);
+ zprop_register_number(VDEV_PROP_SLOW_IO_T, "slow_io_t", UINT64_MAX,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "<seconds>", "SLOW_IO_T", B_FALSE,
+ sfeatures);
/* default index (boolean) properties */
zprop_register_index(VDEV_PROP_REMOVING, "removing", 0,
@@ -418,8 +445,14 @@ vdev_prop_init(void)
zprop_register_index(VDEV_PROP_ALLOCATING, "allocating", 1,
PROP_DEFAULT, ZFS_TYPE_VDEV, "on | off", "ALLOCATING",
boolean_na_table, sfeatures);
+ zprop_register_index(VDEV_PROP_RAIDZ_EXPANDING, "raidz_expanding", 0,
+ PROP_READONLY, ZFS_TYPE_VDEV, "on | off", "RAIDZ_EXPANDING",
+ boolean_table, sfeatures);
/* default index properties */
+ zprop_register_index(VDEV_PROP_FAILFAST, "failfast", B_TRUE,
+ PROP_DEFAULT, ZFS_TYPE_VDEV, "on | off", "FAILFAST", boolean_table,
+ sfeatures);
/* hidden properties */
zprop_register_hidden(VDEV_PROP_NAME, "name", PROP_TYPE_STRING,
diff --git a/module/zcommon/zprop_common.c b/module/zcommon/zprop_common.c
index b1da4ca64bd5..eb635b38ceb5 100644
--- a/module/zcommon/zprop_common.c
+++ b/module/zcommon/zprop_common.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/abd.c b/module/zfs/abd.c
index b6d7ac6407e3..2c0cda25dbc6 100644
--- a/module/zfs/abd.c
+++ b/module/zfs/abd.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -109,7 +109,6 @@ void
abd_verify(abd_t *abd)
{
#ifdef ZFS_DEBUG
- ASSERT3U(abd->abd_size, >, 0);
ASSERT3U(abd->abd_size, <=, SPA_MAXBLOCKSIZE);
ASSERT3U(abd->abd_flags, ==, abd->abd_flags & (ABD_FLAG_LINEAR |
ABD_FLAG_OWNER | ABD_FLAG_META | ABD_FLAG_MULTI_ZONE |
@@ -118,6 +117,7 @@ abd_verify(abd_t *abd)
IMPLY(abd->abd_parent != NULL, !(abd->abd_flags & ABD_FLAG_OWNER));
IMPLY(abd->abd_flags & ABD_FLAG_META, abd->abd_flags & ABD_FLAG_OWNER);
if (abd_is_linear(abd)) {
+ ASSERT3U(abd->abd_size, >, 0);
ASSERT3P(ABD_LINEAR_BUF(abd), !=, NULL);
} else if (abd_is_gang(abd)) {
uint_t child_sizes = 0;
@@ -130,6 +130,7 @@ abd_verify(abd_t *abd)
}
ASSERT3U(abd->abd_size, ==, child_sizes);
} else {
+ ASSERT3U(abd->abd_size, >, 0);
abd_verify_scatter(abd);
}
#endif
@@ -369,7 +370,20 @@ abd_gang_add_gang(abd_t *pabd, abd_t *cabd, boolean_t free_on_free)
* will retain all the free_on_free settings after being
* added to the parents list.
*/
+#ifdef ZFS_DEBUG
+ /*
+ * If cabd had abd_parent, we have to drop it here. We can't
+ * transfer it to pabd, nor we can clear abd_size leaving it.
+ */
+ if (cabd->abd_parent != NULL) {
+ (void) zfs_refcount_remove_many(
+ &cabd->abd_parent->abd_children,
+ cabd->abd_size, cabd);
+ cabd->abd_parent = NULL;
+ }
+#endif
pabd->abd_size += cabd->abd_size;
+ cabd->abd_size = 0;
list_move_tail(&ABD_GANG(pabd).abd_gang_chain,
&ABD_GANG(cabd).abd_gang_chain);
ASSERT(list_is_empty(&ABD_GANG(cabd).abd_gang_chain));
@@ -407,7 +421,6 @@ abd_gang_add(abd_t *pabd, abd_t *cabd, boolean_t free_on_free)
*/
if (abd_is_gang(cabd)) {
ASSERT(!list_link_active(&cabd->abd_gang_link));
- ASSERT(!list_is_empty(&ABD_GANG(cabd).abd_gang_chain));
return (abd_gang_add_gang(pabd, cabd, free_on_free));
}
ASSERT(!abd_is_gang(cabd));
@@ -667,15 +680,15 @@ abd_return_buf(abd_t *abd, void *buf, size_t n)
{
abd_verify(abd);
ASSERT3U(abd->abd_size, >=, n);
+#ifdef ZFS_DEBUG
+ (void) zfs_refcount_remove_many(&abd->abd_children, n, buf);
+#endif
if (abd_is_linear(abd)) {
ASSERT3P(buf, ==, abd_to_buf(abd));
} else {
ASSERT0(abd_cmp_buf(abd, buf, n));
zio_buf_free(buf, n);
}
-#ifdef ZFS_DEBUG
- (void) zfs_refcount_remove_many(&abd->abd_children, n, buf);
-#endif
}
void
@@ -789,13 +802,10 @@ abd_iterate_func(abd_t *abd, size_t off, size_t size,
abd_verify(abd);
ASSERT3U(off + size, <=, abd->abd_size);
- boolean_t gang = abd_is_gang(abd);
abd_t *c_abd = abd_init_abd_iter(abd, &aiter, off);
while (size > 0) {
- /* If we are at the end of the gang ABD we are done */
- if (gang && !c_abd)
- break;
+ IMPLY(abd_is_gang(abd), c_abd != NULL);
abd_iter_map(&aiter);
@@ -816,6 +826,48 @@ abd_iterate_func(abd_t *abd, size_t off, size_t size,
return (ret);
}
+#if defined(__linux__) && defined(_KERNEL)
+int
+abd_iterate_page_func(abd_t *abd, size_t off, size_t size,
+ abd_iter_page_func_t *func, void *private)
+{
+ struct abd_iter aiter;
+ int ret = 0;
+
+ if (size == 0)
+ return (0);
+
+ abd_verify(abd);
+ ASSERT3U(off + size, <=, abd->abd_size);
+
+ abd_t *c_abd = abd_init_abd_iter(abd, &aiter, off);
+
+ while (size > 0) {
+ IMPLY(abd_is_gang(abd), c_abd != NULL);
+
+ abd_iter_page(&aiter);
+
+ size_t len = MIN(aiter.iter_page_dsize, size);
+ ASSERT3U(len, >, 0);
+
+ ret = func(aiter.iter_page, aiter.iter_page_doff,
+ len, private);
+
+ aiter.iter_page = NULL;
+ aiter.iter_page_doff = 0;
+ aiter.iter_page_dsize = 0;
+
+ if (ret != 0)
+ break;
+
+ size -= len;
+ c_abd = abd_advance_abd_iter(abd, c_abd, &aiter, len);
+ }
+
+ return (ret);
+}
+#endif
+
struct buf_arg {
void *arg_buf;
};
@@ -917,7 +969,6 @@ abd_iterate_func2(abd_t *dabd, abd_t *sabd, size_t doff, size_t soff,
{
int ret = 0;
struct abd_iter daiter, saiter;
- boolean_t dabd_is_gang_abd, sabd_is_gang_abd;
abd_t *c_dabd, *c_sabd;
if (size == 0)
@@ -929,16 +980,12 @@ abd_iterate_func2(abd_t *dabd, abd_t *sabd, size_t doff, size_t soff,
ASSERT3U(doff + size, <=, dabd->abd_size);
ASSERT3U(soff + size, <=, sabd->abd_size);
- dabd_is_gang_abd = abd_is_gang(dabd);
- sabd_is_gang_abd = abd_is_gang(sabd);
c_dabd = abd_init_abd_iter(dabd, &daiter, doff);
c_sabd = abd_init_abd_iter(sabd, &saiter, soff);
while (size > 0) {
- /* if we are at the end of the gang ABD we are done */
- if ((dabd_is_gang_abd && !c_dabd) ||
- (sabd_is_gang_abd && !c_sabd))
- break;
+ IMPLY(abd_is_gang(dabd), c_dabd != NULL);
+ IMPLY(abd_is_gang(sabd), c_sabd != NULL);
abd_iter_map(&daiter);
abd_iter_map(&saiter);
@@ -1012,87 +1059,63 @@ abd_cmp(abd_t *dabd, abd_t *sabd)
* is the same when taking linear and when taking scatter
*/
void
-abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
- ssize_t csize, ssize_t dsize, const unsigned parity,
+abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd, size_t off,
+ size_t csize, size_t dsize, const unsigned parity,
void (*func_raidz_gen)(void **, const void *, size_t, size_t))
{
int i;
- ssize_t len, dlen;
+ size_t len, dlen;
struct abd_iter caiters[3];
- struct abd_iter daiter = {0};
- void *caddrs[3];
+ struct abd_iter daiter;
+ void *caddrs[3], *daddr;
unsigned long flags __maybe_unused = 0;
abd_t *c_cabds[3];
abd_t *c_dabd = NULL;
- boolean_t cabds_is_gang_abd[3];
- boolean_t dabd_is_gang_abd = B_FALSE;
ASSERT3U(parity, <=, 3);
-
for (i = 0; i < parity; i++) {
- cabds_is_gang_abd[i] = abd_is_gang(cabds[i]);
- c_cabds[i] = abd_init_abd_iter(cabds[i], &caiters[i], 0);
+ abd_verify(cabds[i]);
+ ASSERT3U(off + csize, <=, cabds[i]->abd_size);
+ c_cabds[i] = abd_init_abd_iter(cabds[i], &caiters[i], off);
}
- if (dabd) {
- dabd_is_gang_abd = abd_is_gang(dabd);
- c_dabd = abd_init_abd_iter(dabd, &daiter, 0);
+ if (dsize > 0) {
+ ASSERT(dabd);
+ abd_verify(dabd);
+ ASSERT3U(off + dsize, <=, dabd->abd_size);
+ c_dabd = abd_init_abd_iter(dabd, &daiter, off);
}
- ASSERT3S(dsize, >=, 0);
-
abd_enter_critical(flags);
while (csize > 0) {
- /* if we are at the end of the gang ABD we are done */
- if (dabd_is_gang_abd && !c_dabd)
- break;
-
+ len = csize;
for (i = 0; i < parity; i++) {
- /*
- * If we are at the end of the gang ABD we are
- * done.
- */
- if (cabds_is_gang_abd[i] && !c_cabds[i])
- break;
+ IMPLY(abd_is_gang(cabds[i]), c_cabds[i] != NULL);
abd_iter_map(&caiters[i]);
caddrs[i] = caiters[i].iter_mapaddr;
+ len = MIN(caiters[i].iter_mapsize, len);
}
- len = csize;
-
- if (dabd && dsize > 0)
+ if (dsize > 0) {
+ IMPLY(abd_is_gang(dabd), c_dabd != NULL);
abd_iter_map(&daiter);
-
- switch (parity) {
- case 3:
- len = MIN(caiters[2].iter_mapsize, len);
- zfs_fallthrough;
- case 2:
- len = MIN(caiters[1].iter_mapsize, len);
- zfs_fallthrough;
- case 1:
- len = MIN(caiters[0].iter_mapsize, len);
- }
-
- /* must be progressive */
- ASSERT3S(len, >, 0);
-
- if (dabd && dsize > 0) {
- /* this needs precise iter.length */
+ daddr = daiter.iter_mapaddr;
len = MIN(daiter.iter_mapsize, len);
dlen = len;
- } else
+ } else {
+ daddr = NULL;
dlen = 0;
+ }
/* must be progressive */
- ASSERT3S(len, >, 0);
+ ASSERT3U(len, >, 0);
/*
* The iterated function likely will not do well if each
* segment except the last one is not multiple of 512 (raidz).
*/
ASSERT3U(((uint64_t)len & 511ULL), ==, 0);
- func_raidz_gen(caddrs, daiter.iter_mapaddr, len, dlen);
+ func_raidz_gen(caddrs, daddr, len, dlen);
for (i = parity-1; i >= 0; i--) {
abd_iter_unmap(&caiters[i]);
@@ -1101,7 +1124,7 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
&caiters[i], len);
}
- if (dabd && dsize > 0) {
+ if (dsize > 0) {
abd_iter_unmap(&daiter);
c_dabd =
abd_advance_abd_iter(dabd, c_dabd, &daiter,
@@ -1110,9 +1133,6 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
}
csize -= len;
-
- ASSERT3S(dsize, >=, 0);
- ASSERT3S(csize, >=, 0);
}
abd_exit_critical(flags);
}
@@ -1129,27 +1149,27 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
*/
void
abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
- ssize_t tsize, const unsigned parity,
+ size_t tsize, const unsigned parity,
void (*func_raidz_rec)(void **t, const size_t tsize, void **c,
const unsigned *mul),
const unsigned *mul)
{
int i;
- ssize_t len;
+ size_t len;
struct abd_iter citers[3];
struct abd_iter xiters[3];
void *caddrs[3], *xaddrs[3];
unsigned long flags __maybe_unused = 0;
- boolean_t cabds_is_gang_abd[3];
- boolean_t tabds_is_gang_abd[3];
abd_t *c_cabds[3];
abd_t *c_tabds[3];
ASSERT3U(parity, <=, 3);
for (i = 0; i < parity; i++) {
- cabds_is_gang_abd[i] = abd_is_gang(cabds[i]);
- tabds_is_gang_abd[i] = abd_is_gang(tabds[i]);
+ abd_verify(cabds[i]);
+ abd_verify(tabds[i]);
+ ASSERT3U(tsize, <=, cabds[i]->abd_size);
+ ASSERT3U(tsize, <=, tabds[i]->abd_size);
c_cabds[i] =
abd_init_abd_iter(cabds[i], &citers[i], 0);
c_tabds[i] =
@@ -1158,36 +1178,18 @@ abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
abd_enter_critical(flags);
while (tsize > 0) {
-
+ len = tsize;
for (i = 0; i < parity; i++) {
- /*
- * If we are at the end of the gang ABD we
- * are done.
- */
- if (cabds_is_gang_abd[i] && !c_cabds[i])
- break;
- if (tabds_is_gang_abd[i] && !c_tabds[i])
- break;
+ IMPLY(abd_is_gang(cabds[i]), c_cabds[i] != NULL);
+ IMPLY(abd_is_gang(tabds[i]), c_tabds[i] != NULL);
abd_iter_map(&citers[i]);
abd_iter_map(&xiters[i]);
caddrs[i] = citers[i].iter_mapaddr;
xaddrs[i] = xiters[i].iter_mapaddr;
+ len = MIN(citers[i].iter_mapsize, len);
+ len = MIN(xiters[i].iter_mapsize, len);
}
- len = tsize;
- switch (parity) {
- case 3:
- len = MIN(xiters[2].iter_mapsize, len);
- len = MIN(citers[2].iter_mapsize, len);
- zfs_fallthrough;
- case 2:
- len = MIN(xiters[1].iter_mapsize, len);
- len = MIN(citers[1].iter_mapsize, len);
- zfs_fallthrough;
- case 1:
- len = MIN(xiters[0].iter_mapsize, len);
- len = MIN(citers[0].iter_mapsize, len);
- }
/* must be progressive */
ASSERT3S(len, >, 0);
/*
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index 74019ad08b4c..51039af9bcc0 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -108,12 +108,11 @@
* the active state mutex must be held before the ghost state mutex.
*
* It as also possible to register a callback which is run when the
- * arc_meta_limit is reached and no buffers can be safely evicted. In
+ * metadata limit is reached and no buffers can be safely evicted. In
* this case the arc user should drop a reference on some arc buffers so
- * they can be reclaimed and the arc_meta_limit honored. For example,
- * when using the ZPL each dentry holds a references on a znode. These
- * dentries must be pruned before the arc buffer holding the znode can
- * be safely evicted.
+ * they can be reclaimed. For example, when using the ZPL each dentry
+ * holds a references on a znode. These dentries must be pruned before
+ * the arc buffer holding the znode can be safely evicted.
*
* Note that the majority of the performance stats are manipulated
* with atomic operations.
@@ -333,6 +332,7 @@ static int arc_state_evict_marker_count;
static kmutex_t arc_evict_lock;
static boolean_t arc_evict_needed = B_FALSE;
+static clock_t arc_last_uncached_flush;
/*
* Count of bytes evicted since boot.
@@ -354,7 +354,7 @@ static list_t arc_evict_waiters;
* can still happen, even during the potentially long time that arc_size is
* more than arc_c.
*/
-static int zfs_arc_eviction_pct = 200;
+static uint_t zfs_arc_eviction_pct = 200;
/*
* The number of headers to evict in arc_evict_state_impl() before
@@ -363,10 +363,10 @@ static int zfs_arc_eviction_pct = 200;
* oldest header in the arc state), but comes with higher overhead
* (i.e. more invocations of arc_evict_state_impl()).
*/
-static int zfs_arc_evict_batch_limit = 10;
+static uint_t zfs_arc_evict_batch_limit = 10;
/* number of seconds before growing cache again */
-int arc_grow_retry = 5;
+uint_t arc_grow_retry = 5;
/*
* Minimum time between calls to arc_kmem_reap_soon().
@@ -376,11 +376,8 @@ static const int arc_kmem_cache_reap_retry_ms = 1000;
/* shift of arc_c for calculating overflow limit in arc_get_data_impl */
static int zfs_arc_overflow_shift = 8;
-/* shift of arc_c for calculating both min and max arc_p */
-static int arc_p_min_shift = 4;
-
/* log2(fraction of arc to reclaim) */
-int arc_shrink_shift = 7;
+uint_t arc_shrink_shift = 7;
/* percent of pagecache to reclaim arc to */
#ifdef _KERNEL
@@ -396,20 +393,20 @@ uint_t zfs_arc_pc_percent = 0;
* This must be less than arc_shrink_shift, so that when we shrink the ARC,
* we will still not allow it to grow.
*/
-int arc_no_grow_shift = 5;
+uint_t arc_no_grow_shift = 5;
/*
* minimum lifespan of a prefetch block in clock ticks
* (initialized in arc_init())
*/
-static int arc_min_prefetch_ms;
-static int arc_min_prescient_prefetch_ms;
+static uint_t arc_min_prefetch_ms;
+static uint_t arc_min_prescient_prefetch_ms;
/*
* If this percent of memory is free, don't throttle.
*/
-int arc_lotsfree_percent = 10;
+uint_t arc_lotsfree_percent = 10;
/*
* The arc has filled available memory and has now warmed up.
@@ -419,16 +416,13 @@ boolean_t arc_warm;
/*
* These tunables are for performance analysis.
*/
-unsigned long zfs_arc_max = 0;
-unsigned long zfs_arc_min = 0;
-unsigned long zfs_arc_meta_limit = 0;
-unsigned long zfs_arc_meta_min = 0;
-static unsigned long zfs_arc_dnode_limit = 0;
-static unsigned long zfs_arc_dnode_reduce_percent = 10;
-static int zfs_arc_grow_retry = 0;
-static int zfs_arc_shrink_shift = 0;
-static int zfs_arc_p_min_shift = 0;
-int zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
+uint64_t zfs_arc_max = 0;
+uint64_t zfs_arc_min = 0;
+static uint64_t zfs_arc_dnode_limit = 0;
+static uint_t zfs_arc_dnode_reduce_percent = 10;
+static uint_t zfs_arc_grow_retry = 0;
+static uint_t zfs_arc_shrink_shift = 0;
+uint_t zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
/*
* ARC dirty data constraints for arc_tempreserve_space() throttle:
@@ -446,56 +440,60 @@ static const unsigned long zfs_arc_pool_dirty_percent = 20;
int zfs_compressed_arc_enabled = B_TRUE;
/*
- * ARC will evict meta buffers that exceed arc_meta_limit. This
- * tunable make arc_meta_limit adjustable for different workloads.
+ * Balance between metadata and data on ghost hits. Values above 100
+ * increase metadata caching by proportionally reducing effect of ghost
+ * data hits on target data/metadata rate.
*/
-static unsigned long zfs_arc_meta_limit_percent = 75;
+static uint_t zfs_arc_meta_balance = 500;
/*
* Percentage that can be consumed by dnodes of ARC meta buffers.
*/
-static unsigned long zfs_arc_dnode_limit_percent = 10;
+static uint_t zfs_arc_dnode_limit_percent = 10;
/*
* These tunables are Linux-specific
*/
-static unsigned long zfs_arc_sys_free = 0;
-static int zfs_arc_min_prefetch_ms = 0;
-static int zfs_arc_min_prescient_prefetch_ms = 0;
-static int zfs_arc_p_dampener_disable = 1;
-static int zfs_arc_meta_prune = 10000;
-static int zfs_arc_meta_strategy = ARC_STRATEGY_META_BALANCED;
-static int zfs_arc_meta_adjust_restarts = 4096;
-static int zfs_arc_lotsfree_percent = 10;
+static uint64_t zfs_arc_sys_free = 0;
+static uint_t zfs_arc_min_prefetch_ms = 0;
+static uint_t zfs_arc_min_prescient_prefetch_ms = 0;
+static uint_t zfs_arc_lotsfree_percent = 10;
/*
* Number of arc_prune threads
*/
static int zfs_arc_prune_task_threads = 1;
-/* The 6 states: */
+/* The 7 states: */
arc_state_t ARC_anon;
arc_state_t ARC_mru;
arc_state_t ARC_mru_ghost;
arc_state_t ARC_mfu;
arc_state_t ARC_mfu_ghost;
arc_state_t ARC_l2c_only;
+arc_state_t ARC_uncached;
arc_stats_t arc_stats = {
{ "hits", KSTAT_DATA_UINT64 },
+ { "iohits", KSTAT_DATA_UINT64 },
{ "misses", KSTAT_DATA_UINT64 },
{ "demand_data_hits", KSTAT_DATA_UINT64 },
+ { "demand_data_iohits", KSTAT_DATA_UINT64 },
{ "demand_data_misses", KSTAT_DATA_UINT64 },
{ "demand_metadata_hits", KSTAT_DATA_UINT64 },
+ { "demand_metadata_iohits", KSTAT_DATA_UINT64 },
{ "demand_metadata_misses", KSTAT_DATA_UINT64 },
{ "prefetch_data_hits", KSTAT_DATA_UINT64 },
+ { "prefetch_data_iohits", KSTAT_DATA_UINT64 },
{ "prefetch_data_misses", KSTAT_DATA_UINT64 },
{ "prefetch_metadata_hits", KSTAT_DATA_UINT64 },
+ { "prefetch_metadata_iohits", KSTAT_DATA_UINT64 },
{ "prefetch_metadata_misses", KSTAT_DATA_UINT64 },
{ "mru_hits", KSTAT_DATA_UINT64 },
{ "mru_ghost_hits", KSTAT_DATA_UINT64 },
{ "mfu_hits", KSTAT_DATA_UINT64 },
{ "mfu_ghost_hits", KSTAT_DATA_UINT64 },
+ { "uncached_hits", KSTAT_DATA_UINT64 },
{ "deleted", KSTAT_DATA_UINT64 },
{ "mutex_miss", KSTAT_DATA_UINT64 },
{ "access_skip", KSTAT_DATA_UINT64 },
@@ -512,7 +510,9 @@ arc_stats_t arc_stats = {
{ "hash_collisions", KSTAT_DATA_UINT64 },
{ "hash_chains", KSTAT_DATA_UINT64 },
{ "hash_chain_max", KSTAT_DATA_UINT64 },
- { "p", KSTAT_DATA_UINT64 },
+ { "meta", KSTAT_DATA_UINT64 },
+ { "pd", KSTAT_DATA_UINT64 },
+ { "pm", KSTAT_DATA_UINT64 },
{ "c", KSTAT_DATA_UINT64 },
{ "c_min", KSTAT_DATA_UINT64 },
{ "c_max", KSTAT_DATA_UINT64 },
@@ -530,20 +530,35 @@ arc_stats_t arc_stats = {
{ "other_size", KSTAT_DATA_UINT64 },
#endif
{ "anon_size", KSTAT_DATA_UINT64 },
+ { "anon_data", KSTAT_DATA_UINT64 },
+ { "anon_metadata", KSTAT_DATA_UINT64 },
{ "anon_evictable_data", KSTAT_DATA_UINT64 },
{ "anon_evictable_metadata", KSTAT_DATA_UINT64 },
{ "mru_size", KSTAT_DATA_UINT64 },
+ { "mru_data", KSTAT_DATA_UINT64 },
+ { "mru_metadata", KSTAT_DATA_UINT64 },
{ "mru_evictable_data", KSTAT_DATA_UINT64 },
{ "mru_evictable_metadata", KSTAT_DATA_UINT64 },
{ "mru_ghost_size", KSTAT_DATA_UINT64 },
+ { "mru_ghost_data", KSTAT_DATA_UINT64 },
+ { "mru_ghost_metadata", KSTAT_DATA_UINT64 },
{ "mru_ghost_evictable_data", KSTAT_DATA_UINT64 },
{ "mru_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
{ "mfu_size", KSTAT_DATA_UINT64 },
+ { "mfu_data", KSTAT_DATA_UINT64 },
+ { "mfu_metadata", KSTAT_DATA_UINT64 },
{ "mfu_evictable_data", KSTAT_DATA_UINT64 },
{ "mfu_evictable_metadata", KSTAT_DATA_UINT64 },
{ "mfu_ghost_size", KSTAT_DATA_UINT64 },
+ { "mfu_ghost_data", KSTAT_DATA_UINT64 },
+ { "mfu_ghost_metadata", KSTAT_DATA_UINT64 },
{ "mfu_ghost_evictable_data", KSTAT_DATA_UINT64 },
{ "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
+ { "uncached_size", KSTAT_DATA_UINT64 },
+ { "uncached_data", KSTAT_DATA_UINT64 },
+ { "uncached_metadata", KSTAT_DATA_UINT64 },
+ { "uncached_evictable_data", KSTAT_DATA_UINT64 },
+ { "uncached_evictable_metadata", KSTAT_DATA_UINT64 },
{ "l2_hits", KSTAT_DATA_UINT64 },
{ "l2_misses", KSTAT_DATA_UINT64 },
{ "l2_prefetch_asize", KSTAT_DATA_UINT64 },
@@ -596,13 +611,14 @@ arc_stats_t arc_stats = {
{ "arc_loaned_bytes", KSTAT_DATA_UINT64 },
{ "arc_prune", KSTAT_DATA_UINT64 },
{ "arc_meta_used", KSTAT_DATA_UINT64 },
- { "arc_meta_limit", KSTAT_DATA_UINT64 },
{ "arc_dnode_limit", KSTAT_DATA_UINT64 },
- { "arc_meta_max", KSTAT_DATA_UINT64 },
- { "arc_meta_min", KSTAT_DATA_UINT64 },
{ "async_upgrade_sync", KSTAT_DATA_UINT64 },
+ { "predictive_prefetch", KSTAT_DATA_UINT64 },
{ "demand_hit_predictive_prefetch", KSTAT_DATA_UINT64 },
+ { "demand_iohit_predictive_prefetch", KSTAT_DATA_UINT64 },
+ { "prescient_prefetch", KSTAT_DATA_UINT64 },
{ "demand_hit_prescient_prefetch", KSTAT_DATA_UINT64 },
+ { "demand_iohit_prescient_prefetch", KSTAT_DATA_UINT64 },
{ "arc_need_free", KSTAT_DATA_UINT64 },
{ "arc_sys_free", KSTAT_DATA_UINT64 },
{ "arc_raw_size", KSTAT_DATA_UINT64 },
@@ -668,10 +684,7 @@ static kstat_t *arc_ksp;
*/
#define arc_tempreserve ARCSTAT(arcstat_tempreserve)
#define arc_loaned_bytes ARCSTAT(arcstat_loaned_bytes)
-#define arc_meta_limit ARCSTAT(arcstat_meta_limit) /* max size for metadata */
-/* max size for dnodes */
-#define arc_dnode_size_limit ARCSTAT(arcstat_dnode_limit)
-#define arc_meta_min ARCSTAT(arcstat_meta_min) /* min size for metadata */
+#define arc_dnode_limit ARCSTAT(arcstat_dnode_limit) /* max size for dnodes */
#define arc_need_free ARCSTAT(arcstat_need_free) /* waiting to be evicted */
hrtime_t arc_growtime;
@@ -693,6 +706,7 @@ taskq_t *arc_prune_taskq;
((hdr)->b_flags & ARC_FLAG_COMPRESSED_ARC)
#define HDR_L2CACHE(hdr) ((hdr)->b_flags & ARC_FLAG_L2CACHE)
+#define HDR_UNCACHED(hdr) ((hdr)->b_flags & ARC_FLAG_UNCACHED)
#define HDR_L2_READING(hdr) \
(((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS) && \
((hdr)->b_flags & ARC_FLAG_HAS_L2HDR))
@@ -734,8 +748,7 @@ taskq_t *arc_prune_taskq;
* Other sizes
*/
-#define HDR_FULL_CRYPT_SIZE ((int64_t)sizeof (arc_buf_hdr_t))
-#define HDR_FULL_SIZE ((int64_t)offsetof(arc_buf_hdr_t, b_crypt_hdr))
+#define HDR_FULL_SIZE ((int64_t)sizeof (arc_buf_hdr_t))
#define HDR_L2ONLY_SIZE ((int64_t)offsetof(arc_buf_hdr_t, b_l1hdr))
/*
@@ -763,8 +776,8 @@ uint64_t zfs_crc64_table[256];
* Level 2 ARC
*/
-#define L2ARC_WRITE_SIZE (8 * 1024 * 1024) /* initial write max */
-#define L2ARC_HEADROOM 2 /* num of writes */
+#define L2ARC_WRITE_SIZE (32 * 1024 * 1024) /* initial write max */
+#define L2ARC_HEADROOM 8 /* num of writes */
/*
* If we discover during ARC scan any buffers to be compressed, we boost
@@ -781,16 +794,16 @@ uint64_t zfs_crc64_table[256];
#define L2ARC_FEED_TYPES 4
/* L2ARC Performance Tunables */
-unsigned long l2arc_write_max = L2ARC_WRITE_SIZE; /* def max write size */
-unsigned long l2arc_write_boost = L2ARC_WRITE_SIZE; /* extra warmup write */
-unsigned long l2arc_headroom = L2ARC_HEADROOM; /* # of dev writes */
-unsigned long l2arc_headroom_boost = L2ARC_HEADROOM_BOOST;
-unsigned long l2arc_feed_secs = L2ARC_FEED_SECS; /* interval seconds */
-unsigned long l2arc_feed_min_ms = L2ARC_FEED_MIN_MS; /* min interval msecs */
+uint64_t l2arc_write_max = L2ARC_WRITE_SIZE; /* def max write size */
+uint64_t l2arc_write_boost = L2ARC_WRITE_SIZE; /* extra warmup write */
+uint64_t l2arc_headroom = L2ARC_HEADROOM; /* # of dev writes */
+uint64_t l2arc_headroom_boost = L2ARC_HEADROOM_BOOST;
+uint64_t l2arc_feed_secs = L2ARC_FEED_SECS; /* interval seconds */
+uint64_t l2arc_feed_min_ms = L2ARC_FEED_MIN_MS; /* min interval msecs */
int l2arc_noprefetch = B_TRUE; /* don't cache prefetch bufs */
int l2arc_feed_again = B_TRUE; /* turbo warmup */
int l2arc_norw = B_FALSE; /* no reads during writes */
-static int l2arc_meta_percent = 33; /* limit on headers size */
+static uint_t l2arc_meta_percent = 33; /* limit on headers size */
/*
* L2ARC Internals
@@ -843,8 +856,8 @@ static kcondvar_t l2arc_rebuild_thr_cv;
enum arc_hdr_alloc_flags {
ARC_HDR_ALLOC_RDATA = 0x1,
- ARC_HDR_DO_ADAPT = 0x2,
ARC_HDR_USE_RESERVE = 0x4,
+ ARC_HDR_ALLOC_LINEAR = 0x8,
};
@@ -857,8 +870,10 @@ static void arc_free_data_impl(arc_buf_hdr_t *hdr, uint64_t size,
const void *tag);
static void arc_hdr_free_abd(arc_buf_hdr_t *, boolean_t);
static void arc_hdr_alloc_abd(arc_buf_hdr_t *, int);
-static void arc_access(arc_buf_hdr_t *, kmutex_t *);
+static void arc_hdr_destroy(arc_buf_hdr_t *);
+static void arc_access(arc_buf_hdr_t *, arc_flags_t, boolean_t);
static void arc_buf_watch(arc_buf_t *);
+static void arc_change_state(arc_state_t *, arc_buf_hdr_t *);
static arc_buf_contents_t arc_buf_type(arc_buf_hdr_t *);
static uint32_t arc_bufc_to_flags(arc_buf_contents_t);
@@ -871,6 +886,8 @@ static void l2arc_do_free_on_write(void);
static void l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr,
boolean_t state_only);
+static void arc_prune_async(uint64_t adjust);
+
#define l2arc_hdr_arcstats_increment(hdr) \
l2arc_hdr_arcstats_update((hdr), B_TRUE, B_FALSE)
#define l2arc_hdr_arcstats_decrement(hdr) \
@@ -909,7 +926,7 @@ static int l2arc_mfuonly = 0;
* will vary depending of how well the specific device handles
* these commands.
*/
-static unsigned long l2arc_trim_ahead = 0;
+static uint64_t l2arc_trim_ahead = 0;
/*
* Performance tuning of L2ARC persistence:
@@ -925,7 +942,7 @@ static unsigned long l2arc_trim_ahead = 0;
* not to waste space.
*/
static int l2arc_rebuild_enabled = B_TRUE;
-static unsigned long l2arc_rebuild_blocks_min_l2size = 1024 * 1024 * 1024;
+static uint64_t l2arc_rebuild_blocks_min_l2size = 1024 * 1024 * 1024;
/* L2ARC persistence rebuild control routines. */
void l2arc_rebuild_vdev(vdev_t *vd, boolean_t reopen);
@@ -949,7 +966,7 @@ static void l2arc_hdr_restore(const l2arc_log_ent_phys_t *le,
l2arc_dev_t *dev);
/* L2ARC persistence write I/O routines. */
-static void l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio,
+static uint64_t l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio,
l2arc_write_callback_t *cb);
/* L2ARC persistence auxiliary routines. */
@@ -997,7 +1014,7 @@ static arc_buf_hdr_t *
buf_hash_find(uint64_t spa, const blkptr_t *bp, kmutex_t **lockp)
{
const dva_t *dva = BP_IDENTITY(bp);
- uint64_t birth = BP_PHYSICAL_BIRTH(bp);
+ uint64_t birth = BP_GET_BIRTH(bp);
uint64_t idx = BUF_HASH_INDEX(spa, dva, birth);
kmutex_t *hash_lock = BUF_HASH_LOCK(idx);
arc_buf_hdr_t *hdr;
@@ -1097,7 +1114,6 @@ buf_hash_remove(arc_buf_hdr_t *hdr)
*/
static kmem_cache_t *hdr_full_cache;
-static kmem_cache_t *hdr_full_crypt_cache;
static kmem_cache_t *hdr_l2only_cache;
static kmem_cache_t *buf_cache;
@@ -1118,7 +1134,6 @@ buf_fini(void)
for (int i = 0; i < BUF_LOCKS; i++)
mutex_destroy(BUF_HASH_LOCK(i));
kmem_cache_destroy(hdr_full_cache);
- kmem_cache_destroy(hdr_full_crypt_cache);
kmem_cache_destroy(hdr_l2only_cache);
kmem_cache_destroy(buf_cache);
}
@@ -1135,31 +1150,18 @@ hdr_full_cons(void *vbuf, void *unused, int kmflag)
memset(hdr, 0, HDR_FULL_SIZE);
hdr->b_l1hdr.b_byteswap = DMU_BSWAP_NUMFUNCS;
- cv_init(&hdr->b_l1hdr.b_cv, NULL, CV_DEFAULT, NULL);
zfs_refcount_create(&hdr->b_l1hdr.b_refcnt);
+#ifdef ZFS_DEBUG
mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL);
- list_link_init(&hdr->b_l1hdr.b_arc_node);
- list_link_init(&hdr->b_l2hdr.b_l2node);
+#endif
multilist_link_init(&hdr->b_l1hdr.b_arc_node);
+ list_link_init(&hdr->b_l2hdr.b_l2node);
arc_space_consume(HDR_FULL_SIZE, ARC_SPACE_HDRS);
return (0);
}
static int
-hdr_full_crypt_cons(void *vbuf, void *unused, int kmflag)
-{
- (void) unused;
- arc_buf_hdr_t *hdr = vbuf;
-
- hdr_full_cons(vbuf, unused, kmflag);
- memset(&hdr->b_crypt_hdr, 0, sizeof (hdr->b_crypt_hdr));
- arc_space_consume(sizeof (hdr->b_crypt_hdr), ARC_SPACE_HDRS);
-
- return (0);
-}
-
-static int
hdr_l2only_cons(void *vbuf, void *unused, int kmflag)
{
(void) unused, (void) kmflag;
@@ -1178,7 +1180,6 @@ buf_cons(void *vbuf, void *unused, int kmflag)
arc_buf_t *buf = vbuf;
memset(buf, 0, sizeof (arc_buf_t));
- mutex_init(&buf->b_evict_lock, NULL, MUTEX_DEFAULT, NULL);
arc_space_consume(sizeof (arc_buf_t), ARC_SPACE_HDRS);
return (0);
@@ -1195,24 +1196,15 @@ hdr_full_dest(void *vbuf, void *unused)
arc_buf_hdr_t *hdr = vbuf;
ASSERT(HDR_EMPTY(hdr));
- cv_destroy(&hdr->b_l1hdr.b_cv);
zfs_refcount_destroy(&hdr->b_l1hdr.b_refcnt);
+#ifdef ZFS_DEBUG
mutex_destroy(&hdr->b_l1hdr.b_freeze_lock);
+#endif
ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
arc_space_return(HDR_FULL_SIZE, ARC_SPACE_HDRS);
}
static void
-hdr_full_crypt_dest(void *vbuf, void *unused)
-{
- (void) vbuf, (void) unused;
-
- hdr_full_dest(vbuf, unused);
- arc_space_return(sizeof (((arc_buf_hdr_t *)NULL)->b_crypt_hdr),
- ARC_SPACE_HDRS);
-}
-
-static void
hdr_l2only_dest(void *vbuf, void *unused)
{
(void) unused;
@@ -1226,9 +1218,8 @@ static void
buf_dest(void *vbuf, void *unused)
{
(void) unused;
- arc_buf_t *buf = vbuf;
+ (void) vbuf;
- mutex_destroy(&buf->b_evict_lock);
arc_space_return(sizeof (arc_buf_t), ARC_SPACE_HDRS);
}
@@ -1268,9 +1259,6 @@ retry:
hdr_full_cache = kmem_cache_create("arc_buf_hdr_t_full", HDR_FULL_SIZE,
0, hdr_full_cons, hdr_full_dest, NULL, NULL, NULL, 0);
- hdr_full_crypt_cache = kmem_cache_create("arc_buf_hdr_t_full_crypt",
- HDR_FULL_CRYPT_SIZE, 0, hdr_full_crypt_cons, hdr_full_crypt_dest,
- NULL, NULL, NULL, 0);
hdr_l2only_cache = kmem_cache_create("arc_buf_hdr_t_l2only",
HDR_L2ONLY_SIZE, 0, hdr_l2only_cons, hdr_l2only_dest, NULL,
NULL, NULL, 0);
@@ -1378,7 +1366,7 @@ arc_buf_is_shared(arc_buf_t *buf)
abd_is_linear(buf->b_hdr->b_l1hdr.b_pabd) &&
buf->b_data == abd_to_buf(buf->b_hdr->b_l1hdr.b_pabd));
IMPLY(shared, HDR_SHARED_DATA(buf->b_hdr));
- IMPLY(shared, ARC_BUF_SHARED(buf));
+ EQUIV(shared, ARC_BUF_SHARED(buf));
IMPLY(shared, ARC_BUF_COMPRESSED(buf) || ARC_BUF_LAST(buf));
/*
@@ -1396,6 +1384,7 @@ arc_buf_is_shared(arc_buf_t *buf)
static inline void
arc_cksum_free(arc_buf_hdr_t *hdr)
{
+#ifdef ZFS_DEBUG
ASSERT(HDR_HAS_L1HDR(hdr));
mutex_enter(&hdr->b_l1hdr.b_freeze_lock);
@@ -1404,6 +1393,7 @@ arc_cksum_free(arc_buf_hdr_t *hdr)
hdr->b_l1hdr.b_freeze_cksum = NULL;
}
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
+#endif
}
/*
@@ -1432,6 +1422,7 @@ arc_hdr_has_uncompressed_buf(arc_buf_hdr_t *hdr)
static void
arc_cksum_verify(arc_buf_t *buf)
{
+#ifdef ZFS_DEBUG
arc_buf_hdr_t *hdr = buf->b_hdr;
zio_cksum_t zc;
@@ -1454,6 +1445,7 @@ arc_cksum_verify(arc_buf_t *buf)
if (!ZIO_CHECKSUM_EQUAL(*hdr->b_l1hdr.b_freeze_cksum, zc))
panic("buffer modified while frozen!");
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
+#endif
}
/*
@@ -1494,14 +1486,13 @@ arc_cksum_is_equal(arc_buf_hdr_t *hdr, zio_t *zio)
static void
arc_cksum_compute(arc_buf_t *buf)
{
- arc_buf_hdr_t *hdr = buf->b_hdr;
-
if (!(zfs_flags & ZFS_DEBUG_MODIFY))
return;
+#ifdef ZFS_DEBUG
+ arc_buf_hdr_t *hdr = buf->b_hdr;
ASSERT(HDR_HAS_L1HDR(hdr));
-
- mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
+ mutex_enter(&hdr->b_l1hdr.b_freeze_lock);
if (hdr->b_l1hdr.b_freeze_cksum != NULL || ARC_BUF_COMPRESSED(buf)) {
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
return;
@@ -1514,6 +1505,7 @@ arc_cksum_compute(arc_buf_t *buf)
fletcher_2_native(buf->b_data, arc_buf_size(buf), NULL,
hdr->b_l1hdr.b_freeze_cksum);
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
+#endif
arc_buf_watch(buf);
}
@@ -1699,12 +1691,14 @@ arc_buf_try_copy_decompressed_data(arc_buf_t *buf)
}
}
+#ifdef ZFS_DEBUG
/*
* There were no decompressed bufs, so there should not be a
* checksum on the hdr either.
*/
if (zfs_flags & ZFS_DEBUG_MODIFY)
EQUIV(!copied, hdr->b_l1hdr.b_freeze_cksum == NULL);
+#endif
return (copied);
}
@@ -1790,12 +1784,13 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
*/
if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF &&
!HDR_COMPRESSION_ENABLED(hdr)) {
- tmpbuf = zio_buf_alloc(lsize);
- abd = abd_get_from_buf(tmpbuf, lsize);
- abd_take_ownership_of_buf(abd, B_TRUE);
+
csize = zio_compress_data(HDR_GET_COMPRESS(hdr),
- hdr->b_l1hdr.b_pabd, tmpbuf, lsize, hdr->b_complevel);
+ hdr->b_l1hdr.b_pabd, &tmpbuf, lsize, hdr->b_complevel);
+ ASSERT3P(tmpbuf, !=, NULL);
ASSERT3U(csize, <=, psize);
+ abd = abd_get_from_buf(tmpbuf, lsize);
+ abd_take_ownership_of_buf(abd, B_TRUE);
abd_zero_off(abd, csize, psize - csize);
}
@@ -1848,7 +1843,7 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb)
ASSERT(HDR_EMPTY_OR_LOCKED(hdr));
ASSERT(HDR_ENCRYPTED(hdr));
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT);
+ arc_hdr_alloc_abd(hdr, 0);
ret = spa_do_crypt_abd(B_FALSE, spa, zb, hdr->b_crypt_hdr.b_ot,
B_FALSE, bswap, hdr->b_crypt_hdr.b_salt, hdr->b_crypt_hdr.b_iv,
@@ -1875,8 +1870,7 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb)
* and then loan a buffer from it, rather than allocating a
* linear buffer and wrapping it in an abd later.
*/
- cabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr,
- ARC_HDR_DO_ADAPT);
+ cabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr, 0);
tmp = abd_borrow_buf(cabd, arc_hdr_size(hdr));
ret = zio_decompress_data(HDR_GET_COMPRESS(hdr),
@@ -1966,13 +1960,12 @@ arc_buf_untransform_in_place(arc_buf_t *buf)
ASSERT(HDR_ENCRYPTED(hdr));
ASSERT3U(hdr->b_crypt_hdr.b_ot, ==, DMU_OT_DNODE);
ASSERT(HDR_EMPTY_OR_LOCKED(hdr));
- ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
+ ASSERT3PF(hdr->b_l1hdr.b_pabd, !=, NULL, "hdr %px buf %px", hdr, buf);
zio_crypt_copy_dnode_bonus(hdr->b_l1hdr.b_pabd, buf->b_data,
arc_buf_size(buf));
buf->b_flags &= ~ARC_BUF_FLAG_ENCRYPTED;
buf->b_flags &= ~ARC_BUF_FLAG_COMPRESSED;
- hdr->b_crypt_hdr.b_ebufcnt -= 1;
}
/*
@@ -2007,7 +2000,7 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
IMPLY(encrypted, HDR_ENCRYPTED(hdr));
IMPLY(encrypted, ARC_BUF_ENCRYPTED(buf));
IMPLY(encrypted, ARC_BUF_COMPRESSED(buf));
- IMPLY(encrypted, !ARC_BUF_SHARED(buf));
+ IMPLY(encrypted, !arc_buf_is_shared(buf));
/*
* If the caller wanted encrypted data we just need to copy it from
@@ -2075,7 +2068,9 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
}
if (hdr_compressed == compressed) {
- if (!arc_buf_is_shared(buf)) {
+ if (ARC_BUF_SHARED(buf)) {
+ ASSERT(arc_buf_is_shared(buf));
+ } else {
abd_copy_to_buf(buf->b_data, hdr->b_l1hdr.b_pabd,
arc_buf_size(buf));
}
@@ -2087,8 +2082,9 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
* If the buf is sharing its data with the hdr, unlink it and
* allocate a new data buffer for the buf.
*/
- if (arc_buf_is_shared(buf)) {
- ASSERT(ARC_BUF_COMPRESSED(buf));
+ if (ARC_BUF_SHARED(buf)) {
+ ASSERTF(ARC_BUF_COMPRESSED(buf),
+ "buf %p was uncompressed", buf);
/* We need to give the buf its own b_data */
buf->b_flags &= ~ARC_BUF_FLAG_SHARED;
@@ -2099,6 +2095,8 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
/* Previously overhead was 0; just add new overhead */
ARCSTAT_INCR(arcstat_overhead_size, HDR_GET_LSIZE(hdr));
} else if (ARC_BUF_COMPRESSED(buf)) {
+ ASSERT(!arc_buf_is_shared(buf));
+
/* We need to reallocate the buf's b_data */
arc_free_data_buf(hdr, buf->b_data, HDR_GET_PSIZE(hdr),
buf);
@@ -2186,7 +2184,7 @@ arc_untransform(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
* (and generate an ereport) before leaving the ARC.
*/
ret = SET_ERROR(EIO);
- spa_log_error(spa, zb);
+ spa_log_error(spa, zb, buf->b_hdr->b_birth);
(void) zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
spa, NULL, zb, NULL, 0);
}
@@ -2207,7 +2205,6 @@ arc_evictable_space_increment(arc_buf_hdr_t *hdr, arc_state_t *state)
ASSERT(HDR_HAS_L1HDR(hdr));
if (GHOST_STATE(state)) {
- ASSERT0(hdr->b_l1hdr.b_bufcnt);
ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
ASSERT(!HDR_HAS_RABD(hdr));
@@ -2227,7 +2224,7 @@ arc_evictable_space_increment(arc_buf_hdr_t *hdr, arc_state_t *state)
for (arc_buf_t *buf = hdr->b_l1hdr.b_buf; buf != NULL;
buf = buf->b_next) {
- if (arc_buf_is_shared(buf))
+ if (ARC_BUF_SHARED(buf))
continue;
(void) zfs_refcount_add_many(&state->arcs_esize[type],
arc_buf_size(buf), buf);
@@ -2247,7 +2244,6 @@ arc_evictable_space_decrement(arc_buf_hdr_t *hdr, arc_state_t *state)
ASSERT(HDR_HAS_L1HDR(hdr));
if (GHOST_STATE(state)) {
- ASSERT0(hdr->b_l1hdr.b_bufcnt);
ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
ASSERT(!HDR_HAS_RABD(hdr));
@@ -2267,7 +2263,7 @@ arc_evictable_space_decrement(arc_buf_hdr_t *hdr, arc_state_t *state)
for (arc_buf_t *buf = hdr->b_l1hdr.b_buf; buf != NULL;
buf = buf->b_next) {
- if (arc_buf_is_shared(buf))
+ if (ARC_BUF_SHARED(buf))
continue;
(void) zfs_refcount_remove_many(&state->arcs_esize[type],
arc_buf_size(buf), buf);
@@ -2283,31 +2279,20 @@ arc_evictable_space_decrement(arc_buf_hdr_t *hdr, arc_state_t *state)
static void
add_reference(arc_buf_hdr_t *hdr, const void *tag)
{
- arc_state_t *state;
+ arc_state_t *state = hdr->b_l1hdr.b_state;
ASSERT(HDR_HAS_L1HDR(hdr));
if (!HDR_EMPTY(hdr) && !MUTEX_HELD(HDR_LOCK(hdr))) {
- ASSERT(hdr->b_l1hdr.b_state == arc_anon);
+ ASSERT(state == arc_anon);
ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
}
- state = hdr->b_l1hdr.b_state;
-
if ((zfs_refcount_add(&hdr->b_l1hdr.b_refcnt, tag) == 1) &&
- (state != arc_anon)) {
+ state != arc_anon && state != arc_l2c_only) {
/* We don't use the L2-only state list. */
- if (state != arc_l2c_only) {
- multilist_remove(&state->arcs_list[arc_buf_type(hdr)],
- hdr);
- arc_evictable_space_decrement(hdr, state);
- }
- /* remove the prefetch flag if we get a reference */
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_decrement_state(hdr);
- arc_hdr_clear_flags(hdr, ARC_FLAG_PREFETCH);
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_increment_state(hdr);
+ multilist_remove(&state->arcs_list[arc_buf_type(hdr)], hdr);
+ arc_evictable_space_decrement(hdr, state);
}
}
@@ -2317,26 +2302,30 @@ add_reference(arc_buf_hdr_t *hdr, const void *tag)
* list making it eligible for eviction.
*/
static int
-remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, const void *tag)
+remove_reference(arc_buf_hdr_t *hdr, const void *tag)
{
int cnt;
arc_state_t *state = hdr->b_l1hdr.b_state;
ASSERT(HDR_HAS_L1HDR(hdr));
- ASSERT(state == arc_anon || MUTEX_HELD(hash_lock));
- ASSERT(!GHOST_STATE(state));
+ ASSERT(state == arc_anon || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(!GHOST_STATE(state)); /* arc_l2c_only counts as a ghost. */
- /*
- * arc_l2c_only counts as a ghost state so we don't need to explicitly
- * check to prevent usage of the arc_l2c_only list.
- */
- if (((cnt = zfs_refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) == 0) &&
- (state != arc_anon)) {
- multilist_insert(&state->arcs_list[arc_buf_type(hdr)], hdr);
- ASSERT3U(hdr->b_l1hdr.b_bufcnt, >, 0);
- arc_evictable_space_increment(hdr, state);
+ if ((cnt = zfs_refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) != 0)
+ return (cnt);
+
+ if (state == arc_anon) {
+ arc_hdr_destroy(hdr);
+ return (0);
+ }
+ if (state == arc_uncached && !HDR_PREFETCH(hdr)) {
+ arc_change_state(arc_anon, hdr);
+ arc_hdr_destroy(hdr);
+ return (0);
}
- return (cnt);
+ multilist_insert(&state->arcs_list[arc_buf_type(hdr)], hdr);
+ arc_evictable_space_increment(hdr, state);
+ return (0);
}
/*
@@ -2370,7 +2359,9 @@ arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
l2hdr = &hdr->b_l2hdr;
if (l1hdr) {
- abi->abi_bufcnt = l1hdr->b_bufcnt;
+ abi->abi_bufcnt = 0;
+ for (arc_buf_t *buf = l1hdr->b_buf; buf; buf = buf->b_next)
+ abi->abi_bufcnt++;
abi->abi_access = l1hdr->b_arc_access;
abi->abi_mru_hits = l1hdr->b_mru_hits;
abi->abi_mru_ghost_hits = l1hdr->b_mru_ghost_hits;
@@ -2394,14 +2385,12 @@ arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
* for the buffer must be held by the caller.
*/
static void
-arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
- kmutex_t *hash_lock)
+arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr)
{
arc_state_t *old_state;
int64_t refcnt;
- uint32_t bufcnt;
boolean_t update_old, update_new;
- arc_buf_contents_t buftype = arc_buf_type(hdr);
+ arc_buf_contents_t type = arc_buf_type(hdr);
/*
* We almost always have an L1 hdr here, since we call arc_hdr_realloc()
@@ -2413,21 +2402,26 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
if (HDR_HAS_L1HDR(hdr)) {
old_state = hdr->b_l1hdr.b_state;
refcnt = zfs_refcount_count(&hdr->b_l1hdr.b_refcnt);
- bufcnt = hdr->b_l1hdr.b_bufcnt;
- update_old = (bufcnt > 0 || hdr->b_l1hdr.b_pabd != NULL ||
- HDR_HAS_RABD(hdr));
+ update_old = (hdr->b_l1hdr.b_buf != NULL ||
+ hdr->b_l1hdr.b_pabd != NULL || HDR_HAS_RABD(hdr));
+
+ IMPLY(GHOST_STATE(old_state), hdr->b_l1hdr.b_buf == NULL);
+ IMPLY(GHOST_STATE(new_state), hdr->b_l1hdr.b_buf == NULL);
+ IMPLY(old_state == arc_anon, hdr->b_l1hdr.b_buf == NULL ||
+ ARC_BUF_LAST(hdr->b_l1hdr.b_buf));
} else {
old_state = arc_l2c_only;
refcnt = 0;
- bufcnt = 0;
update_old = B_FALSE;
}
update_new = update_old;
+ if (GHOST_STATE(old_state))
+ update_old = B_TRUE;
+ if (GHOST_STATE(new_state))
+ update_new = B_TRUE;
- ASSERT(MUTEX_HELD(hash_lock));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)));
ASSERT3P(new_state, !=, old_state);
- ASSERT(!GHOST_STATE(new_state) || bufcnt == 0);
- ASSERT(old_state != arc_anon || bufcnt <= 1);
/*
* If this buffer is evictable, transfer it from the
@@ -2436,14 +2430,12 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
if (refcnt == 0) {
if (old_state != arc_anon && old_state != arc_l2c_only) {
ASSERT(HDR_HAS_L1HDR(hdr));
- multilist_remove(&old_state->arcs_list[buftype], hdr);
-
- if (GHOST_STATE(old_state)) {
- ASSERT0(bufcnt);
- ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
- update_old = B_TRUE;
+ /* remove_reference() saves on insert. */
+ if (multilist_link_active(&hdr->b_l1hdr.b_arc_node)) {
+ multilist_remove(&old_state->arcs_list[type],
+ hdr);
+ arc_evictable_space_decrement(hdr, old_state);
}
- arc_evictable_space_decrement(hdr, old_state);
}
if (new_state != arc_anon && new_state != arc_l2c_only) {
/*
@@ -2453,13 +2445,7 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
* beforehand.
*/
ASSERT(HDR_HAS_L1HDR(hdr));
- multilist_insert(&new_state->arcs_list[buftype], hdr);
-
- if (GHOST_STATE(new_state)) {
- ASSERT0(bufcnt);
- ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
- update_new = B_TRUE;
- }
+ multilist_insert(&new_state->arcs_list[type], hdr);
arc_evictable_space_increment(hdr, new_state);
}
}
@@ -2473,21 +2459,19 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
if (update_new && new_state != arc_l2c_only) {
ASSERT(HDR_HAS_L1HDR(hdr));
if (GHOST_STATE(new_state)) {
- ASSERT0(bufcnt);
/*
* When moving a header to a ghost state, we first
- * remove all arc buffers. Thus, we'll have a
- * bufcnt of zero, and no arc buffer to use for
- * the reference. As a result, we use the arc
- * header pointer for the reference.
+ * remove all arc buffers. Thus, we'll have no arc
+ * buffer to use for the reference. As a result, we
+ * use the arc header pointer for the reference.
*/
- (void) zfs_refcount_add_many(&new_state->arcs_size,
+ (void) zfs_refcount_add_many(
+ &new_state->arcs_size[type],
HDR_GET_LSIZE(hdr), hdr);
ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
ASSERT(!HDR_HAS_RABD(hdr));
} else {
- uint32_t buffers = 0;
/*
* Each individual buffer holds a unique reference,
@@ -2496,8 +2480,6 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
*/
for (arc_buf_t *buf = hdr->b_l1hdr.b_buf; buf != NULL;
buf = buf->b_next) {
- ASSERT3U(bufcnt, !=, 0);
- buffers++;
/*
* When the arc_buf_t is sharing the data
@@ -2506,24 +2488,23 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
* add to the refcount if the arc_buf_t is
* not shared.
*/
- if (arc_buf_is_shared(buf))
+ if (ARC_BUF_SHARED(buf))
continue;
(void) zfs_refcount_add_many(
- &new_state->arcs_size,
+ &new_state->arcs_size[type],
arc_buf_size(buf), buf);
}
- ASSERT3U(bufcnt, ==, buffers);
if (hdr->b_l1hdr.b_pabd != NULL) {
(void) zfs_refcount_add_many(
- &new_state->arcs_size,
+ &new_state->arcs_size[type],
arc_hdr_size(hdr), hdr);
}
if (HDR_HAS_RABD(hdr)) {
(void) zfs_refcount_add_many(
- &new_state->arcs_size,
+ &new_state->arcs_size[type],
HDR_GET_PSIZE(hdr), hdr);
}
}
@@ -2532,7 +2513,6 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
if (update_old && old_state != arc_l2c_only) {
ASSERT(HDR_HAS_L1HDR(hdr));
if (GHOST_STATE(old_state)) {
- ASSERT0(bufcnt);
ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
ASSERT(!HDR_HAS_RABD(hdr));
@@ -2544,10 +2524,10 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
* header on the ghost state.
*/
- (void) zfs_refcount_remove_many(&old_state->arcs_size,
+ (void) zfs_refcount_remove_many(
+ &old_state->arcs_size[type],
HDR_GET_LSIZE(hdr), hdr);
} else {
- uint32_t buffers = 0;
/*
* Each individual buffer holds a unique reference,
@@ -2556,8 +2536,6 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
*/
for (arc_buf_t *buf = hdr->b_l1hdr.b_buf; buf != NULL;
buf = buf->b_next) {
- ASSERT3U(bufcnt, !=, 0);
- buffers++;
/*
* When the arc_buf_t is sharing the data
@@ -2566,27 +2544,26 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
* add to the refcount if the arc_buf_t is
* not shared.
*/
- if (arc_buf_is_shared(buf))
+ if (ARC_BUF_SHARED(buf))
continue;
(void) zfs_refcount_remove_many(
- &old_state->arcs_size, arc_buf_size(buf),
- buf);
+ &old_state->arcs_size[type],
+ arc_buf_size(buf), buf);
}
- ASSERT3U(bufcnt, ==, buffers);
ASSERT(hdr->b_l1hdr.b_pabd != NULL ||
HDR_HAS_RABD(hdr));
if (hdr->b_l1hdr.b_pabd != NULL) {
(void) zfs_refcount_remove_many(
- &old_state->arcs_size, arc_hdr_size(hdr),
- hdr);
+ &old_state->arcs_size[type],
+ arc_hdr_size(hdr), hdr);
}
if (HDR_HAS_RABD(hdr)) {
(void) zfs_refcount_remove_many(
- &old_state->arcs_size, HDR_GET_PSIZE(hdr),
- hdr);
+ &old_state->arcs_size[type],
+ HDR_GET_PSIZE(hdr), hdr);
}
}
}
@@ -2620,7 +2597,7 @@ arc_space_consume(uint64_t space, arc_space_type_t type)
ARCSTAT_INCR(arcstat_bonus_size, space);
break;
case ARC_SPACE_DNODE:
- aggsum_add(&arc_sums.arcstat_dnode_size, space);
+ ARCSTAT_INCR(arcstat_dnode_size, space);
break;
case ARC_SPACE_DBUF:
ARCSTAT_INCR(arcstat_dbuf_size, space);
@@ -2643,7 +2620,7 @@ arc_space_consume(uint64_t space, arc_space_type_t type)
}
if (type != ARC_SPACE_DATA && type != ARC_SPACE_ABD_CHUNK_WASTE)
- aggsum_add(&arc_sums.arcstat_meta_used, space);
+ ARCSTAT_INCR(arcstat_meta_used, space);
aggsum_add(&arc_sums.arcstat_size, space);
}
@@ -2666,7 +2643,7 @@ arc_space_return(uint64_t space, arc_space_type_t type)
ARCSTAT_INCR(arcstat_bonus_size, -space);
break;
case ARC_SPACE_DNODE:
- aggsum_add(&arc_sums.arcstat_dnode_size, -space);
+ ARCSTAT_INCR(arcstat_dnode_size, -space);
break;
case ARC_SPACE_DBUF:
ARCSTAT_INCR(arcstat_dbuf_size, -space);
@@ -2682,13 +2659,8 @@ arc_space_return(uint64_t space, arc_space_type_t type)
break;
}
- if (type != ARC_SPACE_DATA && type != ARC_SPACE_ABD_CHUNK_WASTE) {
- ASSERT(aggsum_compare(&arc_sums.arcstat_meta_used,
- space) >= 0);
- ARCSTAT_MAX(arcstat_meta_max,
- aggsum_upper_bound(&arc_sums.arcstat_meta_used));
- aggsum_add(&arc_sums.arcstat_meta_used, -space);
- }
+ if (type != ARC_SPACE_DATA && type != ARC_SPACE_ABD_CHUNK_WASTE)
+ ARCSTAT_INCR(arcstat_meta_used, -space);
ASSERT(aggsum_compare(&arc_sums.arcstat_size, space) >= 0);
aggsum_add(&arc_sums.arcstat_size, -space);
@@ -2826,9 +2798,6 @@ arc_buf_alloc_impl(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb,
VERIFY3P(buf->b_data, !=, NULL);
hdr->b_l1hdr.b_buf = buf;
- hdr->b_l1hdr.b_bufcnt += 1;
- if (encrypted)
- hdr->b_crypt_hdr.b_ebufcnt += 1;
/*
* If the user wants the data from the hdr, we need to either copy or
@@ -2955,7 +2924,7 @@ arc_hdr_free_on_write(arc_buf_hdr_t *hdr, boolean_t free_rdata)
(void) zfs_refcount_remove_many(&state->arcs_esize[type],
size, hdr);
}
- (void) zfs_refcount_remove_many(&state->arcs_size, size, hdr);
+ (void) zfs_refcount_remove_many(&state->arcs_size[type], size, hdr);
if (type == ARC_BUFC_METADATA) {
arc_space_return(size, ARC_SPACE_META);
} else {
@@ -2988,7 +2957,8 @@ arc_share_buf(arc_buf_hdr_t *hdr, arc_buf_t *buf)
* refcount ownership to the hdr since it always owns
* the refcount whenever an arc_buf_t is shared.
*/
- zfs_refcount_transfer_ownership_many(&hdr->b_l1hdr.b_state->arcs_size,
+ zfs_refcount_transfer_ownership_many(
+ &hdr->b_l1hdr.b_state->arcs_size[arc_buf_type(hdr)],
arc_hdr_size(hdr), buf, hdr);
hdr->b_l1hdr.b_pabd = abd_get_from_buf(buf->b_data, arc_buf_size(buf));
abd_take_ownership_of_buf(hdr->b_l1hdr.b_pabd,
@@ -3017,7 +2987,8 @@ arc_unshare_buf(arc_buf_hdr_t *hdr, arc_buf_t *buf)
* We are no longer sharing this buffer so we need
* to transfer its ownership to the rightful owner.
*/
- zfs_refcount_transfer_ownership_many(&hdr->b_l1hdr.b_state->arcs_size,
+ zfs_refcount_transfer_ownership_many(
+ &hdr->b_l1hdr.b_state->arcs_size[arc_buf_type(hdr)],
arc_hdr_size(hdr), hdr, buf);
arc_hdr_clear_flags(hdr, ARC_FLAG_SHARED_DATA);
abd_release_ownership_of_buf(hdr->b_l1hdr.b_pabd);
@@ -3068,8 +3039,6 @@ arc_buf_remove(arc_buf_hdr_t *hdr, arc_buf_t *buf)
}
buf->b_next = NULL;
ASSERT3P(lastbuf, !=, buf);
- IMPLY(hdr->b_l1hdr.b_bufcnt > 0, lastbuf != NULL);
- IMPLY(hdr->b_l1hdr.b_bufcnt > 0, hdr->b_l1hdr.b_buf != NULL);
IMPLY(lastbuf != NULL, ARC_BUF_LAST(lastbuf));
return (lastbuf);
@@ -3099,31 +3068,30 @@ arc_buf_destroy_impl(arc_buf_t *buf)
arc_cksum_verify(buf);
arc_buf_unwatch(buf);
- if (arc_buf_is_shared(buf)) {
+ if (ARC_BUF_SHARED(buf)) {
arc_hdr_clear_flags(hdr, ARC_FLAG_SHARED_DATA);
} else {
+ ASSERT(!arc_buf_is_shared(buf));
uint64_t size = arc_buf_size(buf);
arc_free_data_buf(hdr, buf->b_data, size, buf);
ARCSTAT_INCR(arcstat_overhead_size, -size);
}
buf->b_data = NULL;
- ASSERT(hdr->b_l1hdr.b_bufcnt > 0);
- hdr->b_l1hdr.b_bufcnt -= 1;
-
- if (ARC_BUF_ENCRYPTED(buf)) {
- hdr->b_crypt_hdr.b_ebufcnt -= 1;
-
- /*
- * If we have no more encrypted buffers and we've
- * already gotten a copy of the decrypted data we can
- * free b_rabd to save some space.
- */
- if (hdr->b_crypt_hdr.b_ebufcnt == 0 &&
- HDR_HAS_RABD(hdr) && hdr->b_l1hdr.b_pabd != NULL &&
- !HDR_IO_IN_PROGRESS(hdr)) {
- arc_hdr_free_abd(hdr, B_TRUE);
+ /*
+ * If we have no more encrypted buffers and we've already
+ * gotten a copy of the decrypted data we can free b_rabd
+ * to save some space.
+ */
+ if (ARC_BUF_ENCRYPTED(buf) && HDR_HAS_RABD(hdr) &&
+ hdr->b_l1hdr.b_pabd != NULL && !HDR_IO_IN_PROGRESS(hdr)) {
+ arc_buf_t *b;
+ for (b = hdr->b_l1hdr.b_buf; b; b = b->b_next) {
+ if (b != buf && ARC_BUF_ENCRYPTED(b))
+ break;
}
+ if (b == NULL)
+ arc_hdr_free_abd(hdr, B_TRUE);
}
}
@@ -3144,9 +3112,9 @@ arc_buf_destroy_impl(arc_buf_t *buf)
*/
if (lastbuf != NULL && !ARC_BUF_ENCRYPTED(lastbuf)) {
/* Only one buf can be shared at once */
- VERIFY(!arc_buf_is_shared(lastbuf));
+ ASSERT(!arc_buf_is_shared(lastbuf));
/* hdr is uncompressed so can't have compressed buf */
- VERIFY(!ARC_BUF_COMPRESSED(lastbuf));
+ ASSERT(!ARC_BUF_COMPRESSED(lastbuf));
ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
arc_hdr_free_abd(hdr, B_FALSE);
@@ -3284,14 +3252,12 @@ arc_hdr_alloc(uint64_t spa, int32_t psize, int32_t lsize,
arc_buf_hdr_t *hdr;
VERIFY(type == ARC_BUFC_DATA || type == ARC_BUFC_METADATA);
- if (protected) {
- hdr = kmem_cache_alloc(hdr_full_crypt_cache, KM_PUSHPAGE);
- } else {
- hdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE);
- }
+ hdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE);
ASSERT(HDR_EMPTY(hdr));
+#ifdef ZFS_DEBUG
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
+#endif
HDR_SET_PSIZE(hdr, psize);
HDR_SET_LSIZE(hdr, lsize);
hdr->b_spa = spa;
@@ -3309,7 +3275,6 @@ arc_hdr_alloc(uint64_t spa, int32_t psize, int32_t lsize,
hdr->b_l1hdr.b_mru_ghost_hits = 0;
hdr->b_l1hdr.b_mfu_hits = 0;
hdr->b_l1hdr.b_mfu_ghost_hits = 0;
- hdr->b_l1hdr.b_bufcnt = 0;
hdr->b_l1hdr.b_buf = NULL;
ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
@@ -3335,16 +3300,6 @@ arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
ASSERT((old == hdr_full_cache && new == hdr_l2only_cache) ||
(old == hdr_l2only_cache && new == hdr_full_cache));
- /*
- * if the caller wanted a new full header and the header is to be
- * encrypted we will actually allocate the header from the full crypt
- * cache instead. The same applies to freeing from the old cache.
- */
- if (HDR_PROTECTED(hdr) && new == hdr_full_cache)
- new = hdr_full_crypt_cache;
- if (HDR_PROTECTED(hdr) && old == hdr_full_cache)
- old = hdr_full_crypt_cache;
-
nhdr = kmem_cache_alloc(new, KM_PUSHPAGE);
ASSERT(MUTEX_HELD(HDR_LOCK(hdr)));
@@ -3352,7 +3307,7 @@ arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
memcpy(nhdr, hdr, HDR_L2ONLY_SIZE);
- if (new == hdr_full_cache || new == hdr_full_crypt_cache) {
+ if (new == hdr_full_cache) {
arc_hdr_set_flags(nhdr, ARC_FLAG_HAS_L1HDR);
/*
* arc_access and arc_change_state need to be aware that a
@@ -3366,8 +3321,9 @@ arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
ASSERT(!HDR_HAS_RABD(hdr));
} else {
ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
- ASSERT0(hdr->b_l1hdr.b_bufcnt);
+#ifdef ZFS_DEBUG
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
+#endif
/*
* If we've reached here, We must have been called from
@@ -3431,125 +3387,6 @@ arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
}
/*
- * This function allows an L1 header to be reallocated as a crypt
- * header and vice versa. If we are going to a crypt header, the
- * new fields will be zeroed out.
- */
-static arc_buf_hdr_t *
-arc_hdr_realloc_crypt(arc_buf_hdr_t *hdr, boolean_t need_crypt)
-{
- arc_buf_hdr_t *nhdr;
- arc_buf_t *buf;
- kmem_cache_t *ncache, *ocache;
-
- /*
- * This function requires that hdr is in the arc_anon state.
- * Therefore it won't have any L2ARC data for us to worry
- * about copying.
- */
- ASSERT(HDR_HAS_L1HDR(hdr));
- ASSERT(!HDR_HAS_L2HDR(hdr));
- ASSERT3U(!!HDR_PROTECTED(hdr), !=, need_crypt);
- ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
- ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
- ASSERT(!list_link_active(&hdr->b_l2hdr.b_l2node));
- ASSERT3P(hdr->b_hash_next, ==, NULL);
-
- if (need_crypt) {
- ncache = hdr_full_crypt_cache;
- ocache = hdr_full_cache;
- } else {
- ncache = hdr_full_cache;
- ocache = hdr_full_crypt_cache;
- }
-
- nhdr = kmem_cache_alloc(ncache, KM_PUSHPAGE);
-
- /*
- * Copy all members that aren't locks or condvars to the new header.
- * No lists are pointing to us (as we asserted above), so we don't
- * need to worry about the list nodes.
- */
- nhdr->b_dva = hdr->b_dva;
- nhdr->b_birth = hdr->b_birth;
- nhdr->b_type = hdr->b_type;
- nhdr->b_flags = hdr->b_flags;
- nhdr->b_psize = hdr->b_psize;
- nhdr->b_lsize = hdr->b_lsize;
- nhdr->b_spa = hdr->b_spa;
- nhdr->b_l1hdr.b_freeze_cksum = hdr->b_l1hdr.b_freeze_cksum;
- nhdr->b_l1hdr.b_bufcnt = hdr->b_l1hdr.b_bufcnt;
- nhdr->b_l1hdr.b_byteswap = hdr->b_l1hdr.b_byteswap;
- nhdr->b_l1hdr.b_state = hdr->b_l1hdr.b_state;
- nhdr->b_l1hdr.b_arc_access = hdr->b_l1hdr.b_arc_access;
- nhdr->b_l1hdr.b_mru_hits = hdr->b_l1hdr.b_mru_hits;
- nhdr->b_l1hdr.b_mru_ghost_hits = hdr->b_l1hdr.b_mru_ghost_hits;
- nhdr->b_l1hdr.b_mfu_hits = hdr->b_l1hdr.b_mfu_hits;
- nhdr->b_l1hdr.b_mfu_ghost_hits = hdr->b_l1hdr.b_mfu_ghost_hits;
- nhdr->b_l1hdr.b_acb = hdr->b_l1hdr.b_acb;
- nhdr->b_l1hdr.b_pabd = hdr->b_l1hdr.b_pabd;
-
- /*
- * This zfs_refcount_add() exists only to ensure that the individual
- * arc buffers always point to a header that is referenced, avoiding
- * a small race condition that could trigger ASSERTs.
- */
- (void) zfs_refcount_add(&nhdr->b_l1hdr.b_refcnt, FTAG);
- nhdr->b_l1hdr.b_buf = hdr->b_l1hdr.b_buf;
- for (buf = nhdr->b_l1hdr.b_buf; buf != NULL; buf = buf->b_next) {
- mutex_enter(&buf->b_evict_lock);
- buf->b_hdr = nhdr;
- mutex_exit(&buf->b_evict_lock);
- }
-
- zfs_refcount_transfer(&nhdr->b_l1hdr.b_refcnt, &hdr->b_l1hdr.b_refcnt);
- (void) zfs_refcount_remove(&nhdr->b_l1hdr.b_refcnt, FTAG);
- ASSERT0(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt));
-
- if (need_crypt) {
- arc_hdr_set_flags(nhdr, ARC_FLAG_PROTECTED);
- } else {
- arc_hdr_clear_flags(nhdr, ARC_FLAG_PROTECTED);
- }
-
- /* unset all members of the original hdr */
- memset(&hdr->b_dva, 0, sizeof (dva_t));
- hdr->b_birth = 0;
- hdr->b_type = ARC_BUFC_INVALID;
- hdr->b_flags = 0;
- hdr->b_psize = 0;
- hdr->b_lsize = 0;
- hdr->b_spa = 0;
- hdr->b_l1hdr.b_freeze_cksum = NULL;
- hdr->b_l1hdr.b_buf = NULL;
- hdr->b_l1hdr.b_bufcnt = 0;
- hdr->b_l1hdr.b_byteswap = 0;
- hdr->b_l1hdr.b_state = NULL;
- hdr->b_l1hdr.b_arc_access = 0;
- hdr->b_l1hdr.b_mru_hits = 0;
- hdr->b_l1hdr.b_mru_ghost_hits = 0;
- hdr->b_l1hdr.b_mfu_hits = 0;
- hdr->b_l1hdr.b_mfu_ghost_hits = 0;
- hdr->b_l1hdr.b_acb = NULL;
- hdr->b_l1hdr.b_pabd = NULL;
-
- if (ocache == hdr_full_crypt_cache) {
- ASSERT(!HDR_HAS_RABD(hdr));
- hdr->b_crypt_hdr.b_ot = DMU_OT_NONE;
- hdr->b_crypt_hdr.b_ebufcnt = 0;
- hdr->b_crypt_hdr.b_dsobj = 0;
- memset(hdr->b_crypt_hdr.b_salt, 0, ZIO_DATA_SALT_LEN);
- memset(hdr->b_crypt_hdr.b_iv, 0, ZIO_DATA_IV_LEN);
- memset(hdr->b_crypt_hdr.b_mac, 0, ZIO_DATA_MAC_LEN);
- }
-
- buf_discard_identity(hdr);
- kmem_cache_free(ocache, hdr);
-
- return (nhdr);
-}
-
-/*
* This function is used by the send / receive code to convert a newly
* allocated arc_buf_t to one that is suitable for a raw encrypted write. It
* is also used to allow the root objset block to be updated without altering
@@ -3568,8 +3405,7 @@ arc_convert_to_raw(arc_buf_t *buf, uint64_t dsobj, boolean_t byteorder,
ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
buf->b_flags |= (ARC_BUF_FLAG_COMPRESSED | ARC_BUF_FLAG_ENCRYPTED);
- if (!HDR_PROTECTED(hdr))
- hdr = arc_hdr_realloc_crypt(hdr, B_TRUE);
+ arc_hdr_set_flags(hdr, ARC_FLAG_PROTECTED);
hdr->b_crypt_hdr.b_dsobj = dsobj;
hdr->b_crypt_hdr.b_ot = ot;
hdr->b_l1hdr.b_byteswap = (byteorder == ZFS_HOST_BYTEORDER) ?
@@ -3624,7 +3460,6 @@ arc_alloc_compressed_buf(spa_t *spa, const void *tag, uint64_t psize,
VERIFY0(arc_buf_alloc_impl(hdr, spa, NULL, tag, B_FALSE,
B_TRUE, B_FALSE, B_FALSE, &buf));
arc_buf_thaw(buf);
- ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
/*
* To ensure that the hdr has the correct data in it if we call
@@ -3672,7 +3507,6 @@ arc_alloc_raw_buf(spa_t *spa, const void *tag, uint64_t dsobj,
VERIFY0(arc_buf_alloc_impl(hdr, spa, NULL, tag, B_TRUE, B_TRUE,
B_FALSE, B_FALSE, &buf));
arc_buf_thaw(buf);
- ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
return (buf);
}
@@ -3772,8 +3606,6 @@ static void
arc_hdr_destroy(arc_buf_hdr_t *hdr)
{
if (HDR_HAS_L1HDR(hdr)) {
- ASSERT(hdr->b_l1hdr.b_buf == NULL ||
- hdr->b_l1hdr.b_bufcnt > 0);
ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
}
@@ -3834,12 +3666,10 @@ arc_hdr_destroy(arc_buf_hdr_t *hdr)
if (HDR_HAS_L1HDR(hdr)) {
ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL);
-
- if (!HDR_PROTECTED(hdr)) {
- kmem_cache_free(hdr_full_cache, hdr);
- } else {
- kmem_cache_free(hdr_full_crypt_cache, hdr);
- }
+#ifdef ZFS_DEBUG
+ ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
+#endif
+ kmem_cache_free(hdr_full_cache, hdr);
} else {
kmem_cache_free(hdr_l2only_cache, hdr);
}
@@ -3851,10 +3681,10 @@ arc_buf_destroy(arc_buf_t *buf, const void *tag)
arc_buf_hdr_t *hdr = buf->b_hdr;
if (hdr->b_l1hdr.b_state == arc_anon) {
- ASSERT3U(hdr->b_l1hdr.b_bufcnt, ==, 1);
+ ASSERT3P(hdr->b_l1hdr.b_buf, ==, buf);
+ ASSERT(ARC_BUF_LAST(buf));
ASSERT(!HDR_IO_IN_PROGRESS(hdr));
- VERIFY0(remove_reference(hdr, NULL, tag));
- arc_hdr_destroy(hdr);
+ VERIFY0(remove_reference(hdr, tag));
return;
}
@@ -3862,13 +3692,13 @@ arc_buf_destroy(arc_buf_t *buf, const void *tag)
mutex_enter(hash_lock);
ASSERT3P(hdr, ==, buf->b_hdr);
- ASSERT(hdr->b_l1hdr.b_bufcnt > 0);
+ ASSERT3P(hdr->b_l1hdr.b_buf, !=, NULL);
ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
ASSERT3P(hdr->b_l1hdr.b_state, !=, arc_anon);
ASSERT3P(buf->b_data, !=, NULL);
- (void) remove_reference(hdr, hash_lock, tag);
arc_buf_destroy_impl(buf);
+ (void) remove_reference(hdr, tag);
mutex_exit(hash_lock);
}
@@ -3883,6 +3713,7 @@ arc_buf_destroy(arc_buf_t *buf, const void *tag)
* - arc_mru_ghost -> deleted
* - arc_mfu_ghost -> arc_l2c_only
* - arc_mfu_ghost -> deleted
+ * - arc_uncached -> deleted
*
* Return total size of evicted data buffers for eviction progress tracking.
* When evicting from ghost states return logical buffer size to make eviction
@@ -3894,21 +3725,22 @@ arc_buf_destroy(arc_buf_t *buf, const void *tag)
* only the evicted headers size.
*/
static int64_t
-arc_evict_hdr(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, uint64_t *real_evicted)
+arc_evict_hdr(arc_buf_hdr_t *hdr, uint64_t *real_evicted)
{
arc_state_t *evicted_state, *state;
int64_t bytes_evicted = 0;
- int min_lifetime = HDR_PRESCIENT_PREFETCH(hdr) ?
+ uint_t min_lifetime = HDR_PRESCIENT_PREFETCH(hdr) ?
arc_min_prescient_prefetch_ms : arc_min_prefetch_ms;
- ASSERT(MUTEX_HELD(hash_lock));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)));
ASSERT(HDR_HAS_L1HDR(hdr));
+ ASSERT(!HDR_IO_IN_PROGRESS(hdr));
+ ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
+ ASSERT0(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt));
*real_evicted = 0;
state = hdr->b_l1hdr.b_state;
if (GHOST_STATE(state)) {
- ASSERT(!HDR_IO_IN_PROGRESS(hdr));
- ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
/*
* l2arc_write_buffers() relies on a header's L1 portion
@@ -3934,49 +3766,34 @@ arc_evict_hdr(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, uint64_t *real_evicted)
* This buffer is cached on the 2nd Level ARC;
* don't destroy the header.
*/
- arc_change_state(arc_l2c_only, hdr, hash_lock);
+ arc_change_state(arc_l2c_only, hdr);
/*
* dropping from L1+L2 cached to L2-only,
* realloc to remove the L1 header.
*/
- hdr = arc_hdr_realloc(hdr, hdr_full_cache,
+ (void) arc_hdr_realloc(hdr, hdr_full_cache,
hdr_l2only_cache);
*real_evicted += HDR_FULL_SIZE - HDR_L2ONLY_SIZE;
} else {
- arc_change_state(arc_anon, hdr, hash_lock);
+ arc_change_state(arc_anon, hdr);
arc_hdr_destroy(hdr);
*real_evicted += HDR_FULL_SIZE;
}
return (bytes_evicted);
}
- ASSERT(state == arc_mru || state == arc_mfu);
- evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost;
+ ASSERT(state == arc_mru || state == arc_mfu || state == arc_uncached);
+ evicted_state = (state == arc_uncached) ? arc_anon :
+ ((state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost);
/* prefetch buffers have a minimum lifespan */
- if (HDR_IO_IN_PROGRESS(hdr) ||
- ((hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT)) &&
+ if ((hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT)) &&
ddi_get_lbolt() - hdr->b_l1hdr.b_arc_access <
- MSEC_TO_TICK(min_lifetime))) {
+ MSEC_TO_TICK(min_lifetime)) {
ARCSTAT_BUMP(arcstat_evict_skip);
return (bytes_evicted);
}
- ASSERT0(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt));
- while (hdr->b_l1hdr.b_buf) {
- arc_buf_t *buf = hdr->b_l1hdr.b_buf;
- if (!mutex_tryenter(&buf->b_evict_lock)) {
- ARCSTAT_BUMP(arcstat_mutex_miss);
- break;
- }
- if (buf->b_data != NULL) {
- bytes_evicted += HDR_GET_LSIZE(hdr);
- *real_evicted += HDR_GET_LSIZE(hdr);
- }
- mutex_exit(&buf->b_evict_lock);
- arc_buf_destroy_impl(buf);
- }
-
if (HDR_HAS_L2HDR(hdr)) {
ARCSTAT_INCR(arcstat_evict_l2_cached, HDR_GET_LSIZE(hdr));
} else {
@@ -4004,28 +3821,27 @@ arc_evict_hdr(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, uint64_t *real_evicted)
}
}
- if (hdr->b_l1hdr.b_bufcnt == 0) {
- arc_cksum_free(hdr);
-
- bytes_evicted += arc_hdr_size(hdr);
- *real_evicted += arc_hdr_size(hdr);
+ bytes_evicted += arc_hdr_size(hdr);
+ *real_evicted += arc_hdr_size(hdr);
- /*
- * If this hdr is being evicted and has a compressed
- * buffer then we discard it here before we change states.
- * This ensures that the accounting is updated correctly
- * in arc_free_data_impl().
- */
- if (hdr->b_l1hdr.b_pabd != NULL)
- arc_hdr_free_abd(hdr, B_FALSE);
+ /*
+ * If this hdr is being evicted and has a compressed buffer then we
+ * discard it here before we change states. This ensures that the
+ * accounting is updated correctly in arc_free_data_impl().
+ */
+ if (hdr->b_l1hdr.b_pabd != NULL)
+ arc_hdr_free_abd(hdr, B_FALSE);
- if (HDR_HAS_RABD(hdr))
- arc_hdr_free_abd(hdr, B_TRUE);
+ if (HDR_HAS_RABD(hdr))
+ arc_hdr_free_abd(hdr, B_TRUE);
- arc_change_state(evicted_state, hdr, hash_lock);
+ arc_change_state(evicted_state, hdr);
+ DTRACE_PROBE1(arc__evict, arc_buf_hdr_t *, hdr);
+ if (evicted_state == arc_anon) {
+ arc_hdr_destroy(hdr);
+ *real_evicted += HDR_FULL_SIZE;
+ } else {
ASSERT(HDR_IN_HASH_TABLE(hdr));
- arc_hdr_set_flags(hdr, ARC_FLAG_IN_HASH_TABLE);
- DTRACE_PROBE1(arc__evict, arc_buf_hdr_t *, hdr);
}
return (bytes_evicted);
@@ -4053,15 +3869,15 @@ arc_evict_state_impl(multilist_t *ml, int idx, arc_buf_hdr_t *marker,
uint64_t bytes_evicted = 0, real_evicted = 0;
arc_buf_hdr_t *hdr;
kmutex_t *hash_lock;
- int evict_count = zfs_arc_evict_batch_limit;
+ uint_t evict_count = zfs_arc_evict_batch_limit;
ASSERT3P(marker, !=, NULL);
- mls = multilist_sublist_lock(ml, idx);
+ mls = multilist_sublist_lock_idx(ml, idx);
for (hdr = multilist_sublist_prev(mls, marker); likely(hdr != NULL);
hdr = multilist_sublist_prev(mls, marker)) {
- if ((evict_count <= 0) || (bytes_evicted >= bytes))
+ if ((evict_count == 0) || (bytes_evicted >= bytes))
break;
/*
@@ -4110,8 +3926,7 @@ arc_evict_state_impl(multilist_t *ml, int idx, arc_buf_hdr_t *marker,
if (mutex_tryenter(hash_lock)) {
uint64_t revicted;
- uint64_t evicted = arc_evict_hdr(hdr, hash_lock,
- &revicted);
+ uint64_t evicted = arc_evict_hdr(hdr, &revicted);
mutex_exit(hash_lock);
bytes_evicted += evicted;
@@ -4165,11 +3980,31 @@ arc_evict_state_impl(multilist_t *ml, int idx, arc_buf_hdr_t *marker,
* this CPU are able to make progress, make a voluntary preemption
* call here.
*/
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
return (bytes_evicted);
}
+static arc_buf_hdr_t *
+arc_state_alloc_marker(void)
+{
+ arc_buf_hdr_t *marker = kmem_cache_alloc(hdr_full_cache, KM_SLEEP);
+
+ /*
+ * A b_spa of 0 is used to indicate that this header is
+ * a marker. This fact is used in arc_evict_state_impl().
+ */
+ marker->b_spa = 0;
+
+ return (marker);
+}
+
+static void
+arc_state_free_marker(arc_buf_hdr_t *marker)
+{
+ kmem_cache_free(hdr_full_cache, marker);
+}
+
/*
* Allocate an array of buffer headers used as placeholders during arc state
* eviction.
@@ -4180,17 +4015,8 @@ arc_state_alloc_markers(int count)
arc_buf_hdr_t **markers;
markers = kmem_zalloc(sizeof (*markers) * count, KM_SLEEP);
- for (int i = 0; i < count; i++) {
- markers[i] = kmem_cache_alloc(hdr_full_cache, KM_SLEEP);
-
- /*
- * A b_spa of 0 is used to indicate that this header is
- * a marker. This fact is used in arc_evict_type() and
- * arc_evict_state_impl().
- */
- markers[i]->b_spa = 0;
-
- }
+ for (int i = 0; i < count; i++)
+ markers[i] = arc_state_alloc_marker();
return (markers);
}
@@ -4198,7 +4024,7 @@ static void
arc_state_free_markers(arc_buf_hdr_t **markers, int count)
{
for (int i = 0; i < count; i++)
- kmem_cache_free(hdr_full_cache, markers[i]);
+ arc_state_free_marker(markers[i]);
kmem_free(markers, sizeof (*markers) * count);
}
@@ -4216,8 +4042,8 @@ arc_state_free_markers(arc_buf_hdr_t **markers, int count)
* the given arc state; which is used by arc_flush().
*/
static uint64_t
-arc_evict_state(arc_state_t *state, uint64_t spa, uint64_t bytes,
- arc_buf_contents_t type)
+arc_evict_state(arc_state_t *state, arc_buf_contents_t type, uint64_t spa,
+ uint64_t bytes)
{
uint64_t total_evicted = 0;
multilist_t *ml = &state->arcs_list[type];
@@ -4242,7 +4068,7 @@ arc_evict_state(arc_state_t *state, uint64_t spa, uint64_t bytes,
for (int i = 0; i < num_sublists; i++) {
multilist_sublist_t *mls;
- mls = multilist_sublist_lock(ml, i);
+ mls = multilist_sublist_lock_idx(ml, i);
multilist_sublist_insert_tail(mls, markers[i]);
multilist_sublist_unlock(mls);
}
@@ -4256,19 +4082,6 @@ arc_evict_state(arc_state_t *state, uint64_t spa, uint64_t bytes,
uint64_t scan_evicted = 0;
/*
- * Try to reduce pinned dnodes with a floor of arc_dnode_limit.
- * Request that 10% of the LRUs be scanned by the superblock
- * shrinker.
- */
- if (type == ARC_BUFC_DATA && aggsum_compare(
- &arc_sums.arcstat_dnode_size, arc_dnode_size_limit) > 0) {
- arc_prune_async((aggsum_upper_bound(
- &arc_sums.arcstat_dnode_size) -
- arc_dnode_size_limit) / sizeof (dnode_t) /
- zfs_arc_dnode_reduce_percent);
- }
-
- /*
* Start eviction using a randomly selected sublist,
* this is to try and evenly balance eviction across all
* sublists. Always starting at the same sublist
@@ -4320,7 +4133,7 @@ arc_evict_state(arc_state_t *state, uint64_t spa, uint64_t bytes,
}
for (int i = 0; i < num_sublists; i++) {
- multilist_sublist_t *mls = multilist_sublist_lock(ml, i);
+ multilist_sublist_t *mls = multilist_sublist_lock_idx(ml, i);
multilist_sublist_remove(mls, markers[i]);
multilist_sublist_unlock(mls);
}
@@ -4352,7 +4165,7 @@ arc_flush_state(arc_state_t *state, uint64_t spa, arc_buf_contents_t type,
uint64_t evicted = 0;
while (zfs_refcount_count(&state->arcs_esize[type]) != 0) {
- evicted += arc_evict_state(state, spa, ARC_EVICT_ALL, type);
+ evicted += arc_evict_state(state, type, spa, ARC_EVICT_ALL);
if (!retry)
break;
@@ -4362,252 +4175,64 @@ arc_flush_state(arc_state_t *state, uint64_t spa, arc_buf_contents_t type,
}
/*
- * Evict the specified number of bytes from the state specified,
- * restricting eviction to the spa and type given. This function
- * prevents us from trying to evict more from a state's list than
- * is "evictable", and to skip evicting altogether when passed a
+ * Evict the specified number of bytes from the state specified. This
+ * function prevents us from trying to evict more from a state's list
+ * than is "evictable", and to skip evicting altogether when passed a
* negative value for "bytes". In contrast, arc_evict_state() will
* evict everything it can, when passed a negative value for "bytes".
*/
static uint64_t
-arc_evict_impl(arc_state_t *state, uint64_t spa, int64_t bytes,
- arc_buf_contents_t type)
+arc_evict_impl(arc_state_t *state, arc_buf_contents_t type, int64_t bytes)
{
uint64_t delta;
if (bytes > 0 && zfs_refcount_count(&state->arcs_esize[type]) > 0) {
delta = MIN(zfs_refcount_count(&state->arcs_esize[type]),
bytes);
- return (arc_evict_state(state, spa, delta, type));
+ return (arc_evict_state(state, type, 0, delta));
}
return (0);
}
/*
- * The goal of this function is to evict enough meta data buffers from the
- * ARC in order to enforce the arc_meta_limit. Achieving this is slightly
- * more complicated than it appears because it is common for data buffers
- * to have holds on meta data buffers. In addition, dnode meta data buffers
- * will be held by the dnodes in the block preventing them from being freed.
- * This means we can't simply traverse the ARC and expect to always find
- * enough unheld meta data buffer to release.
- *
- * Therefore, this function has been updated to make alternating passes
- * over the ARC releasing data buffers and then newly unheld meta data
- * buffers. This ensures forward progress is maintained and meta_used
- * will decrease. Normally this is sufficient, but if required the ARC
- * will call the registered prune callbacks causing dentry and inodes to
- * be dropped from the VFS cache. This will make dnode meta data buffers
- * available for reclaim.
+ * Adjust specified fraction, taking into account initial ghost state(s) size,
+ * ghost hit bytes towards increasing the fraction, ghost hit bytes towards
+ * decreasing it, plus a balance factor, controlling the decrease rate, used
+ * to balance metadata vs data.
*/
static uint64_t
-arc_evict_meta_balanced(uint64_t meta_used)
+arc_evict_adj(uint64_t frac, uint64_t total, uint64_t up, uint64_t down,
+ uint_t balance)
{
- int64_t delta, prune = 0, adjustmnt;
- uint64_t total_evicted = 0;
- arc_buf_contents_t type = ARC_BUFC_DATA;
- int restarts = MAX(zfs_arc_meta_adjust_restarts, 0);
-
-restart:
- /*
- * This slightly differs than the way we evict from the mru in
- * arc_evict because we don't have a "target" value (i.e. no
- * "meta" arc_p). As a result, I think we can completely
- * cannibalize the metadata in the MRU before we evict the
- * metadata from the MFU. I think we probably need to implement a
- * "metadata arc_p" value to do this properly.
- */
- adjustmnt = meta_used - arc_meta_limit;
-
- if (adjustmnt > 0 &&
- zfs_refcount_count(&arc_mru->arcs_esize[type]) > 0) {
- delta = MIN(zfs_refcount_count(&arc_mru->arcs_esize[type]),
- adjustmnt);
- total_evicted += arc_evict_impl(arc_mru, 0, delta, type);
- adjustmnt -= delta;
- }
-
- /*
- * We can't afford to recalculate adjustmnt here. If we do,
- * new metadata buffers can sneak into the MRU or ANON lists,
- * thus penalize the MFU metadata. Although the fudge factor is
- * small, it has been empirically shown to be significant for
- * certain workloads (e.g. creating many empty directories). As
- * such, we use the original calculation for adjustmnt, and
- * simply decrement the amount of data evicted from the MRU.
- */
-
- if (adjustmnt > 0 &&
- zfs_refcount_count(&arc_mfu->arcs_esize[type]) > 0) {
- delta = MIN(zfs_refcount_count(&arc_mfu->arcs_esize[type]),
- adjustmnt);
- total_evicted += arc_evict_impl(arc_mfu, 0, delta, type);
- }
-
- adjustmnt = meta_used - arc_meta_limit;
-
- if (adjustmnt > 0 &&
- zfs_refcount_count(&arc_mru_ghost->arcs_esize[type]) > 0) {
- delta = MIN(adjustmnt,
- zfs_refcount_count(&arc_mru_ghost->arcs_esize[type]));
- total_evicted += arc_evict_impl(arc_mru_ghost, 0, delta, type);
- adjustmnt -= delta;
- }
-
- if (adjustmnt > 0 &&
- zfs_refcount_count(&arc_mfu_ghost->arcs_esize[type]) > 0) {
- delta = MIN(adjustmnt,
- zfs_refcount_count(&arc_mfu_ghost->arcs_esize[type]));
- total_evicted += arc_evict_impl(arc_mfu_ghost, 0, delta, type);
- }
-
- /*
- * If after attempting to make the requested adjustment to the ARC
- * the meta limit is still being exceeded then request that the
- * higher layers drop some cached objects which have holds on ARC
- * 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 (type == ARC_BUFC_DATA) {
- type = ARC_BUFC_METADATA;
- } else {
- type = ARC_BUFC_DATA;
-
- if (zfs_arc_meta_prune) {
- prune += zfs_arc_meta_prune;
- arc_prune_async(prune);
- }
- }
-
- if (restarts > 0) {
- restarts--;
- goto restart;
- }
- }
- return (total_evicted);
-}
-
-/*
- * Evict metadata buffers from the cache, such that arcstat_meta_used is
- * capped by the arc_meta_limit tunable.
- */
-static uint64_t
-arc_evict_meta_only(uint64_t meta_used)
-{
- uint64_t total_evicted = 0;
- int64_t target;
-
- /*
- * If we're over the meta limit, we want to evict enough
- * metadata to get back under the meta limit. We don't want to
- * evict so much that we drop the MRU below arc_p, though. If
- * we're over the meta limit more than we're over arc_p, we
- * evict some from the MRU here, and some from the MFU below.
- */
- target = MIN((int64_t)(meta_used - arc_meta_limit),
- (int64_t)(zfs_refcount_count(&arc_anon->arcs_size) +
- zfs_refcount_count(&arc_mru->arcs_size) - arc_p));
-
- total_evicted += arc_evict_impl(arc_mru, 0, target, ARC_BUFC_METADATA);
-
- /*
- * Similar to the above, we want to evict enough bytes to get us
- * below the meta limit, but not so much as to drop us below the
- * space allotted to the MFU (which is defined as arc_c - arc_p).
- */
- target = MIN((int64_t)(meta_used - arc_meta_limit),
- (int64_t)(zfs_refcount_count(&arc_mfu->arcs_size) -
- (arc_c - arc_p)));
-
- total_evicted += arc_evict_impl(arc_mfu, 0, target, ARC_BUFC_METADATA);
-
- return (total_evicted);
-}
-
-static uint64_t
-arc_evict_meta(uint64_t meta_used)
-{
- if (zfs_arc_meta_strategy == ARC_STRATEGY_META_ONLY)
- return (arc_evict_meta_only(meta_used));
- else
- return (arc_evict_meta_balanced(meta_used));
-}
-
-/*
- * Return the type of the oldest buffer in the given arc state
- *
- * This function will select a random sublist of type ARC_BUFC_DATA and
- * a random sublist of type ARC_BUFC_METADATA. The tail of each sublist
- * is compared, and the type which contains the "older" buffer will be
- * returned.
- */
-static arc_buf_contents_t
-arc_evict_type(arc_state_t *state)
-{
- multilist_t *data_ml = &state->arcs_list[ARC_BUFC_DATA];
- multilist_t *meta_ml = &state->arcs_list[ARC_BUFC_METADATA];
- int data_idx = multilist_get_random_index(data_ml);
- int meta_idx = multilist_get_random_index(meta_ml);
- multilist_sublist_t *data_mls;
- multilist_sublist_t *meta_mls;
- arc_buf_contents_t type;
- arc_buf_hdr_t *data_hdr;
- arc_buf_hdr_t *meta_hdr;
+ if (total < 8 || up + down == 0)
+ return (frac);
/*
- * We keep the sublist lock until we're finished, to prevent
- * the headers from being destroyed via arc_evict_state().
+ * We should not have more ghost hits than ghost size, but they
+ * may get close. Restrict maximum adjustment in that case.
*/
- data_mls = multilist_sublist_lock(data_ml, data_idx);
- meta_mls = multilist_sublist_lock(meta_ml, meta_idx);
-
- /*
- * These two loops are to ensure we skip any markers that
- * might be at the tail of the lists due to arc_evict_state().
- */
-
- for (data_hdr = multilist_sublist_tail(data_mls); data_hdr != NULL;
- data_hdr = multilist_sublist_prev(data_mls, data_hdr)) {
- if (data_hdr->b_spa != 0)
- break;
+ if (up + down >= total / 4) {
+ uint64_t scale = (up + down) / (total / 8);
+ up /= scale;
+ down /= scale;
}
- for (meta_hdr = multilist_sublist_tail(meta_mls); meta_hdr != NULL;
- meta_hdr = multilist_sublist_prev(meta_mls, meta_hdr)) {
- if (meta_hdr->b_spa != 0)
- break;
- }
-
- if (data_hdr == NULL && meta_hdr == NULL) {
- type = ARC_BUFC_DATA;
- } else if (data_hdr == NULL) {
- ASSERT3P(meta_hdr, !=, NULL);
- type = ARC_BUFC_METADATA;
- } else if (meta_hdr == NULL) {
- ASSERT3P(data_hdr, !=, NULL);
- type = ARC_BUFC_DATA;
- } else {
- ASSERT3P(data_hdr, !=, NULL);
- ASSERT3P(meta_hdr, !=, NULL);
-
- /* The headers can't be on the sublist without an L1 header */
- ASSERT(HDR_HAS_L1HDR(data_hdr));
- ASSERT(HDR_HAS_L1HDR(meta_hdr));
+ /* Get maximal dynamic range by choosing optimal shifts. */
+ int s = highbit64(total);
+ s = MIN(64 - s, 32);
- if (data_hdr->b_l1hdr.b_arc_access <
- meta_hdr->b_l1hdr.b_arc_access) {
- type = ARC_BUFC_DATA;
- } else {
- type = ARC_BUFC_METADATA;
- }
- }
+ uint64_t ofrac = (1ULL << 32) - frac;
- multilist_sublist_unlock(meta_mls);
- multilist_sublist_unlock(data_mls);
+ if (frac >= 4 * ofrac)
+ up /= frac / (2 * ofrac + 1);
+ up = (up << s) / (total >> (32 - s));
+ if (ofrac >= 4 * frac)
+ down /= ofrac / (2 * frac + 1);
+ down = (down << s) / (total >> (32 - s));
+ down = down * 100 / balance;
- return (type);
+ return (frac + up - down);
}
/*
@@ -4616,150 +4241,128 @@ arc_evict_type(arc_state_t *state)
static uint64_t
arc_evict(void)
{
- uint64_t total_evicted = 0;
- uint64_t bytes;
- int64_t target;
- uint64_t asize = aggsum_value(&arc_sums.arcstat_size);
- uint64_t ameta = aggsum_value(&arc_sums.arcstat_meta_used);
-
- /*
- * If we're over arc_meta_limit, we want to correct that before
- * potentially evicting data buffers below.
- */
- total_evicted += arc_evict_meta(ameta);
+ uint64_t asize, bytes, total_evicted = 0;
+ int64_t e, mrud, mrum, mfud, mfum, w;
+ static uint64_t ogrd, ogrm, ogfd, ogfm;
+ static uint64_t gsrd, gsrm, gsfd, gsfm;
+ uint64_t ngrd, ngrm, ngfd, ngfm;
+
+ /* Get current size of ARC states we can evict from. */
+ mrud = zfs_refcount_count(&arc_mru->arcs_size[ARC_BUFC_DATA]) +
+ zfs_refcount_count(&arc_anon->arcs_size[ARC_BUFC_DATA]);
+ mrum = zfs_refcount_count(&arc_mru->arcs_size[ARC_BUFC_METADATA]) +
+ zfs_refcount_count(&arc_anon->arcs_size[ARC_BUFC_METADATA]);
+ mfud = zfs_refcount_count(&arc_mfu->arcs_size[ARC_BUFC_DATA]);
+ mfum = zfs_refcount_count(&arc_mfu->arcs_size[ARC_BUFC_METADATA]);
+ uint64_t d = mrud + mfud;
+ uint64_t m = mrum + mfum;
+ uint64_t t = d + m;
+
+ /* Get ARC ghost hits since last eviction. */
+ ngrd = wmsum_value(&arc_mru_ghost->arcs_hits[ARC_BUFC_DATA]);
+ uint64_t grd = ngrd - ogrd;
+ ogrd = ngrd;
+ ngrm = wmsum_value(&arc_mru_ghost->arcs_hits[ARC_BUFC_METADATA]);
+ uint64_t grm = ngrm - ogrm;
+ ogrm = ngrm;
+ ngfd = wmsum_value(&arc_mfu_ghost->arcs_hits[ARC_BUFC_DATA]);
+ uint64_t gfd = ngfd - ogfd;
+ ogfd = ngfd;
+ ngfm = wmsum_value(&arc_mfu_ghost->arcs_hits[ARC_BUFC_METADATA]);
+ uint64_t gfm = ngfm - ogfm;
+ ogfm = ngfm;
+
+ /* Adjust ARC states balance based on ghost hits. */
+ arc_meta = arc_evict_adj(arc_meta, gsrd + gsrm + gsfd + gsfm,
+ grm + gfm, grd + gfd, zfs_arc_meta_balance);
+ arc_pd = arc_evict_adj(arc_pd, gsrd + gsfd, grd, gfd, 100);
+ arc_pm = arc_evict_adj(arc_pm, gsrm + gsfm, grm, gfm, 100);
- /*
- * Adjust MRU size
- *
- * If we're over the target cache size, we want to evict enough
- * from the list to get back to our target size. We don't want
- * to evict too much from the MRU, such that it drops below
- * arc_p. So, if we're over our target cache size more than
- * the MRU is over arc_p, we'll evict enough to get back to
- * arc_p here, and then evict more from the MFU below.
- */
- target = MIN((int64_t)(asize - arc_c),
- (int64_t)(zfs_refcount_count(&arc_anon->arcs_size) +
- zfs_refcount_count(&arc_mru->arcs_size) + ameta - arc_p));
-
- /*
- * If we're below arc_meta_min, always prefer to evict data.
- * Otherwise, try to satisfy the requested number of bytes to
- * evict from the type which contains older buffers; in an
- * effort to keep newer buffers in the cache regardless of their
- * type. If we cannot satisfy the number of bytes from this
- * type, spill over into the next type.
- */
- if (arc_evict_type(arc_mru) == ARC_BUFC_METADATA &&
- ameta > arc_meta_min) {
- bytes = arc_evict_impl(arc_mru, 0, target, ARC_BUFC_METADATA);
- total_evicted += bytes;
-
- /*
- * If we couldn't evict our target number of bytes from
- * metadata, we try to get the rest from data.
- */
- target -= bytes;
-
- total_evicted +=
- arc_evict_impl(arc_mru, 0, target, ARC_BUFC_DATA);
- } else {
- bytes = arc_evict_impl(arc_mru, 0, target, ARC_BUFC_DATA);
- total_evicted += bytes;
-
- /*
- * If we couldn't evict our target number of bytes from
- * data, we try to get the rest from metadata.
- */
- target -= bytes;
-
- total_evicted +=
- arc_evict_impl(arc_mru, 0, target, ARC_BUFC_METADATA);
- }
-
- /*
- * Re-sum ARC stats after the first round of evictions.
- */
asize = aggsum_value(&arc_sums.arcstat_size);
- ameta = aggsum_value(&arc_sums.arcstat_meta_used);
-
-
- /*
- * Adjust MFU size
- *
- * Now that we've tried to evict enough from the MRU to get its
- * size back to arc_p, if we're still above the target cache
- * size, we evict the rest from the MFU.
- */
- target = asize - arc_c;
-
- if (arc_evict_type(arc_mfu) == ARC_BUFC_METADATA &&
- ameta > arc_meta_min) {
- bytes = arc_evict_impl(arc_mfu, 0, target, ARC_BUFC_METADATA);
- total_evicted += bytes;
-
- /*
- * If we couldn't evict our target number of bytes from
- * metadata, we try to get the rest from data.
- */
- target -= bytes;
-
- total_evicted +=
- arc_evict_impl(arc_mfu, 0, target, ARC_BUFC_DATA);
- } else {
- bytes = arc_evict_impl(arc_mfu, 0, target, ARC_BUFC_DATA);
- total_evicted += bytes;
-
- /*
- * If we couldn't evict our target number of bytes from
- * data, we try to get the rest from data.
- */
- target -= bytes;
-
- total_evicted +=
- arc_evict_impl(arc_mfu, 0, target, ARC_BUFC_METADATA);
- }
-
- /*
- * Adjust ghost lists
- *
- * In addition to the above, the ARC also defines target values
- * for the ghost lists. The sum of the mru list and mru ghost
- * list should never exceed the target size of the cache, and
- * the sum of the mru list, mfu list, mru ghost list, and mfu
- * ghost list should never exceed twice the target size of the
- * cache. The following logic enforces these limits on the ghost
- * caches, and evicts from them as needed.
- */
- target = zfs_refcount_count(&arc_mru->arcs_size) +
- zfs_refcount_count(&arc_mru_ghost->arcs_size) - arc_c;
-
- bytes = arc_evict_impl(arc_mru_ghost, 0, target, ARC_BUFC_DATA);
+ int64_t wt = t - (asize - arc_c);
+
+ /*
+ * Try to reduce pinned dnodes if more than 3/4 of wanted metadata
+ * target is not evictable or if they go over arc_dnode_limit.
+ */
+ int64_t prune = 0;
+ int64_t dn = wmsum_value(&arc_sums.arcstat_dnode_size);
+ w = wt * (int64_t)(arc_meta >> 16) >> 16;
+ if (zfs_refcount_count(&arc_mru->arcs_size[ARC_BUFC_METADATA]) +
+ zfs_refcount_count(&arc_mfu->arcs_size[ARC_BUFC_METADATA]) -
+ zfs_refcount_count(&arc_mru->arcs_esize[ARC_BUFC_METADATA]) -
+ zfs_refcount_count(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]) >
+ w * 3 / 4) {
+ prune = dn / sizeof (dnode_t) *
+ zfs_arc_dnode_reduce_percent / 100;
+ } else if (dn > arc_dnode_limit) {
+ prune = (dn - arc_dnode_limit) / sizeof (dnode_t) *
+ zfs_arc_dnode_reduce_percent / 100;
+ }
+ if (prune > 0)
+ arc_prune_async(prune);
+
+ /* Evict MRU metadata. */
+ w = wt * (int64_t)(arc_meta * arc_pm >> 48) >> 16;
+ e = MIN((int64_t)(asize - arc_c), (int64_t)(mrum - w));
+ bytes = arc_evict_impl(arc_mru, ARC_BUFC_METADATA, e);
total_evicted += bytes;
+ mrum -= bytes;
+ asize -= bytes;
- target -= bytes;
+ /* Evict MFU metadata. */
+ w = wt * (int64_t)(arc_meta >> 16) >> 16;
+ e = MIN((int64_t)(asize - arc_c), (int64_t)(m - w));
+ bytes = arc_evict_impl(arc_mfu, ARC_BUFC_METADATA, e);
+ total_evicted += bytes;
+ mfum -= bytes;
+ asize -= bytes;
+
+ /* Evict MRU data. */
+ wt -= m - total_evicted;
+ w = wt * (int64_t)(arc_pd >> 16) >> 16;
+ e = MIN((int64_t)(asize - arc_c), (int64_t)(mrud - w));
+ bytes = arc_evict_impl(arc_mru, ARC_BUFC_DATA, e);
+ total_evicted += bytes;
+ mrud -= bytes;
+ asize -= bytes;
- total_evicted +=
- arc_evict_impl(arc_mru_ghost, 0, target, ARC_BUFC_METADATA);
+ /* Evict MFU data. */
+ e = asize - arc_c;
+ bytes = arc_evict_impl(arc_mfu, ARC_BUFC_DATA, e);
+ mfud -= bytes;
+ total_evicted += bytes;
/*
- * We assume the sum of the mru list and mfu list is less than
- * or equal to arc_c (we enforced this above), which means we
- * can use the simpler of the two equations below:
+ * Evict ghost lists
*
- * mru + mfu + mru ghost + mfu ghost <= 2 * arc_c
- * mru ghost + mfu ghost <= arc_c
- */
- target = zfs_refcount_count(&arc_mru_ghost->arcs_size) +
- zfs_refcount_count(&arc_mfu_ghost->arcs_size) - arc_c;
-
- bytes = arc_evict_impl(arc_mfu_ghost, 0, target, ARC_BUFC_DATA);
- total_evicted += bytes;
-
- target -= bytes;
-
- total_evicted +=
- arc_evict_impl(arc_mfu_ghost, 0, target, ARC_BUFC_METADATA);
+ * Size of each state's ghost list represents how much that state
+ * may grow by shrinking the other states. Would it need to shrink
+ * other states to zero (that is unlikely), its ghost size would be
+ * equal to sum of other three state sizes. But excessive ghost
+ * size may result in false ghost hits (too far back), that may
+ * never result in real cache hits if several states are competing.
+ * So choose some arbitraty point of 1/2 of other state sizes.
+ */
+ gsrd = (mrum + mfud + mfum) / 2;
+ e = zfs_refcount_count(&arc_mru_ghost->arcs_size[ARC_BUFC_DATA]) -
+ gsrd;
+ (void) arc_evict_impl(arc_mru_ghost, ARC_BUFC_DATA, e);
+
+ gsrm = (mrud + mfud + mfum) / 2;
+ e = zfs_refcount_count(&arc_mru_ghost->arcs_size[ARC_BUFC_METADATA]) -
+ gsrm;
+ (void) arc_evict_impl(arc_mru_ghost, ARC_BUFC_METADATA, e);
+
+ gsfd = (mrud + mrum + mfum) / 2;
+ e = zfs_refcount_count(&arc_mfu_ghost->arcs_size[ARC_BUFC_DATA]) -
+ gsfd;
+ (void) arc_evict_impl(arc_mfu_ghost, ARC_BUFC_DATA, e);
+
+ gsfm = (mrud + mrum + mfud) / 2;
+ e = zfs_refcount_count(&arc_mfu_ghost->arcs_size[ARC_BUFC_METADATA]) -
+ gsfm;
+ (void) arc_evict_impl(arc_mfu_ghost, ARC_BUFC_METADATA, e);
return (total_evicted);
}
@@ -4774,7 +4377,7 @@ arc_flush(spa_t *spa, boolean_t retry)
* no good way to determine if all of a spa's buffers have been
* evicted from an arc state.
*/
- ASSERT(!retry || spa == 0);
+ ASSERT(!retry || spa == NULL);
if (spa != NULL)
guid = spa_load_guid(spa);
@@ -4790,12 +4393,18 @@ arc_flush(spa_t *spa, boolean_t retry)
(void) arc_flush_state(arc_mfu_ghost, guid, ARC_BUFC_DATA, retry);
(void) arc_flush_state(arc_mfu_ghost, guid, ARC_BUFC_METADATA, retry);
+
+ (void) arc_flush_state(arc_uncached, guid, ARC_BUFC_DATA, retry);
+ (void) arc_flush_state(arc_uncached, guid, ARC_BUFC_METADATA, retry);
}
void
arc_reduce_target_size(int64_t to_free)
{
- uint64_t asize = aggsum_value(&arc_sums.arcstat_size);
+ uint64_t c = arc_c;
+
+ if (c <= arc_c_min)
+ return;
/*
* All callers want the ARC to actually evict (at least) this much
@@ -4805,26 +4414,16 @@ arc_reduce_target_size(int64_t to_free)
* immediately have arc_c < arc_size and therefore the arc_evict_zthr
* will evict.
*/
- uint64_t c = MIN(arc_c, asize);
-
- if (c > to_free && c - to_free > arc_c_min) {
- arc_c = c - to_free;
- atomic_add_64(&arc_p, -(arc_p >> arc_shrink_shift));
- if (arc_p > arc_c)
- arc_p = (arc_c >> 1);
- ASSERT(arc_c >= arc_c_min);
- ASSERT((int64_t)arc_p >= 0);
- } else {
- arc_c = arc_c_min;
- }
+ uint64_t asize = aggsum_value(&arc_sums.arcstat_size);
+ if (asize < c)
+ to_free += c - asize;
+ arc_c = MAX((int64_t)c - to_free, (int64_t)arc_c_min);
- if (asize > arc_c) {
- /* See comment in arc_evict_cb_check() on why lock+flag */
- mutex_enter(&arc_evict_lock);
- arc_evict_needed = B_TRUE;
- mutex_exit(&arc_evict_lock);
- zthr_wakeup(arc_evict_zthr);
- }
+ /* See comment in arc_evict_cb_check() on why lock+flag */
+ mutex_enter(&arc_evict_lock);
+ arc_evict_needed = B_TRUE;
+ mutex_exit(&arc_evict_lock);
+ zthr_wakeup(arc_evict_zthr);
}
/*
@@ -4846,14 +4445,6 @@ arc_kmem_reap_soon(void)
kmem_cache_t *prev_data_cache = NULL;
#ifdef _KERNEL
- if ((aggsum_compare(&arc_sums.arcstat_meta_used,
- arc_meta_limit) >= 0) && zfs_arc_meta_prune) {
- /*
- * We are exceeding our meta-data cache limit.
- * Prune some entries to release holds on meta-data.
- */
- arc_prune_async(zfs_arc_meta_prune);
- }
#if defined(_ILP32)
/*
* Reclaim unused memory from all kmem caches.
@@ -4921,7 +4512,16 @@ arc_evict_cb_check(void *arg, zthr_t *zthr)
* which is held before this function is called, and is held by
* arc_wait_for_eviction() when it calls zthr_wakeup().
*/
- return (arc_evict_needed);
+ if (arc_evict_needed)
+ return (B_TRUE);
+
+ /*
+ * If we have buffers in uncached state, evict them periodically.
+ */
+ return ((zfs_refcount_count(&arc_uncached->arcs_esize[ARC_BUFC_DATA]) +
+ zfs_refcount_count(&arc_uncached->arcs_esize[ARC_BUFC_METADATA]) &&
+ ddi_get_lbolt() - arc_last_uncached_flush >
+ MSEC_TO_TICK(arc_min_prefetch_ms / 2)));
}
/*
@@ -4931,13 +4531,19 @@ arc_evict_cb_check(void *arg, zthr_t *zthr)
static void
arc_evict_cb(void *arg, zthr_t *zthr)
{
- (void) arg, (void) zthr;
+ (void) arg;
uint64_t evicted = 0;
fstrans_cookie_t cookie = spl_fstrans_mark();
- /* Evict from cache */
- evicted = arc_evict();
+ /* Always try to evict from uncached state. */
+ arc_last_uncached_flush = ddi_get_lbolt();
+ evicted += arc_flush_state(arc_uncached, 0, ARC_BUFC_DATA, B_FALSE);
+ evicted += arc_flush_state(arc_uncached, 0, ARC_BUFC_METADATA, B_FALSE);
+
+ /* Evict from other states only if told to. */
+ if (arc_evict_needed)
+ evicted += arc_evict();
/*
* If evicted is zero, we couldn't evict anything
@@ -4949,9 +4555,13 @@ arc_evict_cb(void *arg, zthr_t *zthr)
* infinite loop. Additionally, zthr_iscancelled() is
* checked here so that if the arc is shutting down, the
* broadcast will wake any remaining arc evict waiters.
+ *
+ * Note we cancel using zthr instead of arc_evict_zthr
+ * because the latter may not yet be initializd when the
+ * callback is first invoked.
*/
mutex_enter(&arc_evict_lock);
- arc_evict_needed = !zthr_iscancelled(arc_evict_zthr) &&
+ arc_evict_needed = !zthr_iscancelled(zthr) &&
evicted > 0 && aggsum_compare(&arc_sums.arcstat_size, arc_c) > 0;
if (!arc_evict_needed) {
/*
@@ -5051,10 +4661,11 @@ arc_reap_cb(void *arg, zthr_t *zthr)
*/
free_memory = arc_available_memory();
- int64_t to_free =
- (arc_c >> arc_shrink_shift) - free_memory;
- if (to_free > 0) {
- arc_reduce_target_size(to_free);
+ int64_t can_free = arc_c - arc_c_min;
+ if (can_free > 0) {
+ int64_t to_free = (can_free >> arc_shrink_shift) - free_memory;
+ if (to_free > 0)
+ arc_reduce_target_size(to_free);
}
spl_fstrans_unmark(cookie);
}
@@ -5114,40 +4725,8 @@ arc_reap_cb(void *arg, zthr_t *zthr)
* when we are adding new content to the cache.
*/
static void
-arc_adapt(int bytes, arc_state_t *state)
+arc_adapt(uint64_t bytes)
{
- int mult;
- uint64_t arc_p_min = (arc_c >> arc_p_min_shift);
- int64_t mrug_size = zfs_refcount_count(&arc_mru_ghost->arcs_size);
- int64_t mfug_size = zfs_refcount_count(&arc_mfu_ghost->arcs_size);
-
- ASSERT(bytes > 0);
- /*
- * Adapt the target size of the MRU list:
- * - if we just hit in the MRU ghost list, then increase
- * the target size of the MRU list.
- * - if we just hit in the MFU ghost list, then increase
- * the target size of the MFU list by decreasing the
- * target size of the MRU list.
- */
- if (state == arc_mru_ghost) {
- mult = (mrug_size >= mfug_size) ? 1 : (mfug_size / mrug_size);
- if (!zfs_arc_p_dampener_disable)
- mult = MIN(mult, 10); /* avoid wild arc_p adjustment */
-
- arc_p = MIN(arc_c - arc_p_min, arc_p + bytes * mult);
- } else if (state == arc_mfu_ghost) {
- uint64_t delta;
-
- mult = (mfug_size >= mrug_size) ? 1 : (mrug_size / mfug_size);
- if (!zfs_arc_p_dampener_disable)
- mult = MIN(mult, 10);
-
- delta = MIN(bytes * mult, arc_p);
- arc_p = MAX(arc_p_min, arc_p - delta);
- }
- ASSERT((int64_t)arc_p >= 0);
-
/*
* Wake reap thread if we do not have any available memory
*/
@@ -5166,18 +4745,12 @@ arc_adapt(int bytes, arc_state_t *state)
* If we're within (2 * maxblocksize) bytes of the target
* cache size, increment the target cache size
*/
- ASSERT3U(arc_c, >=, 2ULL << SPA_MAXBLOCKSHIFT);
- if (aggsum_upper_bound(&arc_sums.arcstat_size) >=
- arc_c - (2ULL << SPA_MAXBLOCKSHIFT)) {
- atomic_add_64(&arc_c, (int64_t)bytes);
- if (arc_c > arc_c_max)
+ if (aggsum_upper_bound(&arc_sums.arcstat_size) +
+ 2 * SPA_MAXBLOCKSIZE >= arc_c) {
+ uint64_t dc = MAX(bytes, SPA_OLD_MAXBLOCKSIZE);
+ if (atomic_add_64_nv(&arc_c, dc) > arc_c_max)
arc_c = arc_c_max;
- else if (state == arc_anon)
- atomic_add_64(&arc_p, (int64_t)bytes);
- if (arc_p > arc_c)
- arc_p = arc_c;
}
- ASSERT((int64_t)arc_p >= 0);
}
/*
@@ -5215,12 +4788,10 @@ arc_get_data_abd(arc_buf_hdr_t *hdr, uint64_t size, const void *tag,
arc_buf_contents_t type = arc_buf_type(hdr);
arc_get_data_impl(hdr, size, tag, alloc_flags);
- if (type == ARC_BUFC_METADATA) {
- return (abd_alloc(size, B_TRUE));
- } else {
- ASSERT(type == ARC_BUFC_DATA);
- return (abd_alloc(size, B_FALSE));
- }
+ if (alloc_flags & ARC_HDR_ALLOC_LINEAR)
+ return (abd_alloc_linear(size, type == ARC_BUFC_METADATA));
+ else
+ return (abd_alloc(size, type == ARC_BUFC_METADATA));
}
static void *
@@ -5228,7 +4799,7 @@ arc_get_data_buf(arc_buf_hdr_t *hdr, uint64_t size, const void *tag)
{
arc_buf_contents_t type = arc_buf_type(hdr);
- arc_get_data_impl(hdr, size, tag, ARC_HDR_DO_ADAPT);
+ arc_get_data_impl(hdr, size, tag, 0);
if (type == ARC_BUFC_METADATA) {
return (zio_buf_alloc(size));
} else {
@@ -5326,11 +4897,7 @@ static void
arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag,
int alloc_flags)
{
- arc_state_t *state = hdr->b_l1hdr.b_state;
- arc_buf_contents_t type = arc_buf_type(hdr);
-
- if (alloc_flags & ARC_HDR_DO_ADAPT)
- arc_adapt(size, state);
+ arc_adapt(size);
/*
* If arc_size is currently overflowing, we must be adding data
@@ -5348,7 +4915,7 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag,
arc_wait_for_eviction(size * zfs_arc_eviction_pct / 100,
alloc_flags & ARC_HDR_USE_RESERVE);
- VERIFY3U(hdr->b_type, ==, type);
+ arc_buf_contents_t type = arc_buf_type(hdr);
if (type == ARC_BUFC_METADATA) {
arc_space_consume(size, ARC_SPACE_META);
} else {
@@ -5359,9 +4926,11 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag,
* Update the state size. Note that ghost states have a
* "ghost size" and so don't need to be updated.
*/
+ arc_state_t *state = hdr->b_l1hdr.b_state;
if (!GHOST_STATE(state)) {
- (void) zfs_refcount_add_many(&state->arcs_size, size, tag);
+ (void) zfs_refcount_add_many(&state->arcs_size[type], size,
+ tag);
/*
* If this is reached via arc_read, the link is
@@ -5377,16 +4946,6 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag,
(void) zfs_refcount_add_many(&state->arcs_esize[type],
size, tag);
}
-
- /*
- * If we are growing the cache, and we are adding anonymous
- * data, and we have outgrown arc_p, update arc_p
- */
- 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))
- arc_p = MIN(arc_c, arc_p + size);
}
}
@@ -5429,7 +4988,7 @@ arc_free_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag)
(void) zfs_refcount_remove_many(&state->arcs_esize[type],
size, tag);
}
- (void) zfs_refcount_remove_many(&state->arcs_size, size, tag);
+ (void) zfs_refcount_remove_many(&state->arcs_size[type], size, tag);
VERIFY3U(hdr->b_type, ==, type);
if (type == ARC_BUFC_METADATA) {
@@ -5442,150 +5001,155 @@ arc_free_data_impl(arc_buf_hdr_t *hdr, uint64_t size, const void *tag)
/*
* This routine is called whenever a buffer is accessed.
- * NOTE: the hash lock is dropped in this function.
*/
static void
-arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
+arc_access(arc_buf_hdr_t *hdr, arc_flags_t arc_flags, boolean_t hit)
{
- clock_t now;
-
- ASSERT(MUTEX_HELD(hash_lock));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)));
ASSERT(HDR_HAS_L1HDR(hdr));
+ /*
+ * Update buffer prefetch status.
+ */
+ boolean_t was_prefetch = HDR_PREFETCH(hdr);
+ boolean_t now_prefetch = arc_flags & ARC_FLAG_PREFETCH;
+ if (was_prefetch != now_prefetch) {
+ if (was_prefetch) {
+ ARCSTAT_CONDSTAT(hit, demand_hit, demand_iohit,
+ HDR_PRESCIENT_PREFETCH(hdr), prescient, predictive,
+ prefetch);
+ }
+ if (HDR_HAS_L2HDR(hdr))
+ l2arc_hdr_arcstats_decrement_state(hdr);
+ if (was_prefetch) {
+ arc_hdr_clear_flags(hdr,
+ ARC_FLAG_PREFETCH | ARC_FLAG_PRESCIENT_PREFETCH);
+ } else {
+ arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);
+ }
+ if (HDR_HAS_L2HDR(hdr))
+ l2arc_hdr_arcstats_increment_state(hdr);
+ }
+ if (now_prefetch) {
+ if (arc_flags & ARC_FLAG_PRESCIENT_PREFETCH) {
+ arc_hdr_set_flags(hdr, ARC_FLAG_PRESCIENT_PREFETCH);
+ ARCSTAT_BUMP(arcstat_prescient_prefetch);
+ } else {
+ ARCSTAT_BUMP(arcstat_predictive_prefetch);
+ }
+ }
+ if (arc_flags & ARC_FLAG_L2CACHE)
+ arc_hdr_set_flags(hdr, ARC_FLAG_L2CACHE);
+
+ clock_t now = ddi_get_lbolt();
if (hdr->b_l1hdr.b_state == arc_anon) {
+ arc_state_t *new_state;
/*
- * This buffer is not in the cache, and does not
- * appear in our "ghost" list. Add the new buffer
- * to the MRU state.
+ * This buffer is not in the cache, and does not appear in
+ * our "ghost" lists. Add it to the MRU or uncached state.
*/
-
ASSERT0(hdr->b_l1hdr.b_arc_access);
- hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
- DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
- arc_change_state(arc_mru, hdr, hash_lock);
-
+ hdr->b_l1hdr.b_arc_access = now;
+ if (HDR_UNCACHED(hdr)) {
+ new_state = arc_uncached;
+ DTRACE_PROBE1(new_state__uncached, arc_buf_hdr_t *,
+ hdr);
+ } else {
+ new_state = arc_mru;
+ DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
+ }
+ arc_change_state(new_state, hdr);
} else if (hdr->b_l1hdr.b_state == arc_mru) {
- now = ddi_get_lbolt();
+ /*
+ * This buffer has been accessed once recently and either
+ * its read is still in progress or it is in the cache.
+ */
+ if (HDR_IO_IN_PROGRESS(hdr)) {
+ hdr->b_l1hdr.b_arc_access = now;
+ return;
+ }
+ hdr->b_l1hdr.b_mru_hits++;
+ ARCSTAT_BUMP(arcstat_mru_hits);
/*
- * If this buffer is here because of a prefetch, then either:
- * - clear the flag if this is a "referencing" read
- * (any subsequent access will bump this into the MFU state).
- * or
- * - move the buffer to the head of the list if this is
- * another prefetch (to make it less likely to be evicted).
+ * If the previous access was a prefetch, then it already
+ * handled possible promotion, so nothing more to do for now.
*/
- if (HDR_PREFETCH(hdr) || HDR_PRESCIENT_PREFETCH(hdr)) {
- if (zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
- /* link protected by hash lock */
- ASSERT(multilist_link_active(
- &hdr->b_l1hdr.b_arc_node));
- } else {
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_decrement_state(hdr);
- arc_hdr_clear_flags(hdr,
- ARC_FLAG_PREFETCH |
- ARC_FLAG_PRESCIENT_PREFETCH);
- hdr->b_l1hdr.b_mru_hits++;
- ARCSTAT_BUMP(arcstat_mru_hits);
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_increment_state(hdr);
- }
+ if (was_prefetch) {
hdr->b_l1hdr.b_arc_access = now;
return;
}
/*
- * This buffer has been "accessed" only once so far,
- * but it is still in the cache. Move it to the MFU
- * state.
+ * If more than ARC_MINTIME have passed from the previous
+ * hit, promote the buffer to the MFU state.
*/
if (ddi_time_after(now, hdr->b_l1hdr.b_arc_access +
ARC_MINTIME)) {
- /*
- * More than 125ms have passed since we
- * instantiated this buffer. Move it to the
- * most frequently used state.
- */
hdr->b_l1hdr.b_arc_access = now;
DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
- arc_change_state(arc_mfu, hdr, hash_lock);
+ arc_change_state(arc_mfu, hdr);
}
- hdr->b_l1hdr.b_mru_hits++;
- ARCSTAT_BUMP(arcstat_mru_hits);
} else if (hdr->b_l1hdr.b_state == arc_mru_ghost) {
arc_state_t *new_state;
/*
- * This buffer has been "accessed" recently, but
- * was evicted from the cache. Move it to the
- * MFU state.
+ * This buffer has been accessed once recently, but was
+ * evicted from the cache. Would we have bigger MRU, it
+ * would be an MRU hit, so handle it the same way, except
+ * we don't need to check the previous access time.
*/
- if (HDR_PREFETCH(hdr) || HDR_PRESCIENT_PREFETCH(hdr)) {
+ hdr->b_l1hdr.b_mru_ghost_hits++;
+ ARCSTAT_BUMP(arcstat_mru_ghost_hits);
+ hdr->b_l1hdr.b_arc_access = now;
+ wmsum_add(&arc_mru_ghost->arcs_hits[arc_buf_type(hdr)],
+ arc_hdr_size(hdr));
+ if (was_prefetch) {
new_state = arc_mru;
- if (zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) > 0) {
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_decrement_state(hdr);
- arc_hdr_clear_flags(hdr,
- ARC_FLAG_PREFETCH |
- ARC_FLAG_PRESCIENT_PREFETCH);
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_increment_state(hdr);
- }
DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
} else {
new_state = arc_mfu;
DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
}
-
- hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
- arc_change_state(new_state, hdr, hash_lock);
-
- hdr->b_l1hdr.b_mru_ghost_hits++;
- ARCSTAT_BUMP(arcstat_mru_ghost_hits);
+ arc_change_state(new_state, hdr);
} else if (hdr->b_l1hdr.b_state == arc_mfu) {
/*
- * This buffer has been accessed more than once and is
- * still in the cache. Keep it in the MFU state.
- *
- * NOTE: an add_reference() that occurred when we did
- * the arc_read() will have kicked this off the list.
- * If it was a prefetch, we will explicitly move it to
- * the head of the list now.
+ * This buffer has been accessed more than once and either
+ * still in the cache or being restored from one of ghosts.
*/
-
- hdr->b_l1hdr.b_mfu_hits++;
- ARCSTAT_BUMP(arcstat_mfu_hits);
- hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
+ if (!HDR_IO_IN_PROGRESS(hdr)) {
+ hdr->b_l1hdr.b_mfu_hits++;
+ ARCSTAT_BUMP(arcstat_mfu_hits);
+ }
+ hdr->b_l1hdr.b_arc_access = now;
} else if (hdr->b_l1hdr.b_state == arc_mfu_ghost) {
- arc_state_t *new_state = arc_mfu;
/*
- * This buffer has been accessed more than once but has
- * been evicted from the cache. Move it back to the
- * MFU state.
+ * This buffer has been accessed more than once recently, but
+ * has been evicted from the cache. Would we have bigger MFU
+ * it would stay in cache, so move it back to MFU state.
*/
-
- if (HDR_PREFETCH(hdr) || HDR_PRESCIENT_PREFETCH(hdr)) {
- /*
- * This is a prefetch access...
- * move this block back to the MRU state.
- */
- new_state = arc_mru;
- }
-
- hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
- DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
- arc_change_state(new_state, hdr, hash_lock);
-
hdr->b_l1hdr.b_mfu_ghost_hits++;
ARCSTAT_BUMP(arcstat_mfu_ghost_hits);
+ hdr->b_l1hdr.b_arc_access = now;
+ wmsum_add(&arc_mfu_ghost->arcs_hits[arc_buf_type(hdr)],
+ arc_hdr_size(hdr));
+ DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
+ arc_change_state(arc_mfu, hdr);
+ } else if (hdr->b_l1hdr.b_state == arc_uncached) {
+ /*
+ * This buffer is uncacheable, but we got a hit. Probably
+ * a demand read after prefetch. Nothing more to do here.
+ */
+ if (!HDR_IO_IN_PROGRESS(hdr))
+ ARCSTAT_BUMP(arcstat_uncached_hits);
+ hdr->b_l1hdr.b_arc_access = now;
} else if (hdr->b_l1hdr.b_state == arc_l2c_only) {
/*
- * This buffer is on the 2nd Level ARC.
+ * This buffer is on the 2nd Level ARC and was not accessed
+ * for a long time, so treat it as new and put into MRU.
*/
-
- hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
- DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
- arc_change_state(arc_mfu, hdr, hash_lock);
+ hdr->b_l1hdr.b_arc_access = now;
+ DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
+ arc_change_state(arc_mru, hdr);
} else {
cmn_err(CE_PANIC, "invalid arc state 0x%p",
hdr->b_l1hdr.b_state);
@@ -5599,7 +5163,6 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
void
arc_buf_access(arc_buf_t *buf)
{
- mutex_enter(&buf->b_evict_lock);
arc_buf_hdr_t *hdr = buf->b_hdr;
/*
@@ -5607,33 +5170,29 @@ arc_buf_access(arc_buf_t *buf)
* The header must be checked again under the hash_lock in order
* to handle the case where it is concurrently being released.
*/
- if (hdr->b_l1hdr.b_state == arc_anon || HDR_EMPTY(hdr)) {
- mutex_exit(&buf->b_evict_lock);
+ if (hdr->b_l1hdr.b_state == arc_anon || HDR_EMPTY(hdr))
return;
- }
kmutex_t *hash_lock = HDR_LOCK(hdr);
mutex_enter(hash_lock);
if (hdr->b_l1hdr.b_state == arc_anon || HDR_EMPTY(hdr)) {
mutex_exit(hash_lock);
- mutex_exit(&buf->b_evict_lock);
ARCSTAT_BUMP(arcstat_access_skip);
return;
}
- mutex_exit(&buf->b_evict_lock);
-
ASSERT(hdr->b_l1hdr.b_state == arc_mru ||
- hdr->b_l1hdr.b_state == arc_mfu);
+ hdr->b_l1hdr.b_state == arc_mfu ||
+ hdr->b_l1hdr.b_state == arc_uncached);
DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
- arc_access(hdr, hash_lock);
+ arc_access(hdr, 0, B_TRUE);
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_hits);
- ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr) && !HDR_PRESCIENT_PREFETCH(hdr),
- demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data, metadata, hits);
+ ARCSTAT_CONDSTAT(B_TRUE /* demand */, demand, prefetch,
+ !HDR_ISTYPE_METADATA(hdr), data, metadata, hits);
}
/* a generic arc_read_done_func_t which you can use */
@@ -5693,7 +5252,6 @@ arc_read_done(zio_t *zio)
kmutex_t *hash_lock = NULL;
arc_callback_t *callback_list;
arc_callback_t *acb;
- boolean_t freeable = B_FALSE;
/*
* The hdr was inserted into hash-table and removed from lists
@@ -5706,7 +5264,7 @@ arc_read_done(zio_t *zio)
if (HDR_IN_HASH_TABLE(hdr)) {
arc_buf_hdr_t *found;
- ASSERT3U(hdr->b_birth, ==, BP_PHYSICAL_BIRTH(zio->io_bp));
+ ASSERT3U(hdr->b_birth, ==, BP_GET_BIRTH(zio->io_bp));
ASSERT3U(hdr->b_dva.dva_word[0], ==,
BP_IDENTITY(zio->io_bp)->dva_word[0]);
ASSERT3U(hdr->b_dva.dva_word[1], ==,
@@ -5766,17 +5324,7 @@ arc_read_done(zio_t *zio)
callback_list = hdr->b_l1hdr.b_acb;
ASSERT3P(callback_list, !=, NULL);
-
- if (hash_lock && zio->io_error == 0 &&
- hdr->b_l1hdr.b_state == arc_anon) {
- /*
- * Only call arc_access on anonymous buffers. This is because
- * if we've issued an I/O for an evicted buffer, we've already
- * called arc_access (to prevent any simultaneous readers from
- * getting confused).
- */
- arc_access(hdr, hash_lock);
- }
+ hdr->b_l1hdr.b_acb = NULL;
/*
* If a read request has a callback (i.e. acb_done is not NULL), then we
@@ -5786,6 +5334,10 @@ arc_read_done(zio_t *zio)
*/
int callback_cnt = 0;
for (acb = callback_list; acb != NULL; acb = acb->acb_next) {
+
+ /* We need the last one to call below in original order. */
+ callback_list = acb;
+
if (!acb->acb_done || acb->acb_nobuf)
continue;
@@ -5814,7 +5366,8 @@ arc_read_done(zio_t *zio)
ASSERT(BP_IS_PROTECTED(bp));
error = SET_ERROR(EIO);
if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) {
- spa_log_error(zio->io_spa, &acb->acb_zb);
+ spa_log_error(zio->io_spa, &acb->acb_zb,
+ BP_GET_LOGICAL_BIRTH(zio->io_bp));
(void) zfs_ereport_post(
FM_EREPORT_ZFS_AUTHENTICATION,
zio->io_spa, NULL, &acb->acb_zb, zio, 0);
@@ -5849,44 +5402,21 @@ arc_read_done(zio_t *zio)
*/
ASSERT(callback_cnt < 2 || hash_lock != NULL);
- hdr->b_l1hdr.b_acb = NULL;
- arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
- if (callback_cnt == 0)
- ASSERT(hdr->b_l1hdr.b_pabd != NULL || HDR_HAS_RABD(hdr));
-
- ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt) ||
- callback_list != NULL);
-
if (zio->io_error == 0) {
arc_hdr_verify(hdr, zio->io_bp);
} else {
arc_hdr_set_flags(hdr, ARC_FLAG_IO_ERROR);
if (hdr->b_l1hdr.b_state != arc_anon)
- arc_change_state(arc_anon, hdr, hash_lock);
+ arc_change_state(arc_anon, hdr);
if (HDR_IN_HASH_TABLE(hdr))
buf_hash_remove(hdr);
- freeable = zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
}
- /*
- * Broadcast before we drop the hash_lock to avoid the possibility
- * that the hdr (and hence the cv) might be freed before we get to
- * the cv_broadcast().
- */
- cv_broadcast(&hdr->b_l1hdr.b_cv);
+ arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
+ (void) remove_reference(hdr, hdr);
- if (hash_lock != NULL) {
+ if (hash_lock != NULL)
mutex_exit(hash_lock);
- } else {
- /*
- * This block was freed while we waited for the read to
- * complete. It has been removed from the hash table and
- * moved to the anonymous state (so that it won't show up
- * in the cache).
- */
- ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
- freeable = zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
- }
/* execute each callback and free its structure */
while ((acb = callback_list) != NULL) {
@@ -5910,12 +5440,18 @@ arc_read_done(zio_t *zio)
zio_nowait(acb->acb_zio_dummy);
}
- callback_list = acb->acb_next;
- kmem_free(acb, sizeof (arc_callback_t));
+ callback_list = acb->acb_prev;
+ if (acb->acb_wait) {
+ mutex_enter(&acb->acb_wait_lock);
+ acb->acb_wait_error = zio->io_error;
+ acb->acb_wait = B_FALSE;
+ cv_signal(&acb->acb_wait_cv);
+ mutex_exit(&acb->acb_wait_lock);
+ /* acb will be freed by the waiting thread. */
+ } else {
+ kmem_free(acb, sizeof (arc_callback_t));
+ }
}
-
- if (freeable)
- arc_hdr_destroy(hdr);
}
/*
@@ -5952,6 +5488,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
(zio_flags & ZIO_FLAG_RAW_ENCRYPT) != 0;
boolean_t embedded_bp = !!BP_IS_EMBEDDED(bp);
boolean_t no_buf = *arc_flags & ARC_FLAG_NO_BUF;
+ arc_buf_t *buf = NULL;
int rc = 0;
ASSERT(!embedded_bp ||
@@ -5978,10 +5515,10 @@ top:
* and treat it as a checksum error. This allows an alternate blkptr
* to be tried when one is available (e.g. ditto blocks).
*/
- if (!zfs_blkptr_verify(spa, bp, zio_flags & ZIO_FLAG_CONFIG_WRITER,
- BLK_VERIFY_LOG)) {
+ if (!zfs_blkptr_verify(spa, bp, (zio_flags & ZIO_FLAG_CONFIG_WRITER) ?
+ BLK_CONFIG_HELD : BLK_CONFIG_NEEDED, BLK_VERIFY_LOG)) {
rc = SET_ERROR(ECKSUM);
- goto out;
+ goto done;
}
if (!embedded_bp) {
@@ -6001,19 +5538,17 @@ top:
*/
if (hdr != NULL && HDR_HAS_L1HDR(hdr) && (HDR_HAS_RABD(hdr) ||
(hdr->b_l1hdr.b_pabd != NULL && !encrypted_read))) {
- arc_buf_t *buf = NULL;
- *arc_flags |= ARC_FLAG_CACHED;
+ boolean_t is_data = !HDR_ISTYPE_METADATA(hdr);
if (HDR_IO_IN_PROGRESS(hdr)) {
- zio_t *head_zio = hdr->b_l1hdr.b_acb->acb_zio_head;
-
if (*arc_flags & ARC_FLAG_CACHED_ONLY) {
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_cached_only_in_progress);
rc = SET_ERROR(ENOENT);
- goto out;
+ goto done;
}
+ zio_t *head_zio = hdr->b_l1hdr.b_acb->acb_zio_head;
ASSERT3P(head_zio, !=, NULL);
if ((hdr->b_flags & ARC_FLAG_PRIO_ASYNC_READ) &&
priority == ZIO_PRIORITY_SYNC_READ) {
@@ -6027,21 +5562,28 @@ top:
arc_buf_hdr_t *, hdr);
ARCSTAT_BUMP(arcstat_async_upgrade_sync);
}
- if (hdr->b_flags & ARC_FLAG_PREDICTIVE_PREFETCH) {
- arc_hdr_clear_flags(hdr,
- ARC_FLAG_PREDICTIVE_PREFETCH);
- }
- if (*arc_flags & ARC_FLAG_WAIT) {
- cv_wait(&hdr->b_l1hdr.b_cv, hash_lock);
- mutex_exit(hash_lock);
- goto top;
- }
- ASSERT(*arc_flags & ARC_FLAG_NOWAIT);
-
- if (done) {
- arc_callback_t *acb = NULL;
+ DTRACE_PROBE1(arc__iohit, arc_buf_hdr_t *, hdr);
+ arc_access(hdr, *arc_flags, B_FALSE);
+ /*
+ * If there are multiple threads reading the same block
+ * and that block is not yet in the ARC, then only one
+ * thread will do the physical I/O and all other
+ * threads will wait until that I/O completes.
+ * Synchronous reads use the acb_wait_cv whereas nowait
+ * reads register a callback. Both are signalled/called
+ * in arc_read_done.
+ *
+ * Errors of the physical I/O may need to be propagated.
+ * Synchronous read errors are returned here from
+ * arc_read_done via acb_wait_error. Nowait reads
+ * attach the acb_zio_dummy zio to pio and
+ * arc_read_done propagates the physical I/O's io_error
+ * to acb_zio_dummy, and thereby to pio.
+ */
+ arc_callback_t *acb = NULL;
+ if (done || pio || *arc_flags & ARC_FLAG_WAIT) {
acb = kmem_zalloc(sizeof (arc_callback_t),
KM_SLEEP);
acb->acb_done = done;
@@ -6050,46 +5592,52 @@ top:
acb->acb_encrypted = encrypted_read;
acb->acb_noauth = noauth_read;
acb->acb_nobuf = no_buf;
+ if (*arc_flags & ARC_FLAG_WAIT) {
+ acb->acb_wait = B_TRUE;
+ mutex_init(&acb->acb_wait_lock, NULL,
+ MUTEX_DEFAULT, NULL);
+ cv_init(&acb->acb_wait_cv, NULL,
+ CV_DEFAULT, NULL);
+ }
acb->acb_zb = *zb;
- if (pio != NULL)
+ if (pio != NULL) {
acb->acb_zio_dummy = zio_null(pio,
spa, NULL, NULL, NULL, zio_flags);
-
- ASSERT3P(acb->acb_done, !=, NULL);
+ }
acb->acb_zio_head = head_zio;
acb->acb_next = hdr->b_l1hdr.b_acb;
+ hdr->b_l1hdr.b_acb->acb_prev = acb;
hdr->b_l1hdr.b_acb = acb;
}
mutex_exit(hash_lock);
+
+ ARCSTAT_BUMP(arcstat_iohits);
+ ARCSTAT_CONDSTAT(!(*arc_flags & ARC_FLAG_PREFETCH),
+ demand, prefetch, is_data, data, metadata, iohits);
+
+ if (*arc_flags & ARC_FLAG_WAIT) {
+ mutex_enter(&acb->acb_wait_lock);
+ while (acb->acb_wait) {
+ cv_wait(&acb->acb_wait_cv,
+ &acb->acb_wait_lock);
+ }
+ rc = acb->acb_wait_error;
+ mutex_exit(&acb->acb_wait_lock);
+ mutex_destroy(&acb->acb_wait_lock);
+ cv_destroy(&acb->acb_wait_cv);
+ kmem_free(acb, sizeof (arc_callback_t));
+ }
goto out;
}
ASSERT(hdr->b_l1hdr.b_state == arc_mru ||
- hdr->b_l1hdr.b_state == arc_mfu);
-
- if (done && !no_buf) {
- if (hdr->b_flags & ARC_FLAG_PREDICTIVE_PREFETCH) {
- /*
- * This is a demand read which does not have to
- * wait for i/o because we did a predictive
- * prefetch i/o for it, which has completed.
- */
- DTRACE_PROBE1(
- arc__demand__hit__predictive__prefetch,
- arc_buf_hdr_t *, hdr);
- ARCSTAT_BUMP(
- arcstat_demand_hit_predictive_prefetch);
- arc_hdr_clear_flags(hdr,
- ARC_FLAG_PREDICTIVE_PREFETCH);
- }
+ hdr->b_l1hdr.b_state == arc_mfu ||
+ hdr->b_l1hdr.b_state == arc_uncached);
- if (hdr->b_flags & ARC_FLAG_PRESCIENT_PREFETCH) {
- ARCSTAT_BUMP(
- arcstat_demand_hit_prescient_prefetch);
- arc_hdr_clear_flags(hdr,
- ARC_FLAG_PRESCIENT_PREFETCH);
- }
+ DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
+ arc_access(hdr, *arc_flags, B_TRUE);
+ if (done && !no_buf) {
ASSERT(!embedded_bp || !BP_IS_HOLE(bp));
/* Get a buf with the desired data in it. */
@@ -6104,44 +5652,28 @@ top:
*/
rc = SET_ERROR(EIO);
if ((zio_flags & ZIO_FLAG_SPECULATIVE) == 0) {
- spa_log_error(spa, zb);
+ spa_log_error(spa, zb, hdr->b_birth);
(void) zfs_ereport_post(
FM_EREPORT_ZFS_AUTHENTICATION,
spa, NULL, zb, NULL, 0);
}
}
if (rc != 0) {
- (void) remove_reference(hdr, hash_lock,
- private);
arc_buf_destroy_impl(buf);
buf = NULL;
+ (void) remove_reference(hdr, private);
}
/* assert any errors weren't due to unloaded keys */
ASSERT((zio_flags & ZIO_FLAG_SPECULATIVE) ||
rc != EACCES);
- } else if (*arc_flags & ARC_FLAG_PREFETCH &&
- zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_decrement_state(hdr);
- arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_increment_state(hdr);
}
- DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
- arc_access(hdr, hash_lock);
- if (*arc_flags & ARC_FLAG_PRESCIENT_PREFETCH)
- arc_hdr_set_flags(hdr, ARC_FLAG_PRESCIENT_PREFETCH);
- if (*arc_flags & ARC_FLAG_L2CACHE)
- arc_hdr_set_flags(hdr, ARC_FLAG_L2CACHE);
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_hits);
- ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
- demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
- data, metadata, hits);
-
- if (done)
- done(NULL, zb, bp, buf, private);
+ ARCSTAT_CONDSTAT(!(*arc_flags & ARC_FLAG_PREFETCH),
+ demand, prefetch, is_data, data, metadata, hits);
+ *arc_flags |= ARC_FLAG_CACHED;
+ goto done;
} else {
uint64_t lsize = BP_GET_LSIZE(bp);
uint64_t psize = BP_GET_PSIZE(bp);
@@ -6152,12 +5684,13 @@ top:
uint64_t size;
abd_t *hdr_abd;
int alloc_flags = encrypted_read ? ARC_HDR_ALLOC_RDATA : 0;
+ arc_buf_contents_t type = BP_GET_BUFC_TYPE(bp);
if (*arc_flags & ARC_FLAG_CACHED_ONLY) {
- rc = SET_ERROR(ENOENT);
if (hash_lock != NULL)
mutex_exit(hash_lock);
- goto out;
+ rc = SET_ERROR(ENOENT);
+ goto done;
}
if (hdr == NULL) {
@@ -6166,13 +5699,12 @@ top:
* embedded data.
*/
arc_buf_hdr_t *exists = NULL;
- arc_buf_contents_t type = BP_GET_BUFC_TYPE(bp);
- hdr = arc_hdr_alloc(spa_load_guid(spa), psize, lsize,
+ hdr = arc_hdr_alloc(guid, psize, lsize,
BP_IS_PROTECTED(bp), BP_GET_COMPRESS(bp), 0, type);
if (!embedded_bp) {
hdr->b_dva = *BP_IDENTITY(bp);
- hdr->b_birth = BP_PHYSICAL_BIRTH(bp);
+ hdr->b_birth = BP_GET_BIRTH(bp);
exists = buf_hash_insert(hdr, &hash_lock);
}
if (exists != NULL) {
@@ -6182,7 +5714,6 @@ top:
arc_hdr_destroy(hdr);
goto top; /* restart the IO request */
}
- alloc_flags |= ARC_HDR_DO_ADAPT;
} else {
/*
* This block is in the ghost cache or encrypted data
@@ -6202,7 +5733,9 @@ top:
ASSERT0(zfs_refcount_count(
&hdr->b_l1hdr.b_refcnt));
ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
+#ifdef ZFS_DEBUG
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
+#endif
} else if (HDR_IO_IN_PROGRESS(hdr)) {
/*
* If this header already had an IO in progress
@@ -6213,25 +5746,47 @@ top:
* and so the performance impact shouldn't
* matter.
*/
- cv_wait(&hdr->b_l1hdr.b_cv, hash_lock);
+ arc_callback_t *acb = kmem_zalloc(
+ sizeof (arc_callback_t), KM_SLEEP);
+ acb->acb_wait = B_TRUE;
+ mutex_init(&acb->acb_wait_lock, NULL,
+ MUTEX_DEFAULT, NULL);
+ cv_init(&acb->acb_wait_cv, NULL, CV_DEFAULT,
+ NULL);
+ acb->acb_zio_head =
+ hdr->b_l1hdr.b_acb->acb_zio_head;
+ acb->acb_next = hdr->b_l1hdr.b_acb;
+ hdr->b_l1hdr.b_acb->acb_prev = acb;
+ hdr->b_l1hdr.b_acb = acb;
mutex_exit(hash_lock);
+ mutex_enter(&acb->acb_wait_lock);
+ while (acb->acb_wait) {
+ cv_wait(&acb->acb_wait_cv,
+ &acb->acb_wait_lock);
+ }
+ mutex_exit(&acb->acb_wait_lock);
+ mutex_destroy(&acb->acb_wait_lock);
+ cv_destroy(&acb->acb_wait_cv);
+ kmem_free(acb, sizeof (arc_callback_t));
goto top;
}
-
- /*
- * This is a delicate dance that we play here.
- * This hdr might be in the ghost list so we access
- * it to move it out of the ghost list before we
- * initiate the read. If it's a prefetch then
- * it won't have a callback so we'll remove the
- * reference that arc_buf_alloc_impl() created. We
- * do this after we've called arc_access() to
- * avoid hitting an assert in remove_reference().
- */
- arc_adapt(arc_hdr_size(hdr), hdr->b_l1hdr.b_state);
- arc_access(hdr, hash_lock);
+ }
+ if (*arc_flags & ARC_FLAG_UNCACHED) {
+ arc_hdr_set_flags(hdr, ARC_FLAG_UNCACHED);
+ if (!encrypted_read)
+ alloc_flags |= ARC_HDR_ALLOC_LINEAR;
}
+ /*
+ * Take additional reference for IO_IN_PROGRESS. It stops
+ * arc_access() from putting this header without any buffers
+ * and so other references but obviously nonevictable onto
+ * the evictable list of MRU or MFU state.
+ */
+ add_reference(hdr, hdr);
+ if (!embedded_bp)
+ arc_access(hdr, *arc_flags, B_FALSE);
+ arc_hdr_set_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
arc_hdr_alloc_abd(hdr, alloc_flags);
if (encrypted_read) {
ASSERT(HDR_HAS_RABD(hdr));
@@ -6258,24 +5813,10 @@ top:
zio_flags |= ZIO_FLAG_RAW_ENCRYPT;
}
- if (*arc_flags & ARC_FLAG_PREFETCH &&
- zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_decrement_state(hdr);
- arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);
- if (HDR_HAS_L2HDR(hdr))
- l2arc_hdr_arcstats_increment_state(hdr);
- }
- if (*arc_flags & ARC_FLAG_PRESCIENT_PREFETCH)
- arc_hdr_set_flags(hdr, ARC_FLAG_PRESCIENT_PREFETCH);
- if (*arc_flags & ARC_FLAG_L2CACHE)
- arc_hdr_set_flags(hdr, ARC_FLAG_L2CACHE);
if (BP_IS_AUTHENTICATED(bp))
arc_hdr_set_flags(hdr, ARC_FLAG_NOAUTH);
if (BP_GET_LEVEL(bp) > 0)
arc_hdr_set_flags(hdr, ARC_FLAG_INDIRECT);
- if (*arc_flags & ARC_FLAG_PREDICTIVE_PREFETCH)
- arc_hdr_set_flags(hdr, ARC_FLAG_PREDICTIVE_PREFETCH);
ASSERT(!GHOST_STATE(hdr->b_l1hdr.b_state));
acb = kmem_zalloc(sizeof (arc_callback_t), KM_SLEEP);
@@ -6288,7 +5829,6 @@ top:
ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL);
hdr->b_l1hdr.b_acb = acb;
- arc_hdr_set_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
if (HDR_HAS_L2HDR(hdr) &&
(vd = hdr->b_l2hdr.b_dev->l2ad_vdev) != NULL) {
@@ -6329,7 +5869,7 @@ top:
blkptr_t *, bp, uint64_t, lsize,
zbookmark_phys_t *, zb);
ARCSTAT_BUMP(arcstat_misses);
- ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
+ ARCSTAT_CONDSTAT(!(*arc_flags & ARC_FLAG_PREFETCH),
demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data,
metadata, misses);
zfs_racct_read(size, 1);
@@ -6347,11 +5887,9 @@ top:
* 3. This buffer isn't currently writing to the L2ARC.
* 4. The L2ARC entry wasn't evicted, which may
* also have invalidated the vdev.
- * 5. This isn't prefetch or l2arc_noprefetch is 0.
*/
if (HDR_HAS_L2HDR(hdr) &&
- !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) &&
- !(l2arc_noprefetch && HDR_PREFETCH(hdr))) {
+ !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr)) {
l2arc_read_callback_t *cb;
abd_t *abd;
uint64_t asize;
@@ -6403,8 +5941,7 @@ top:
asize, abd,
ZIO_CHECKSUM_OFF,
l2arc_read_done, cb, priority,
- zio_flags | ZIO_FLAG_DONT_CACHE |
- ZIO_FLAG_CANFAIL |
+ zio_flags | ZIO_FLAG_CANFAIL |
ZIO_FLAG_DONT_PROPAGATE |
ZIO_FLAG_DONT_RETRY, B_FALSE);
acb->acb_zio_head = rzio;
@@ -6483,6 +6020,16 @@ out:
spa_read_history_add(spa, zb, *arc_flags);
spl_fstrans_unmark(cookie);
return (rc);
+
+done:
+ if (done)
+ done(NULL, zb, bp, buf, private);
+ if (pio && rc != 0) {
+ zio_t *zio = zio_null(pio, spa, NULL, NULL, NULL, zio_flags);
+ zio->io_error = rc;
+ zio_nowait(zio);
+ }
+ goto out;
}
arc_prune_t *
@@ -6523,6 +6070,56 @@ arc_remove_prune_callback(arc_prune_t *p)
}
/*
+ * Helper function for arc_prune_async() it is responsible for safely
+ * handling the execution of a registered arc_prune_func_t.
+ */
+static void
+arc_prune_task(void *ptr)
+{
+ arc_prune_t *ap = (arc_prune_t *)ptr;
+ arc_prune_func_t *func = ap->p_pfunc;
+
+ if (func != NULL)
+ func(ap->p_adjust, ap->p_private);
+
+ (void) zfs_refcount_remove(&ap->p_refcnt, func);
+}
+
+/*
+ * Notify registered consumers they must drop holds on a portion of the ARC
+ * buffers they reference. This provides a mechanism to ensure the ARC can
+ * honor the metadata limit and reclaim otherwise pinned ARC buffers.
+ *
+ * This operation is performed asynchronously so it may be safely called
+ * in the context of the arc_reclaim_thread(). A reference is taken here
+ * for each registered arc_prune_t and the arc_prune_task() is responsible
+ * for releasing it once the registered arc_prune_func_t has completed.
+ */
+static void
+arc_prune_async(uint64_t adjust)
+{
+ arc_prune_t *ap;
+
+ mutex_enter(&arc_prune_mtx);
+ for (ap = list_head(&arc_prune_list); ap != NULL;
+ ap = list_next(&arc_prune_list, ap)) {
+
+ if (zfs_refcount_count(&ap->p_refcnt) >= 2)
+ continue;
+
+ zfs_refcount_add(&ap->p_refcnt, ap->p_pfunc);
+ ap->p_adjust = adjust;
+ if (taskq_dispatch(arc_prune_taskq, arc_prune_task,
+ ap, TQ_SLEEP) == TASKQID_INVALID) {
+ (void) zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
+ continue;
+ }
+ ARCSTAT_BUMP(arcstat_prune);
+ }
+ mutex_exit(&arc_prune_mtx);
+}
+
+/*
* Notify the arc that a block was freed, and thus will never be used again.
*/
void
@@ -6540,10 +6137,8 @@ arc_freed(spa_t *spa, const blkptr_t *bp)
/*
* We might be trying to free a block that is still doing I/O
- * (i.e. prefetch) or has a reference (i.e. a dedup-ed,
- * dmu_sync-ed block). If this block is being prefetched, then it
- * would still have the ARC_FLAG_IO_IN_PROGRESS flag set on the hdr
- * until the I/O completes. A block may also have a reference if it is
+ * (i.e. prefetch) or has some other reference (i.e. a dedup-ed,
+ * dmu_sync-ed block). A block may also have a reference if it is
* part of a dedup-ed, dmu_synced write. The dmu_sync() function would
* have written the new block to its final resting place on disk but
* without the dedup flag set. This would have left the hdr in the MRU
@@ -6560,9 +6155,9 @@ arc_freed(spa_t *spa, const blkptr_t *bp)
* freed. So if we have an I/O in progress, or a reference to
* this hdr, then we don't destroy the hdr.
*/
- if (!HDR_HAS_L1HDR(hdr) || (!HDR_IO_IN_PROGRESS(hdr) &&
- zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt))) {
- arc_change_state(arc_anon, hdr, hash_lock);
+ if (!HDR_HAS_L1HDR(hdr) ||
+ zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
+ arc_change_state(arc_anon, hdr);
arc_hdr_destroy(hdr);
mutex_exit(hash_lock);
} else {
@@ -6588,8 +6183,6 @@ arc_release(arc_buf_t *buf, const void *tag)
* But we don't know that information at this level.
*/
- mutex_enter(&buf->b_evict_lock);
-
ASSERT(HDR_HAS_L1HDR(hdr));
/*
@@ -6598,14 +6191,14 @@ arc_release(arc_buf_t *buf, const void *tag)
* linked into the hash table.
*/
if (hdr->b_l1hdr.b_state == arc_anon) {
- mutex_exit(&buf->b_evict_lock);
ASSERT(!HDR_IO_IN_PROGRESS(hdr));
ASSERT(!HDR_IN_HASH_TABLE(hdr));
ASSERT(!HDR_HAS_L2HDR(hdr));
- ASSERT3U(hdr->b_l1hdr.b_bufcnt, ==, 1);
+ ASSERT3P(hdr->b_l1hdr.b_buf, ==, buf);
+ ASSERT(ARC_BUF_LAST(buf));
ASSERT3S(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt), ==, 1);
- ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
+ ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
hdr->b_l1hdr.b_arc_access = 0;
@@ -6654,7 +6247,7 @@ arc_release(arc_buf_t *buf, const void *tag)
/*
* Do we have more than one buf?
*/
- if (hdr->b_l1hdr.b_bufcnt > 1) {
+ if (hdr->b_l1hdr.b_buf != buf || !ARC_BUF_LAST(buf)) {
arc_buf_hdr_t *nhdr;
uint64_t spa = hdr->b_spa;
uint64_t psize = HDR_GET_PSIZE(hdr);
@@ -6665,9 +6258,9 @@ arc_release(arc_buf_t *buf, const void *tag)
VERIFY3U(hdr->b_type, ==, type);
ASSERT(hdr->b_l1hdr.b_buf != buf || buf->b_next != NULL);
- (void) remove_reference(hdr, hash_lock, tag);
+ VERIFY3S(remove_reference(hdr, tag), >, 0);
- if (arc_buf_is_shared(buf) && !ARC_BUF_COMPRESSED(buf)) {
+ if (ARC_BUF_SHARED(buf) && !ARC_BUF_COMPRESSED(buf)) {
ASSERT3P(hdr->b_l1hdr.b_buf, !=, buf);
ASSERT(ARC_BUF_LAST(buf));
}
@@ -6684,9 +6277,9 @@ arc_release(arc_buf_t *buf, const void *tag)
* If the current arc_buf_t and the hdr are sharing their data
* buffer, then we must stop sharing that block.
*/
- if (arc_buf_is_shared(buf)) {
+ if (ARC_BUF_SHARED(buf)) {
ASSERT3P(hdr->b_l1hdr.b_buf, !=, buf);
- VERIFY(!arc_buf_is_shared(lastbuf));
+ ASSERT(!arc_buf_is_shared(lastbuf));
/*
* First, sever the block sharing relationship between
@@ -6703,7 +6296,7 @@ arc_release(arc_buf_t *buf, const void *tag)
if (arc_can_share(hdr, lastbuf)) {
arc_share_buf(hdr, lastbuf);
} else {
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT);
+ arc_hdr_alloc_abd(hdr, 0);
abd_copy_from_buf(hdr->b_l1hdr.b_pabd,
buf->b_data, psize);
}
@@ -6719,13 +6312,13 @@ arc_release(arc_buf_t *buf, const void *tag)
*/
ASSERT(arc_buf_is_shared(lastbuf) ||
arc_hdr_get_compress(hdr) != ZIO_COMPRESS_OFF);
- ASSERT(!ARC_BUF_SHARED(buf));
+ ASSERT(!arc_buf_is_shared(buf));
}
ASSERT(hdr->b_l1hdr.b_pabd != NULL || HDR_HAS_RABD(hdr));
ASSERT3P(state, !=, arc_l2c_only);
- (void) zfs_refcount_remove_many(&state->arcs_size,
+ (void) zfs_refcount_remove_many(&state->arcs_size[type],
arc_buf_size(buf), buf);
if (zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
@@ -6735,10 +6328,6 @@ arc_release(arc_buf_t *buf, const void *tag)
arc_buf_size(buf), buf);
}
- hdr->b_l1hdr.b_bufcnt -= 1;
- if (ARC_BUF_ENCRYPTED(buf))
- hdr->b_crypt_hdr.b_ebufcnt -= 1;
-
arc_cksum_verify(buf);
arc_buf_unwatch(buf);
@@ -6748,30 +6337,20 @@ arc_release(arc_buf_t *buf, const void *tag)
mutex_exit(hash_lock);
- /*
- * Allocate a new hdr. The new hdr will contain a b_pabd
- * buffer which will be freed in arc_write().
- */
nhdr = arc_hdr_alloc(spa, psize, lsize, protected,
compress, hdr->b_complevel, type);
ASSERT3P(nhdr->b_l1hdr.b_buf, ==, NULL);
- ASSERT0(nhdr->b_l1hdr.b_bufcnt);
ASSERT0(zfs_refcount_count(&nhdr->b_l1hdr.b_refcnt));
VERIFY3U(nhdr->b_type, ==, type);
ASSERT(!HDR_SHARED_DATA(nhdr));
nhdr->b_l1hdr.b_buf = buf;
- nhdr->b_l1hdr.b_bufcnt = 1;
- if (ARC_BUF_ENCRYPTED(buf))
- nhdr->b_crypt_hdr.b_ebufcnt = 1;
(void) zfs_refcount_add(&nhdr->b_l1hdr.b_refcnt, tag);
buf->b_hdr = nhdr;
- mutex_exit(&buf->b_evict_lock);
- (void) zfs_refcount_add_many(&arc_anon->arcs_size,
+ (void) zfs_refcount_add_many(&arc_anon->arcs_size[type],
arc_buf_size(buf), buf);
} else {
- mutex_exit(&buf->b_evict_lock);
ASSERT(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) == 1);
/* protected by hash lock, or hdr is on arc_anon */
ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
@@ -6780,7 +6359,7 @@ arc_release(arc_buf_t *buf, const void *tag)
hdr->b_l1hdr.b_mru_ghost_hits = 0;
hdr->b_l1hdr.b_mfu_hits = 0;
hdr->b_l1hdr.b_mfu_ghost_hits = 0;
- arc_change_state(arc_anon, hdr, hash_lock);
+ arc_change_state(arc_anon, hdr);
hdr->b_l1hdr.b_arc_access = 0;
mutex_exit(hash_lock);
@@ -6792,25 +6371,15 @@ arc_release(arc_buf_t *buf, const void *tag)
int
arc_released(arc_buf_t *buf)
{
- int released;
-
- mutex_enter(&buf->b_evict_lock);
- released = (buf->b_data != NULL &&
+ return (buf->b_data != NULL &&
buf->b_hdr->b_l1hdr.b_state == arc_anon);
- mutex_exit(&buf->b_evict_lock);
- return (released);
}
#ifdef ZFS_DEBUG
int
arc_referenced(arc_buf_t *buf)
{
- int referenced;
-
- mutex_enter(&buf->b_evict_lock);
- referenced = (zfs_refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt));
- mutex_exit(&buf->b_evict_lock);
- return (referenced);
+ return (zfs_refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt));
}
#endif
@@ -6826,7 +6395,7 @@ arc_write_ready(zio_t *zio)
ASSERT(HDR_HAS_L1HDR(hdr));
ASSERT(!zfs_refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt));
- ASSERT(hdr->b_l1hdr.b_bufcnt > 0);
+ ASSERT3P(hdr->b_l1hdr.b_buf, !=, NULL);
/*
* If we're reexecuting this zio because the pool suspended, then
@@ -6837,9 +6406,10 @@ arc_write_ready(zio_t *zio)
arc_cksum_free(hdr);
arc_buf_unwatch(buf);
if (hdr->b_l1hdr.b_pabd != NULL) {
- if (arc_buf_is_shared(buf)) {
+ if (ARC_BUF_SHARED(buf)) {
arc_unshare_buf(hdr, buf);
} else {
+ ASSERT(!arc_buf_is_shared(buf));
arc_hdr_free_abd(hdr, B_FALSE);
}
}
@@ -6854,18 +6424,16 @@ arc_write_ready(zio_t *zio)
callback->awcb_ready(zio, buf, callback->awcb_private);
- if (HDR_IO_IN_PROGRESS(hdr))
+ if (HDR_IO_IN_PROGRESS(hdr)) {
ASSERT(zio->io_flags & ZIO_FLAG_REEXECUTED);
-
- arc_hdr_set_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
-
- if (BP_IS_PROTECTED(bp) != !!HDR_PROTECTED(hdr))
- hdr = arc_hdr_realloc_crypt(hdr, BP_IS_PROTECTED(bp));
+ } else {
+ arc_hdr_set_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
+ add_reference(hdr, hdr); /* For IO_IN_PROGRESS. */
+ }
if (BP_IS_PROTECTED(bp)) {
/* ZIL blocks are written through zio_rewrite */
ASSERT3U(BP_GET_TYPE(bp), !=, DMU_OT_INTENT_LOG);
- ASSERT(HDR_PROTECTED(hdr));
if (BP_SHOULD_BYTESWAP(bp)) {
if (BP_GET_LEVEL(bp) > 0) {
@@ -6878,11 +6446,14 @@ arc_write_ready(zio_t *zio)
hdr->b_l1hdr.b_byteswap = DMU_BSWAP_NUMFUNCS;
}
+ arc_hdr_set_flags(hdr, ARC_FLAG_PROTECTED);
hdr->b_crypt_hdr.b_ot = BP_GET_TYPE(bp);
hdr->b_crypt_hdr.b_dsobj = zio->io_bookmark.zb_objset;
zio_crypt_decode_params_bp(bp, hdr->b_crypt_hdr.b_salt,
hdr->b_crypt_hdr.b_iv);
zio_crypt_decode_mac_bp(bp, hdr->b_crypt_hdr.b_mac);
+ } else {
+ arc_hdr_clear_flags(hdr, ARC_FLAG_PROTECTED);
}
/*
@@ -6933,10 +6504,11 @@ arc_write_ready(zio_t *zio)
if (ARC_BUF_ENCRYPTED(buf)) {
ASSERT3U(psize, >, 0);
ASSERT(ARC_BUF_COMPRESSED(buf));
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT | ARC_HDR_ALLOC_RDATA |
+ arc_hdr_alloc_abd(hdr, ARC_HDR_ALLOC_RDATA |
ARC_HDR_USE_RESERVE);
abd_copy(hdr->b_crypt_hdr.b_rabd, zio->io_abd, psize);
- } else if (!abd_size_alloc_linear(arc_buf_size(buf)) ||
+ } else if (!(HDR_UNCACHED(hdr) ||
+ abd_size_alloc_linear(arc_buf_size(buf))) ||
!arc_can_share(hdr, buf)) {
/*
* Ideally, we would always copy the io_abd into b_pabd, but the
@@ -6945,26 +6517,25 @@ arc_write_ready(zio_t *zio)
*/
if (BP_IS_ENCRYPTED(bp)) {
ASSERT3U(psize, >, 0);
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT |
- ARC_HDR_ALLOC_RDATA | ARC_HDR_USE_RESERVE);
+ arc_hdr_alloc_abd(hdr, ARC_HDR_ALLOC_RDATA |
+ ARC_HDR_USE_RESERVE);
abd_copy(hdr->b_crypt_hdr.b_rabd, zio->io_abd, psize);
} else if (arc_hdr_get_compress(hdr) != ZIO_COMPRESS_OFF &&
!ARC_BUF_COMPRESSED(buf)) {
ASSERT3U(psize, >, 0);
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT |
- ARC_HDR_USE_RESERVE);
+ arc_hdr_alloc_abd(hdr, ARC_HDR_USE_RESERVE);
abd_copy(hdr->b_l1hdr.b_pabd, zio->io_abd, psize);
} else {
ASSERT3U(zio->io_orig_size, ==, arc_hdr_size(hdr));
- arc_hdr_alloc_abd(hdr, ARC_HDR_DO_ADAPT |
- ARC_HDR_USE_RESERVE);
+ arc_hdr_alloc_abd(hdr, ARC_HDR_USE_RESERVE);
abd_copy_from_buf(hdr->b_l1hdr.b_pabd, buf->b_data,
arc_buf_size(buf));
}
} else {
ASSERT3P(buf->b_data, ==, abd_to_buf(zio->io_orig_abd));
ASSERT3U(zio->io_orig_size, ==, arc_buf_size(buf));
- ASSERT3U(hdr->b_l1hdr.b_bufcnt, ==, 1);
+ ASSERT3P(hdr->b_l1hdr.b_buf, ==, buf);
+ ASSERT(ARC_BUF_LAST(buf));
arc_share_buf(hdr, buf);
}
@@ -6983,18 +6554,6 @@ arc_write_children_ready(zio_t *zio)
callback->awcb_children_ready(zio, buf, callback->awcb_private);
}
-/*
- * The SPA calls this callback for each physical write that happens on behalf
- * of a logical write. See the comment in dbuf_write_physdone() for details.
- */
-static void
-arc_write_physdone(zio_t *zio)
-{
- arc_write_callback_t *cb = zio->io_private;
- if (cb->awcb_physdone != NULL)
- cb->awcb_physdone(zio, cb->awcb_buf, cb->awcb_private);
-}
-
static void
arc_write_done(zio_t *zio)
{
@@ -7011,7 +6570,7 @@ arc_write_done(zio_t *zio)
buf_discard_identity(hdr);
} else {
hdr->b_dva = *BP_IDENTITY(zio->io_bp);
- hdr->b_birth = BP_PHYSICAL_BIRTH(zio->io_bp);
+ hdr->b_birth = BP_GET_BIRTH(zio->io_bp);
}
} else {
ASSERT(HDR_EMPTY(hdr));
@@ -7044,7 +6603,7 @@ arc_write_done(zio_t *zio)
(void *)hdr, (void *)exists);
ASSERT(zfs_refcount_is_zero(
&exists->b_l1hdr.b_refcnt));
- arc_change_state(arc_anon, exists, hash_lock);
+ arc_change_state(arc_anon, exists);
arc_hdr_destroy(exists);
mutex_exit(hash_lock);
exists = buf_hash_insert(hdr, &hash_lock);
@@ -7057,22 +6616,24 @@ arc_write_done(zio_t *zio)
(void *)hdr, (void *)exists);
} else {
/* Dedup */
- ASSERT(hdr->b_l1hdr.b_bufcnt == 1);
+ ASSERT3P(hdr->b_l1hdr.b_buf, !=, NULL);
+ ASSERT(ARC_BUF_LAST(hdr->b_l1hdr.b_buf));
ASSERT(hdr->b_l1hdr.b_state == arc_anon);
ASSERT(BP_GET_DEDUP(zio->io_bp));
ASSERT(BP_GET_LEVEL(zio->io_bp) == 0);
}
}
arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
+ VERIFY3S(remove_reference(hdr, hdr), >, 0);
/* if it's not anon, we are doing a scrub */
if (exists == NULL && hdr->b_l1hdr.b_state == arc_anon)
- arc_access(hdr, hash_lock);
+ arc_access(hdr, 0, B_FALSE);
mutex_exit(hash_lock);
} else {
arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
+ VERIFY3S(remove_reference(hdr, hdr), >, 0);
}
- ASSERT(!zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
callback->awcb_done(zio, buf, callback->awcb_private);
abd_free(zio->io_abd);
@@ -7081,11 +6642,11 @@ arc_write_done(zio_t *zio)
zio_t *
arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
- blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc,
+ blkptr_t *bp, arc_buf_t *buf, boolean_t uncached, boolean_t l2arc,
const zio_prop_t *zp, arc_write_done_func_t *ready,
- arc_write_done_func_t *children_ready, arc_write_done_func_t *physdone,
- arc_write_done_func_t *done, void *private, zio_priority_t priority,
- int zio_flags, const zbookmark_phys_t *zb)
+ arc_write_done_func_t *children_ready, arc_write_done_func_t *done,
+ void *private, zio_priority_t priority, int zio_flags,
+ const zbookmark_phys_t *zb)
{
arc_buf_hdr_t *hdr = buf->b_hdr;
arc_write_callback_t *callback;
@@ -7097,8 +6658,10 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
ASSERT(!HDR_IO_ERROR(hdr));
ASSERT(!HDR_IO_IN_PROGRESS(hdr));
ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL);
- ASSERT3U(hdr->b_l1hdr.b_bufcnt, >, 0);
- if (l2arc)
+ ASSERT3P(hdr->b_l1hdr.b_buf, !=, NULL);
+ if (uncached)
+ arc_hdr_set_flags(hdr, ARC_FLAG_UNCACHED);
+ else if (l2arc)
arc_hdr_set_flags(hdr, ARC_FLAG_L2CACHE);
if (ARC_BUF_ENCRYPTED(buf)) {
@@ -7130,7 +6693,6 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
callback = kmem_zalloc(sizeof (arc_write_callback_t), KM_SLEEP);
callback->awcb_ready = ready;
callback->awcb_children_ready = children_ready;
- callback->awcb_physdone = physdone;
callback->awcb_done = done;
callback->awcb_private = private;
callback->awcb_buf = buf;
@@ -7146,9 +6708,10 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
* The hdr will remain with a NULL data pointer and the
* buf will take sole ownership of the block.
*/
- if (arc_buf_is_shared(buf)) {
+ if (ARC_BUF_SHARED(buf)) {
arc_unshare_buf(hdr, buf);
} else {
+ ASSERT(!arc_buf_is_shared(buf));
arc_hdr_free_abd(hdr, B_FALSE);
}
VERIFY3P(buf->b_data, !=, NULL);
@@ -7167,8 +6730,7 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
abd_get_from_buf(buf->b_data, HDR_GET_LSIZE(hdr)),
HDR_GET_LSIZE(hdr), arc_buf_size(buf), &localprop, arc_write_ready,
(children_ready != NULL) ? arc_write_children_ready : NULL,
- arc_write_physdone, arc_write_done, callback,
- priority, zio_flags, zb);
+ arc_write_done, callback, priority, zio_flags, zb);
return (zio);
}
@@ -7209,7 +6771,9 @@ arc_tempreserve_space(spa_t *spa, uint64_t reserve, uint64_t txg)
/* assert that it has not wrapped around */
ASSERT3S(atomic_add_64_nv(&arc_loaned_bytes, 0), >=, 0);
- anon_size = MAX((int64_t)(zfs_refcount_count(&arc_anon->arcs_size) -
+ anon_size = MAX((int64_t)
+ (zfs_refcount_count(&arc_anon->arcs_size[ARC_BUFC_DATA]) +
+ zfs_refcount_count(&arc_anon->arcs_size[ARC_BUFC_METADATA]) -
arc_loaned_bytes), 0);
/*
@@ -7265,9 +6829,14 @@ arc_tempreserve_space(spa_t *spa, uint64_t reserve, uint64_t txg)
static void
arc_kstat_update_state(arc_state_t *state, kstat_named_t *size,
+ kstat_named_t *data, kstat_named_t *metadata,
kstat_named_t *evict_data, kstat_named_t *evict_metadata)
{
- size->value.ui64 = zfs_refcount_count(&state->arcs_size);
+ data->value.ui64 =
+ zfs_refcount_count(&state->arcs_size[ARC_BUFC_DATA]);
+ metadata->value.ui64 =
+ zfs_refcount_count(&state->arcs_size[ARC_BUFC_METADATA]);
+ size->value.ui64 = data->value.ui64 + metadata->value.ui64;
evict_data->value.ui64 =
zfs_refcount_count(&state->arcs_esize[ARC_BUFC_DATA]);
evict_metadata->value.ui64 =
@@ -7284,22 +6853,32 @@ arc_kstat_update(kstat_t *ksp, int rw)
as->arcstat_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_hits);
+ as->arcstat_iohits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_iohits);
as->arcstat_misses.value.ui64 =
wmsum_value(&arc_sums.arcstat_misses);
as->arcstat_demand_data_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_data_hits);
+ as->arcstat_demand_data_iohits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_demand_data_iohits);
as->arcstat_demand_data_misses.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_data_misses);
as->arcstat_demand_metadata_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_metadata_hits);
+ as->arcstat_demand_metadata_iohits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_demand_metadata_iohits);
as->arcstat_demand_metadata_misses.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_metadata_misses);
as->arcstat_prefetch_data_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_prefetch_data_hits);
+ as->arcstat_prefetch_data_iohits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_prefetch_data_iohits);
as->arcstat_prefetch_data_misses.value.ui64 =
wmsum_value(&arc_sums.arcstat_prefetch_data_misses);
as->arcstat_prefetch_metadata_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_prefetch_metadata_hits);
+ as->arcstat_prefetch_metadata_iohits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_prefetch_metadata_iohits);
as->arcstat_prefetch_metadata_misses.value.ui64 =
wmsum_value(&arc_sums.arcstat_prefetch_metadata_misses);
as->arcstat_mru_hits.value.ui64 =
@@ -7310,6 +6889,8 @@ arc_kstat_update(kstat_t *ksp, int rw)
wmsum_value(&arc_sums.arcstat_mfu_hits);
as->arcstat_mfu_ghost_hits.value.ui64 =
wmsum_value(&arc_sums.arcstat_mfu_ghost_hits);
+ as->arcstat_uncached_hits.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_uncached_hits);
as->arcstat_deleted.value.ui64 =
wmsum_value(&arc_sums.arcstat_deleted);
as->arcstat_mutex_miss.value.ui64 =
@@ -7355,33 +6936,49 @@ arc_kstat_update(kstat_t *ksp, int rw)
#if defined(COMPAT_FREEBSD11)
as->arcstat_other_size.value.ui64 =
wmsum_value(&arc_sums.arcstat_bonus_size) +
- aggsum_value(&arc_sums.arcstat_dnode_size) +
+ wmsum_value(&arc_sums.arcstat_dnode_size) +
wmsum_value(&arc_sums.arcstat_dbuf_size);
#endif
arc_kstat_update_state(arc_anon,
&as->arcstat_anon_size,
+ &as->arcstat_anon_data,
+ &as->arcstat_anon_metadata,
&as->arcstat_anon_evictable_data,
&as->arcstat_anon_evictable_metadata);
arc_kstat_update_state(arc_mru,
&as->arcstat_mru_size,
+ &as->arcstat_mru_data,
+ &as->arcstat_mru_metadata,
&as->arcstat_mru_evictable_data,
&as->arcstat_mru_evictable_metadata);
arc_kstat_update_state(arc_mru_ghost,
&as->arcstat_mru_ghost_size,
+ &as->arcstat_mru_ghost_data,
+ &as->arcstat_mru_ghost_metadata,
&as->arcstat_mru_ghost_evictable_data,
&as->arcstat_mru_ghost_evictable_metadata);
arc_kstat_update_state(arc_mfu,
&as->arcstat_mfu_size,
+ &as->arcstat_mfu_data,
+ &as->arcstat_mfu_metadata,
&as->arcstat_mfu_evictable_data,
&as->arcstat_mfu_evictable_metadata);
arc_kstat_update_state(arc_mfu_ghost,
&as->arcstat_mfu_ghost_size,
+ &as->arcstat_mfu_ghost_data,
+ &as->arcstat_mfu_ghost_metadata,
&as->arcstat_mfu_ghost_evictable_data,
&as->arcstat_mfu_ghost_evictable_metadata);
+ arc_kstat_update_state(arc_uncached,
+ &as->arcstat_uncached_size,
+ &as->arcstat_uncached_data,
+ &as->arcstat_uncached_metadata,
+ &as->arcstat_uncached_evictable_data,
+ &as->arcstat_uncached_evictable_metadata);
as->arcstat_dnode_size.value.ui64 =
- aggsum_value(&arc_sums.arcstat_dnode_size);
+ wmsum_value(&arc_sums.arcstat_dnode_size);
as->arcstat_bonus_size.value.ui64 =
wmsum_value(&arc_sums.arcstat_bonus_size);
as->arcstat_l2_hits.value.ui64 =
@@ -7479,13 +7076,21 @@ arc_kstat_update(kstat_t *ksp, int rw)
as->arcstat_prune.value.ui64 =
wmsum_value(&arc_sums.arcstat_prune);
as->arcstat_meta_used.value.ui64 =
- aggsum_value(&arc_sums.arcstat_meta_used);
+ wmsum_value(&arc_sums.arcstat_meta_used);
as->arcstat_async_upgrade_sync.value.ui64 =
wmsum_value(&arc_sums.arcstat_async_upgrade_sync);
+ as->arcstat_predictive_prefetch.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_predictive_prefetch);
as->arcstat_demand_hit_predictive_prefetch.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_hit_predictive_prefetch);
+ as->arcstat_demand_iohit_predictive_prefetch.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_demand_iohit_predictive_prefetch);
+ as->arcstat_prescient_prefetch.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_prescient_prefetch);
as->arcstat_demand_hit_prescient_prefetch.value.ui64 =
wmsum_value(&arc_sums.arcstat_demand_hit_prescient_prefetch);
+ as->arcstat_demand_iohit_prescient_prefetch.value.ui64 =
+ wmsum_value(&arc_sums.arcstat_demand_iohit_prescient_prefetch);
as->arcstat_raw_size.value.ui64 =
wmsum_value(&arc_sums.arcstat_raw_size);
as->arcstat_cached_only_in_progress.value.ui64 =
@@ -7557,7 +7162,6 @@ void
arc_tuning_update(boolean_t verbose)
{
uint64_t allmem = arc_all_memory();
- unsigned long limit;
/* Valid range: 32M - <arc_c_max> */
if ((zfs_arc_min) && (zfs_arc_min != arc_c_min) &&
@@ -7574,44 +7178,15 @@ arc_tuning_update(boolean_t verbose)
(zfs_arc_max > arc_c_min)) {
arc_c_max = zfs_arc_max;
arc_c = MIN(arc_c, arc_c_max);
- arc_p = (arc_c >> 1);
- if (arc_meta_limit > arc_c_max)
- arc_meta_limit = arc_c_max;
- if (arc_dnode_size_limit > arc_meta_limit)
- arc_dnode_size_limit = arc_meta_limit;
+ if (arc_dnode_limit > arc_c_max)
+ arc_dnode_limit = arc_c_max;
}
WARN_IF_TUNING_IGNORED(zfs_arc_max, arc_c_max, verbose);
- /* Valid range: 16M - <arc_c_max> */
- if ((zfs_arc_meta_min) && (zfs_arc_meta_min != arc_meta_min) &&
- (zfs_arc_meta_min >= 1ULL << SPA_MAXBLOCKSHIFT) &&
- (zfs_arc_meta_min <= arc_c_max)) {
- arc_meta_min = zfs_arc_meta_min;
- if (arc_meta_limit < arc_meta_min)
- arc_meta_limit = arc_meta_min;
- if (arc_dnode_size_limit < arc_meta_min)
- arc_dnode_size_limit = arc_meta_min;
- }
- WARN_IF_TUNING_IGNORED(zfs_arc_meta_min, arc_meta_min, verbose);
-
- /* Valid range: <arc_meta_min> - <arc_c_max> */
- limit = zfs_arc_meta_limit ? zfs_arc_meta_limit :
- MIN(zfs_arc_meta_limit_percent, 100) * arc_c_max / 100;
- if ((limit != arc_meta_limit) &&
- (limit >= arc_meta_min) &&
- (limit <= arc_c_max))
- arc_meta_limit = limit;
- WARN_IF_TUNING_IGNORED(zfs_arc_meta_limit, arc_meta_limit, verbose);
-
- /* Valid range: <arc_meta_min> - <arc_meta_limit> */
- limit = zfs_arc_dnode_limit ? zfs_arc_dnode_limit :
- MIN(zfs_arc_dnode_limit_percent, 100) * arc_meta_limit / 100;
- if ((limit != arc_dnode_size_limit) &&
- (limit >= arc_meta_min) &&
- (limit <= arc_meta_limit))
- arc_dnode_size_limit = limit;
- WARN_IF_TUNING_IGNORED(zfs_arc_dnode_limit, arc_dnode_size_limit,
- verbose);
+ /* Valid range: 0 - <all physical memory> */
+ arc_dnode_limit = zfs_arc_dnode_limit ? zfs_arc_dnode_limit :
+ MIN(zfs_arc_dnode_limit_percent, 100) * arc_c_max / 100;
+ WARN_IF_TUNING_IGNORED(zfs_arc_dnode_limit, arc_dnode_limit, verbose);
/* Valid range: 1 - N */
if (zfs_arc_grow_retry)
@@ -7623,10 +7198,6 @@ arc_tuning_update(boolean_t verbose)
arc_no_grow_shift = MIN(arc_no_grow_shift, arc_shrink_shift -1);
}
- /* Valid range: 1 - N */
- if (zfs_arc_p_min_shift)
- arc_p_min_shift = zfs_arc_p_min_shift;
-
/* Valid range: 1 - N ms */
if (zfs_arc_min_prefetch_ms)
arc_min_prefetch_ms = zfs_arc_min_prefetch_ms;
@@ -7638,15 +7209,14 @@ arc_tuning_update(boolean_t verbose)
}
/* Valid range: 0 - 100 */
- if ((zfs_arc_lotsfree_percent >= 0) &&
- (zfs_arc_lotsfree_percent <= 100))
+ if (zfs_arc_lotsfree_percent <= 100)
arc_lotsfree_percent = zfs_arc_lotsfree_percent;
WARN_IF_TUNING_IGNORED(zfs_arc_lotsfree_percent, arc_lotsfree_percent,
verbose);
/* Valid range: 0 - <all physical memory> */
if ((zfs_arc_sys_free) && (zfs_arc_sys_free != arc_sys_free))
- arc_sys_free = MIN(MAX(zfs_arc_sys_free, 0), allmem);
+ arc_sys_free = MIN(zfs_arc_sys_free, allmem);
WARN_IF_TUNING_IGNORED(zfs_arc_sys_free, arc_sys_free, verbose);
}
@@ -7680,6 +7250,10 @@ arc_state_init(void)
arc_state_multilist_index_func, &num_sublists);
arc_state_multilist_init(&arc_mfu_ghost->arcs_list[ARC_BUFC_DATA],
arc_state_multilist_index_func, &num_sublists);
+ arc_state_multilist_init(&arc_uncached->arcs_list[ARC_BUFC_METADATA],
+ arc_state_multilist_index_func, &num_sublists);
+ arc_state_multilist_init(&arc_uncached->arcs_list[ARC_BUFC_DATA],
+ arc_state_multilist_index_func, &num_sublists);
/*
* L2 headers should never be on the L2 state list since they don't
@@ -7709,28 +7283,49 @@ arc_state_init(void)
zfs_refcount_create(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
zfs_refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
zfs_refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
-
- zfs_refcount_create(&arc_anon->arcs_size);
- zfs_refcount_create(&arc_mru->arcs_size);
- zfs_refcount_create(&arc_mru_ghost->arcs_size);
- zfs_refcount_create(&arc_mfu->arcs_size);
- zfs_refcount_create(&arc_mfu_ghost->arcs_size);
- zfs_refcount_create(&arc_l2c_only->arcs_size);
+ zfs_refcount_create(&arc_uncached->arcs_esize[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_uncached->arcs_esize[ARC_BUFC_DATA]);
+
+ zfs_refcount_create(&arc_anon->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_anon->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_mru->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_mru->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_mru_ghost->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_mru_ghost->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_mfu->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_mfu->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_mfu_ghost->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_mfu_ghost->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_l2c_only->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_l2c_only->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_create(&arc_uncached->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_create(&arc_uncached->arcs_size[ARC_BUFC_METADATA]);
+
+ wmsum_init(&arc_mru_ghost->arcs_hits[ARC_BUFC_DATA], 0);
+ wmsum_init(&arc_mru_ghost->arcs_hits[ARC_BUFC_METADATA], 0);
+ wmsum_init(&arc_mfu_ghost->arcs_hits[ARC_BUFC_DATA], 0);
+ wmsum_init(&arc_mfu_ghost->arcs_hits[ARC_BUFC_METADATA], 0);
wmsum_init(&arc_sums.arcstat_hits, 0);
+ wmsum_init(&arc_sums.arcstat_iohits, 0);
wmsum_init(&arc_sums.arcstat_misses, 0);
wmsum_init(&arc_sums.arcstat_demand_data_hits, 0);
+ wmsum_init(&arc_sums.arcstat_demand_data_iohits, 0);
wmsum_init(&arc_sums.arcstat_demand_data_misses, 0);
wmsum_init(&arc_sums.arcstat_demand_metadata_hits, 0);
+ wmsum_init(&arc_sums.arcstat_demand_metadata_iohits, 0);
wmsum_init(&arc_sums.arcstat_demand_metadata_misses, 0);
wmsum_init(&arc_sums.arcstat_prefetch_data_hits, 0);
+ wmsum_init(&arc_sums.arcstat_prefetch_data_iohits, 0);
wmsum_init(&arc_sums.arcstat_prefetch_data_misses, 0);
wmsum_init(&arc_sums.arcstat_prefetch_metadata_hits, 0);
+ wmsum_init(&arc_sums.arcstat_prefetch_metadata_iohits, 0);
wmsum_init(&arc_sums.arcstat_prefetch_metadata_misses, 0);
wmsum_init(&arc_sums.arcstat_mru_hits, 0);
wmsum_init(&arc_sums.arcstat_mru_ghost_hits, 0);
wmsum_init(&arc_sums.arcstat_mfu_hits, 0);
wmsum_init(&arc_sums.arcstat_mfu_ghost_hits, 0);
+ wmsum_init(&arc_sums.arcstat_uncached_hits, 0);
wmsum_init(&arc_sums.arcstat_deleted, 0);
wmsum_init(&arc_sums.arcstat_mutex_miss, 0);
wmsum_init(&arc_sums.arcstat_access_skip, 0);
@@ -7752,7 +7347,7 @@ arc_state_init(void)
wmsum_init(&arc_sums.arcstat_data_size, 0);
wmsum_init(&arc_sums.arcstat_metadata_size, 0);
wmsum_init(&arc_sums.arcstat_dbuf_size, 0);
- aggsum_init(&arc_sums.arcstat_dnode_size, 0);
+ wmsum_init(&arc_sums.arcstat_dnode_size, 0);
wmsum_init(&arc_sums.arcstat_bonus_size, 0);
wmsum_init(&arc_sums.arcstat_l2_hits, 0);
wmsum_init(&arc_sums.arcstat_l2_misses, 0);
@@ -7797,10 +7392,14 @@ arc_state_init(void)
wmsum_init(&arc_sums.arcstat_memory_direct_count, 0);
wmsum_init(&arc_sums.arcstat_memory_indirect_count, 0);
wmsum_init(&arc_sums.arcstat_prune, 0);
- aggsum_init(&arc_sums.arcstat_meta_used, 0);
+ wmsum_init(&arc_sums.arcstat_meta_used, 0);
wmsum_init(&arc_sums.arcstat_async_upgrade_sync, 0);
+ wmsum_init(&arc_sums.arcstat_predictive_prefetch, 0);
wmsum_init(&arc_sums.arcstat_demand_hit_predictive_prefetch, 0);
+ wmsum_init(&arc_sums.arcstat_demand_iohit_predictive_prefetch, 0);
+ wmsum_init(&arc_sums.arcstat_prescient_prefetch, 0);
wmsum_init(&arc_sums.arcstat_demand_hit_prescient_prefetch, 0);
+ wmsum_init(&arc_sums.arcstat_demand_iohit_prescient_prefetch, 0);
wmsum_init(&arc_sums.arcstat_raw_size, 0);
wmsum_init(&arc_sums.arcstat_cached_only_in_progress, 0);
wmsum_init(&arc_sums.arcstat_abd_chunk_waste_size, 0);
@@ -7811,6 +7410,7 @@ arc_state_init(void)
arc_mfu->arcs_state = ARC_STATE_MFU;
arc_mfu_ghost->arcs_state = ARC_STATE_MFU_GHOST;
arc_l2c_only->arcs_state = ARC_STATE_L2C_ONLY;
+ arc_uncached->arcs_state = ARC_STATE_UNCACHED;
}
static void
@@ -7828,13 +7428,23 @@ arc_state_fini(void)
zfs_refcount_destroy(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
zfs_refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
zfs_refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
-
- zfs_refcount_destroy(&arc_anon->arcs_size);
- zfs_refcount_destroy(&arc_mru->arcs_size);
- zfs_refcount_destroy(&arc_mru_ghost->arcs_size);
- zfs_refcount_destroy(&arc_mfu->arcs_size);
- zfs_refcount_destroy(&arc_mfu_ghost->arcs_size);
- zfs_refcount_destroy(&arc_l2c_only->arcs_size);
+ zfs_refcount_destroy(&arc_uncached->arcs_esize[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_uncached->arcs_esize[ARC_BUFC_DATA]);
+
+ zfs_refcount_destroy(&arc_anon->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_anon->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_mru->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_mru->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_mru_ghost->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_mru_ghost->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_mfu->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_mfu->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_mfu_ghost->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_mfu_ghost->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_l2c_only->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_l2c_only->arcs_size[ARC_BUFC_METADATA]);
+ zfs_refcount_destroy(&arc_uncached->arcs_size[ARC_BUFC_DATA]);
+ zfs_refcount_destroy(&arc_uncached->arcs_size[ARC_BUFC_METADATA]);
multilist_destroy(&arc_mru->arcs_list[ARC_BUFC_METADATA]);
multilist_destroy(&arc_mru_ghost->arcs_list[ARC_BUFC_METADATA]);
@@ -7846,21 +7456,34 @@ arc_state_fini(void)
multilist_destroy(&arc_mfu_ghost->arcs_list[ARC_BUFC_DATA]);
multilist_destroy(&arc_l2c_only->arcs_list[ARC_BUFC_METADATA]);
multilist_destroy(&arc_l2c_only->arcs_list[ARC_BUFC_DATA]);
+ multilist_destroy(&arc_uncached->arcs_list[ARC_BUFC_METADATA]);
+ multilist_destroy(&arc_uncached->arcs_list[ARC_BUFC_DATA]);
+
+ wmsum_fini(&arc_mru_ghost->arcs_hits[ARC_BUFC_DATA]);
+ wmsum_fini(&arc_mru_ghost->arcs_hits[ARC_BUFC_METADATA]);
+ wmsum_fini(&arc_mfu_ghost->arcs_hits[ARC_BUFC_DATA]);
+ wmsum_fini(&arc_mfu_ghost->arcs_hits[ARC_BUFC_METADATA]);
wmsum_fini(&arc_sums.arcstat_hits);
+ wmsum_fini(&arc_sums.arcstat_iohits);
wmsum_fini(&arc_sums.arcstat_misses);
wmsum_fini(&arc_sums.arcstat_demand_data_hits);
+ wmsum_fini(&arc_sums.arcstat_demand_data_iohits);
wmsum_fini(&arc_sums.arcstat_demand_data_misses);
wmsum_fini(&arc_sums.arcstat_demand_metadata_hits);
+ wmsum_fini(&arc_sums.arcstat_demand_metadata_iohits);
wmsum_fini(&arc_sums.arcstat_demand_metadata_misses);
wmsum_fini(&arc_sums.arcstat_prefetch_data_hits);
+ wmsum_fini(&arc_sums.arcstat_prefetch_data_iohits);
wmsum_fini(&arc_sums.arcstat_prefetch_data_misses);
wmsum_fini(&arc_sums.arcstat_prefetch_metadata_hits);
+ wmsum_fini(&arc_sums.arcstat_prefetch_metadata_iohits);
wmsum_fini(&arc_sums.arcstat_prefetch_metadata_misses);
wmsum_fini(&arc_sums.arcstat_mru_hits);
wmsum_fini(&arc_sums.arcstat_mru_ghost_hits);
wmsum_fini(&arc_sums.arcstat_mfu_hits);
wmsum_fini(&arc_sums.arcstat_mfu_ghost_hits);
+ wmsum_fini(&arc_sums.arcstat_uncached_hits);
wmsum_fini(&arc_sums.arcstat_deleted);
wmsum_fini(&arc_sums.arcstat_mutex_miss);
wmsum_fini(&arc_sums.arcstat_access_skip);
@@ -7882,7 +7505,7 @@ arc_state_fini(void)
wmsum_fini(&arc_sums.arcstat_data_size);
wmsum_fini(&arc_sums.arcstat_metadata_size);
wmsum_fini(&arc_sums.arcstat_dbuf_size);
- aggsum_fini(&arc_sums.arcstat_dnode_size);
+ wmsum_fini(&arc_sums.arcstat_dnode_size);
wmsum_fini(&arc_sums.arcstat_bonus_size);
wmsum_fini(&arc_sums.arcstat_l2_hits);
wmsum_fini(&arc_sums.arcstat_l2_misses);
@@ -7927,10 +7550,14 @@ arc_state_fini(void)
wmsum_fini(&arc_sums.arcstat_memory_direct_count);
wmsum_fini(&arc_sums.arcstat_memory_indirect_count);
wmsum_fini(&arc_sums.arcstat_prune);
- aggsum_fini(&arc_sums.arcstat_meta_used);
+ wmsum_fini(&arc_sums.arcstat_meta_used);
wmsum_fini(&arc_sums.arcstat_async_upgrade_sync);
+ wmsum_fini(&arc_sums.arcstat_predictive_prefetch);
wmsum_fini(&arc_sums.arcstat_demand_hit_predictive_prefetch);
+ wmsum_fini(&arc_sums.arcstat_demand_iohit_predictive_prefetch);
+ wmsum_fini(&arc_sums.arcstat_prescient_prefetch);
wmsum_fini(&arc_sums.arcstat_demand_hit_prescient_prefetch);
+ wmsum_fini(&arc_sums.arcstat_demand_iohit_prescient_prefetch);
wmsum_fini(&arc_sums.arcstat_raw_size);
wmsum_fini(&arc_sums.arcstat_cached_only_in_progress);
wmsum_fini(&arc_sums.arcstat_abd_chunk_waste_size);
@@ -7995,18 +7622,16 @@ arc_init(void)
#endif
arc_c = arc_c_min;
- arc_p = (arc_c >> 1);
-
- /* Set min to 1/2 of arc_c_min */
- arc_meta_min = 1ULL << SPA_MAXBLOCKSHIFT;
/*
- * Set arc_meta_limit to a percent of arc_c_max with a floor of
- * arc_meta_min, and a ceiling of arc_c_max.
+ * 32-bit fixed point fractions of metadata from total ARC size,
+ * MRU data from all data and MRU metadata from all metadata.
*/
- percent = MIN(zfs_arc_meta_limit_percent, 100);
- arc_meta_limit = MAX(arc_meta_min, (percent * arc_c_max) / 100);
+ arc_meta = (1ULL << 32) / 4; /* Metadata is 25% of arc_c. */
+ arc_pd = (1ULL << 32) / 2; /* Data MRU is 50% of data. */
+ arc_pm = (1ULL << 32) / 2; /* Metadata MRU is 50% of metadata. */
+
percent = MIN(zfs_arc_dnode_limit_percent, 100);
- arc_dnode_size_limit = (percent * arc_meta_limit) / 100;
+ arc_dnode_limit = arc_c_max * percent / 100;
/* Apply user specified tunings */
arc_tuning_update(B_TRUE);
@@ -8041,8 +7666,8 @@ arc_init(void)
arc_state_evict_markers =
arc_state_alloc_markers(arc_state_evict_marker_count);
- arc_evict_zthr = zthr_create("arc_evict",
- arc_evict_cb_check, arc_evict_cb, NULL, defclsyspri);
+ arc_evict_zthr = zthr_create_timer("arc_evict",
+ arc_evict_cb_check, arc_evict_cb, NULL, SEC2NSEC(1), defclsyspri);
arc_reap_zthr = zthr_create_timer("arc_reap",
arc_reap_cb_check, arc_reap_cb, NULL, SEC2NSEC(1), minclsyspri);
@@ -8107,9 +7732,8 @@ arc_fini(void)
taskq_destroy(arc_prune_taskq);
mutex_enter(&arc_prune_mtx);
- while ((p = list_head(&arc_prune_list)) != NULL) {
- list_remove(&arc_prune_list, p);
- zfs_refcount_remove(&p->p_refcnt, &arc_prune_list);
+ while ((p = list_remove_head(&arc_prune_list)) != NULL) {
+ (void) zfs_refcount_remove(&p->p_refcnt, &arc_prune_list);
zfs_refcount_destroy(&p->p_refcnt);
kmem_free(p, sizeof (*p));
}
@@ -8416,7 +8040,7 @@ l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *hdr)
static uint64_t
l2arc_write_size(l2arc_dev_t *dev)
{
- uint64_t size, dev_size, tsize;
+ uint64_t size;
/*
* Make sure our globals have meaningful values in case the user
@@ -8424,38 +8048,33 @@ l2arc_write_size(l2arc_dev_t *dev)
*/
size = l2arc_write_max;
if (size == 0) {
- cmn_err(CE_NOTE, "Bad value for l2arc_write_max, value must "
- "be greater than zero, resetting it to the default (%d)",
- L2ARC_WRITE_SIZE);
+ cmn_err(CE_NOTE, "l2arc_write_max must be greater than zero, "
+ "resetting it to the default (%d)", L2ARC_WRITE_SIZE);
size = l2arc_write_max = L2ARC_WRITE_SIZE;
}
if (arc_warm == B_FALSE)
size += l2arc_write_boost;
+ /* We need to add in the worst case scenario of log block overhead. */
+ size += l2arc_log_blk_overhead(size, dev);
+ if (dev->l2ad_vdev->vdev_has_trim && l2arc_trim_ahead > 0) {
+ /*
+ * Trim ahead of the write size 64MB or (l2arc_trim_ahead/100)
+ * times the writesize, whichever is greater.
+ */
+ size += MAX(64 * 1024 * 1024,
+ (size * l2arc_trim_ahead) / 100);
+ }
+
/*
* Make sure the write size does not exceed the size of the cache
* device. This is important in l2arc_evict(), otherwise infinite
* iteration can occur.
*/
- dev_size = dev->l2ad_end - dev->l2ad_start;
- tsize = size + l2arc_log_blk_overhead(size, dev);
- if (dev->l2ad_vdev->vdev_has_trim && l2arc_trim_ahead > 0)
- tsize += MAX(64 * 1024 * 1024,
- (tsize * l2arc_trim_ahead) / 100);
-
- if (tsize >= dev_size) {
- cmn_err(CE_NOTE, "l2arc_write_max or l2arc_write_boost "
- "plus the overhead of log blocks (persistent L2ARC, "
- "%llu bytes) exceeds the size of the cache device "
- "(guid %llu), resetting them to the default (%d)",
- (u_longlong_t)l2arc_log_blk_overhead(size, dev),
- (u_longlong_t)dev->l2ad_vdev->vdev_guid, L2ARC_WRITE_SIZE);
- size = l2arc_write_max = l2arc_write_boost = L2ARC_WRITE_SIZE;
+ size = MIN(size, (dev->l2ad_end - dev->l2ad_start) / 4);
- if (arc_warm == B_FALSE)
- size += l2arc_write_boost;
- }
+ size = P2ROUNDUP(size, 1ULL << dev->l2ad_vdev->vdev_ashift);
return (size);
@@ -8522,6 +8141,7 @@ l2arc_dev_get_next(void)
else if (next == first)
break;
+ ASSERT3P(next, !=, NULL);
} while (vdev_is_dead(next->l2ad_vdev) || next->l2ad_rebuild ||
next->l2ad_trim_all);
@@ -8552,20 +8172,14 @@ out:
static void
l2arc_do_free_on_write(void)
{
- list_t *buflist;
- l2arc_data_free_t *df, *df_prev;
+ l2arc_data_free_t *df;
mutex_enter(&l2arc_free_on_write_mtx);
- buflist = l2arc_free_on_write;
-
- for (df = list_tail(buflist); df; df = df_prev) {
- df_prev = list_prev(buflist, df);
+ while ((df = list_remove_head(l2arc_free_on_write)) != NULL) {
ASSERT3P(df->l2df_abd, !=, NULL);
abd_free(df->l2df_abd);
- list_remove(buflist, df);
kmem_free(df, sizeof (l2arc_data_free_t));
}
-
mutex_exit(&l2arc_free_on_write_mtx);
}
@@ -8700,7 +8314,8 @@ top:
ARCSTAT_BUMPDOWN(arcstat_l2_log_blk_count);
zfs_refcount_remove_many(&dev->l2ad_lb_asize, asize,
lb_ptr_buf);
- zfs_refcount_remove(&dev->l2ad_lb_count, lb_ptr_buf);
+ (void) zfs_refcount_remove(&dev->l2ad_lb_count,
+ lb_ptr_buf);
kmem_free(lb_ptr_buf->lb_ptr,
sizeof (l2arc_log_blkptr_t));
kmem_free(lb_ptr_buf, sizeof (l2arc_lb_ptr_buf_t));
@@ -8782,7 +8397,7 @@ l2arc_untransform(zio_t *zio, l2arc_read_callback_t *cb)
*/
if (BP_IS_ENCRYPTED(bp)) {
abd_t *eabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr,
- ARC_HDR_DO_ADAPT | ARC_HDR_USE_RESERVE);
+ ARC_HDR_USE_RESERVE);
zio_crypt_decode_params_bp(bp, salt, iv);
zio_crypt_decode_mac_bp(bp, mac);
@@ -8819,7 +8434,7 @@ l2arc_untransform(zio_t *zio, l2arc_read_callback_t *cb)
if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF &&
!HDR_COMPRESSION_ENABLED(hdr)) {
abd_t *cabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr,
- ARC_HDR_DO_ADAPT | ARC_HDR_USE_RESERVE);
+ ARC_HDR_USE_RESERVE);
void *tmp = abd_borrow_buf(cabd, arc_hdr_size(hdr));
ret = zio_decompress_data(HDR_GET_COMPRESS(hdr),
@@ -9031,7 +8646,7 @@ l2arc_sublist_lock(int list_num)
* sublists being selected.
*/
idx = multilist_get_random_index(ml);
- return (multilist_sublist_lock(ml, idx));
+ return (multilist_sublist_lock_idx(ml, idx));
}
/*
@@ -9076,22 +8691,9 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
buflist = &dev->l2ad_buflist;
- /*
- * We need to add in the worst case scenario of log block overhead.
- */
- distance += l2arc_log_blk_overhead(distance, dev);
- if (vd->vdev_has_trim && l2arc_trim_ahead > 0) {
- /*
- * Trim ahead of the write size 64MB or (l2arc_trim_ahead/100)
- * times the write size, whichever is greater.
- */
- distance += MAX(64 * 1024 * 1024,
- (distance * l2arc_trim_ahead) / 100);
- }
-
top:
rerun = B_FALSE;
- if (dev->l2ad_hand >= (dev->l2ad_end - distance)) {
+ if (dev->l2ad_hand + distance > dev->l2ad_end) {
/*
* When there is no space to accommodate upcoming writes,
* evict to the end. Then bump the write and evict hands
@@ -9184,7 +8786,8 @@ retry:
ARCSTAT_BUMPDOWN(arcstat_l2_log_blk_count);
zfs_refcount_remove_many(&dev->l2ad_lb_asize, asize,
lb_ptr_buf);
- zfs_refcount_remove(&dev->l2ad_lb_count, lb_ptr_buf);
+ (void) zfs_refcount_remove(&dev->l2ad_lb_count,
+ lb_ptr_buf);
list_remove(&dev->l2ad_lbptr_list, lb_ptr_buf);
kmem_free(lb_ptr_buf->lb_ptr,
sizeof (l2arc_log_blkptr_t));
@@ -9240,7 +8843,7 @@ retry:
* arc_hdr_destroy() will call list_remove()
* and decrement arcstat_l2_lsize.
*/
- arc_change_state(arc_anon, hdr, hash_lock);
+ arc_change_state(arc_anon, hdr);
arc_hdr_destroy(hdr);
} else {
ASSERT(hdr->b_l1hdr.b_state != arc_l2c_only);
@@ -9285,7 +8888,7 @@ out:
*/
ASSERT3U(dev->l2ad_hand + distance, <, dev->l2ad_end);
if (!dev->l2ad_first)
- ASSERT3U(dev->l2ad_hand, <, dev->l2ad_evict);
+ ASSERT3U(dev->l2ad_hand, <=, dev->l2ad_evict);
}
}
@@ -9299,7 +8902,6 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
abd_t **abd_out)
{
int ret;
- void *tmp = NULL;
abd_t *cabd = NULL, *eabd = NULL, *to_write = hdr->b_l1hdr.b_pabd;
enum zio_compress compress = HDR_GET_COMPRESS(hdr);
uint64_t psize = HDR_GET_PSIZE(hdr);
@@ -9320,12 +8922,11 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
* and copy the data. This may be done to eliminate a dependency on a
* shared buffer or to reallocate the buffer to match asize.
*/
- if (HDR_HAS_RABD(hdr) && asize != psize) {
- ASSERT3U(asize, >=, psize);
+ if (HDR_HAS_RABD(hdr)) {
+ ASSERT3U(asize, >, psize);
to_write = abd_alloc_for_io(asize, ismd);
abd_copy(to_write, hdr->b_crypt_hdr.b_rabd, psize);
- if (psize != asize)
- abd_zero_off(to_write, psize, asize - psize);
+ abd_zero_off(to_write, psize, asize - psize);
goto out;
}
@@ -9334,47 +8935,31 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
ASSERT3U(size, ==, psize);
to_write = abd_alloc_for_io(asize, ismd);
abd_copy(to_write, hdr->b_l1hdr.b_pabd, size);
- if (size != asize)
+ if (asize > size)
abd_zero_off(to_write, size, asize - size);
goto out;
}
if (compress != ZIO_COMPRESS_OFF && !HDR_COMPRESSION_ENABLED(hdr)) {
- /*
- * In some cases, we can wind up with size > asize, so
- * we need to opt for the larger allocation option here.
- *
- * (We also need abd_return_buf_copy in all cases because
- * it's an ASSERT() to modify the buffer before returning it
- * with arc_return_buf(), and all the compressors
- * write things before deciding to fail compression in nearly
- * every case.)
- */
- cabd = abd_alloc_for_io(size, ismd);
- tmp = abd_borrow_buf(cabd, size);
-
- psize = zio_compress_data(compress, to_write, tmp, size,
- hdr->b_complevel);
-
- if (psize >= asize) {
- psize = HDR_GET_PSIZE(hdr);
- abd_return_buf_copy(cabd, tmp, size);
- HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
- to_write = cabd;
- abd_copy(to_write, hdr->b_l1hdr.b_pabd, psize);
- if (psize != asize)
- abd_zero_off(to_write, psize, asize - psize);
- goto encrypt;
+ size_t bufsize = MAX(size, asize);
+ void *buf = zio_buf_alloc(bufsize);
+ uint64_t csize = zio_compress_data(compress, to_write, &buf,
+ size, hdr->b_complevel);
+ if (csize > psize) {
+ /*
+ * We can't re-compress the block into the original
+ * psize. Even if it fits into asize, it does not
+ * matter, since checksum will never match on read.
+ */
+ zio_buf_free(buf, bufsize);
+ return (SET_ERROR(EIO));
}
- ASSERT3U(psize, <=, HDR_GET_PSIZE(hdr));
- if (psize < asize)
- memset((char *)tmp + psize, 0, asize - psize);
- psize = HDR_GET_PSIZE(hdr);
- abd_return_buf_copy(cabd, tmp, size);
- to_write = cabd;
+ if (asize > csize)
+ memset((char *)buf + csize, 0, asize - csize);
+ to_write = cabd = abd_get_from_buf(buf, bufsize);
+ abd_take_ownership_of_buf(cabd, B_TRUE);
}
-encrypt:
if (HDR_ENCRYPTED(hdr)) {
eabd = abd_alloc_for_io(asize, ismd);
@@ -9455,9 +9040,9 @@ l2arc_blk_fetch_done(zio_t *zio)
static uint64_t
l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
{
- arc_buf_hdr_t *hdr, *hdr_prev, *head;
- uint64_t write_asize, write_psize, write_lsize, headroom;
- boolean_t full;
+ arc_buf_hdr_t *hdr, *head, *marker;
+ uint64_t write_asize, write_psize, headroom;
+ boolean_t full, from_head = !arc_warm;
l2arc_write_callback_t *cb = NULL;
zio_t *pio, *wzio;
uint64_t guid = spa_load_guid(spa);
@@ -9466,10 +9051,11 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
ASSERT3P(dev->l2ad_vdev, !=, NULL);
pio = NULL;
- write_lsize = write_asize = write_psize = 0;
+ write_asize = write_psize = 0;
full = B_FALSE;
head = kmem_cache_alloc(hdr_l2only_cache, KM_PUSHPAGE);
arc_hdr_set_flags(head, ARC_FLAG_L2_WRITE_HEAD | ARC_FLAG_HAS_L2HDR);
+ marker = arc_state_alloc_marker();
/*
* Copy buffers for L2ARC writing.
@@ -9484,40 +9070,34 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
continue;
}
- multilist_sublist_t *mls = l2arc_sublist_lock(pass);
uint64_t passed_sz = 0;
-
- VERIFY3P(mls, !=, NULL);
+ headroom = target_sz * l2arc_headroom;
+ if (zfs_compressed_arc_enabled)
+ headroom = (headroom * l2arc_headroom_boost) / 100;
/*
- * L2ARC fast warmup.
- *
* Until the ARC is warm and starts to evict, read from the
* head of the ARC lists rather than the tail.
*/
- if (arc_warm == B_FALSE)
+ multilist_sublist_t *mls = l2arc_sublist_lock(pass);
+ ASSERT3P(mls, !=, NULL);
+ if (from_head)
hdr = multilist_sublist_head(mls);
else
hdr = multilist_sublist_tail(mls);
- headroom = target_sz * l2arc_headroom;
- if (zfs_compressed_arc_enabled)
- headroom = (headroom * l2arc_headroom_boost) / 100;
-
- for (; hdr; hdr = hdr_prev) {
+ while (hdr != NULL) {
kmutex_t *hash_lock;
abd_t *to_write = NULL;
- if (arc_warm == B_FALSE)
- hdr_prev = multilist_sublist_next(mls, hdr);
- else
- hdr_prev = multilist_sublist_prev(mls, hdr);
-
hash_lock = HDR_LOCK(hdr);
if (!mutex_tryenter(hash_lock)) {
- /*
- * Skip this buffer rather than waiting.
- */
+skip:
+ /* Skip this buffer rather than waiting. */
+ if (from_head)
+ hdr = multilist_sublist_next(mls, hdr);
+ else
+ hdr = multilist_sublist_prev(mls, hdr);
continue;
}
@@ -9532,11 +9112,10 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
if (!l2arc_write_eligible(guid, hdr)) {
mutex_exit(hash_lock);
- continue;
+ goto skip;
}
ASSERT(HDR_HAS_L1HDR(hdr));
-
ASSERT3U(HDR_GET_PSIZE(hdr), >, 0);
ASSERT3U(arc_hdr_size(hdr), >, 0);
ASSERT(hdr->b_l1hdr.b_pabd != NULL ||
@@ -9545,19 +9124,31 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
psize);
- if ((write_asize + asize) > target_sz) {
+ /*
+ * If the allocated size of this buffer plus the max
+ * size for the pending log block exceeds the evicted
+ * target size, terminate writing buffers for this run.
+ */
+ if (write_asize + asize +
+ sizeof (l2arc_log_blk_phys_t) > target_sz) {
full = B_TRUE;
mutex_exit(hash_lock);
break;
}
/*
- * We rely on the L1 portion of the header below, so
- * it's invalid for this header to have been evicted out
- * of the ghost cache, prior to being written out. The
- * ARC_FLAG_L2_WRITING bit ensures this won't happen.
+ * We should not sleep with sublist lock held or it
+ * may block ARC eviction. Insert a marker to save
+ * the position and drop the lock.
*/
- arc_hdr_set_flags(hdr, ARC_FLAG_L2_WRITING);
+ if (from_head) {
+ multilist_sublist_insert_after(mls, hdr,
+ marker);
+ } else {
+ multilist_sublist_insert_before(mls, hdr,
+ marker);
+ }
+ multilist_sublist_unlock(mls);
/*
* If this header has b_rabd, we can use this since it
@@ -9588,32 +9179,45 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
&to_write);
if (ret != 0) {
arc_hdr_clear_flags(hdr,
- ARC_FLAG_L2_WRITING);
+ ARC_FLAG_L2CACHE);
mutex_exit(hash_lock);
- continue;
+ goto next;
}
l2arc_free_abd_on_write(to_write, asize, type);
}
+ hdr->b_l2hdr.b_dev = dev;
+ hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
+ hdr->b_l2hdr.b_hits = 0;
+ hdr->b_l2hdr.b_arcs_state =
+ hdr->b_l1hdr.b_state->arcs_state;
+ mutex_enter(&dev->l2ad_mtx);
if (pio == NULL) {
/*
* Insert a dummy header on the buflist so
* l2arc_write_done() can find where the
* write buffers begin without searching.
*/
- mutex_enter(&dev->l2ad_mtx);
list_insert_head(&dev->l2ad_buflist, head);
- mutex_exit(&dev->l2ad_mtx);
+ }
+ list_insert_head(&dev->l2ad_buflist, hdr);
+ mutex_exit(&dev->l2ad_mtx);
+ arc_hdr_set_flags(hdr, ARC_FLAG_HAS_L2HDR |
+ ARC_FLAG_L2_WRITING);
+
+ (void) zfs_refcount_add_many(&dev->l2ad_alloc,
+ arc_hdr_size(hdr), hdr);
+ l2arc_hdr_arcstats_increment(hdr);
+ boolean_t commit = l2arc_log_blk_insert(dev, hdr);
+ mutex_exit(hash_lock);
+
+ if (pio == NULL) {
cb = kmem_alloc(
sizeof (l2arc_write_callback_t), KM_SLEEP);
cb->l2wcb_dev = dev;
cb->l2wcb_head = head;
- /*
- * Create a list to save allocated abd buffers
- * for l2arc_log_blk_commit().
- */
list_create(&cb->l2wcb_abd_list,
sizeof (l2arc_lb_abd_buf_t),
offsetof(l2arc_lb_abd_buf_t, node));
@@ -9621,48 +9225,34 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
ZIO_FLAG_CANFAIL);
}
- hdr->b_l2hdr.b_dev = dev;
- hdr->b_l2hdr.b_hits = 0;
-
- hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
- hdr->b_l2hdr.b_arcs_state =
- hdr->b_l1hdr.b_state->arcs_state;
- arc_hdr_set_flags(hdr, ARC_FLAG_HAS_L2HDR);
-
- mutex_enter(&dev->l2ad_mtx);
- list_insert_head(&dev->l2ad_buflist, hdr);
- mutex_exit(&dev->l2ad_mtx);
-
- (void) zfs_refcount_add_many(&dev->l2ad_alloc,
- arc_hdr_size(hdr), hdr);
-
wzio = zio_write_phys(pio, dev->l2ad_vdev,
- hdr->b_l2hdr.b_daddr, asize, to_write,
+ dev->l2ad_hand, asize, to_write,
ZIO_CHECKSUM_OFF, NULL, hdr,
ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_CANFAIL, B_FALSE);
- write_lsize += HDR_GET_LSIZE(hdr);
DTRACE_PROBE2(l2arc__write, vdev_t *, dev->l2ad_vdev,
zio_t *, wzio);
+ zio_nowait(wzio);
write_psize += psize;
write_asize += asize;
dev->l2ad_hand += asize;
- l2arc_hdr_arcstats_increment(hdr);
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);
- mutex_exit(hash_lock);
-
- /*
- * Append buf info to current log and commit if full.
- * arcstat_l2_{size,asize} kstats are updated
- * internally.
- */
- if (l2arc_log_blk_insert(dev, hdr))
- l2arc_log_blk_commit(dev, pio, cb);
+ if (commit) {
+ /* l2ad_hand will be adjusted inside. */
+ write_asize +=
+ l2arc_log_blk_commit(dev, pio, cb);
+ }
- zio_nowait(wzio);
+next:
+ multilist_sublist_lock(mls);
+ if (from_head)
+ hdr = multilist_sublist_next(mls, marker);
+ else
+ hdr = multilist_sublist_prev(mls, marker);
+ multilist_sublist_remove(mls, marker);
}
multilist_sublist_unlock(mls);
@@ -9671,9 +9261,11 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
break;
}
+ arc_state_free_marker(marker);
+
/* No buffers selected for writing? */
if (pio == NULL) {
- ASSERT0(write_lsize);
+ ASSERT0(write_psize);
ASSERT(!HDR_HAS_L1HDR(head));
kmem_cache_free(hdr_l2only_cache, head);
@@ -9713,7 +9305,7 @@ l2arc_hdr_limit_reached(void)
{
int64_t s = aggsum_upper_bound(&arc_sums.arcstat_l2_hdr_size);
- return (arc_reclaim_needed() || (s > arc_meta_limit * 3 / 4) ||
+ return (arc_reclaim_needed() ||
(s > (arc_warm ? arc_c : arc_c_max) * l2arc_meta_percent / 100));
}
@@ -10317,7 +9909,7 @@ l2arc_rebuild(l2arc_dev_t *dev)
!dev->l2ad_first)
goto out;
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
for (;;) {
mutex_enter(&l2arc_rebuild_thr_lock);
if (dev->l2ad_rebuild_cancel) {
@@ -10419,8 +10011,7 @@ l2arc_dev_hdr_read(l2arc_dev_t *dev)
err = zio_wait(zio_read_phys(NULL, dev->l2ad_vdev,
VDEV_LABEL_START_SIZE, l2dhdr_asize, abd,
ZIO_CHECKSUM_LABEL, NULL, NULL, ZIO_PRIORITY_SYNC_READ,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
- ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
ZIO_FLAG_SPECULATIVE, B_FALSE));
abd_free(abd);
@@ -10603,7 +10194,7 @@ l2arc_log_blk_restore(l2arc_dev_t *dev, const l2arc_log_blk_phys_t *lb,
* since we may allocate significant amount of memory here, let ARC
* grow its arc_c.
*/
- arc_adapt(log_entries * HDR_L2ONLY_SIZE, arc_l2c_only);
+ arc_adapt(log_entries * HDR_L2ONLY_SIZE);
for (int i = log_entries - 1; i >= 0; i--) {
/*
@@ -10740,11 +10331,10 @@ l2arc_log_blk_fetch(vdev_t *vd, const l2arc_log_blkptr_t *lbp,
cb = kmem_zalloc(sizeof (l2arc_read_callback_t), KM_SLEEP);
cb->l2rcb_abd = abd_get_from_buf(lb, asize);
pio = zio_root(vd->vdev_spa, l2arc_blk_fetch_done, cb,
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE |
- ZIO_FLAG_DONT_RETRY);
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY);
(void) zio_nowait(zio_read_phys(pio, vd, lbp->lbp_daddr, asize,
cb->l2rcb_abd, ZIO_CHECKSUM_OFF, NULL, NULL,
- ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL |
ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY, B_FALSE));
return (pio);
@@ -10810,7 +10400,7 @@ l2arc_dev_hdr_update(l2arc_dev_t *dev)
* This function allocates some memory to temporarily hold the serialized
* buffer to be written. This is then released in l2arc_write_done.
*/
-static void
+static uint64_t
l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
{
l2arc_log_blk_phys_t *lb = &dev->l2ad_log_blk;
@@ -10818,12 +10408,11 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
uint64_t psize, asize;
zio_t *wzio;
l2arc_lb_abd_buf_t *abd_buf;
- uint8_t *tmpbuf;
+ uint8_t *tmpbuf = NULL;
l2arc_lb_ptr_buf_t *lb_ptr_buf;
VERIFY3S(dev->l2ad_log_ent_idx, ==, dev->l2ad_log_entries);
- tmpbuf = zio_buf_alloc(sizeof (*lb));
abd_buf = zio_buf_alloc(sizeof (*abd_buf));
abd_buf->abd = abd_get_from_buf(lb, sizeof (*lb));
lb_ptr_buf = kmem_zalloc(sizeof (l2arc_lb_ptr_buf_t), KM_SLEEP);
@@ -10842,7 +10431,7 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
/* try to compress the buffer */
psize = zio_compress_data(ZIO_COMPRESS_LZ4,
- abd_buf->abd, tmpbuf, sizeof (*lb), 0);
+ abd_buf->abd, (void **) &tmpbuf, sizeof (*lb), 0);
/* a log block is never entirely zero */
ASSERT(psize != 0);
@@ -10922,6 +10511,8 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
dev->l2ad_log_ent_idx = 0;
dev->l2ad_log_blk_payload_asize = 0;
dev->l2ad_log_blk_payload_start = 0;
+
+ return (asize);
}
/*
@@ -11002,7 +10593,7 @@ l2arc_log_blk_insert(l2arc_dev_t *dev, const arc_buf_hdr_t *hdr)
L2BLK_SET_TYPE((le)->le_prop, hdr->b_type);
L2BLK_SET_PROTECTED((le)->le_prop, !!(HDR_PROTECTED(hdr)));
L2BLK_SET_PREFETCH((le)->le_prop, !!(HDR_PREFETCH(hdr)));
- L2BLK_SET_STATE((le)->le_prop, hdr->b_l1hdr.b_state->arcs_state);
+ L2BLK_SET_STATE((le)->le_prop, hdr->b_l2hdr.b_arcs_state);
dev->l2ad_log_blk_payload_asize += vdev_psize_to_asize(dev->l2ad_vdev,
HDR_GET_PSIZE(hdr));
@@ -11059,77 +10650,55 @@ EXPORT_SYMBOL(arc_add_prune_callback);
EXPORT_SYMBOL(arc_remove_prune_callback);
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, min, param_set_arc_min,
- param_get_long, ZMOD_RW, "Minimum ARC size in bytes");
+ spl_param_get_u64, ZMOD_RW, "Minimum ARC size in bytes");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, max, param_set_arc_max,
- param_get_long, ZMOD_RW, "Maximum ARC size in bytes");
-
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, meta_limit, param_set_arc_long,
- param_get_long, ZMOD_RW, "Metadata limit for ARC size in bytes");
-
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, meta_limit_percent,
- param_set_arc_long, param_get_long, ZMOD_RW,
- "Percent of ARC size for ARC meta limit");
+ spl_param_get_u64, ZMOD_RW, "Maximum ARC size in bytes");
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, meta_min, param_set_arc_long,
- param_get_long, ZMOD_RW, "Minimum ARC metadata size in bytes");
-
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, meta_prune, INT, ZMOD_RW,
- "Meta objects to scan for prune");
-
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, meta_adjust_restarts, INT, ZMOD_RW,
- "Limit number of restarts in arc_evict_meta");
-
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, meta_strategy, INT, ZMOD_RW,
- "Meta reclaim strategy");
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, meta_balance, UINT, ZMOD_RW,
+ "Balance between metadata and data on ghost hits.");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, grow_retry, param_set_arc_int,
- param_get_int, ZMOD_RW, "Seconds before growing ARC size");
-
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, p_dampener_disable, INT, ZMOD_RW,
- "Disable arc_p adapt dampener");
+ param_get_uint, ZMOD_RW, "Seconds before growing ARC size");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, shrink_shift, param_set_arc_int,
- param_get_int, ZMOD_RW, "log2(fraction of ARC to reclaim)");
+ param_get_uint, ZMOD_RW, "log2(fraction of ARC to reclaim)");
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, pc_percent, UINT, ZMOD_RW,
"Percent of pagecache to reclaim ARC to");
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, p_min_shift, param_set_arc_int,
- param_get_int, ZMOD_RW, "arc_c shift to calc min/max arc_p");
-
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, average_blocksize, INT, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, average_blocksize, UINT, ZMOD_RD,
"Target average block size");
ZFS_MODULE_PARAM(zfs, zfs_, compressed_arc_enabled, INT, ZMOD_RW,
"Disable compressed ARC buffers");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, min_prefetch_ms, param_set_arc_int,
- param_get_int, ZMOD_RW, "Min life of prefetch block in ms");
+ param_get_uint, ZMOD_RW, "Min life of prefetch block in ms");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, min_prescient_prefetch_ms,
- param_set_arc_int, param_get_int, ZMOD_RW,
+ param_set_arc_int, param_get_uint, ZMOD_RW,
"Min life of prescient prefetched block in ms");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, write_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, write_max, U64, ZMOD_RW,
"Max write bytes per interval");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, write_boost, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, write_boost, U64, ZMOD_RW,
"Extra write bytes during device warmup");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, headroom, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, headroom, U64, ZMOD_RW,
"Number of max device writes to precache");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, headroom_boost, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, headroom_boost, U64, ZMOD_RW,
"Compressed l2arc_headroom multiplier");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, trim_ahead, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, trim_ahead, U64, ZMOD_RW,
"TRIM ahead L2ARC write size multiplier");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, feed_secs, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, feed_secs, U64, ZMOD_RW,
"Seconds between L2ARC writing");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, feed_min_ms, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, feed_min_ms, U64, ZMOD_RW,
"Min feed interval in milliseconds");
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, noprefetch, INT, ZMOD_RW,
@@ -11141,13 +10710,13 @@ ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, feed_again, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, norw, INT, ZMOD_RW,
"No reads during writes");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, meta_percent, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, meta_percent, UINT, ZMOD_RW,
"Percent of ARC size allowed for L2ARC-only headers");
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_enabled, INT, ZMOD_RW,
"Rebuild the L2ARC when importing a pool");
-ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_blocks_min_l2size, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_blocks_min_l2size, U64, ZMOD_RW,
"Min size in bytes to write rebuild log blocks in L2ARC");
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, mfuonly, INT, ZMOD_RW,
@@ -11157,25 +10726,25 @@ ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, exclude_special, INT, ZMOD_RW,
"Exclude dbufs on special vdevs from being cached to L2ARC if set.");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, lotsfree_percent, param_set_arc_int,
- param_get_int, ZMOD_RW, "System free memory I/O throttle in bytes");
+ param_get_uint, ZMOD_RW, "System free memory I/O throttle in bytes");
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, sys_free, param_set_arc_long,
- param_get_long, ZMOD_RW, "System free memory target size in bytes");
+ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, sys_free, param_set_arc_u64,
+ spl_param_get_u64, ZMOD_RW, "System free memory target size in bytes");
-ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, dnode_limit, param_set_arc_long,
- param_get_long, ZMOD_RW, "Minimum bytes of dnodes in ARC");
+ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, dnode_limit, param_set_arc_u64,
+ spl_param_get_u64, ZMOD_RW, "Minimum bytes of dnodes in ARC");
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, dnode_limit_percent,
- param_set_arc_long, param_get_long, ZMOD_RW,
+ param_set_arc_int, param_get_uint, ZMOD_RW,
"Percent of ARC meta buffers for dnodes");
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, dnode_reduce_percent, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, dnode_reduce_percent, UINT, ZMOD_RW,
"Percentage of excess dnodes to try to unpin");
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, eviction_pct, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, eviction_pct, UINT, ZMOD_RW,
"When full, ARC allocation waits for eviction of this % of alloc size");
-ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, evict_batch_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, evict_batch_limit, UINT, ZMOD_RW,
"The number of headers to evict per sublist before moving to the next");
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, prune_task_threads, INT, ZMOD_RW,
diff --git a/module/zfs/blake3_zfs.c b/module/zfs/blake3_zfs.c
index 7560f30fd4e4..7783282b671a 100644
--- a/module/zfs/blake3_zfs.c
+++ b/module/zfs/blake3_zfs.c
@@ -47,10 +47,11 @@ void
abd_checksum_blake3_native(abd_t *abd, uint64_t size, const void *ctx_template,
zio_cksum_t *zcp)
{
- ASSERT(ctx_template != 0);
+ ASSERT(ctx_template != NULL);
#if defined(_KERNEL)
- BLAKE3_CTX *ctx = blake3_per_cpu_ctx[CPU_SEQID_UNSTABLE];
+ kpreempt_disable();
+ BLAKE3_CTX *ctx = blake3_per_cpu_ctx[CPU_SEQID];
#else
BLAKE3_CTX *ctx = kmem_alloc(sizeof (*ctx), KM_SLEEP);
#endif
@@ -59,7 +60,9 @@ abd_checksum_blake3_native(abd_t *abd, uint64_t size, const void *ctx_template,
(void) abd_iterate_func(abd, 0, size, blake3_incremental, ctx);
Blake3_Final(ctx, (uint8_t *)zcp);
-#if !defined(_KERNEL)
+#if defined(_KERNEL)
+ kpreempt_enable();
+#else
memset(ctx, 0, sizeof (*ctx));
kmem_free(ctx, sizeof (*ctx));
#endif
@@ -76,7 +79,7 @@ abd_checksum_blake3_byteswap(abd_t *abd, uint64_t size,
{
zio_cksum_t tmp;
- ASSERT(ctx_template != 0);
+ ASSERT(ctx_template != NULL);
abd_checksum_blake3_native(abd, size, ctx_template, &tmp);
zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]);
diff --git a/module/zfs/bplist.c b/module/zfs/bplist.c
index 47ea364ef26f..da7360f8ce10 100644
--- a/module/zfs/bplist.c
+++ b/module/zfs/bplist.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -65,9 +65,8 @@ bplist_iterate(bplist_t *bpl, bplist_itor_t *func, void *arg, dmu_tx_t *tx)
bplist_entry_t *bpe;
mutex_enter(&bpl->bpl_lock);
- while ((bpe = list_head(&bpl->bpl_list))) {
+ while ((bpe = list_remove_head(&bpl->bpl_list))) {
bplist_iterate_last_removed = bpe;
- list_remove(&bpl->bpl_list, bpe);
mutex_exit(&bpl->bpl_lock);
func(arg, &bpe->bpe_blk, tx);
kmem_free(bpe, sizeof (*bpe));
@@ -82,10 +81,7 @@ bplist_clear(bplist_t *bpl)
bplist_entry_t *bpe;
mutex_enter(&bpl->bpl_lock);
- while ((bpe = list_head(&bpl->bpl_list))) {
- bplist_iterate_last_removed = bpe;
- list_remove(&bpl->bpl_list, bpe);
+ while ((bpe = list_remove_head(&bpl->bpl_list)))
kmem_free(bpe, sizeof (*bpe));
- }
mutex_exit(&bpl->bpl_lock);
}
diff --git a/module/zfs/bpobj.c b/module/zfs/bpobj.c
index fb29ccfe31eb..96e1601c4e9c 100644
--- a/module/zfs/bpobj.c
+++ b/module/zfs/bpobj.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -284,7 +284,17 @@ bpobj_iterate_blkptrs(bpobj_info_t *bpi, bpobj_itor_t func, void *arg,
dmu_buf_t *dbuf = NULL;
bpobj_t *bpo = bpi->bpi_bpo;
- for (int64_t i = bpo->bpo_phys->bpo_num_blkptrs - 1; i >= start; i--) {
+ int64_t i = bpo->bpo_phys->bpo_num_blkptrs - 1;
+ uint64_t pe = P2ALIGN_TYPED(i, bpo->bpo_epb, uint64_t) *
+ sizeof (blkptr_t);
+ uint64_t ps = start * sizeof (blkptr_t);
+ uint64_t pb = MAX((pe > dmu_prefetch_max) ? pe - dmu_prefetch_max : 0,
+ ps);
+ if (pe > pb) {
+ dmu_prefetch(bpo->bpo_os, bpo->bpo_object, 0, pb, pe - pb,
+ ZIO_PRIORITY_ASYNC_READ);
+ }
+ for (; i >= start; i--) {
uint64_t offset = i * sizeof (blkptr_t);
uint64_t blkoff = P2PHASE(i, bpo->bpo_epb);
@@ -292,9 +302,16 @@ bpobj_iterate_blkptrs(bpobj_info_t *bpi, bpobj_itor_t func, void *arg,
if (dbuf)
dmu_buf_rele(dbuf, FTAG);
err = dmu_buf_hold(bpo->bpo_os, bpo->bpo_object,
- offset, FTAG, &dbuf, 0);
+ offset, FTAG, &dbuf, DMU_READ_NO_PREFETCH);
if (err)
break;
+ pe = pb;
+ pb = MAX((dbuf->db_offset > dmu_prefetch_max) ?
+ dbuf->db_offset - dmu_prefetch_max : 0, ps);
+ if (pe > pb) {
+ dmu_prefetch(bpo->bpo_os, bpo->bpo_object, 0,
+ pb, pe - pb, ZIO_PRIORITY_ASYNC_READ);
+ }
}
ASSERT3U(offset, >=, dbuf->db_offset);
@@ -466,22 +483,30 @@ bpobj_iterate_impl(bpobj_t *initial_bpo, bpobj_itor_t func, void *arg,
int64_t i = bpi->bpi_unprocessed_subobjs - 1;
uint64_t offset = i * sizeof (uint64_t);
- uint64_t obj_from_sublist;
+ uint64_t subobj;
err = dmu_read(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs,
- offset, sizeof (uint64_t), &obj_from_sublist,
- DMU_READ_PREFETCH);
+ offset, sizeof (uint64_t), &subobj,
+ DMU_READ_NO_PREFETCH);
if (err)
break;
- bpobj_t *sublist = kmem_alloc(sizeof (bpobj_t),
- KM_SLEEP);
- err = bpobj_open(sublist, bpo->bpo_os,
- obj_from_sublist);
- if (err)
+ bpobj_t *subbpo = kmem_alloc(sizeof (bpobj_t),
+ KM_SLEEP);
+ err = bpobj_open(subbpo, bpo->bpo_os, subobj);
+ if (err) {
+ kmem_free(subbpo, sizeof (bpobj_t));
break;
+ }
- list_insert_head(&stack, bpi_alloc(sublist, bpi, i));
- mutex_enter(&sublist->bpo_lock);
+ if (subbpo->bpo_havesubobj &&
+ subbpo->bpo_phys->bpo_subobjs != 0) {
+ dmu_prefetch(subbpo->bpo_os,
+ subbpo->bpo_phys->bpo_subobjs, 0, 0, 0,
+ ZIO_PRIORITY_ASYNC_READ);
+ }
+
+ list_insert_head(&stack, bpi_alloc(subbpo, bpi, i));
+ mutex_enter(&subbpo->bpo_lock);
bpi->bpi_unprocessed_subobjs--;
}
}
@@ -663,14 +688,13 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
}
VERIFY3U(0, ==, bpobj_open(&subbpo, bpo->bpo_os, subobj));
- VERIFY3U(0, ==, bpobj_space(&subbpo, &used, &comp, &uncomp));
-
if (bpobj_is_empty(&subbpo)) {
/* No point in having an empty subobj. */
bpobj_close(&subbpo);
bpobj_free(bpo->bpo_os, subobj, tx);
return;
}
+ VERIFY3U(0, ==, bpobj_space(&subbpo, &used, &comp, &uncomp));
mutex_enter(&bpo->bpo_lock);
dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
@@ -780,6 +804,68 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
}
+/*
+ * Prefetch metadata required for bpobj_enqueue_subobj().
+ */
+void
+bpobj_prefetch_subobj(bpobj_t *bpo, uint64_t subobj)
+{
+ dmu_object_info_t doi;
+ bpobj_t subbpo;
+ uint64_t subsubobjs;
+ boolean_t copy_subsub = B_TRUE;
+ boolean_t copy_bps = B_TRUE;
+
+ ASSERT(bpobj_is_open(bpo));
+ ASSERT(subobj != 0);
+
+ if (subobj == dmu_objset_pool(bpo->bpo_os)->dp_empty_bpobj)
+ return;
+
+ if (bpobj_open(&subbpo, bpo->bpo_os, subobj) != 0)
+ return;
+ if (bpobj_is_empty(&subbpo)) {
+ bpobj_close(&subbpo);
+ return;
+ }
+ subsubobjs = subbpo.bpo_phys->bpo_subobjs;
+ bpobj_close(&subbpo);
+
+ if (subsubobjs != 0) {
+ if (dmu_object_info(bpo->bpo_os, subsubobjs, &doi) != 0)
+ return;
+ if (doi.doi_max_offset > doi.doi_data_block_size)
+ copy_subsub = B_FALSE;
+ }
+
+ if (dmu_object_info(bpo->bpo_os, subobj, &doi) != 0)
+ return;
+ if (doi.doi_max_offset > doi.doi_data_block_size || !copy_subsub)
+ copy_bps = B_FALSE;
+
+ if (copy_subsub && subsubobjs != 0) {
+ if (bpo->bpo_phys->bpo_subobjs) {
+ dmu_prefetch(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, 0,
+ bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj), 1,
+ ZIO_PRIORITY_ASYNC_READ);
+ }
+ dmu_prefetch(bpo->bpo_os, subsubobjs, 0, 0, 1,
+ ZIO_PRIORITY_ASYNC_READ);
+ }
+
+ if (copy_bps) {
+ dmu_prefetch(bpo->bpo_os, bpo->bpo_object, 0,
+ bpo->bpo_phys->bpo_num_blkptrs * sizeof (blkptr_t), 1,
+ ZIO_PRIORITY_ASYNC_READ);
+ dmu_prefetch(bpo->bpo_os, subobj, 0, 0, 1,
+ ZIO_PRIORITY_ASYNC_READ);
+ } else if (bpo->bpo_phys->bpo_subobjs) {
+ dmu_prefetch(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, 0,
+ bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj), 1,
+ ZIO_PRIORITY_ASYNC_READ);
+ }
+}
+
void
bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
dmu_tx_t *tx)
@@ -807,7 +893,7 @@ bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
*/
memset(&stored_bp, 0, sizeof (stored_bp));
stored_bp.blk_prop = bp->blk_prop;
- stored_bp.blk_birth = bp->blk_birth;
+ BP_SET_LOGICAL_BIRTH(&stored_bp, BP_GET_LOGICAL_BIRTH(bp));
} else if (!BP_GET_DEDUP(bp)) {
/* The bpobj will compress better without the checksum */
memset(&stored_bp.blk_cksum, 0, sizeof (stored_bp.blk_cksum));
@@ -829,6 +915,7 @@ bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, boolean_t bp_freed,
dmu_buf_rele(bpo->bpo_cached_dbuf, bpo);
VERIFY3U(0, ==, dmu_buf_hold(bpo->bpo_os, bpo->bpo_object,
offset, bpo, &bpo->bpo_cached_dbuf, 0));
+ ASSERT3P(bpo->bpo_cached_dbuf, !=, NULL);
}
dmu_buf_will_dirty(bpo->bpo_cached_dbuf, tx);
@@ -866,7 +953,8 @@ space_range_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
(void) bp_freed, (void) tx;
struct space_range_arg *sra = arg;
- if (bp->blk_birth > sra->mintxg && bp->blk_birth <= sra->maxtxg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) > sra->mintxg &&
+ BP_GET_LOGICAL_BIRTH(bp) <= sra->maxtxg) {
if (dsl_pool_sync_context(spa_get_dsl(sra->spa)))
sra->used += bp_get_dsize_sync(sra->spa, bp);
else
@@ -898,7 +986,7 @@ bpobj_space(bpobj_t *bpo, uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
/*
* Return the amount of space in the bpobj which is:
- * mintxg < blk_birth <= maxtxg
+ * mintxg < logical birth <= maxtxg
*/
int
bpobj_space_range(bpobj_t *bpo, uint64_t mintxg, uint64_t maxtxg,
diff --git a/module/zfs/bptree.c b/module/zfs/bptree.c
index 4e9a4825e262..1f5d8e77bcc0 100644
--- a/module/zfs/bptree.c
+++ b/module/zfs/bptree.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/bqueue.c b/module/zfs/bqueue.c
index 22539efc4e23..a7fa516975de 100644
--- a/module/zfs/bqueue.c
+++ b/module/zfs/bqueue.c
@@ -27,34 +27,46 @@ obj2node(bqueue_t *q, void *data)
/*
* Initialize a blocking queue The maximum capacity of the queue is set to
- * size. Types that are stored in a bqueue must contain a bqueue_node_t,
- * and node_offset must be its offset from the start of the struct.
- * fill_fraction is a performance tuning value; when the queue is full, any
- * threads attempting to enqueue records will block. They will block until
- * they're signaled, which will occur when the queue is at least 1/fill_fraction
+ * size. Types that are stored in a bqueue must contain a bqueue_node_t, and
+ * node_offset must be its offset from the start of the struct. fill_fraction
+ * is a performance tuning value; when the queue is full, any threads
+ * attempting to enqueue records will block. They will block until they're
+ * signaled, which will occur when the queue is at least 1/fill_fraction
* empty. Similar behavior occurs on dequeue; if the queue is empty, threads
- * block. They will be signalled when the queue has 1/fill_fraction full, or
- * when bqueue_flush is called. As a result, you must call bqueue_flush when
- * you enqueue your final record on a thread, in case the dequeueing threads are
- * currently blocked and that enqueue does not cause them to be awoken.
- * Alternatively, this behavior can be disabled (causing signaling to happen
- * immediately) by setting fill_fraction to any value larger than size.
- * Return 0 on success, or -1 on failure.
+ * block. They will be signalled when the queue has 1/fill_fraction full.
+ * As a result, you must call bqueue_enqueue_flush() when you enqueue your
+ * final record on a thread, in case the dequeuing threads are currently
+ * blocked and that enqueue does not cause them to be woken. Alternatively,
+ * this behavior can be disabled (causing signaling to happen immediately) by
+ * setting fill_fraction to any value larger than size. Return 0 on success,
+ * or -1 on failure.
+ *
+ * Note: The caller must ensure that for a given bqueue_t, there's only a
+ * single call to bqueue_enqueue() running at a time (e.g. by calling only
+ * from a single thread, or with locking around the call). Similarly, the
+ * caller must ensure that there's only a single call to bqueue_dequeue()
+ * running at a time. However, the one call to bqueue_enqueue() may be
+ * invoked concurrently with the one call to bqueue_dequeue().
*/
int
-bqueue_init(bqueue_t *q, uint64_t fill_fraction, uint64_t size,
- size_t node_offset)
+bqueue_init(bqueue_t *q, uint_t fill_fraction, size_t size, size_t node_offset)
{
if (fill_fraction == 0) {
return (-1);
}
list_create(&q->bq_list, node_offset + sizeof (bqueue_node_t),
node_offset + offsetof(bqueue_node_t, bqn_node));
+ list_create(&q->bq_dequeuing_list, node_offset + sizeof (bqueue_node_t),
+ node_offset + offsetof(bqueue_node_t, bqn_node));
+ list_create(&q->bq_enqueuing_list, node_offset + sizeof (bqueue_node_t),
+ node_offset + offsetof(bqueue_node_t, bqn_node));
cv_init(&q->bq_add_cv, NULL, CV_DEFAULT, NULL);
cv_init(&q->bq_pop_cv, NULL, CV_DEFAULT, NULL);
mutex_init(&q->bq_lock, NULL, MUTEX_DEFAULT, NULL);
q->bq_node_offset = node_offset;
q->bq_size = 0;
+ q->bq_dequeuing_size = 0;
+ q->bq_enqueuing_size = 0;
q->bq_maxsize = size;
q->bq_fill_fraction = fill_fraction;
return (0);
@@ -70,31 +82,40 @@ bqueue_destroy(bqueue_t *q)
{
mutex_enter(&q->bq_lock);
ASSERT0(q->bq_size);
+ ASSERT0(q->bq_dequeuing_size);
+ ASSERT0(q->bq_enqueuing_size);
cv_destroy(&q->bq_add_cv);
cv_destroy(&q->bq_pop_cv);
list_destroy(&q->bq_list);
+ list_destroy(&q->bq_dequeuing_list);
+ list_destroy(&q->bq_enqueuing_list);
mutex_exit(&q->bq_lock);
mutex_destroy(&q->bq_lock);
}
static void
-bqueue_enqueue_impl(bqueue_t *q, void *data, uint64_t item_size,
- boolean_t flush)
+bqueue_enqueue_impl(bqueue_t *q, void *data, size_t item_size, boolean_t flush)
{
ASSERT3U(item_size, >, 0);
ASSERT3U(item_size, <=, q->bq_maxsize);
- mutex_enter(&q->bq_lock);
+
obj2node(q, data)->bqn_size = item_size;
- while (q->bq_size + item_size > q->bq_maxsize) {
- cv_wait_sig(&q->bq_add_cv, &q->bq_lock);
- }
- q->bq_size += item_size;
- list_insert_tail(&q->bq_list, data);
- if (q->bq_size >= q->bq_maxsize / q->bq_fill_fraction)
- cv_signal(&q->bq_pop_cv);
- if (flush)
+ q->bq_enqueuing_size += item_size;
+ list_insert_tail(&q->bq_enqueuing_list, data);
+
+ if (flush ||
+ q->bq_enqueuing_size >= q->bq_maxsize / q->bq_fill_fraction) {
+ /* Append the enquing list to the shared list. */
+ mutex_enter(&q->bq_lock);
+ while (q->bq_size > q->bq_maxsize) {
+ cv_wait_sig(&q->bq_add_cv, &q->bq_lock);
+ }
+ q->bq_size += q->bq_enqueuing_size;
+ list_move_tail(&q->bq_list, &q->bq_enqueuing_list);
+ q->bq_enqueuing_size = 0;
cv_broadcast(&q->bq_pop_cv);
- mutex_exit(&q->bq_lock);
+ mutex_exit(&q->bq_lock);
+ }
}
/*
@@ -103,7 +124,7 @@ bqueue_enqueue_impl(bqueue_t *q, void *data, uint64_t item_size,
* > 0.
*/
void
-bqueue_enqueue(bqueue_t *q, void *data, uint64_t item_size)
+bqueue_enqueue(bqueue_t *q, void *data, size_t item_size)
{
bqueue_enqueue_impl(q, data, item_size, B_FALSE);
}
@@ -112,12 +133,12 @@ bqueue_enqueue(bqueue_t *q, void *data, uint64_t item_size)
* Enqueue an entry, and then flush the queue. This forces the popping threads
* to wake up, even if we're below the fill fraction. We have this in a single
* function, rather than having a separate call, because it prevents race
- * conditions between the enqueuing thread and the dequeueing thread, where the
- * enqueueing thread will wake up the dequeueing thread, that thread will
+ * conditions between the enqueuing thread and the dequeuing thread, where the
+ * enqueueing thread will wake up the dequeuing thread, that thread will
* destroy the condvar before the enqueuing thread is done.
*/
void
-bqueue_enqueue_flush(bqueue_t *q, void *data, uint64_t item_size)
+bqueue_enqueue_flush(bqueue_t *q, void *data, size_t item_size)
{
bqueue_enqueue_impl(q, data, item_size, B_TRUE);
}
@@ -129,27 +150,26 @@ bqueue_enqueue_flush(bqueue_t *q, void *data, uint64_t item_size)
void *
bqueue_dequeue(bqueue_t *q)
{
- void *ret = NULL;
- uint64_t item_size;
- mutex_enter(&q->bq_lock);
- while (q->bq_size == 0) {
- cv_wait_sig(&q->bq_pop_cv, &q->bq_lock);
+ void *ret = list_remove_head(&q->bq_dequeuing_list);
+ if (ret == NULL) {
+ /*
+ * Dequeuing list is empty. Wait for there to be something on
+ * the shared list, then move the entire shared list to the
+ * dequeuing list.
+ */
+ mutex_enter(&q->bq_lock);
+ while (q->bq_size == 0) {
+ cv_wait_sig(&q->bq_pop_cv, &q->bq_lock);
+ }
+ ASSERT0(q->bq_dequeuing_size);
+ ASSERT(list_is_empty(&q->bq_dequeuing_list));
+ list_move_tail(&q->bq_dequeuing_list, &q->bq_list);
+ q->bq_dequeuing_size = q->bq_size;
+ q->bq_size = 0;
+ cv_broadcast(&q->bq_add_cv);
+ mutex_exit(&q->bq_lock);
+ ret = list_remove_head(&q->bq_dequeuing_list);
}
- ret = list_remove_head(&q->bq_list);
- ASSERT3P(ret, !=, NULL);
- item_size = obj2node(q, ret)->bqn_size;
- q->bq_size -= item_size;
- if (q->bq_size <= q->bq_maxsize - (q->bq_maxsize / q->bq_fill_fraction))
- cv_signal(&q->bq_add_cv);
- mutex_exit(&q->bq_lock);
+ q->bq_dequeuing_size -= obj2node(q, ret)->bqn_size;
return (ret);
}
-
-/*
- * Returns true if the space used is 0.
- */
-boolean_t
-bqueue_empty(bqueue_t *q)
-{
- return (q->bq_size == 0);
-}
diff --git a/module/zfs/brt.c b/module/zfs/brt.c
new file mode 100644
index 000000000000..ea8c0735c4b7
--- /dev/null
+++ b/module/zfs/brt.c
@@ -0,0 +1,1673 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2020, 2021, 2022 by Pawel Jakub Dawidek
+ */
+
+#include <sys/zfs_context.h>
+#include <sys/spa.h>
+#include <sys/spa_impl.h>
+#include <sys/zio.h>
+#include <sys/brt.h>
+#include <sys/brt_impl.h>
+#include <sys/ddt.h>
+#include <sys/bitmap.h>
+#include <sys/zap.h>
+#include <sys/dmu_tx.h>
+#include <sys/arc.h>
+#include <sys/dsl_pool.h>
+#include <sys/dsl_scan.h>
+#include <sys/vdev_impl.h>
+#include <sys/kstat.h>
+#include <sys/wmsum.h>
+
+/*
+ * Block Cloning design.
+ *
+ * Block Cloning allows to manually clone a file (or a subset of its blocks)
+ * into another (or the same) file by just creating additional references to
+ * the data blocks without copying the data itself. Those references are kept
+ * in the Block Reference Tables (BRTs).
+ *
+ * In many ways this is similar to the existing deduplication, but there are
+ * some important differences:
+ *
+ * - Deduplication is automatic and Block Cloning is not - one has to use a
+ * dedicated system call(s) to clone the given file/blocks.
+ * - Deduplication keeps all data blocks in its table, even those referenced
+ * just once. Block Cloning creates an entry in its tables only when there
+ * are at least two references to the given data block. If the block was
+ * never explicitly cloned or the second to last reference was dropped,
+ * there will be neither space nor performance overhead.
+ * - Deduplication needs data to work - one needs to pass real data to the
+ * write(2) syscall, so hash can be calculated. Block Cloning doesn't require
+ * data, just block pointers to the data, so it is extremely fast, as we pay
+ * neither the cost of reading the data, nor the cost of writing the data -
+ * we operate exclusively on metadata.
+ * - If the D (dedup) bit is not set in the block pointer, it means that
+ * the block is not in the dedup table (DDT) and we won't consult the DDT
+ * when we need to free the block. Block Cloning must be consulted on every
+ * free, because we cannot modify the source BP (eg. by setting something
+ * similar to the D bit), thus we have no hint if the block is in the
+ * Block Reference Table (BRT), so we need to look into the BRT. There is
+ * an optimization in place that allows us to eliminate the majority of BRT
+ * lookups which is described below in the "Minimizing free penalty" section.
+ * - The BRT entry is much smaller than the DDT entry - for BRT we only store
+ * 64bit offset and 64bit reference counter.
+ * - Dedup keys are cryptographic hashes, so two blocks that are close to each
+ * other on disk are most likely in totally different parts of the DDT.
+ * The BRT entry keys are offsets into a single top-level VDEV, so data blocks
+ * from one file should have BRT entries close to each other.
+ * - Scrub will only do a single pass over a block that is referenced multiple
+ * times in the DDT. Unfortunately it is not currently (if at all) possible
+ * with Block Cloning and block referenced multiple times will be scrubbed
+ * multiple times. The new, sorted scrub should be able to eliminate
+ * duplicated reads given enough memory.
+ * - Deduplication requires cryptographically strong hash as a checksum or
+ * additional data verification. Block Cloning works with any checksum
+ * algorithm or even with checksumming disabled.
+ *
+ * As mentioned above, the BRT entries are much smaller than the DDT entries.
+ * To uniquely identify a block we just need its vdev id and offset. We also
+ * need to maintain a reference counter. The vdev id will often repeat, as there
+ * is a small number of top-level VDEVs and a large number of blocks stored in
+ * each VDEV. We take advantage of that to reduce the BRT entry size further by
+ * maintaining one BRT for each top-level VDEV, so we can then have only offset
+ * and counter as the BRT entry.
+ *
+ * Minimizing free penalty.
+ *
+ * Block Cloning allows creating additional references to any existing block.
+ * When we free a block there is no hint in the block pointer whether the block
+ * was cloned or not, so on each free we have to check if there is a
+ * corresponding entry in the BRT or not. If there is, we need to decrease
+ * the reference counter. Doing BRT lookup on every free can potentially be
+ * expensive by requiring additional I/Os if the BRT doesn't fit into memory.
+ * This is the main problem with deduplication, so we've learned our lesson and
+ * try not to repeat the same mistake here. How do we do that? We divide each
+ * top-level VDEV into 16MB regions. For each region we maintain a counter that
+ * is a sum of all the BRT entries that have offsets within the region. This
+ * creates the entries count array of 16bit numbers for each top-level VDEV.
+ * The entries count array is always kept in memory and updated on disk in the
+ * same transaction group as the BRT updates to keep everything in-sync. We can
+ * keep the array in memory, because it is very small. With 16MB regions and
+ * 1TB VDEV the array requires only 128kB of memory (we may decide to decrease
+ * the region size even further in the future). Now, when we want to free
+ * a block, we first consult the array. If the counter for the whole region is
+ * zero, there is no need to look for the BRT entry, as there isn't one for
+ * sure. If the counter for the region is greater than zero, only then we will
+ * do a BRT lookup and if an entry is found we will decrease the reference
+ * counter in the BRT entry and in the entry counters array.
+ *
+ * The entry counters array is small, but can potentially be larger for very
+ * large VDEVs or smaller regions. In this case we don't want to rewrite entire
+ * array on every change. We then divide the array into 32kB block and keep
+ * a bitmap of dirty blocks within a transaction group. When we sync the
+ * transaction group we can only update the parts of the entry counters array
+ * that were modified. Note: Keeping track of the dirty parts of the entry
+ * counters array is implemented, but updating only parts of the array on disk
+ * is not yet implemented - for now we will update entire array if there was
+ * any change.
+ *
+ * The implementation tries to be economic: if BRT is not used, or no longer
+ * used, there will be no entries in the MOS and no additional memory used (eg.
+ * the entry counters array is only allocated if needed).
+ *
+ * Interaction between Deduplication and Block Cloning.
+ *
+ * If both functionalities are in use, we could end up with a block that is
+ * referenced multiple times in both DDT and BRT. When we free one of the
+ * references we couldn't tell where it belongs, so we would have to decide
+ * what table takes the precedence: do we first clear DDT references or BRT
+ * references? To avoid this dilemma BRT cooperates with DDT - if a given block
+ * is being cloned using BRT and the BP has the D (dedup) bit set, BRT will
+ * lookup DDT entry instead and increase the counter there. No BRT entry
+ * will be created for a block which has the D (dedup) bit set.
+ * BRT may be more efficient for manual deduplication, but if the block is
+ * already in the DDT, then creating additional BRT entry would be less
+ * efficient. This clever idea was proposed by Allan Jude.
+ *
+ * Block Cloning across datasets.
+ *
+ * Block Cloning is not limited to cloning blocks within the same dataset.
+ * It is possible (and very useful) to clone blocks between different datasets.
+ * One use case is recovering files from snapshots. By cloning the files into
+ * dataset we need no additional storage. Without Block Cloning we would need
+ * additional space for those files.
+ * Another interesting use case is moving the files between datasets
+ * (copying the file content to the new dataset and removing the source file).
+ * In that case Block Cloning will only be used briefly, because the BRT entries
+ * will be removed when the source is removed.
+ * Block Cloning across encrypted datasets is supported as long as both
+ * datasets share the same master key (e.g. snapshots and clones)
+ *
+ * Block Cloning flow through ZFS layers.
+ *
+ * Note: Block Cloning can be used both for cloning file system blocks and ZVOL
+ * blocks. As of this writing no interface is implemented that allows for block
+ * cloning within a ZVOL.
+ * FreeBSD and Linux provides copy_file_range(2) system call and we will use it
+ * for blocking cloning.
+ *
+ * ssize_t
+ * copy_file_range(int infd, off_t *inoffp, int outfd, off_t *outoffp,
+ * size_t len, unsigned int flags);
+ *
+ * Even though offsets and length represent bytes, they have to be
+ * block-aligned or we will return an error so the upper layer can
+ * fallback to the generic mechanism that will just copy the data.
+ * Using copy_file_range(2) will call OS-independent zfs_clone_range() function.
+ * This function was implemented based on zfs_write(), but instead of writing
+ * the given data we first read block pointers using the new dmu_read_l0_bps()
+ * function from the source file. Once we have BPs from the source file we call
+ * the dmu_brt_clone() function on the destination file. This function
+ * allocates BPs for us. We iterate over all source BPs. If the given BP is
+ * a hole or an embedded block, we just copy BP as-is. If it points to a real
+ * data we place this BP on a BRT pending list using the brt_pending_add()
+ * function.
+ *
+ * We use this pending list to keep track of all BPs that got new references
+ * within this transaction group.
+ *
+ * Some special cases to consider and how we address them:
+ * - The block we want to clone may have been created within the same
+ * transaction group that we are trying to clone. Such block has no BP
+ * allocated yet, so cannot be immediately cloned. We return EAGAIN.
+ * - The block we want to clone may have been modified within the same
+ * transaction group. We return EAGAIN.
+ * - A block may be cloned multiple times during one transaction group (that's
+ * why pending list is actually a tree and not an append-only list - this
+ * way we can figure out faster if this block is cloned for the first time
+ * in this txg or consecutive time).
+ * - A block may be cloned and freed within the same transaction group
+ * (see dbuf_undirty()).
+ * - A block may be cloned and within the same transaction group the clone
+ * can be cloned again (see dmu_read_l0_bps()).
+ * - A file might have been deleted, but the caller still has a file descriptor
+ * open to this file and clones it.
+ *
+ * When we free a block we have an additional step in the ZIO pipeline where we
+ * call the zio_brt_free() function. We then call the brt_entry_decref()
+ * that loads the corresponding BRT entry (if one exists) and decreases
+ * reference counter. If this is not the last reference we will stop ZIO
+ * pipeline here. If this is the last reference or the block is not in the
+ * BRT, we continue the pipeline and free the block as usual.
+ *
+ * At the beginning of spa_sync() where there can be no more block cloning,
+ * but before issuing frees we call brt_pending_apply(). This function applies
+ * all the new clones to the BRT table - we load BRT entries and update
+ * reference counters. To sync new BRT entries to disk, we use brt_sync()
+ * function. This function will sync all dirty per-top-level-vdev BRTs,
+ * the entry counters arrays, etc.
+ *
+ * Block Cloning and ZIL.
+ *
+ * Every clone operation is divided into chunks (similar to write) and each
+ * chunk is cloned in a separate transaction. The chunk size is determined by
+ * how many BPs we can fit into a single ZIL entry.
+ * Replaying clone operation is different from the regular clone operation,
+ * as when we log clone operations we cannot use the source object - it may
+ * reside on a different dataset, so we log BPs we want to clone.
+ * The ZIL is replayed when we mount the given dataset, not when the pool is
+ * imported. Taking this into account it is possible that the pool is imported
+ * without mounting datasets and the source dataset is destroyed before the
+ * destination dataset is mounted and its ZIL replayed.
+ * To address this situation we leverage zil_claim() mechanism where ZFS will
+ * parse all the ZILs on pool import. When we come across TX_CLONE_RANGE
+ * entries, we will bump reference counters for their BPs in the BRT. Then
+ * on mount and ZIL replay we bump the reference counters once more, while the
+ * first references are dropped during ZIL destroy by zil_free_clone_range().
+ * It is possible that after zil_claim() we never mount the destination, so
+ * we never replay its ZIL and just destroy it. In this case the only taken
+ * references will be dropped by zil_free_clone_range(), since the cloning is
+ * not going to ever take place.
+ */
+
+static kmem_cache_t *brt_entry_cache;
+static kmem_cache_t *brt_pending_entry_cache;
+
+/*
+ * Enable/disable prefetching of BRT entries that we are going to modify.
+ */
+static int brt_zap_prefetch = 1;
+
+#ifdef ZFS_DEBUG
+#define BRT_DEBUG(...) do { \
+ if ((zfs_flags & ZFS_DEBUG_BRT) != 0) { \
+ __dprintf(B_TRUE, __FILE__, __func__, __LINE__, __VA_ARGS__); \
+ } \
+} while (0)
+#else
+#define BRT_DEBUG(...) do { } while (0)
+#endif
+
+static int brt_zap_default_bs = 12;
+static int brt_zap_default_ibs = 12;
+
+static kstat_t *brt_ksp;
+
+typedef struct brt_stats {
+ kstat_named_t brt_addref_entry_in_memory;
+ kstat_named_t brt_addref_entry_not_on_disk;
+ kstat_named_t brt_addref_entry_on_disk;
+ kstat_named_t brt_addref_entry_read_lost_race;
+ kstat_named_t brt_decref_entry_in_memory;
+ kstat_named_t brt_decref_entry_loaded_from_disk;
+ kstat_named_t brt_decref_entry_not_in_memory;
+ kstat_named_t brt_decref_entry_not_on_disk;
+ kstat_named_t brt_decref_entry_read_lost_race;
+ kstat_named_t brt_decref_entry_still_referenced;
+ kstat_named_t brt_decref_free_data_later;
+ kstat_named_t brt_decref_free_data_now;
+ kstat_named_t brt_decref_no_entry;
+} brt_stats_t;
+
+static brt_stats_t brt_stats = {
+ { "addref_entry_in_memory", KSTAT_DATA_UINT64 },
+ { "addref_entry_not_on_disk", KSTAT_DATA_UINT64 },
+ { "addref_entry_on_disk", KSTAT_DATA_UINT64 },
+ { "addref_entry_read_lost_race", KSTAT_DATA_UINT64 },
+ { "decref_entry_in_memory", KSTAT_DATA_UINT64 },
+ { "decref_entry_loaded_from_disk", KSTAT_DATA_UINT64 },
+ { "decref_entry_not_in_memory", KSTAT_DATA_UINT64 },
+ { "decref_entry_not_on_disk", KSTAT_DATA_UINT64 },
+ { "decref_entry_read_lost_race", KSTAT_DATA_UINT64 },
+ { "decref_entry_still_referenced", KSTAT_DATA_UINT64 },
+ { "decref_free_data_later", KSTAT_DATA_UINT64 },
+ { "decref_free_data_now", KSTAT_DATA_UINT64 },
+ { "decref_no_entry", KSTAT_DATA_UINT64 }
+};
+
+struct {
+ wmsum_t brt_addref_entry_in_memory;
+ wmsum_t brt_addref_entry_not_on_disk;
+ wmsum_t brt_addref_entry_on_disk;
+ wmsum_t brt_addref_entry_read_lost_race;
+ wmsum_t brt_decref_entry_in_memory;
+ wmsum_t brt_decref_entry_loaded_from_disk;
+ wmsum_t brt_decref_entry_not_in_memory;
+ wmsum_t brt_decref_entry_not_on_disk;
+ wmsum_t brt_decref_entry_read_lost_race;
+ wmsum_t brt_decref_entry_still_referenced;
+ wmsum_t brt_decref_free_data_later;
+ wmsum_t brt_decref_free_data_now;
+ wmsum_t brt_decref_no_entry;
+} brt_sums;
+
+#define BRTSTAT_BUMP(stat) wmsum_add(&brt_sums.stat, 1)
+
+static int brt_entry_compare(const void *x1, const void *x2);
+static int brt_pending_entry_compare(const void *x1, const void *x2);
+
+static void
+brt_rlock(brt_t *brt)
+{
+ rw_enter(&brt->brt_lock, RW_READER);
+}
+
+static void
+brt_wlock(brt_t *brt)
+{
+ rw_enter(&brt->brt_lock, RW_WRITER);
+}
+
+static void
+brt_unlock(brt_t *brt)
+{
+ rw_exit(&brt->brt_lock);
+}
+
+static uint16_t
+brt_vdev_entcount_get(const brt_vdev_t *brtvd, uint64_t idx)
+{
+
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ if (unlikely(brtvd->bv_need_byteswap)) {
+ return (BSWAP_16(brtvd->bv_entcount[idx]));
+ } else {
+ return (brtvd->bv_entcount[idx]);
+ }
+}
+
+static void
+brt_vdev_entcount_set(brt_vdev_t *brtvd, uint64_t idx, uint16_t entcnt)
+{
+
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ if (unlikely(brtvd->bv_need_byteswap)) {
+ brtvd->bv_entcount[idx] = BSWAP_16(entcnt);
+ } else {
+ brtvd->bv_entcount[idx] = entcnt;
+ }
+}
+
+static void
+brt_vdev_entcount_inc(brt_vdev_t *brtvd, uint64_t idx)
+{
+ uint16_t entcnt;
+
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ entcnt = brt_vdev_entcount_get(brtvd, idx);
+ ASSERT(entcnt < UINT16_MAX);
+
+ brt_vdev_entcount_set(brtvd, idx, entcnt + 1);
+}
+
+static void
+brt_vdev_entcount_dec(brt_vdev_t *brtvd, uint64_t idx)
+{
+ uint16_t entcnt;
+
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ entcnt = brt_vdev_entcount_get(brtvd, idx);
+ ASSERT(entcnt > 0);
+
+ brt_vdev_entcount_set(brtvd, idx, entcnt - 1);
+}
+
+#ifdef ZFS_DEBUG
+static void
+brt_vdev_dump(brt_vdev_t *brtvd)
+{
+ uint64_t idx;
+
+ zfs_dbgmsg(" BRT vdevid=%llu meta_dirty=%d entcount_dirty=%d "
+ "size=%llu totalcount=%llu nblocks=%llu bitmapsize=%zu\n",
+ (u_longlong_t)brtvd->bv_vdevid,
+ brtvd->bv_meta_dirty, brtvd->bv_entcount_dirty,
+ (u_longlong_t)brtvd->bv_size,
+ (u_longlong_t)brtvd->bv_totalcount,
+ (u_longlong_t)brtvd->bv_nblocks,
+ (size_t)BT_SIZEOFMAP(brtvd->bv_nblocks));
+ if (brtvd->bv_totalcount > 0) {
+ zfs_dbgmsg(" entcounts:");
+ for (idx = 0; idx < brtvd->bv_size; idx++) {
+ uint16_t entcnt = brt_vdev_entcount_get(brtvd, idx);
+ if (entcnt > 0) {
+ zfs_dbgmsg(" [%04llu] %hu",
+ (u_longlong_t)idx, entcnt);
+ }
+ }
+ }
+ if (brtvd->bv_entcount_dirty) {
+ char *bitmap;
+
+ bitmap = kmem_alloc(brtvd->bv_nblocks + 1, KM_SLEEP);
+ for (idx = 0; idx < brtvd->bv_nblocks; idx++) {
+ bitmap[idx] =
+ BT_TEST(brtvd->bv_bitmap, idx) ? 'x' : '.';
+ }
+ bitmap[idx] = '\0';
+ zfs_dbgmsg(" dirty: %s", bitmap);
+ kmem_free(bitmap, brtvd->bv_nblocks + 1);
+ }
+}
+#endif
+
+static brt_vdev_t *
+brt_vdev(brt_t *brt, uint64_t vdevid)
+{
+ brt_vdev_t *brtvd;
+
+ ASSERT(RW_LOCK_HELD(&brt->brt_lock));
+
+ if (vdevid < brt->brt_nvdevs) {
+ brtvd = &brt->brt_vdevs[vdevid];
+ } else {
+ brtvd = NULL;
+ }
+
+ return (brtvd);
+}
+
+static void
+brt_vdev_create(brt_t *brt, brt_vdev_t *brtvd, dmu_tx_t *tx)
+{
+ char name[64];
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ ASSERT0(brtvd->bv_mos_brtvdev);
+ ASSERT0(brtvd->bv_mos_entries);
+ ASSERT(brtvd->bv_entcount != NULL);
+ ASSERT(brtvd->bv_size > 0);
+ ASSERT(brtvd->bv_bitmap != NULL);
+ ASSERT(brtvd->bv_nblocks > 0);
+
+ brtvd->bv_mos_entries = zap_create_flags(brt->brt_mos, 0,
+ ZAP_FLAG_HASH64 | ZAP_FLAG_UINT64_KEY, DMU_OTN_ZAP_METADATA,
+ brt_zap_default_bs, brt_zap_default_ibs, DMU_OT_NONE, 0, tx);
+ VERIFY(brtvd->bv_mos_entries != 0);
+ BRT_DEBUG("MOS entries created, object=%llu",
+ (u_longlong_t)brtvd->bv_mos_entries);
+
+ /*
+ * We allocate DMU buffer to store the bv_entcount[] array.
+ * We will keep array size (bv_size) and cummulative count for all
+ * bv_entcount[]s (bv_totalcount) in the bonus buffer.
+ */
+ brtvd->bv_mos_brtvdev = dmu_object_alloc(brt->brt_mos,
+ DMU_OTN_UINT64_METADATA, BRT_BLOCKSIZE,
+ DMU_OTN_UINT64_METADATA, sizeof (brt_vdev_phys_t), tx);
+ VERIFY(brtvd->bv_mos_brtvdev != 0);
+ BRT_DEBUG("MOS BRT VDEV created, object=%llu",
+ (u_longlong_t)brtvd->bv_mos_brtvdev);
+
+ snprintf(name, sizeof (name), "%s%llu", BRT_OBJECT_VDEV_PREFIX,
+ (u_longlong_t)brtvd->bv_vdevid);
+ VERIFY0(zap_add(brt->brt_mos, DMU_POOL_DIRECTORY_OBJECT, name,
+ sizeof (uint64_t), 1, &brtvd->bv_mos_brtvdev, tx));
+ BRT_DEBUG("Pool directory object created, object=%s", name);
+
+ spa_feature_incr(brt->brt_spa, SPA_FEATURE_BLOCK_CLONING, tx);
+}
+
+static void
+brt_vdev_realloc(brt_t *brt, brt_vdev_t *brtvd)
+{
+ vdev_t *vd;
+ uint16_t *entcount;
+ ulong_t *bitmap;
+ uint64_t nblocks, size;
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+
+ spa_config_enter(brt->brt_spa, SCL_VDEV, FTAG, RW_READER);
+ vd = vdev_lookup_top(brt->brt_spa, brtvd->bv_vdevid);
+ size = (vdev_get_min_asize(vd) - 1) / brt->brt_rangesize + 1;
+ spa_config_exit(brt->brt_spa, SCL_VDEV, FTAG);
+
+ entcount = vmem_zalloc(sizeof (entcount[0]) * size, KM_SLEEP);
+ nblocks = BRT_RANGESIZE_TO_NBLOCKS(size);
+ bitmap = kmem_zalloc(BT_SIZEOFMAP(nblocks), KM_SLEEP);
+
+ if (!brtvd->bv_initiated) {
+ ASSERT0(brtvd->bv_size);
+ ASSERT(brtvd->bv_entcount == NULL);
+ ASSERT(brtvd->bv_bitmap == NULL);
+ ASSERT0(brtvd->bv_nblocks);
+
+ avl_create(&brtvd->bv_tree, brt_entry_compare,
+ sizeof (brt_entry_t), offsetof(brt_entry_t, bre_node));
+ } else {
+ ASSERT(brtvd->bv_size > 0);
+ ASSERT(brtvd->bv_entcount != NULL);
+ ASSERT(brtvd->bv_bitmap != NULL);
+ ASSERT(brtvd->bv_nblocks > 0);
+ /*
+ * TODO: Allow vdev shrinking. We only need to implement
+ * shrinking the on-disk BRT VDEV object.
+ * dmu_free_range(brt->brt_mos, brtvd->bv_mos_brtvdev, offset,
+ * size, tx);
+ */
+ ASSERT3U(brtvd->bv_size, <=, size);
+
+ memcpy(entcount, brtvd->bv_entcount,
+ sizeof (entcount[0]) * MIN(size, brtvd->bv_size));
+ memcpy(bitmap, brtvd->bv_bitmap, MIN(BT_SIZEOFMAP(nblocks),
+ BT_SIZEOFMAP(brtvd->bv_nblocks)));
+ vmem_free(brtvd->bv_entcount,
+ sizeof (entcount[0]) * brtvd->bv_size);
+ kmem_free(brtvd->bv_bitmap, BT_SIZEOFMAP(brtvd->bv_nblocks));
+ }
+
+ brtvd->bv_size = size;
+ brtvd->bv_entcount = entcount;
+ brtvd->bv_bitmap = bitmap;
+ brtvd->bv_nblocks = nblocks;
+ if (!brtvd->bv_initiated) {
+ brtvd->bv_need_byteswap = FALSE;
+ brtvd->bv_initiated = TRUE;
+ BRT_DEBUG("BRT VDEV %llu initiated.",
+ (u_longlong_t)brtvd->bv_vdevid);
+ }
+}
+
+static void
+brt_vdev_load(brt_t *brt, brt_vdev_t *brtvd)
+{
+ char name[64];
+ dmu_buf_t *db;
+ brt_vdev_phys_t *bvphys;
+ int error;
+
+ snprintf(name, sizeof (name), "%s%llu", BRT_OBJECT_VDEV_PREFIX,
+ (u_longlong_t)brtvd->bv_vdevid);
+ error = zap_lookup(brt->brt_mos, DMU_POOL_DIRECTORY_OBJECT, name,
+ sizeof (uint64_t), 1, &brtvd->bv_mos_brtvdev);
+ if (error != 0)
+ return;
+ ASSERT(brtvd->bv_mos_brtvdev != 0);
+
+ error = dmu_bonus_hold(brt->brt_mos, brtvd->bv_mos_brtvdev, FTAG, &db);
+ ASSERT0(error);
+ if (error != 0)
+ return;
+
+ bvphys = db->db_data;
+ if (brt->brt_rangesize == 0) {
+ brt->brt_rangesize = bvphys->bvp_rangesize;
+ } else {
+ ASSERT3U(brt->brt_rangesize, ==, bvphys->bvp_rangesize);
+ }
+
+ ASSERT(!brtvd->bv_initiated);
+ brt_vdev_realloc(brt, brtvd);
+
+ /* TODO: We don't support VDEV shrinking. */
+ ASSERT3U(bvphys->bvp_size, <=, brtvd->bv_size);
+
+ /*
+ * If VDEV grew, we will leave new bv_entcount[] entries zeroed out.
+ */
+ error = dmu_read(brt->brt_mos, brtvd->bv_mos_brtvdev, 0,
+ MIN(brtvd->bv_size, bvphys->bvp_size) * sizeof (uint16_t),
+ brtvd->bv_entcount, DMU_READ_NO_PREFETCH);
+ ASSERT0(error);
+
+ brtvd->bv_mos_entries = bvphys->bvp_mos_entries;
+ ASSERT(brtvd->bv_mos_entries != 0);
+ brtvd->bv_need_byteswap =
+ (bvphys->bvp_byteorder != BRT_NATIVE_BYTEORDER);
+ brtvd->bv_totalcount = bvphys->bvp_totalcount;
+ brtvd->bv_usedspace = bvphys->bvp_usedspace;
+ brtvd->bv_savedspace = bvphys->bvp_savedspace;
+ brt->brt_usedspace += brtvd->bv_usedspace;
+ brt->brt_savedspace += brtvd->bv_savedspace;
+
+ dmu_buf_rele(db, FTAG);
+
+ BRT_DEBUG("MOS BRT VDEV %s loaded: mos_brtvdev=%llu, mos_entries=%llu",
+ name, (u_longlong_t)brtvd->bv_mos_brtvdev,
+ (u_longlong_t)brtvd->bv_mos_entries);
+}
+
+static void
+brt_vdev_dealloc(brt_t *brt, brt_vdev_t *brtvd)
+{
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ ASSERT(brtvd->bv_initiated);
+
+ vmem_free(brtvd->bv_entcount, sizeof (uint16_t) * brtvd->bv_size);
+ brtvd->bv_entcount = NULL;
+ kmem_free(brtvd->bv_bitmap, BT_SIZEOFMAP(brtvd->bv_nblocks));
+ brtvd->bv_bitmap = NULL;
+ ASSERT0(avl_numnodes(&brtvd->bv_tree));
+ avl_destroy(&brtvd->bv_tree);
+
+ brtvd->bv_size = 0;
+ brtvd->bv_nblocks = 0;
+
+ brtvd->bv_initiated = FALSE;
+ BRT_DEBUG("BRT VDEV %llu deallocated.", (u_longlong_t)brtvd->bv_vdevid);
+}
+
+static void
+brt_vdev_destroy(brt_t *brt, brt_vdev_t *brtvd, dmu_tx_t *tx)
+{
+ char name[64];
+ uint64_t count;
+ dmu_buf_t *db;
+ brt_vdev_phys_t *bvphys;
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ ASSERT(brtvd->bv_mos_brtvdev != 0);
+ ASSERT(brtvd->bv_mos_entries != 0);
+
+ VERIFY0(zap_count(brt->brt_mos, brtvd->bv_mos_entries, &count));
+ VERIFY0(count);
+ VERIFY0(zap_destroy(brt->brt_mos, brtvd->bv_mos_entries, tx));
+ BRT_DEBUG("MOS entries destroyed, object=%llu",
+ (u_longlong_t)brtvd->bv_mos_entries);
+ brtvd->bv_mos_entries = 0;
+
+ VERIFY0(dmu_bonus_hold(brt->brt_mos, brtvd->bv_mos_brtvdev, FTAG, &db));
+ bvphys = db->db_data;
+ ASSERT0(bvphys->bvp_totalcount);
+ ASSERT0(bvphys->bvp_usedspace);
+ ASSERT0(bvphys->bvp_savedspace);
+ dmu_buf_rele(db, FTAG);
+
+ VERIFY0(dmu_object_free(brt->brt_mos, brtvd->bv_mos_brtvdev, tx));
+ BRT_DEBUG("MOS BRT VDEV destroyed, object=%llu",
+ (u_longlong_t)brtvd->bv_mos_brtvdev);
+ brtvd->bv_mos_brtvdev = 0;
+
+ snprintf(name, sizeof (name), "%s%llu", BRT_OBJECT_VDEV_PREFIX,
+ (u_longlong_t)brtvd->bv_vdevid);
+ VERIFY0(zap_remove(brt->brt_mos, DMU_POOL_DIRECTORY_OBJECT, name, tx));
+ BRT_DEBUG("Pool directory object removed, object=%s", name);
+
+ brt_vdev_dealloc(brt, brtvd);
+
+ spa_feature_decr(brt->brt_spa, SPA_FEATURE_BLOCK_CLONING, tx);
+}
+
+static void
+brt_vdevs_expand(brt_t *brt, uint64_t nvdevs)
+{
+ brt_vdev_t *brtvd, *vdevs;
+ uint64_t vdevid;
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ ASSERT3U(nvdevs, >, brt->brt_nvdevs);
+
+ vdevs = kmem_zalloc(sizeof (vdevs[0]) * nvdevs, KM_SLEEP);
+ if (brt->brt_nvdevs > 0) {
+ ASSERT(brt->brt_vdevs != NULL);
+
+ memcpy(vdevs, brt->brt_vdevs,
+ sizeof (brt_vdev_t) * brt->brt_nvdevs);
+ kmem_free(brt->brt_vdevs,
+ sizeof (brt_vdev_t) * brt->brt_nvdevs);
+ }
+ for (vdevid = brt->brt_nvdevs; vdevid < nvdevs; vdevid++) {
+ brtvd = &vdevs[vdevid];
+
+ brtvd->bv_vdevid = vdevid;
+ brtvd->bv_initiated = FALSE;
+ }
+
+ BRT_DEBUG("BRT VDEVs expanded from %llu to %llu.",
+ (u_longlong_t)brt->brt_nvdevs, (u_longlong_t)nvdevs);
+
+ brt->brt_vdevs = vdevs;
+ brt->brt_nvdevs = nvdevs;
+}
+
+static boolean_t
+brt_vdev_lookup(brt_t *brt, brt_vdev_t *brtvd, const brt_entry_t *bre)
+{
+ uint64_t idx;
+
+ ASSERT(RW_LOCK_HELD(&brt->brt_lock));
+
+ idx = bre->bre_offset / brt->brt_rangesize;
+ if (brtvd->bv_entcount != NULL && idx < brtvd->bv_size) {
+ /* VDEV wasn't expanded. */
+ return (brt_vdev_entcount_get(brtvd, idx) > 0);
+ }
+
+ return (FALSE);
+}
+
+static void
+brt_vdev_addref(brt_t *brt, brt_vdev_t *brtvd, const brt_entry_t *bre,
+ uint64_t dsize)
+{
+ uint64_t idx;
+
+ ASSERT(RW_LOCK_HELD(&brt->brt_lock));
+ ASSERT(brtvd != NULL);
+ ASSERT(brtvd->bv_entcount != NULL);
+
+ brt->brt_savedspace += dsize;
+ brtvd->bv_savedspace += dsize;
+ brtvd->bv_meta_dirty = TRUE;
+
+ if (bre->bre_refcount > 1) {
+ return;
+ }
+
+ brt->brt_usedspace += dsize;
+ brtvd->bv_usedspace += dsize;
+
+ idx = bre->bre_offset / brt->brt_rangesize;
+ if (idx >= brtvd->bv_size) {
+ /* VDEV has been expanded. */
+ brt_vdev_realloc(brt, brtvd);
+ }
+
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ brtvd->bv_totalcount++;
+ brt_vdev_entcount_inc(brtvd, idx);
+ brtvd->bv_entcount_dirty = TRUE;
+ idx = idx / BRT_BLOCKSIZE / 8;
+ BT_SET(brtvd->bv_bitmap, idx);
+
+#ifdef ZFS_DEBUG
+ if (zfs_flags & ZFS_DEBUG_BRT)
+ brt_vdev_dump(brtvd);
+#endif
+}
+
+static void
+brt_vdev_decref(brt_t *brt, brt_vdev_t *brtvd, const brt_entry_t *bre,
+ uint64_t dsize)
+{
+ uint64_t idx;
+
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ ASSERT(brtvd != NULL);
+ ASSERT(brtvd->bv_entcount != NULL);
+
+ brt->brt_savedspace -= dsize;
+ brtvd->bv_savedspace -= dsize;
+ brtvd->bv_meta_dirty = TRUE;
+
+ if (bre->bre_refcount > 0) {
+ return;
+ }
+
+ brt->brt_usedspace -= dsize;
+ brtvd->bv_usedspace -= dsize;
+
+ idx = bre->bre_offset / brt->brt_rangesize;
+ ASSERT3U(idx, <, brtvd->bv_size);
+
+ ASSERT(brtvd->bv_totalcount > 0);
+ brtvd->bv_totalcount--;
+ brt_vdev_entcount_dec(brtvd, idx);
+ brtvd->bv_entcount_dirty = TRUE;
+ idx = idx / BRT_BLOCKSIZE / 8;
+ BT_SET(brtvd->bv_bitmap, idx);
+
+#ifdef ZFS_DEBUG
+ if (zfs_flags & ZFS_DEBUG_BRT)
+ brt_vdev_dump(brtvd);
+#endif
+}
+
+static void
+brt_vdev_sync(brt_t *brt, brt_vdev_t *brtvd, dmu_tx_t *tx)
+{
+ dmu_buf_t *db;
+ brt_vdev_phys_t *bvphys;
+
+ ASSERT(brtvd->bv_meta_dirty);
+ ASSERT(brtvd->bv_mos_brtvdev != 0);
+ ASSERT(dmu_tx_is_syncing(tx));
+
+ VERIFY0(dmu_bonus_hold(brt->brt_mos, brtvd->bv_mos_brtvdev, FTAG, &db));
+
+ if (brtvd->bv_entcount_dirty) {
+ /*
+ * TODO: Walk brtvd->bv_bitmap and write only the dirty blocks.
+ */
+ dmu_write(brt->brt_mos, brtvd->bv_mos_brtvdev, 0,
+ brtvd->bv_size * sizeof (brtvd->bv_entcount[0]),
+ brtvd->bv_entcount, tx);
+ memset(brtvd->bv_bitmap, 0, BT_SIZEOFMAP(brtvd->bv_nblocks));
+ brtvd->bv_entcount_dirty = FALSE;
+ }
+
+ dmu_buf_will_dirty(db, tx);
+ bvphys = db->db_data;
+ bvphys->bvp_mos_entries = brtvd->bv_mos_entries;
+ bvphys->bvp_size = brtvd->bv_size;
+ if (brtvd->bv_need_byteswap) {
+ bvphys->bvp_byteorder = BRT_NON_NATIVE_BYTEORDER;
+ } else {
+ bvphys->bvp_byteorder = BRT_NATIVE_BYTEORDER;
+ }
+ bvphys->bvp_totalcount = brtvd->bv_totalcount;
+ bvphys->bvp_rangesize = brt->brt_rangesize;
+ bvphys->bvp_usedspace = brtvd->bv_usedspace;
+ bvphys->bvp_savedspace = brtvd->bv_savedspace;
+ dmu_buf_rele(db, FTAG);
+
+ brtvd->bv_meta_dirty = FALSE;
+}
+
+static void
+brt_vdevs_alloc(brt_t *brt, boolean_t load)
+{
+ brt_vdev_t *brtvd;
+ uint64_t vdevid;
+
+ brt_wlock(brt);
+
+ brt_vdevs_expand(brt, brt->brt_spa->spa_root_vdev->vdev_children);
+
+ if (load) {
+ for (vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brtvd = &brt->brt_vdevs[vdevid];
+ ASSERT(brtvd->bv_entcount == NULL);
+
+ brt_vdev_load(brt, brtvd);
+ }
+ }
+
+ if (brt->brt_rangesize == 0) {
+ brt->brt_rangesize = BRT_RANGESIZE;
+ }
+
+ brt_unlock(brt);
+}
+
+static void
+brt_vdevs_free(brt_t *brt)
+{
+ brt_vdev_t *brtvd;
+ uint64_t vdevid;
+
+ brt_wlock(brt);
+
+ for (vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brtvd = &brt->brt_vdevs[vdevid];
+ if (brtvd->bv_initiated)
+ brt_vdev_dealloc(brt, brtvd);
+ }
+ kmem_free(brt->brt_vdevs, sizeof (brt_vdev_t) * brt->brt_nvdevs);
+
+ brt_unlock(brt);
+}
+
+static void
+brt_entry_fill(const blkptr_t *bp, brt_entry_t *bre, uint64_t *vdevidp)
+{
+
+ bre->bre_offset = DVA_GET_OFFSET(&bp->blk_dva[0]);
+ bre->bre_refcount = 0;
+
+ *vdevidp = DVA_GET_VDEV(&bp->blk_dva[0]);
+}
+
+static int
+brt_entry_compare(const void *x1, const void *x2)
+{
+ const brt_entry_t *bre1 = x1;
+ const brt_entry_t *bre2 = x2;
+
+ return (TREE_CMP(bre1->bre_offset, bre2->bre_offset));
+}
+
+static int
+brt_entry_lookup(brt_t *brt, brt_vdev_t *brtvd, brt_entry_t *bre)
+{
+ uint64_t mos_entries;
+ int error;
+
+ ASSERT(RW_LOCK_HELD(&brt->brt_lock));
+
+ if (!brt_vdev_lookup(brt, brtvd, bre))
+ return (SET_ERROR(ENOENT));
+
+ /*
+ * Remember mos_entries object number. After we reacquire the BRT lock,
+ * the brtvd pointer may be invalid.
+ */
+ mos_entries = brtvd->bv_mos_entries;
+ if (mos_entries == 0)
+ return (SET_ERROR(ENOENT));
+
+ brt_unlock(brt);
+
+ error = zap_lookup_uint64(brt->brt_mos, mos_entries, &bre->bre_offset,
+ BRT_KEY_WORDS, 1, sizeof (bre->bre_refcount), &bre->bre_refcount);
+
+ brt_wlock(brt);
+
+ return (error);
+}
+
+static void
+brt_entry_prefetch(brt_t *brt, uint64_t vdevid, brt_entry_t *bre)
+{
+ brt_vdev_t *brtvd;
+ uint64_t mos_entries = 0;
+
+ brt_rlock(brt);
+ brtvd = brt_vdev(brt, vdevid);
+ if (brtvd != NULL)
+ mos_entries = brtvd->bv_mos_entries;
+ brt_unlock(brt);
+
+ if (mos_entries == 0)
+ return;
+
+ (void) zap_prefetch_uint64(brt->brt_mos, mos_entries,
+ (uint64_t *)&bre->bre_offset, BRT_KEY_WORDS);
+}
+
+/*
+ * Return TRUE if we _can_ have BRT entry for this bp. It might be false
+ * positive, but gives us quick answer if we should look into BRT, which
+ * may require reads and thus will be more expensive.
+ */
+boolean_t
+brt_maybe_exists(spa_t *spa, const blkptr_t *bp)
+{
+ brt_t *brt = spa->spa_brt;
+ brt_vdev_t *brtvd;
+ brt_entry_t bre_search;
+ boolean_t mayexists = FALSE;
+ uint64_t vdevid;
+
+ brt_entry_fill(bp, &bre_search, &vdevid);
+
+ brt_rlock(brt);
+
+ brtvd = brt_vdev(brt, vdevid);
+ if (brtvd != NULL && brtvd->bv_initiated) {
+ if (!avl_is_empty(&brtvd->bv_tree) ||
+ brt_vdev_lookup(brt, brtvd, &bre_search)) {
+ mayexists = TRUE;
+ }
+ }
+
+ brt_unlock(brt);
+
+ return (mayexists);
+}
+
+uint64_t
+brt_get_dspace(spa_t *spa)
+{
+ brt_t *brt = spa->spa_brt;
+
+ if (brt == NULL)
+ return (0);
+
+ return (brt->brt_savedspace);
+}
+
+uint64_t
+brt_get_used(spa_t *spa)
+{
+ brt_t *brt = spa->spa_brt;
+
+ if (brt == NULL)
+ return (0);
+
+ return (brt->brt_usedspace);
+}
+
+uint64_t
+brt_get_saved(spa_t *spa)
+{
+ brt_t *brt = spa->spa_brt;
+
+ if (brt == NULL)
+ return (0);
+
+ return (brt->brt_savedspace);
+}
+
+uint64_t
+brt_get_ratio(spa_t *spa)
+{
+ brt_t *brt = spa->spa_brt;
+
+ if (brt->brt_usedspace == 0)
+ return (100);
+
+ return ((brt->brt_usedspace + brt->brt_savedspace) * 100 /
+ brt->brt_usedspace);
+}
+
+static int
+brt_kstats_update(kstat_t *ksp, int rw)
+{
+ brt_stats_t *bs = ksp->ks_data;
+
+ if (rw == KSTAT_WRITE)
+ return (EACCES);
+
+ bs->brt_addref_entry_in_memory.value.ui64 =
+ wmsum_value(&brt_sums.brt_addref_entry_in_memory);
+ bs->brt_addref_entry_not_on_disk.value.ui64 =
+ wmsum_value(&brt_sums.brt_addref_entry_not_on_disk);
+ bs->brt_addref_entry_on_disk.value.ui64 =
+ wmsum_value(&brt_sums.brt_addref_entry_on_disk);
+ bs->brt_addref_entry_read_lost_race.value.ui64 =
+ wmsum_value(&brt_sums.brt_addref_entry_read_lost_race);
+ bs->brt_decref_entry_in_memory.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_in_memory);
+ bs->brt_decref_entry_loaded_from_disk.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_loaded_from_disk);
+ bs->brt_decref_entry_not_in_memory.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_not_in_memory);
+ bs->brt_decref_entry_not_on_disk.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_not_on_disk);
+ bs->brt_decref_entry_read_lost_race.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_read_lost_race);
+ bs->brt_decref_entry_still_referenced.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_entry_still_referenced);
+ bs->brt_decref_free_data_later.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_free_data_later);
+ bs->brt_decref_free_data_now.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_free_data_now);
+ bs->brt_decref_no_entry.value.ui64 =
+ wmsum_value(&brt_sums.brt_decref_no_entry);
+
+ return (0);
+}
+
+static void
+brt_stat_init(void)
+{
+
+ wmsum_init(&brt_sums.brt_addref_entry_in_memory, 0);
+ wmsum_init(&brt_sums.brt_addref_entry_not_on_disk, 0);
+ wmsum_init(&brt_sums.brt_addref_entry_on_disk, 0);
+ wmsum_init(&brt_sums.brt_addref_entry_read_lost_race, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_in_memory, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_loaded_from_disk, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_not_in_memory, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_not_on_disk, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_read_lost_race, 0);
+ wmsum_init(&brt_sums.brt_decref_entry_still_referenced, 0);
+ wmsum_init(&brt_sums.brt_decref_free_data_later, 0);
+ wmsum_init(&brt_sums.brt_decref_free_data_now, 0);
+ wmsum_init(&brt_sums.brt_decref_no_entry, 0);
+
+ brt_ksp = kstat_create("zfs", 0, "brtstats", "misc", KSTAT_TYPE_NAMED,
+ sizeof (brt_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
+ if (brt_ksp != NULL) {
+ brt_ksp->ks_data = &brt_stats;
+ brt_ksp->ks_update = brt_kstats_update;
+ kstat_install(brt_ksp);
+ }
+}
+
+static void
+brt_stat_fini(void)
+{
+ if (brt_ksp != NULL) {
+ kstat_delete(brt_ksp);
+ brt_ksp = NULL;
+ }
+
+ wmsum_fini(&brt_sums.brt_addref_entry_in_memory);
+ wmsum_fini(&brt_sums.brt_addref_entry_not_on_disk);
+ wmsum_fini(&brt_sums.brt_addref_entry_on_disk);
+ wmsum_fini(&brt_sums.brt_addref_entry_read_lost_race);
+ wmsum_fini(&brt_sums.brt_decref_entry_in_memory);
+ wmsum_fini(&brt_sums.brt_decref_entry_loaded_from_disk);
+ wmsum_fini(&brt_sums.brt_decref_entry_not_in_memory);
+ wmsum_fini(&brt_sums.brt_decref_entry_not_on_disk);
+ wmsum_fini(&brt_sums.brt_decref_entry_read_lost_race);
+ wmsum_fini(&brt_sums.brt_decref_entry_still_referenced);
+ wmsum_fini(&brt_sums.brt_decref_free_data_later);
+ wmsum_fini(&brt_sums.brt_decref_free_data_now);
+ wmsum_fini(&brt_sums.brt_decref_no_entry);
+}
+
+void
+brt_init(void)
+{
+ brt_entry_cache = kmem_cache_create("brt_entry_cache",
+ sizeof (brt_entry_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
+ brt_pending_entry_cache = kmem_cache_create("brt_pending_entry_cache",
+ sizeof (brt_pending_entry_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
+
+ brt_stat_init();
+}
+
+void
+brt_fini(void)
+{
+ brt_stat_fini();
+
+ kmem_cache_destroy(brt_entry_cache);
+ kmem_cache_destroy(brt_pending_entry_cache);
+}
+
+static brt_entry_t *
+brt_entry_alloc(const brt_entry_t *bre_init)
+{
+ brt_entry_t *bre;
+
+ bre = kmem_cache_alloc(brt_entry_cache, KM_SLEEP);
+ bre->bre_offset = bre_init->bre_offset;
+ bre->bre_refcount = bre_init->bre_refcount;
+
+ return (bre);
+}
+
+static void
+brt_entry_free(brt_entry_t *bre)
+{
+
+ kmem_cache_free(brt_entry_cache, bre);
+}
+
+static void
+brt_entry_addref(brt_t *brt, const blkptr_t *bp)
+{
+ brt_vdev_t *brtvd;
+ brt_entry_t *bre, *racebre;
+ brt_entry_t bre_search;
+ avl_index_t where;
+ uint64_t vdevid;
+ int error;
+
+ ASSERT(!RW_WRITE_HELD(&brt->brt_lock));
+
+ brt_entry_fill(bp, &bre_search, &vdevid);
+
+ brt_wlock(brt);
+
+ brtvd = brt_vdev(brt, vdevid);
+ if (brtvd == NULL) {
+ ASSERT3U(vdevid, >=, brt->brt_nvdevs);
+
+ /* New VDEV was added. */
+ brt_vdevs_expand(brt, vdevid + 1);
+ brtvd = brt_vdev(brt, vdevid);
+ }
+ ASSERT(brtvd != NULL);
+ if (!brtvd->bv_initiated)
+ brt_vdev_realloc(brt, brtvd);
+
+ bre = avl_find(&brtvd->bv_tree, &bre_search, NULL);
+ if (bre != NULL) {
+ BRTSTAT_BUMP(brt_addref_entry_in_memory);
+ } else {
+ /*
+ * brt_entry_lookup() may drop the BRT (read) lock and
+ * reacquire it (write).
+ */
+ error = brt_entry_lookup(brt, brtvd, &bre_search);
+ /* bre_search now contains correct bre_refcount */
+ ASSERT(error == 0 || error == ENOENT);
+ if (error == 0)
+ BRTSTAT_BUMP(brt_addref_entry_on_disk);
+ else
+ BRTSTAT_BUMP(brt_addref_entry_not_on_disk);
+ /*
+ * When the BRT lock was dropped, brt_vdevs[] may have been
+ * expanded and reallocated, we need to update brtvd's pointer.
+ */
+ brtvd = brt_vdev(brt, vdevid);
+ ASSERT(brtvd != NULL);
+
+ racebre = avl_find(&brtvd->bv_tree, &bre_search, &where);
+ if (racebre == NULL) {
+ bre = brt_entry_alloc(&bre_search);
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ avl_insert(&brtvd->bv_tree, bre, where);
+ brt->brt_nentries++;
+ } else {
+ /*
+ * The entry was added when the BRT lock was dropped in
+ * brt_entry_lookup().
+ */
+ BRTSTAT_BUMP(brt_addref_entry_read_lost_race);
+ bre = racebre;
+ }
+ }
+ bre->bre_refcount++;
+ brt_vdev_addref(brt, brtvd, bre, bp_get_dsize(brt->brt_spa, bp));
+
+ brt_unlock(brt);
+}
+
+/* Return TRUE if block should be freed immediately. */
+boolean_t
+brt_entry_decref(spa_t *spa, const blkptr_t *bp)
+{
+ brt_t *brt = spa->spa_brt;
+ brt_vdev_t *brtvd;
+ brt_entry_t *bre, *racebre;
+ brt_entry_t bre_search;
+ avl_index_t where;
+ uint64_t vdevid;
+ int error;
+
+ brt_entry_fill(bp, &bre_search, &vdevid);
+
+ brt_wlock(brt);
+
+ brtvd = brt_vdev(brt, vdevid);
+ ASSERT(brtvd != NULL);
+
+ bre = avl_find(&brtvd->bv_tree, &bre_search, NULL);
+ if (bre != NULL) {
+ BRTSTAT_BUMP(brt_decref_entry_in_memory);
+ goto out;
+ } else {
+ BRTSTAT_BUMP(brt_decref_entry_not_in_memory);
+ }
+
+ /*
+ * brt_entry_lookup() may drop the BRT lock and reacquire it.
+ */
+ error = brt_entry_lookup(brt, brtvd, &bre_search);
+ /* bre_search now contains correct bre_refcount */
+ ASSERT(error == 0 || error == ENOENT);
+ /*
+ * When the BRT lock was dropped, brt_vdevs[] may have been expanded
+ * and reallocated, we need to update brtvd's pointer.
+ */
+ brtvd = brt_vdev(brt, vdevid);
+ ASSERT(brtvd != NULL);
+
+ if (error == ENOENT) {
+ BRTSTAT_BUMP(brt_decref_entry_not_on_disk);
+ bre = NULL;
+ goto out;
+ }
+
+ racebre = avl_find(&brtvd->bv_tree, &bre_search, &where);
+ if (racebre != NULL) {
+ /*
+ * The entry was added when the BRT lock was dropped in
+ * brt_entry_lookup().
+ */
+ BRTSTAT_BUMP(brt_decref_entry_read_lost_race);
+ bre = racebre;
+ goto out;
+ }
+
+ BRTSTAT_BUMP(brt_decref_entry_loaded_from_disk);
+ bre = brt_entry_alloc(&bre_search);
+ ASSERT(RW_WRITE_HELD(&brt->brt_lock));
+ avl_insert(&brtvd->bv_tree, bre, where);
+ brt->brt_nentries++;
+
+out:
+ if (bre == NULL) {
+ /*
+ * This is a free of a regular (not cloned) block.
+ */
+ brt_unlock(brt);
+ BRTSTAT_BUMP(brt_decref_no_entry);
+ return (B_TRUE);
+ }
+ if (bre->bre_refcount == 0) {
+ brt_unlock(brt);
+ BRTSTAT_BUMP(brt_decref_free_data_now);
+ return (B_TRUE);
+ }
+
+ ASSERT(bre->bre_refcount > 0);
+ bre->bre_refcount--;
+ if (bre->bre_refcount == 0)
+ BRTSTAT_BUMP(brt_decref_free_data_later);
+ else
+ BRTSTAT_BUMP(brt_decref_entry_still_referenced);
+ brt_vdev_decref(brt, brtvd, bre, bp_get_dsize(brt->brt_spa, bp));
+
+ brt_unlock(brt);
+
+ return (B_FALSE);
+}
+
+uint64_t
+brt_entry_get_refcount(spa_t *spa, const blkptr_t *bp)
+{
+ brt_t *brt = spa->spa_brt;
+ brt_vdev_t *brtvd;
+ brt_entry_t bre_search, *bre;
+ uint64_t vdevid, refcnt;
+ int error;
+
+ brt_entry_fill(bp, &bre_search, &vdevid);
+
+ brt_rlock(brt);
+
+ brtvd = brt_vdev(brt, vdevid);
+ ASSERT(brtvd != NULL);
+
+ bre = avl_find(&brtvd->bv_tree, &bre_search, NULL);
+ if (bre == NULL) {
+ error = brt_entry_lookup(brt, brtvd, &bre_search);
+ ASSERT(error == 0 || error == ENOENT);
+ if (error == ENOENT)
+ refcnt = 0;
+ else
+ refcnt = bre_search.bre_refcount;
+ } else
+ refcnt = bre->bre_refcount;
+
+ brt_unlock(brt);
+ return (refcnt);
+}
+
+static void
+brt_prefetch(brt_t *brt, const blkptr_t *bp)
+{
+ brt_entry_t bre;
+ uint64_t vdevid;
+
+ ASSERT(bp != NULL);
+
+ if (!brt_zap_prefetch)
+ return;
+
+ brt_entry_fill(bp, &bre, &vdevid);
+
+ brt_entry_prefetch(brt, vdevid, &bre);
+}
+
+static int
+brt_pending_entry_compare(const void *x1, const void *x2)
+{
+ const brt_pending_entry_t *bpe1 = x1, *bpe2 = x2;
+ const blkptr_t *bp1 = &bpe1->bpe_bp, *bp2 = &bpe2->bpe_bp;
+ int cmp;
+
+ cmp = TREE_CMP(DVA_GET_VDEV(&bp1->blk_dva[0]),
+ DVA_GET_VDEV(&bp2->blk_dva[0]));
+ if (cmp == 0) {
+ cmp = TREE_CMP(DVA_GET_OFFSET(&bp1->blk_dva[0]),
+ DVA_GET_OFFSET(&bp2->blk_dva[0]));
+ if (unlikely(cmp == 0)) {
+ cmp = TREE_CMP(BP_GET_BIRTH(bp1), BP_GET_BIRTH(bp2));
+ }
+ }
+
+ return (cmp);
+}
+
+void
+brt_pending_add(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx)
+{
+ brt_t *brt;
+ avl_tree_t *pending_tree;
+ kmutex_t *pending_lock;
+ brt_pending_entry_t *bpe, *newbpe;
+ avl_index_t where;
+ uint64_t txg;
+
+ brt = spa->spa_brt;
+ txg = dmu_tx_get_txg(tx);
+ ASSERT3U(txg, !=, 0);
+ pending_tree = &brt->brt_pending_tree[txg & TXG_MASK];
+ pending_lock = &brt->brt_pending_lock[txg & TXG_MASK];
+
+ newbpe = kmem_cache_alloc(brt_pending_entry_cache, KM_SLEEP);
+ newbpe->bpe_bp = *bp;
+ newbpe->bpe_count = 1;
+
+ mutex_enter(pending_lock);
+
+ bpe = avl_find(pending_tree, newbpe, &where);
+ if (bpe == NULL) {
+ avl_insert(pending_tree, newbpe, where);
+ newbpe = NULL;
+ } else {
+ bpe->bpe_count++;
+ }
+
+ mutex_exit(pending_lock);
+
+ if (newbpe != NULL) {
+ ASSERT(bpe != NULL);
+ ASSERT(bpe != newbpe);
+ kmem_cache_free(brt_pending_entry_cache, newbpe);
+ } else {
+ ASSERT(bpe == NULL);
+
+ /* Prefetch BRT entry for the syncing context. */
+ brt_prefetch(brt, bp);
+ }
+}
+
+void
+brt_pending_remove(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx)
+{
+ brt_t *brt;
+ avl_tree_t *pending_tree;
+ kmutex_t *pending_lock;
+ brt_pending_entry_t *bpe, bpe_search;
+ uint64_t txg;
+
+ brt = spa->spa_brt;
+ txg = dmu_tx_get_txg(tx);
+ ASSERT3U(txg, !=, 0);
+ pending_tree = &brt->brt_pending_tree[txg & TXG_MASK];
+ pending_lock = &brt->brt_pending_lock[txg & TXG_MASK];
+
+ bpe_search.bpe_bp = *bp;
+
+ mutex_enter(pending_lock);
+
+ bpe = avl_find(pending_tree, &bpe_search, NULL);
+ /* I believe we should always find bpe when this function is called. */
+ if (bpe != NULL) {
+ ASSERT(bpe->bpe_count > 0);
+
+ bpe->bpe_count--;
+ if (bpe->bpe_count == 0) {
+ avl_remove(pending_tree, bpe);
+ kmem_cache_free(brt_pending_entry_cache, bpe);
+ }
+ }
+
+ mutex_exit(pending_lock);
+}
+
+void
+brt_pending_apply(spa_t *spa, uint64_t txg)
+{
+ brt_t *brt = spa->spa_brt;
+ brt_pending_entry_t *bpe;
+ avl_tree_t *pending_tree;
+ void *c;
+
+ ASSERT3U(txg, !=, 0);
+
+ /*
+ * We are in syncing context, so no other brt_pending_tree accesses
+ * are possible for the TXG. Don't need to acquire brt_pending_lock.
+ */
+ pending_tree = &brt->brt_pending_tree[txg & TXG_MASK];
+
+ c = NULL;
+ while ((bpe = avl_destroy_nodes(pending_tree, &c)) != NULL) {
+ boolean_t added_to_ddt;
+
+ for (int i = 0; i < bpe->bpe_count; i++) {
+ /*
+ * If the block has DEDUP bit set, it means that it
+ * already exists in the DEDUP table, so we can just
+ * use that instead of creating new entry in
+ * the BRT table.
+ */
+ if (BP_GET_DEDUP(&bpe->bpe_bp)) {
+ added_to_ddt = ddt_addref(spa, &bpe->bpe_bp);
+ } else {
+ added_to_ddt = B_FALSE;
+ }
+ if (!added_to_ddt)
+ brt_entry_addref(brt, &bpe->bpe_bp);
+ }
+
+ kmem_cache_free(brt_pending_entry_cache, bpe);
+ }
+}
+
+static void
+brt_sync_entry(dnode_t *dn, brt_entry_t *bre, dmu_tx_t *tx)
+{
+ if (bre->bre_refcount == 0) {
+ int error = zap_remove_uint64_by_dnode(dn, &bre->bre_offset,
+ BRT_KEY_WORDS, tx);
+ VERIFY(error == 0 || error == ENOENT);
+ } else {
+ VERIFY0(zap_update_uint64_by_dnode(dn, &bre->bre_offset,
+ BRT_KEY_WORDS, 1, sizeof (bre->bre_refcount),
+ &bre->bre_refcount, tx));
+ }
+}
+
+static void
+brt_sync_table(brt_t *brt, dmu_tx_t *tx)
+{
+ brt_vdev_t *brtvd;
+ brt_entry_t *bre;
+ dnode_t *dn;
+ uint64_t vdevid;
+ void *c;
+
+ brt_wlock(brt);
+
+ for (vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
+ brtvd = &brt->brt_vdevs[vdevid];
+
+ if (!brtvd->bv_initiated)
+ continue;
+
+ if (!brtvd->bv_meta_dirty) {
+ ASSERT(!brtvd->bv_entcount_dirty);
+ ASSERT0(avl_numnodes(&brtvd->bv_tree));
+ continue;
+ }
+
+ ASSERT(!brtvd->bv_entcount_dirty ||
+ avl_numnodes(&brtvd->bv_tree) != 0);
+
+ if (brtvd->bv_mos_brtvdev == 0)
+ brt_vdev_create(brt, brtvd, tx);
+
+ VERIFY0(dnode_hold(brt->brt_mos, brtvd->bv_mos_entries,
+ FTAG, &dn));
+
+ c = NULL;
+ while ((bre = avl_destroy_nodes(&brtvd->bv_tree, &c)) != NULL) {
+ brt_sync_entry(dn, bre, tx);
+ brt_entry_free(bre);
+ ASSERT(brt->brt_nentries > 0);
+ brt->brt_nentries--;
+ }
+
+ dnode_rele(dn, FTAG);
+
+ brt_vdev_sync(brt, brtvd, tx);
+
+ if (brtvd->bv_totalcount == 0)
+ brt_vdev_destroy(brt, brtvd, tx);
+ }
+
+ ASSERT0(brt->brt_nentries);
+
+ brt_unlock(brt);
+}
+
+void
+brt_sync(spa_t *spa, uint64_t txg)
+{
+ dmu_tx_t *tx;
+ brt_t *brt;
+
+ ASSERT(spa_syncing_txg(spa) == txg);
+
+ brt = spa->spa_brt;
+ brt_rlock(brt);
+ if (brt->brt_nentries == 0) {
+ /* No changes. */
+ brt_unlock(brt);
+ return;
+ }
+ brt_unlock(brt);
+
+ tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
+
+ brt_sync_table(brt, tx);
+
+ dmu_tx_commit(tx);
+}
+
+static void
+brt_table_alloc(brt_t *brt)
+{
+
+ for (int i = 0; i < TXG_SIZE; i++) {
+ avl_create(&brt->brt_pending_tree[i],
+ brt_pending_entry_compare,
+ sizeof (brt_pending_entry_t),
+ offsetof(brt_pending_entry_t, bpe_node));
+ mutex_init(&brt->brt_pending_lock[i], NULL, MUTEX_DEFAULT,
+ NULL);
+ }
+}
+
+static void
+brt_table_free(brt_t *brt)
+{
+
+ for (int i = 0; i < TXG_SIZE; i++) {
+ ASSERT(avl_is_empty(&brt->brt_pending_tree[i]));
+
+ avl_destroy(&brt->brt_pending_tree[i]);
+ mutex_destroy(&brt->brt_pending_lock[i]);
+ }
+}
+
+static void
+brt_alloc(spa_t *spa)
+{
+ brt_t *brt;
+
+ ASSERT(spa->spa_brt == NULL);
+
+ brt = kmem_zalloc(sizeof (*brt), KM_SLEEP);
+ rw_init(&brt->brt_lock, NULL, RW_DEFAULT, NULL);
+ brt->brt_spa = spa;
+ brt->brt_rangesize = 0;
+ brt->brt_nentries = 0;
+ brt->brt_vdevs = NULL;
+ brt->brt_nvdevs = 0;
+ brt_table_alloc(brt);
+
+ spa->spa_brt = brt;
+}
+
+void
+brt_create(spa_t *spa)
+{
+
+ brt_alloc(spa);
+ brt_vdevs_alloc(spa->spa_brt, B_FALSE);
+}
+
+int
+brt_load(spa_t *spa)
+{
+
+ brt_alloc(spa);
+ brt_vdevs_alloc(spa->spa_brt, B_TRUE);
+
+ return (0);
+}
+
+void
+brt_unload(spa_t *spa)
+{
+ brt_t *brt = spa->spa_brt;
+
+ if (brt == NULL)
+ return;
+
+ brt_vdevs_free(brt);
+ brt_table_free(brt);
+ rw_destroy(&brt->brt_lock);
+ kmem_free(brt, sizeof (*brt));
+ spa->spa_brt = NULL;
+}
+
+/* BEGIN CSTYLED */
+ZFS_MODULE_PARAM(zfs_brt, , brt_zap_prefetch, INT, ZMOD_RW,
+ "Enable prefetching of BRT ZAP entries");
+ZFS_MODULE_PARAM(zfs_brt, , brt_zap_default_bs, UINT, ZMOD_RW,
+ "BRT ZAP leaf blockshift");
+ZFS_MODULE_PARAM(zfs_brt, , brt_zap_default_ibs, UINT, ZMOD_RW,
+ "BRT ZAP indirect blockshift");
+/* END CSTYLED */
diff --git a/module/zfs/btree.c b/module/zfs/btree.c
index 14cab4054cbc..af2b94a850be 100644
--- a/module/zfs/btree.c
+++ b/module/zfs/btree.c
@@ -53,7 +53,7 @@ kmem_cache_t *zfs_btree_leaf_cache;
* (while the asymptotic complexity of the other steps is the same, the
* importance of the constant factors cannot be denied).
*/
-int zfs_btree_verify_intensity = 0;
+uint_t zfs_btree_verify_intensity = 0;
/*
* Convenience functions to silence warnings from memcpy/memmove's
@@ -102,7 +102,7 @@ zfs_btree_poison_node(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
(void) memset(leaf->btl_elems, 0x0f, hdr->bth_first * size);
(void) memset(leaf->btl_elems +
(hdr->bth_first + hdr->bth_count) * size, 0x0f,
- BTREE_LEAF_ESIZE -
+ tree->bt_leaf_size - offsetof(zfs_btree_leaf_t, btl_elems) -
(hdr->bth_first + hdr->bth_count) * size);
}
#endif
@@ -173,16 +173,52 @@ zfs_btree_fini(void)
kmem_cache_destroy(zfs_btree_leaf_cache);
}
+static void *
+zfs_btree_leaf_alloc(zfs_btree_t *tree)
+{
+ if (tree->bt_leaf_size == BTREE_LEAF_SIZE)
+ return (kmem_cache_alloc(zfs_btree_leaf_cache, KM_SLEEP));
+ else
+ return (kmem_alloc(tree->bt_leaf_size, KM_SLEEP));
+}
+
+static void
+zfs_btree_leaf_free(zfs_btree_t *tree, void *ptr)
+{
+ if (tree->bt_leaf_size == BTREE_LEAF_SIZE)
+ return (kmem_cache_free(zfs_btree_leaf_cache, ptr));
+ else
+ return (kmem_free(ptr, tree->bt_leaf_size));
+}
+
void
zfs_btree_create(zfs_btree_t *tree, int (*compar) (const void *, const void *),
- size_t size)
+ bt_find_in_buf_f bt_find_in_buf, size_t size)
+{
+ zfs_btree_create_custom(tree, compar, bt_find_in_buf, size,
+ BTREE_LEAF_SIZE);
+}
+
+static void *
+zfs_btree_find_in_buf(zfs_btree_t *tree, uint8_t *buf, uint32_t nelems,
+ const void *value, zfs_btree_index_t *where);
+
+void
+zfs_btree_create_custom(zfs_btree_t *tree,
+ int (*compar) (const void *, const void *),
+ bt_find_in_buf_f bt_find_in_buf,
+ size_t size, size_t lsize)
{
- ASSERT3U(size, <=, BTREE_LEAF_ESIZE / 2);
+ size_t esize = lsize - offsetof(zfs_btree_leaf_t, btl_elems);
+ ASSERT3U(size, <=, esize / 2);
memset(tree, 0, sizeof (*tree));
tree->bt_compar = compar;
+ tree->bt_find_in_buf = (bt_find_in_buf == NULL) ?
+ zfs_btree_find_in_buf : bt_find_in_buf;
tree->bt_elem_size = size;
- tree->bt_leaf_cap = P2ALIGN(BTREE_LEAF_ESIZE / size, 2);
+ tree->bt_leaf_size = lsize;
+ tree->bt_leaf_cap = P2ALIGN(esize / size, 2);
tree->bt_height = -1;
tree->bt_bulk = NULL;
}
@@ -275,7 +311,7 @@ zfs_btree_find(zfs_btree_t *tree, const void *value, zfs_btree_index_t *where)
* element in the last leaf, it's in the last leaf or
* it's not in the tree.
*/
- void *d = zfs_btree_find_in_buf(tree,
+ void *d = tree->bt_find_in_buf(tree,
last_leaf->btl_elems +
last_leaf->btl_hdr.bth_first * size,
last_leaf->btl_hdr.bth_count, value, &idx);
@@ -290,7 +326,7 @@ zfs_btree_find(zfs_btree_t *tree, const void *value, zfs_btree_index_t *where)
zfs_btree_core_t *node = NULL;
uint32_t child = 0;
- uint64_t depth = 0;
+ uint32_t depth = 0;
/*
* Iterate down the tree, finding which child the value should be in
@@ -299,7 +335,7 @@ zfs_btree_find(zfs_btree_t *tree, const void *value, zfs_btree_index_t *where)
for (node = (zfs_btree_core_t *)tree->bt_root; depth < tree->bt_height;
node = (zfs_btree_core_t *)node->btc_children[child], depth++) {
ASSERT3P(node, !=, NULL);
- void *d = zfs_btree_find_in_buf(tree, node->btc_elems,
+ void *d = tree->bt_find_in_buf(tree, node->btc_elems,
node->btc_hdr.bth_count, value, &idx);
EQUIV(d != NULL, !idx.bti_before);
if (d != NULL) {
@@ -319,7 +355,7 @@ zfs_btree_find(zfs_btree_t *tree, const void *value, zfs_btree_index_t *where)
*/
zfs_btree_leaf_t *leaf = (depth == 0 ?
(zfs_btree_leaf_t *)tree->bt_root : (zfs_btree_leaf_t *)node);
- void *d = zfs_btree_find_in_buf(tree, leaf->btl_elems +
+ void *d = tree->bt_find_in_buf(tree, leaf->btl_elems +
leaf->btl_hdr.bth_first * size,
leaf->btl_hdr.bth_count, value, &idx);
@@ -643,7 +679,7 @@ zfs_btree_insert_into_parent(zfs_btree_t *tree, zfs_btree_hdr_t *old_node,
zfs_btree_hdr_t *par_hdr = &parent->btc_hdr;
zfs_btree_index_t idx;
ASSERT(zfs_btree_is_core(par_hdr));
- VERIFY3P(zfs_btree_find_in_buf(tree, parent->btc_elems,
+ VERIFY3P(tree->bt_find_in_buf(tree, parent->btc_elems,
par_hdr->bth_count, buf, &idx), ==, NULL);
ASSERT(idx.bti_before);
uint32_t offset = idx.bti_offset;
@@ -811,8 +847,7 @@ zfs_btree_insert_into_leaf(zfs_btree_t *tree, zfs_btree_leaf_t *leaf,
move_count++;
}
tree->bt_num_nodes++;
- zfs_btree_leaf_t *new_leaf = kmem_cache_alloc(zfs_btree_leaf_cache,
- KM_SLEEP);
+ zfs_btree_leaf_t *new_leaf = zfs_btree_leaf_alloc(tree);
zfs_btree_hdr_t *new_hdr = &new_leaf->btl_hdr;
new_hdr->bth_parent = leaf->btl_hdr.bth_parent;
new_hdr->bth_first = (tree->bt_bulk ? 0 : capacity / 4) +
@@ -870,7 +905,7 @@ zfs_btree_find_parent_idx(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
}
zfs_btree_index_t idx;
zfs_btree_core_t *parent = hdr->bth_parent;
- VERIFY3P(zfs_btree_find_in_buf(tree, parent->btc_elems,
+ VERIFY3P(tree->bt_find_in_buf(tree, parent->btc_elems,
parent->btc_hdr.bth_count, buf, &idx), ==, NULL);
ASSERT(idx.bti_before);
ASSERT3U(idx.bti_offset, <=, parent->btc_hdr.bth_count);
@@ -1078,8 +1113,7 @@ zfs_btree_add_idx(zfs_btree_t *tree, const void *value,
ASSERT0(where->bti_offset);
tree->bt_num_nodes++;
- zfs_btree_leaf_t *leaf = kmem_cache_alloc(zfs_btree_leaf_cache,
- KM_SLEEP);
+ zfs_btree_leaf_t *leaf = zfs_btree_leaf_alloc(tree);
tree->bt_root = &leaf->btl_hdr;
tree->bt_height++;
@@ -1378,7 +1412,7 @@ zfs_btree_node_destroy(zfs_btree_t *tree, zfs_btree_hdr_t *node)
{
tree->bt_num_nodes--;
if (!zfs_btree_is_core(node)) {
- kmem_cache_free(zfs_btree_leaf_cache, node);
+ zfs_btree_leaf_free(tree, node);
} else {
kmem_free(node, sizeof (zfs_btree_core_t) +
BTREE_CORE_ELEMS * tree->bt_elem_size);
@@ -1608,8 +1642,8 @@ zfs_btree_remove_from_node(zfs_btree_t *tree, zfs_btree_core_t *node,
zfs_btree_poison_node_at(tree, keep_hdr, keep_hdr->bth_count, 1);
new_rm_hdr->bth_count = 0;
- zfs_btree_node_destroy(tree, new_rm_hdr);
zfs_btree_remove_from_node(tree, parent, new_rm_hdr);
+ zfs_btree_node_destroy(tree, new_rm_hdr);
}
/* Remove the element at the specific location. */
@@ -1817,10 +1851,10 @@ zfs_btree_remove_idx(zfs_btree_t *tree, zfs_btree_index_t *where)
/* Move our elements to the left neighbor. */
bt_transfer_leaf(tree, rm, 0, rm_hdr->bth_count, keep, k_count + 1);
- zfs_btree_node_destroy(tree, rm_hdr);
/* Remove the emptied node from the parent. */
zfs_btree_remove_from_node(tree, parent, rm_hdr);
+ zfs_btree_node_destroy(tree, rm_hdr);
zfs_btree_verify(tree);
}
@@ -1991,7 +2025,7 @@ zfs_btree_verify_counts(zfs_btree_t *tree)
*/
static uint64_t
zfs_btree_verify_height_helper(zfs_btree_t *tree, zfs_btree_hdr_t *hdr,
- int64_t height)
+ int32_t height)
{
if (!zfs_btree_is_core(hdr)) {
VERIFY0(height);
@@ -2117,8 +2151,10 @@ zfs_btree_verify_poison_helper(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
zfs_btree_leaf_t *leaf = (zfs_btree_leaf_t *)hdr;
for (size_t i = 0; i < hdr->bth_first * size; i++)
VERIFY3U(leaf->btl_elems[i], ==, 0x0f);
+ size_t esize = tree->bt_leaf_size -
+ offsetof(zfs_btree_leaf_t, btl_elems);
for (size_t i = (hdr->bth_first + hdr->bth_count) * size;
- i < BTREE_LEAF_ESIZE; i++)
+ i < esize; i++)
VERIFY3U(leaf->btl_elems[i], ==, 0x0f);
} else {
zfs_btree_core_t *node = (zfs_btree_core_t *)hdr;
@@ -2171,3 +2207,9 @@ zfs_btree_verify(zfs_btree_t *tree)
return;
zfs_btree_verify_poison(tree);
}
+
+/* BEGIN CSTYLED */
+ZFS_MODULE_PARAM(zfs, zfs_, btree_verify_intensity, UINT, ZMOD_RW,
+ "Enable btree verification. Levels above 4 require ZFS be built "
+ "with debugging");
+/* END CSTYLED */
diff --git a/module/zfs/dataset_kstats.c b/module/zfs/dataset_kstats.c
index 6b4b31e8c9c6..2ac058fd2c93 100644
--- a/module/zfs/dataset_kstats.c
+++ b/module/zfs/dataset_kstats.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -37,18 +37,37 @@ static dataset_kstat_values_t empty_dataset_kstats = {
{ "nread", KSTAT_DATA_UINT64 },
{ "nunlinks", KSTAT_DATA_UINT64 },
{ "nunlinked", KSTAT_DATA_UINT64 },
+ {
+ { "zil_commit_count", KSTAT_DATA_UINT64 },
+ { "zil_commit_writer_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_indirect_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_indirect_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_copied_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_copied_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_needcopy_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_needcopy_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_write", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_alloc", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_count", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_write", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_alloc", KSTAT_DATA_UINT64 }
+ }
};
static int
dataset_kstats_update(kstat_t *ksp, int rw)
{
dataset_kstats_t *dk = ksp->ks_private;
- ASSERT3P(dk->dk_kstats->ks_data, ==, ksp->ks_data);
+ dataset_kstat_values_t *dkv = ksp->ks_data;
+ ASSERT3P(dk->dk_kstats->ks_data, ==, dkv);
if (rw == KSTAT_WRITE)
return (EACCES);
- dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;
dkv->dkv_writes.value.ui64 =
wmsum_value(&dk->dk_sums.dss_writes);
dkv->dkv_nwritten.value.ui64 =
@@ -62,10 +81,12 @@ dataset_kstats_update(kstat_t *ksp, int rw)
dkv->dkv_nunlinked.value.ui64 =
wmsum_value(&dk->dk_sums.dss_nunlinked);
+ zil_kstat_values_update(&dkv->dkv_zil_stats, &dk->dk_zil_sums);
+
return (0);
}
-void
+int
dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
{
/*
@@ -75,7 +96,7 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
* a filesystem with many snapshots, we skip them for now.
*/
if (dmu_objset_is_snapshot(objset))
- return;
+ return (0);
/*
* At the time of this writing, KSTAT_STRLEN is 255 in Linux,
@@ -94,13 +115,13 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
" snprintf() for kstat module name returned %d",
(unsigned long long)dmu_objset_id(objset), n);
- return;
+ return (SET_ERROR(EINVAL));
} else if (n >= KSTAT_STRLEN) {
zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
"kstat module name length (%d) exceeds limit (%d)",
(unsigned long long)dmu_objset_id(objset),
n, KSTAT_STRLEN);
- return;
+ return (SET_ERROR(ENAMETOOLONG));
}
char kstat_name[KSTAT_STRLEN];
@@ -110,16 +131,21 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
" snprintf() for kstat name returned %d",
(unsigned long long)dmu_objset_id(objset), n);
- return;
+ return (SET_ERROR(EINVAL));
+ } else if (n >= KSTAT_STRLEN) {
+ zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
+ "kstat name length (%d) exceeds limit (%d)",
+ (unsigned long long)dmu_objset_id(objset),
+ n, KSTAT_STRLEN);
+ return (SET_ERROR(ENAMETOOLONG));
}
- ASSERT3U(n, <, KSTAT_STRLEN);
kstat_t *kstat = kstat_create(kstat_module_name, 0, kstat_name,
"dataset", KSTAT_TYPE_NAMED,
sizeof (empty_dataset_kstats) / sizeof (kstat_named_t),
KSTAT_FLAG_VIRTUAL);
if (kstat == NULL)
- return;
+ return (SET_ERROR(ENOMEM));
dataset_kstat_values_t *dk_kstats =
kmem_alloc(sizeof (empty_dataset_kstats), KM_SLEEP);
@@ -137,15 +163,17 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
kstat->ks_private = dk;
kstat->ks_data_size += ZFS_MAX_DATASET_NAME_LEN;
- kstat_install(kstat);
- dk->dk_kstats = kstat;
-
wmsum_init(&dk->dk_sums.dss_writes, 0);
wmsum_init(&dk->dk_sums.dss_nwritten, 0);
wmsum_init(&dk->dk_sums.dss_reads, 0);
wmsum_init(&dk->dk_sums.dss_nread, 0);
wmsum_init(&dk->dk_sums.dss_nunlinks, 0);
wmsum_init(&dk->dk_sums.dss_nunlinked, 0);
+ zil_sums_init(&dk->dk_zil_sums);
+
+ dk->dk_kstats = kstat;
+ kstat_install(kstat);
+ return (0);
}
void
@@ -155,19 +183,31 @@ dataset_kstats_destroy(dataset_kstats_t *dk)
return;
dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;
+ kstat_delete(dk->dk_kstats);
+ dk->dk_kstats = NULL;
kmem_free(KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name),
KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name));
kmem_free(dkv, sizeof (empty_dataset_kstats));
- kstat_delete(dk->dk_kstats);
- dk->dk_kstats = NULL;
-
wmsum_fini(&dk->dk_sums.dss_writes);
wmsum_fini(&dk->dk_sums.dss_nwritten);
wmsum_fini(&dk->dk_sums.dss_reads);
wmsum_fini(&dk->dk_sums.dss_nread);
wmsum_fini(&dk->dk_sums.dss_nunlinks);
wmsum_fini(&dk->dk_sums.dss_nunlinked);
+ zil_sums_fini(&dk->dk_zil_sums);
+}
+
+void
+dataset_kstats_rename(dataset_kstats_t *dk, const char *name)
+{
+ dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;
+ char *ds_name;
+
+ ds_name = KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name);
+ ASSERT3S(ds_name, !=, NULL);
+ (void) strlcpy(ds_name, name,
+ KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name));
}
void
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index 00b01611ddd5..bb913f556374 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,6 +26,7 @@
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
+ * Copyright (c) 2021, 2022 by Pawel Jakub Dawidek
*/
#include <sys/zfs_context.h>
@@ -49,6 +50,7 @@
#include <sys/trace_zfs.h>
#include <sys/callb.h>
#include <sys/abd.h>
+#include <sys/brt.h>
#include <sys/vdev.h>
#include <cityhash.h>
#include <sys/spa_impl.h>
@@ -100,6 +102,11 @@ typedef struct dbuf_stats {
*/
kstat_named_t hash_insert_race;
/*
+ * Number of entries in the hash table dbuf and mutex arrays.
+ */
+ kstat_named_t hash_table_count;
+ kstat_named_t hash_mutex_count;
+ /*
* Statistics about the size of the metadata dbuf cache.
*/
kstat_named_t metadata_cache_count;
@@ -131,6 +138,8 @@ dbuf_stats_t dbuf_stats = {
{ "hash_chains", KSTAT_DATA_UINT64 },
{ "hash_chain_max", KSTAT_DATA_UINT64 },
{ "hash_insert_race", KSTAT_DATA_UINT64 },
+ { "hash_table_count", KSTAT_DATA_UINT64 },
+ { "hash_mutex_count", KSTAT_DATA_UINT64 },
{ "metadata_cache_count", KSTAT_DATA_UINT64 },
{ "metadata_cache_size_bytes", KSTAT_DATA_UINT64 },
{ "metadata_cache_size_bytes_max", KSTAT_DATA_UINT64 },
@@ -152,13 +161,13 @@ struct {
} dbuf_sums;
#define DBUF_STAT_INCR(stat, val) \
- wmsum_add(&dbuf_sums.stat, val);
+ wmsum_add(&dbuf_sums.stat, val)
#define DBUF_STAT_DECR(stat, val) \
- DBUF_STAT_INCR(stat, -(val));
+ DBUF_STAT_INCR(stat, -(val))
#define DBUF_STAT_BUMP(stat) \
- DBUF_STAT_INCR(stat, 1);
+ DBUF_STAT_INCR(stat, 1)
#define DBUF_STAT_BUMPDOWN(stat) \
- DBUF_STAT_INCR(stat, -1);
+ DBUF_STAT_INCR(stat, -1)
#define DBUF_STAT_MAX(stat, v) { \
uint64_t _m; \
while ((v) > (_m = dbuf_stats.stat.value.ui64) && \
@@ -166,10 +175,8 @@ struct {
continue; \
}
-static boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
static void dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx);
static void dbuf_sync_leaf_verify_bonus_dnode(dbuf_dirty_record_t *dr);
-static int dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags);
/*
* Global data structures and functions for the dbuf cache.
@@ -220,12 +227,15 @@ typedef struct dbuf_cache {
dbuf_cache_t dbuf_caches[DB_CACHE_MAX];
/* Size limits for the caches */
-static unsigned long dbuf_cache_max_bytes = ULONG_MAX;
-static unsigned long dbuf_metadata_cache_max_bytes = ULONG_MAX;
+static uint64_t dbuf_cache_max_bytes = UINT64_MAX;
+static uint64_t dbuf_metadata_cache_max_bytes = UINT64_MAX;
/* Set the default sizes of the caches to log2 fraction of arc size */
-static int dbuf_cache_shift = 5;
-static int dbuf_metadata_cache_shift = 6;
+static uint_t dbuf_cache_shift = 5;
+static uint_t dbuf_metadata_cache_shift = 6;
+
+/* Set the dbuf hash mutex count as log2 shift (dynamic by default) */
+static uint_t dbuf_mutex_cache_shift = 0;
static unsigned long dbuf_cache_target_bytes(void);
static unsigned long dbuf_metadata_cache_target_bytes(void);
@@ -329,7 +339,8 @@ dbuf_hash(void *os, uint64_t obj, uint8_t lvl, uint64_t blkid)
(dbuf)->db_blkid == (blkid))
dmu_buf_impl_t *
-dbuf_find(objset_t *os, uint64_t obj, uint8_t level, uint64_t blkid)
+dbuf_find(objset_t *os, uint64_t obj, uint8_t level, uint64_t blkid,
+ uint64_t *hash_out)
{
dbuf_hash_table_t *h = &dbuf_hash_table;
uint64_t hv;
@@ -339,18 +350,20 @@ dbuf_find(objset_t *os, uint64_t obj, uint8_t level, uint64_t blkid)
hv = dbuf_hash(os, obj, level, blkid);
idx = hv & h->hash_table_mask;
- rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_READER);
+ mutex_enter(DBUF_HASH_MUTEX(h, idx));
for (db = h->hash_table[idx]; db != NULL; db = db->db_hash_next) {
if (DBUF_EQUAL(db, os, obj, level, blkid)) {
mutex_enter(&db->db_mtx);
if (db->db_state != DB_EVICTING) {
- rw_exit(DBUF_HASH_RWLOCK(h, idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, idx));
return (db);
}
mutex_exit(&db->db_mtx);
}
}
- rw_exit(DBUF_HASH_RWLOCK(h, idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, idx));
+ if (hash_out != NULL)
+ *hash_out = hv;
return (NULL);
}
@@ -385,21 +398,21 @@ dbuf_hash_insert(dmu_buf_impl_t *db)
objset_t *os = db->db_objset;
uint64_t obj = db->db.db_object;
int level = db->db_level;
- uint64_t blkid, hv, idx;
+ uint64_t blkid, idx;
dmu_buf_impl_t *dbf;
uint32_t i;
blkid = db->db_blkid;
- hv = dbuf_hash(os, obj, level, blkid);
- idx = hv & h->hash_table_mask;
+ ASSERT3U(dbuf_hash(os, obj, level, blkid), ==, db->db_hash);
+ idx = db->db_hash & h->hash_table_mask;
- rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_WRITER);
+ mutex_enter(DBUF_HASH_MUTEX(h, idx));
for (dbf = h->hash_table[idx], i = 0; dbf != NULL;
dbf = dbf->db_hash_next, i++) {
if (DBUF_EQUAL(dbf, os, obj, level, blkid)) {
mutex_enter(&dbf->db_mtx);
if (dbf->db_state != DB_EVICTING) {
- rw_exit(DBUF_HASH_RWLOCK(h, idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, idx));
return (dbf);
}
mutex_exit(&dbf->db_mtx);
@@ -417,7 +430,7 @@ dbuf_hash_insert(dmu_buf_impl_t *db)
mutex_enter(&db->db_mtx);
db->db_hash_next = h->hash_table[idx];
h->hash_table[idx] = db;
- rw_exit(DBUF_HASH_RWLOCK(h, idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, idx));
uint64_t he = atomic_inc_64_nv(&dbuf_stats.hash_elements.value.ui64);
DBUF_STAT_MAX(hash_elements_max, he);
@@ -465,22 +478,22 @@ static void
dbuf_hash_remove(dmu_buf_impl_t *db)
{
dbuf_hash_table_t *h = &dbuf_hash_table;
- uint64_t hv, idx;
+ uint64_t idx;
dmu_buf_impl_t *dbf, **dbp;
- hv = dbuf_hash(db->db_objset, db->db.db_object,
- db->db_level, db->db_blkid);
- idx = hv & h->hash_table_mask;
+ ASSERT3U(dbuf_hash(db->db_objset, db->db.db_object, db->db_level,
+ db->db_blkid), ==, db->db_hash);
+ idx = db->db_hash & h->hash_table_mask;
/*
* We mustn't hold db_mtx to maintain lock ordering:
- * DBUF_HASH_RWLOCK > db_mtx.
+ * DBUF_HASH_MUTEX > db_mtx.
*/
ASSERT(zfs_refcount_is_zero(&db->db_holds));
ASSERT(db->db_state == DB_EVICTING);
ASSERT(!MUTEX_HELD(&db->db_mtx));
- rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_WRITER);
+ mutex_enter(DBUF_HASH_MUTEX(h, idx));
dbp = &h->hash_table[idx];
while ((dbf = *dbp) != db) {
dbp = &dbf->db_hash_next;
@@ -491,7 +504,7 @@ dbuf_hash_remove(dmu_buf_impl_t *db)
if (h->hash_table[idx] &&
h->hash_table[idx]->db_hash_next == NULL)
DBUF_STAT_BUMPDOWN(hash_chains);
- rw_exit(DBUF_HASH_RWLOCK(h, idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, idx));
atomic_dec_64(&dbuf_stats.hash_elements.value.ui64);
}
@@ -555,6 +568,21 @@ dbuf_evict_user(dmu_buf_impl_t *db)
*dbu->dbu_clear_on_evict_dbufp = NULL;
#endif
+ if (db->db_caching_status != DB_NO_CACHE) {
+ /*
+ * This is a cached dbuf, so the size of the user data is
+ * included in its cached amount. We adjust it here because the
+ * user data has already been detached from the dbuf, and the
+ * sync functions are not supposed to touch it (the dbuf might
+ * not exist anymore by the time the sync functions run.
+ */
+ uint64_t size = dbu->dbu_size;
+ (void) zfs_refcount_remove_many(
+ &dbuf_caches[db->db_caching_status].size, size, db);
+ if (db->db_caching_status == DB_DBUF_CACHE)
+ DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
+ }
+
/*
* There are two eviction callbacks - one that we call synchronously
* and one that we invoke via a taskq. The async one is useful for
@@ -602,58 +630,58 @@ dbuf_is_metadata(dmu_buf_impl_t *db)
boolean_t
dbuf_is_l2cacheable(dmu_buf_impl_t *db)
{
- vdev_t *vd = NULL;
- zfs_cache_type_t cache = db->db_objset->os_secondary_cache;
- blkptr_t *bp = db->db_blkptr;
-
- if (bp != NULL && !BP_IS_HOLE(bp)) {
+ if (db->db_objset->os_secondary_cache == ZFS_CACHE_ALL ||
+ (db->db_objset->os_secondary_cache ==
+ ZFS_CACHE_METADATA && dbuf_is_metadata(db))) {
+ if (l2arc_exclude_special == 0)
+ return (B_TRUE);
+
+ blkptr_t *bp = db->db_blkptr;
+ if (bp == NULL || BP_IS_HOLE(bp))
+ return (B_FALSE);
uint64_t vdev = DVA_GET_VDEV(bp->blk_dva);
vdev_t *rvd = db->db_objset->os_spa->spa_root_vdev;
+ vdev_t *vd = NULL;
if (vdev < rvd->vdev_children)
vd = rvd->vdev_child[vdev];
- if (cache == ZFS_CACHE_ALL ||
- (dbuf_is_metadata(db) && cache == ZFS_CACHE_METADATA)) {
- if (vd == NULL)
- return (B_TRUE);
+ if (vd == NULL)
+ return (B_TRUE);
- if ((vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
- vd->vdev_alloc_bias != VDEV_BIAS_DEDUP) ||
- l2arc_exclude_special == 0)
- return (B_TRUE);
- }
+ if (vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
+ vd->vdev_alloc_bias != VDEV_BIAS_DEDUP)
+ return (B_TRUE);
}
-
return (B_FALSE);
}
static inline boolean_t
dnode_level_is_l2cacheable(blkptr_t *bp, dnode_t *dn, int64_t level)
{
- vdev_t *vd = NULL;
- zfs_cache_type_t cache = dn->dn_objset->os_secondary_cache;
-
- if (bp != NULL && !BP_IS_HOLE(bp)) {
+ if (dn->dn_objset->os_secondary_cache == ZFS_CACHE_ALL ||
+ (dn->dn_objset->os_secondary_cache == ZFS_CACHE_METADATA &&
+ (level > 0 ||
+ DMU_OT_IS_METADATA(dn->dn_handle->dnh_dnode->dn_type)))) {
+ if (l2arc_exclude_special == 0)
+ return (B_TRUE);
+
+ if (bp == NULL || BP_IS_HOLE(bp))
+ return (B_FALSE);
uint64_t vdev = DVA_GET_VDEV(bp->blk_dva);
vdev_t *rvd = dn->dn_objset->os_spa->spa_root_vdev;
+ vdev_t *vd = NULL;
if (vdev < rvd->vdev_children)
vd = rvd->vdev_child[vdev];
- if (cache == ZFS_CACHE_ALL || ((level > 0 ||
- DMU_OT_IS_METADATA(dn->dn_handle->dnh_dnode->dn_type)) &&
- cache == ZFS_CACHE_METADATA)) {
- if (vd == NULL)
- return (B_TRUE);
+ if (vd == NULL)
+ return (B_TRUE);
- if ((vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
- vd->vdev_alloc_bias != VDEV_BIAS_DEDUP) ||
- l2arc_exclude_special == 0)
- return (B_TRUE);
- }
+ if (vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
+ vd->vdev_alloc_bias != VDEV_BIAS_DEDUP)
+ return (B_TRUE);
}
-
return (B_FALSE);
}
@@ -740,7 +768,7 @@ static void
dbuf_evict_one(void)
{
int idx = multilist_get_random_index(&dbuf_caches[DB_DBUF_CACHE].cache);
- multilist_sublist_t *mls = multilist_sublist_lock(
+ multilist_sublist_t *mls = multilist_sublist_lock_idx(
&dbuf_caches[DB_DBUF_CACHE].cache, idx);
ASSERT(!MUTEX_HELD(&dbuf_evict_lock));
@@ -756,12 +784,12 @@ dbuf_evict_one(void)
if (db != NULL) {
multilist_sublist_remove(mls, db);
multilist_sublist_unlock(mls);
+ uint64_t size = db->db.db_size + dmu_buf_user_size(&db->db);
(void) zfs_refcount_remove_many(
- &dbuf_caches[DB_DBUF_CACHE].size, db->db.db_size, db);
+ &dbuf_caches[DB_DBUF_CACHE].size, size, db);
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
DBUF_STAT_BUMPDOWN(cache_count);
- DBUF_STAT_DECR(cache_levels_bytes[db->db_level],
- db->db.db_size);
+ DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
ASSERT3U(db->db_caching_status, ==, DB_DBUF_CACHE);
db->db_caching_status = DB_NO_CACHE;
dbuf_destroy(db);
@@ -838,6 +866,7 @@ static int
dbuf_kstat_update(kstat_t *ksp, int rw)
{
dbuf_stats_t *ds = ksp->ks_data;
+ dbuf_hash_table_t *h = &dbuf_hash_table;
if (rw == KSTAT_WRITE)
return (SET_ERROR(EACCES));
@@ -867,6 +896,8 @@ dbuf_kstat_update(kstat_t *ksp, int rw)
wmsum_value(&dbuf_sums.hash_chains);
ds->hash_insert_race.value.ui64 =
wmsum_value(&dbuf_sums.hash_insert_race);
+ ds->hash_table_count.value.ui64 = h->hash_table_mask + 1;
+ ds->hash_mutex_count.value.ui64 = h->hash_mutex_mask + 1;
ds->metadata_cache_count.value.ui64 =
wmsum_value(&dbuf_sums.metadata_cache_count);
ds->metadata_cache_size_bytes.value.ui64 = zfs_refcount_count(
@@ -879,9 +910,8 @@ dbuf_kstat_update(kstat_t *ksp, int rw)
void
dbuf_init(void)
{
- uint64_t hsize = 1ULL << 16;
+ uint64_t hmsize, hsize = 1ULL << 16;
dbuf_hash_table_t *h = &dbuf_hash_table;
- int i;
/*
* The hash table is big enough to fill one eighth of physical memory
@@ -892,30 +922,43 @@ dbuf_init(void)
while (hsize * zfs_arc_average_blocksize < arc_all_memory() / 8)
hsize <<= 1;
-retry:
- h->hash_table_mask = hsize - 1;
-#if defined(_KERNEL)
+ h->hash_table = NULL;
+ while (h->hash_table == NULL) {
+ h->hash_table_mask = hsize - 1;
+
+ h->hash_table = vmem_zalloc(hsize * sizeof (void *), KM_SLEEP);
+ if (h->hash_table == NULL)
+ hsize >>= 1;
+
+ ASSERT3U(hsize, >=, 1ULL << 10);
+ }
+
/*
- * Large allocations which do not require contiguous pages
- * should be using vmem_alloc() in the linux kernel
+ * The hash table buckets are protected by an array of mutexes where
+ * each mutex is reponsible for protecting 128 buckets. A minimum
+ * array size of 8192 is targeted to avoid contention.
*/
- h->hash_table = vmem_zalloc(hsize * sizeof (void *), KM_SLEEP);
-#else
- h->hash_table = kmem_zalloc(hsize * sizeof (void *), KM_NOSLEEP);
-#endif
- if (h->hash_table == NULL) {
- /* XXX - we should really return an error instead of assert */
- ASSERT(hsize > (1ULL << 10));
- hsize >>= 1;
- goto retry;
+ if (dbuf_mutex_cache_shift == 0)
+ hmsize = MAX(hsize >> 7, 1ULL << 13);
+ else
+ hmsize = 1ULL << MIN(dbuf_mutex_cache_shift, 24);
+
+ h->hash_mutexes = NULL;
+ while (h->hash_mutexes == NULL) {
+ h->hash_mutex_mask = hmsize - 1;
+
+ h->hash_mutexes = vmem_zalloc(hmsize * sizeof (kmutex_t),
+ KM_SLEEP);
+ if (h->hash_mutexes == NULL)
+ hmsize >>= 1;
}
dbuf_kmem_cache = kmem_cache_create("dmu_buf_impl_t",
sizeof (dmu_buf_impl_t),
0, dbuf_cons, dbuf_dest, NULL, NULL, NULL, 0);
- for (i = 0; i < DBUF_RWLOCKS; i++)
- rw_init(&h->hash_rwlocks[i], NULL, RW_DEFAULT, NULL);
+ for (int i = 0; i < hmsize; i++)
+ mutex_init(&h->hash_mutexes[i], NULL, MUTEX_DEFAULT, NULL);
dbuf_stats_init(h);
@@ -941,7 +984,7 @@ retry:
wmsum_init(&dbuf_sums.cache_count, 0);
wmsum_init(&dbuf_sums.cache_total_evicts, 0);
- for (i = 0; i < DN_MAX_LEVELS; i++) {
+ for (int i = 0; i < DN_MAX_LEVELS; i++) {
wmsum_init(&dbuf_sums.cache_levels[i], 0);
wmsum_init(&dbuf_sums.cache_levels_bytes[i], 0);
}
@@ -957,7 +1000,7 @@ retry:
KSTAT_TYPE_NAMED, sizeof (dbuf_stats) / sizeof (kstat_named_t),
KSTAT_FLAG_VIRTUAL);
if (dbuf_ksp != NULL) {
- for (i = 0; i < DN_MAX_LEVELS; i++) {
+ for (int i = 0; i < DN_MAX_LEVELS; i++) {
snprintf(dbuf_stats.cache_levels[i].name,
KSTAT_STRLEN, "cache_level_%d", i);
dbuf_stats.cache_levels[i].data_type =
@@ -977,21 +1020,16 @@ void
dbuf_fini(void)
{
dbuf_hash_table_t *h = &dbuf_hash_table;
- int i;
dbuf_stats_destroy();
- for (i = 0; i < DBUF_RWLOCKS; i++)
- rw_destroy(&h->hash_rwlocks[i]);
-#if defined(_KERNEL)
- /*
- * Large allocations which do not require contiguous pages
- * should be using vmem_free() in the linux kernel
- */
+ for (int i = 0; i < (h->hash_mutex_mask + 1); i++)
+ mutex_destroy(&h->hash_mutexes[i]);
+
vmem_free(h->hash_table, (h->hash_table_mask + 1) * sizeof (void *));
-#else
- kmem_free(h->hash_table, (h->hash_table_mask + 1) * sizeof (void *));
-#endif
+ vmem_free(h->hash_mutexes, (h->hash_mutex_mask + 1) *
+ sizeof (kmutex_t));
+
kmem_cache_destroy(dbuf_kmem_cache);
taskq_destroy(dbu_evict_taskq);
@@ -1018,7 +1056,7 @@ dbuf_fini(void)
wmsum_fini(&dbuf_sums.cache_count);
wmsum_fini(&dbuf_sums.cache_total_evicts);
- for (i = 0; i < DN_MAX_LEVELS; i++) {
+ for (int i = 0; i < DN_MAX_LEVELS; i++) {
wmsum_fini(&dbuf_sums.cache_levels[i]);
wmsum_fini(&dbuf_sums.cache_levels_bytes[i]);
}
@@ -1132,7 +1170,7 @@ dbuf_verify(dmu_buf_impl_t *db)
if ((db->db_blkptr == NULL || BP_IS_HOLE(db->db_blkptr)) &&
(db->db_buf == NULL || db->db_buf->b_data) &&
db->db.db_data && db->db_blkid != DMU_BONUS_BLKID &&
- db->db_state != DB_FILL && !dn->dn_free_txg) {
+ db->db_state != DB_FILL && (dn == NULL || !dn->dn_free_txg)) {
/*
* If the blkptr isn't set but they have nonzero data,
* it had better be dirty, otherwise we'll lose that
@@ -1178,7 +1216,7 @@ dbuf_verify(dmu_buf_impl_t *db)
ASSERT0(bp->blk_pad[1]);
ASSERT(!BP_IS_EMBEDDED(bp));
ASSERT(BP_IS_HOLE(bp));
- ASSERT0(bp->blk_phys_birth);
+ ASSERT0(BP_GET_PHYSICAL_BIRTH(bp));
}
}
}
@@ -1379,13 +1417,9 @@ dbuf_read_done(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
* a decrypted block. Otherwise success.
*/
static int
-dbuf_read_bonus(dmu_buf_impl_t *db, dnode_t *dn, uint32_t flags)
+dbuf_read_bonus(dmu_buf_impl_t *db, dnode_t *dn)
{
- int bonuslen, max_bonuslen, err;
-
- err = dbuf_read_verify_dnode_crypt(db, flags);
- if (err)
- return (err);
+ int bonuslen, max_bonuslen;
bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen);
max_bonuslen = DN_SLOTS_TO_BONUSLEN(dn->dn_num_slots);
@@ -1404,7 +1438,7 @@ dbuf_read_bonus(dmu_buf_impl_t *db, dnode_t *dn, uint32_t flags)
}
static void
-dbuf_handle_indirect_hole(dmu_buf_impl_t *db, dnode_t *dn)
+dbuf_handle_indirect_hole(dmu_buf_impl_t *db, dnode_t *dn, blkptr_t *dbbp)
{
blkptr_t *bps = db->db.db_data;
uint32_t indbs = 1ULL << dn->dn_indblkshift;
@@ -1413,12 +1447,12 @@ dbuf_handle_indirect_hole(dmu_buf_impl_t *db, dnode_t *dn)
for (int i = 0; i < n_bps; i++) {
blkptr_t *bp = &bps[i];
- ASSERT3U(BP_GET_LSIZE(db->db_blkptr), ==, indbs);
- BP_SET_LSIZE(bp, BP_GET_LEVEL(db->db_blkptr) == 1 ?
- dn->dn_datablksz : BP_GET_LSIZE(db->db_blkptr));
- BP_SET_TYPE(bp, BP_GET_TYPE(db->db_blkptr));
- BP_SET_LEVEL(bp, BP_GET_LEVEL(db->db_blkptr) - 1);
- BP_SET_BIRTH(bp, db->db_blkptr->blk_birth, 0);
+ ASSERT3U(BP_GET_LSIZE(dbbp), ==, indbs);
+ BP_SET_LSIZE(bp, BP_GET_LEVEL(dbbp) == 1 ?
+ dn->dn_datablksz : BP_GET_LSIZE(dbbp));
+ BP_SET_TYPE(bp, BP_GET_TYPE(dbbp));
+ BP_SET_LEVEL(bp, BP_GET_LEVEL(dbbp) - 1);
+ BP_SET_BIRTH(bp, BP_GET_LOGICAL_BIRTH(dbbp), 0);
}
}
@@ -1428,30 +1462,27 @@ dbuf_handle_indirect_hole(dmu_buf_impl_t *db, dnode_t *dn)
* was taken, ENOENT if no action was taken.
*/
static int
-dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn)
+dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn, blkptr_t *bp)
{
ASSERT(MUTEX_HELD(&db->db_mtx));
- int is_hole = db->db_blkptr == NULL || BP_IS_HOLE(db->db_blkptr);
+ int is_hole = bp == NULL || BP_IS_HOLE(bp);
/*
* For level 0 blocks only, if the above check fails:
* Recheck BP_IS_HOLE() after dnode_block_freed() in case dnode_sync()
* processes the delete record and clears the bp while we are waiting
* for the dn_mtx (resulting in a "no" from block_freed).
*/
- if (!is_hole && db->db_level == 0) {
- is_hole = dnode_block_freed(dn, db->db_blkid) ||
- BP_IS_HOLE(db->db_blkptr);
- }
+ if (!is_hole && db->db_level == 0)
+ is_hole = dnode_block_freed(dn, db->db_blkid) || BP_IS_HOLE(bp);
if (is_hole) {
dbuf_set_data(db, dbuf_alloc_arcbuf(db));
memset(db->db.db_data, 0, db->db.db_size);
- if (db->db_blkptr != NULL && db->db_level > 0 &&
- BP_IS_HOLE(db->db_blkptr) &&
- db->db_blkptr->blk_birth != 0) {
- dbuf_handle_indirect_hole(db, dn);
+ if (bp != NULL && db->db_level > 0 && BP_IS_HOLE(bp) &&
+ BP_GET_LOGICAL_BIRTH(bp) != 0) {
+ dbuf_handle_indirect_hole(db, dn, bp);
}
db->db_state = DB_CACHED;
DTRACE_SET_STATE(db, "hole read satisfied");
@@ -1473,32 +1504,46 @@ dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn)
* decrypt / authenticate them when we need to read an encrypted bonus buffer.
*/
static int
-dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags)
+dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, dnode_t *dn, uint32_t flags)
{
- int err = 0;
objset_t *os = db->db_objset;
- arc_buf_t *dnode_abuf;
- dnode_t *dn;
+ dmu_buf_impl_t *dndb;
+ arc_buf_t *dnbuf;
zbookmark_phys_t zb;
+ int err;
- ASSERT(MUTEX_HELD(&db->db_mtx));
+ if ((flags & DB_RF_NO_DECRYPT) != 0 ||
+ !os->os_encrypted || os->os_raw_receive ||
+ (dndb = dn->dn_dbuf) == NULL)
+ return (0);
- if (!os->os_encrypted || os->os_raw_receive ||
- (flags & DB_RF_NO_DECRYPT) != 0)
+ dnbuf = dndb->db_buf;
+ if (!arc_is_encrypted(dnbuf))
return (0);
- DB_DNODE_ENTER(db);
- dn = DB_DNODE(db);
- dnode_abuf = (dn->dn_dbuf != NULL) ? dn->dn_dbuf->db_buf : NULL;
+ mutex_enter(&dndb->db_mtx);
- if (dnode_abuf == NULL || !arc_is_encrypted(dnode_abuf)) {
- DB_DNODE_EXIT(db);
- return (0);
- }
+ /*
+ * Since dnode buffer is modified by sync process, there can be only
+ * one copy of it. It means we can not modify (decrypt) it while it
+ * is being written. I don't see how this may happen now, since
+ * encrypted dnode writes by receive should be completed before any
+ * plain-text reads due to txg wait, but better be safe than sorry.
+ */
+ while (1) {
+ if (!arc_is_encrypted(dnbuf)) {
+ mutex_exit(&dndb->db_mtx);
+ return (0);
+ }
+ dbuf_dirty_record_t *dr = dndb->db_data_pending;
+ if (dr == NULL || dr->dt.dl.dr_data != dnbuf)
+ break;
+ cv_wait(&dndb->db_changed, &dndb->db_mtx);
+ };
SET_BOOKMARK(&zb, dmu_objset_id(os),
- DMU_META_DNODE_OBJECT, 0, dn->dn_dbuf->db_blkid);
- err = arc_untransform(dnode_abuf, os->os_spa, &zb, B_TRUE);
+ DMU_META_DNODE_OBJECT, 0, dndb->db_blkid);
+ err = arc_untransform(dnbuf, os->os_spa, &zb, B_TRUE);
/*
* An error code of EACCES tells us that the key is still not
@@ -1511,7 +1556,7 @@ dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags)
!DMU_OT_IS_ENCRYPTED(dn->dn_bonustype))))
err = 0;
- DB_DNODE_EXIT(db);
+ mutex_exit(&dndb->db_mtx);
return (err);
}
@@ -1521,39 +1566,63 @@ dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags)
* returning.
*/
static int
-dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags,
+dbuf_read_impl(dmu_buf_impl_t *db, dnode_t *dn, zio_t *zio, uint32_t flags,
db_lock_type_t dblt, const void *tag)
{
- dnode_t *dn;
zbookmark_phys_t zb;
uint32_t aflags = ARC_FLAG_NOWAIT;
int err, zio_flags;
+ blkptr_t bp, *bpp = NULL;
- err = zio_flags = 0;
- DB_DNODE_ENTER(db);
- dn = DB_DNODE(db);
ASSERT(!zfs_refcount_is_zero(&db->db_holds));
ASSERT(MUTEX_HELD(&db->db_mtx));
- ASSERT(db->db_state == DB_UNCACHED);
+ ASSERT(db->db_state == DB_UNCACHED || db->db_state == DB_NOFILL);
ASSERT(db->db_buf == NULL);
ASSERT(db->db_parent == NULL ||
RW_LOCK_HELD(&db->db_parent->db_rwlock));
if (db->db_blkid == DMU_BONUS_BLKID) {
- err = dbuf_read_bonus(db, dn, flags);
+ err = dbuf_read_bonus(db, dn);
goto early_unlock;
}
- err = dbuf_read_hole(db, dn);
+ /*
+ * If we have a pending block clone, we don't want to read the
+ * underlying block, but the content of the block being cloned,
+ * pointed by the dirty record, so we have the most recent data.
+ * If there is no dirty record, then we hit a race in a sync
+ * process when the dirty record is already removed, while the
+ * dbuf is not yet destroyed. Such case is equivalent to uncached.
+ */
+ if (db->db_state == DB_NOFILL) {
+ dbuf_dirty_record_t *dr = list_head(&db->db_dirty_records);
+ if (dr != NULL) {
+ if (!dr->dt.dl.dr_brtwrite) {
+ err = EIO;
+ goto early_unlock;
+ }
+ bp = dr->dt.dl.dr_overridden_by;
+ bpp = &bp;
+ }
+ }
+
+ if (bpp == NULL && db->db_blkptr != NULL) {
+ bp = *db->db_blkptr;
+ bpp = &bp;
+ }
+
+ err = dbuf_read_hole(db, dn, bpp);
if (err == 0)
goto early_unlock;
+ ASSERT(bpp != NULL);
+
/*
* Any attempt to read a redacted block should result in an error. This
* will never happen under normal conditions, but can be useful for
* debugging purposes.
*/
- if (BP_IS_REDACTED(db->db_blkptr)) {
+ if (BP_IS_REDACTED(bpp)) {
ASSERT(dsl_dataset_feature_is_active(
db->db_objset->os_dsl_dataset,
SPA_FEATURE_REDACTED_DATASETS));
@@ -1568,25 +1637,20 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags,
* All bps of an encrypted os should have the encryption bit set.
* If this is not true it indicates tampering and we report an error.
*/
- if (db->db_objset->os_encrypted && !BP_USES_CRYPT(db->db_blkptr)) {
- spa_log_error(db->db_objset->os_spa, &zb);
- zfs_panic_recover("unencrypted block in encrypted "
- "object set %llu", dmu_objset_id(db->db_objset));
+ if (db->db_objset->os_encrypted && !BP_USES_CRYPT(bpp)) {
+ spa_log_error(db->db_objset->os_spa, &zb,
+ BP_GET_LOGICAL_BIRTH(bpp));
err = SET_ERROR(EIO);
goto early_unlock;
}
- err = dbuf_read_verify_dnode_crypt(db, flags);
- if (err != 0)
- goto early_unlock;
-
- DB_DNODE_EXIT(db);
-
db->db_state = DB_READ;
DTRACE_SET_STATE(db, "read issued");
mutex_exit(&db->db_mtx);
- if (dbuf_is_l2cacheable(db))
+ if (!DBUF_IS_CACHEABLE(db))
+ aflags |= ARC_FLAG_UNCACHED;
+ else if (dbuf_is_l2cacheable(db))
aflags |= ARC_FLAG_L2CACHE;
dbuf_add_ref(db, NULL);
@@ -1597,20 +1661,18 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags,
if ((flags & DB_RF_NO_DECRYPT) && BP_IS_PROTECTED(db->db_blkptr))
zio_flags |= ZIO_FLAG_RAW;
/*
- * The zio layer will copy the provided blkptr later, but we need to
- * do this now so that we can release the parent's rwlock. We have to
- * do that now so that if dbuf_read_done is called synchronously (on
+ * The zio layer will copy the provided blkptr later, but we have our
+ * own copy so that we can release the parent's rwlock. We have to
+ * do that so that if dbuf_read_done is called synchronously (on
* an l1 cache hit) we don't acquire the db_mtx while holding the
* parent's rwlock, which would be a lock ordering violation.
*/
- blkptr_t bp = *db->db_blkptr;
dmu_buf_unlock_parent(db, dblt, tag);
- (void) arc_read(zio, db->db_objset->os_spa, &bp,
+ return (arc_read(zio, db->db_objset->os_spa, bpp,
dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ, zio_flags,
- &aflags, &zb);
- return (err);
+ &aflags, &zb));
+
early_unlock:
- DB_DNODE_EXIT(db);
mutex_exit(&db->db_mtx);
dmu_buf_unlock_parent(db, dblt, tag);
return (err);
@@ -1695,38 +1757,65 @@ dbuf_fix_old_data(dmu_buf_impl_t *db, uint64_t txg)
}
int
-dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
+dbuf_read(dmu_buf_impl_t *db, zio_t *pio, uint32_t flags)
{
- int err = 0;
- boolean_t prefetch;
dnode_t *dn;
+ boolean_t miss = B_TRUE, need_wait = B_FALSE, prefetch;
+ int err;
- /*
- * We don't have to hold the mutex to check db_state because it
- * can't be freed while we have a hold on the buffer.
- */
ASSERT(!zfs_refcount_is_zero(&db->db_holds));
- if (db->db_state == DB_NOFILL)
- return (SET_ERROR(EIO));
-
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
+ /*
+ * Ensure that this block's dnode has been decrypted if the caller
+ * has requested decrypted data.
+ */
+ err = dbuf_read_verify_dnode_crypt(db, dn, flags);
+ if (err != 0)
+ goto done;
+
prefetch = db->db_level == 0 && db->db_blkid != DMU_BONUS_BLKID &&
- (flags & DB_RF_NOPREFETCH) == 0 && dn != NULL &&
- DBUF_IS_CACHEABLE(db);
+ (flags & DB_RF_NOPREFETCH) == 0;
mutex_enter(&db->db_mtx);
- if (db->db_state == DB_CACHED) {
- spa_t *spa = dn->dn_objset->os_spa;
+ if (flags & DB_RF_PARTIAL_FIRST)
+ db->db_partial_read = B_TRUE;
+ else if (!(flags & DB_RF_PARTIAL_MORE))
+ db->db_partial_read = B_FALSE;
+ miss = (db->db_state != DB_CACHED);
+ if (db->db_state == DB_READ || db->db_state == DB_FILL) {
/*
- * Ensure that this block's dnode has been decrypted if
- * the caller has requested decrypted data.
+ * Another reader came in while the dbuf was in flight between
+ * UNCACHED and CACHED. Either a writer will finish filling
+ * the buffer, sending the dbuf to CACHED, or the first reader's
+ * request will reach the read_done callback and send the dbuf
+ * to CACHED. Otherwise, a failure occurred and the dbuf will
+ * be sent to UNCACHED.
*/
- err = dbuf_read_verify_dnode_crypt(db, flags);
+ if (flags & DB_RF_NEVERWAIT) {
+ mutex_exit(&db->db_mtx);
+ DB_DNODE_EXIT(db);
+ goto done;
+ }
+ do {
+ ASSERT(db->db_state == DB_READ ||
+ (flags & DB_RF_HAVESTRUCT) == 0);
+ DTRACE_PROBE2(blocked__read, dmu_buf_impl_t *, db,
+ zio_t *, pio);
+ cv_wait(&db->db_changed, &db->db_mtx);
+ } while (db->db_state == DB_READ || db->db_state == DB_FILL);
+ if (db->db_state == DB_UNCACHED) {
+ err = SET_ERROR(EIO);
+ mutex_exit(&db->db_mtx);
+ DB_DNODE_EXIT(db);
+ goto done;
+ }
+ }
+ if (db->db_state == DB_CACHED) {
/*
* If the arc buf is compressed or encrypted and the caller
* requested uncompressed data, we need to untransform it
@@ -1734,11 +1823,11 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
* unauthenticated blocks, which will verify their MAC if
* the key is now available.
*/
- if (err == 0 && db->db_buf != NULL &&
- (flags & DB_RF_NO_DECRYPT) == 0 &&
+ if ((flags & DB_RF_NO_DECRYPT) == 0 && db->db_buf != NULL &&
(arc_is_encrypted(db->db_buf) ||
arc_is_unauthenticated(db->db_buf) ||
arc_get_compression(db->db_buf) != ZIO_COMPRESS_OFF)) {
+ spa_t *spa = dn->dn_objset->os_spa;
zbookmark_phys_t zb;
SET_BOOKMARK(&zb, dmu_objset_id(db->db_objset),
@@ -1748,80 +1837,49 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
dbuf_set_data(db, db->db_buf);
}
mutex_exit(&db->db_mtx);
- if (err == 0 && prefetch) {
- dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE,
- B_FALSE, flags & DB_RF_HAVESTRUCT);
- }
- DB_DNODE_EXIT(db);
- DBUF_STAT_BUMP(hash_hits);
- } else if (db->db_state == DB_UNCACHED) {
- spa_t *spa = dn->dn_objset->os_spa;
- boolean_t need_wait = B_FALSE;
-
+ } else {
+ ASSERT(db->db_state == DB_UNCACHED ||
+ db->db_state == DB_NOFILL);
db_lock_type_t dblt = dmu_buf_lock_parent(db, RW_READER, FTAG);
-
- if (zio == NULL &&
- db->db_blkptr != NULL && !BP_IS_HOLE(db->db_blkptr)) {
- zio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
+ if (pio == NULL && (db->db_state == DB_NOFILL ||
+ (db->db_blkptr != NULL && !BP_IS_HOLE(db->db_blkptr)))) {
+ spa_t *spa = dn->dn_objset->os_spa;
+ pio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
need_wait = B_TRUE;
}
- err = dbuf_read_impl(db, zio, flags, dblt, FTAG);
- /*
- * dbuf_read_impl has dropped db_mtx and our parent's rwlock
- * for us
- */
- if (!err && prefetch) {
- dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE,
- db->db_state != DB_CACHED,
- flags & DB_RF_HAVESTRUCT);
- }
+ err = dbuf_read_impl(db, dn, pio, flags, dblt, FTAG);
+ /* dbuf_read_impl drops db_mtx and parent's rwlock. */
+ miss = (db->db_state != DB_CACHED);
+ }
- DB_DNODE_EXIT(db);
- DBUF_STAT_BUMP(hash_misses);
+ if (err == 0 && prefetch) {
+ dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE, miss,
+ flags & DB_RF_HAVESTRUCT);
+ }
+ DB_DNODE_EXIT(db);
- /*
- * If we created a zio_root we must execute it to avoid
- * leaking it, even if it isn't attached to any work due
- * to an error in dbuf_read_impl().
- */
- if (need_wait) {
- if (err == 0)
- err = zio_wait(zio);
- else
- VERIFY0(zio_wait(zio));
- }
- } else {
- /*
- * Another reader came in while the dbuf was in flight
- * between UNCACHED and CACHED. Either a writer will finish
- * writing the buffer (sending the dbuf to CACHED) or the
- * first reader's request will reach the read_done callback
- * and send the dbuf to CACHED. Otherwise, a failure
- * occurred and the dbuf went to UNCACHED.
- */
- mutex_exit(&db->db_mtx);
- if (prefetch) {
- dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE,
- B_TRUE, flags & DB_RF_HAVESTRUCT);
- }
- DB_DNODE_EXIT(db);
- DBUF_STAT_BUMP(hash_misses);
+ /*
+ * If we created a zio we must execute it to avoid leaking it, even if
+ * it isn't attached to any work due to an error in dbuf_read_impl().
+ */
+ if (need_wait) {
+ if (err == 0)
+ err = zio_wait(pio);
+ else
+ (void) zio_wait(pio);
+ pio = NULL;
+ }
- /* Skip the wait per the caller's request. */
- if ((flags & DB_RF_NEVERWAIT) == 0) {
- mutex_enter(&db->db_mtx);
- while (db->db_state == DB_READ ||
- db->db_state == DB_FILL) {
- ASSERT(db->db_state == DB_READ ||
- (flags & DB_RF_HAVESTRUCT) == 0);
- DTRACE_PROBE2(blocked__read, dmu_buf_impl_t *,
- db, zio_t *, zio);
- cv_wait(&db->db_changed, &db->db_mtx);
- }
- if (db->db_state == DB_UNCACHED)
- err = SET_ERROR(EIO);
- mutex_exit(&db->db_mtx);
- }
+done:
+ if (miss)
+ DBUF_STAT_BUMP(hash_misses);
+ else
+ DBUF_STAT_BUMP(hash_hits);
+ if (pio && err != 0) {
+ zio_t *zio = zio_null(pio, pio->io_spa, NULL, NULL, NULL,
+ ZIO_FLAG_CANFAIL);
+ zio->io_error = err;
+ zio_nowait(zio);
}
return (err);
@@ -1875,8 +1933,13 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite)
zio_free(db->db_objset->os_spa, txg, bp);
+ if (dr->dt.dl.dr_brtwrite) {
+ ASSERT0P(dr->dt.dl.dr_data);
+ dr->dt.dl.dr_data = db->db_buf;
+ }
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
dr->dt.dl.dr_nopwrite = B_FALSE;
+ dr->dt.dl.dr_brtwrite = B_FALSE;
dr->dt.dl.dr_has_raw_params = B_FALSE;
/*
@@ -1887,7 +1950,8 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
* the buf thawed to save the effort of freezing &
* immediately re-thawing it.
*/
- arc_release(dr->dt.dl.dr_data, db);
+ if (dr->dt.dl.dr_data)
+ arc_release(dr->dt.dl.dr_data, db);
}
/*
@@ -2106,7 +2170,8 @@ dbuf_dirty_lightweight(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
* Otherwise the buffer contents could be inconsistent between the
* dbuf and the lightweight dirty record.
*/
- ASSERT3P(NULL, ==, dbuf_find(dn->dn_objset, dn->dn_object, 0, blkid));
+ ASSERT3P(NULL, ==, dbuf_find(dn->dn_objset, dn->dn_object, 0, blkid,
+ NULL));
mutex_enter(&dn->dn_mtx);
int txgoff = tx->tx_txg & TXG_MASK;
@@ -2258,7 +2323,7 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
- if (db->db_blkid != DMU_BONUS_BLKID) {
+ if (db->db_blkid != DMU_BONUS_BLKID && db->db_state != DB_NOFILL) {
dmu_objset_willuse_space(os, db->db.db_size, tx);
}
@@ -2301,8 +2366,9 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
sizeof (dbuf_dirty_record_t),
offsetof(dbuf_dirty_record_t, dr_dirty_node));
}
- if (db->db_blkid != DMU_BONUS_BLKID)
+ if (db->db_blkid != DMU_BONUS_BLKID && db->db_state != DB_NOFILL) {
dr->dr_accounted = db->db.db_size;
+ }
dr->dr_dbuf = db;
dr->dr_txg = tx->tx_txg;
list_insert_before(&db->db_dirty_records, dr_next, dr);
@@ -2458,10 +2524,11 @@ dbuf_undirty_bonus(dbuf_dirty_record_t *dr)
* Undirty a buffer in the transaction group referenced by the given
* transaction. Return whether this evicted the dbuf.
*/
-static boolean_t
+boolean_t
dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
{
uint64_t txg = tx->tx_txg;
+ boolean_t brtwrite;
ASSERT(txg != 0);
@@ -2486,6 +2553,16 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
return (B_FALSE);
ASSERT(dr->dr_dbuf == db);
+ brtwrite = dr->dt.dl.dr_brtwrite;
+ if (brtwrite) {
+ /*
+ * We are freeing a block that we cloned in the same
+ * transaction group.
+ */
+ brt_pending_remove(dmu_objset_spa(db->db_objset),
+ &dr->dt.dl.dr_overridden_by, tx);
+ }
+
dnode_t *dn = dr->dr_dnode;
dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
@@ -2515,7 +2592,7 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
mutex_exit(&dn->dn_mtx);
}
- if (db->db_state != DB_NOFILL) {
+ if (db->db_state != DB_NOFILL && !brtwrite) {
dbuf_unoverride(dr);
ASSERT(db->db_buf != NULL);
@@ -2530,7 +2607,8 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
db->db_dirtycnt -= 1;
if (zfs_refcount_remove(&db->db_holds, (void *)(uintptr_t)txg) == 0) {
- ASSERT(db->db_state == DB_NOFILL || arc_released(db->db_buf));
+ ASSERT(db->db_state == DB_NOFILL || brtwrite ||
+ arc_released(db->db_buf));
dbuf_destroy(db);
return (B_TRUE);
}
@@ -2542,30 +2620,40 @@ static void
dmu_buf_will_dirty_impl(dmu_buf_t *db_fake, int flags, dmu_tx_t *tx)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+ boolean_t undirty = B_FALSE;
ASSERT(tx->tx_txg != 0);
ASSERT(!zfs_refcount_is_zero(&db->db_holds));
/*
- * Quick check for dirtiness. For already dirty blocks, this
- * reduces runtime of this function by >90%, and overall performance
- * by 50% for some workloads (e.g. file deletion with indirect blocks
- * cached).
+ * Quick check for dirtiness to improve performance for some workloads
+ * (e.g. file deletion with indirect blocks cached).
*/
mutex_enter(&db->db_mtx);
-
- if (db->db_state == DB_CACHED) {
- dbuf_dirty_record_t *dr = dbuf_find_dirty_eq(db, tx->tx_txg);
+ if (db->db_state == DB_CACHED || db->db_state == DB_NOFILL) {
/*
- * It's possible that it is already dirty but not cached,
+ * It's possible that the dbuf is already dirty but not cached,
* because there are some calls to dbuf_dirty() that don't
* go through dmu_buf_will_dirty().
*/
+ dbuf_dirty_record_t *dr = dbuf_find_dirty_eq(db, tx->tx_txg);
if (dr != NULL) {
- /* This dbuf is already dirty and cached. */
- dbuf_redirty(dr);
- mutex_exit(&db->db_mtx);
- return;
+ if (db->db_level == 0 &&
+ dr->dt.dl.dr_brtwrite) {
+ /*
+ * Block cloning: If we are dirtying a cloned
+ * level 0 block, we cannot simply redirty it,
+ * because this dr has no associated data.
+ * We will go through a full undirtying below,
+ * before dirtying it again.
+ */
+ undirty = B_TRUE;
+ } else {
+ /* This dbuf is already dirty and cached. */
+ dbuf_redirty(dr);
+ mutex_exit(&db->db_mtx);
+ return;
+ }
}
}
mutex_exit(&db->db_mtx);
@@ -2574,7 +2662,20 @@ dmu_buf_will_dirty_impl(dmu_buf_t *db_fake, int flags, dmu_tx_t *tx)
if (RW_WRITE_HELD(&DB_DNODE(db)->dn_struct_rwlock))
flags |= DB_RF_HAVESTRUCT;
DB_DNODE_EXIT(db);
+
+ /*
+ * Block cloning: Do the dbuf_read() before undirtying the dbuf, as we
+ * want to make sure dbuf_read() will read the pending cloned block and
+ * not the uderlying block that is being replaced. dbuf_undirty() will
+ * do dbuf_unoverride(), so we will end up with cloned block content,
+ * without overridden BP.
+ */
(void) dbuf_read(db, NULL, flags);
+ if (undirty) {
+ mutex_enter(&db->db_mtx);
+ VERIFY(!dbuf_undirty(db, tx));
+ mutex_exit(&db->db_mtx);
+ }
(void) dbuf_dirty(db, tx);
}
@@ -2598,17 +2699,51 @@ dmu_buf_is_dirty(dmu_buf_t *db_fake, dmu_tx_t *tx)
}
void
+dmu_buf_will_clone(dmu_buf_t *db_fake, dmu_tx_t *tx)
+{
+ dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+
+ /*
+ * Block cloning: We are going to clone into this block, so undirty
+ * modifications done to this block so far in this txg. This includes
+ * writes and clones into this block.
+ */
+ mutex_enter(&db->db_mtx);
+ DBUF_VERIFY(db);
+ VERIFY(!dbuf_undirty(db, tx));
+ ASSERT0P(dbuf_find_dirty_eq(db, tx->tx_txg));
+ if (db->db_buf != NULL) {
+ arc_buf_destroy(db->db_buf, db);
+ db->db_buf = NULL;
+ dbuf_clear_data(db);
+ }
+
+ db->db_state = DB_NOFILL;
+ DTRACE_SET_STATE(db, "allocating NOFILL buffer for clone");
+
+ DBUF_VERIFY(db);
+ mutex_exit(&db->db_mtx);
+
+ dbuf_noread(db);
+ (void) dbuf_dirty(db, tx);
+}
+
+void
dmu_buf_will_not_fill(dmu_buf_t *db_fake, dmu_tx_t *tx)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+ mutex_enter(&db->db_mtx);
db->db_state = DB_NOFILL;
DTRACE_SET_STATE(db, "allocating NOFILL buffer");
- dmu_buf_will_fill(db_fake, tx);
+ mutex_exit(&db->db_mtx);
+
+ dbuf_noread(db);
+ (void) dbuf_dirty(db, tx);
}
void
-dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx)
+dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx, boolean_t canfail)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
@@ -2620,6 +2755,25 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx)
ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT ||
dmu_tx_private_ok(tx));
+ mutex_enter(&db->db_mtx);
+ if (db->db_state == DB_NOFILL) {
+ /*
+ * Block cloning: We will be completely overwriting a block
+ * cloned in this transaction group, so let's undirty the
+ * pending clone and mark the block as uncached. This will be
+ * as if the clone was never done. But if the fill can fail
+ * we should have a way to return back to the cloned data.
+ */
+ if (canfail && dbuf_find_dirty_eq(db, tx->tx_txg) != NULL) {
+ mutex_exit(&db->db_mtx);
+ dmu_buf_will_dirty(db_fake, tx);
+ return;
+ }
+ VERIFY(!dbuf_undirty(db, tx));
+ db->db_state = DB_UNCACHED;
+ }
+ mutex_exit(&db->db_mtx);
+
dbuf_noread(db);
(void) dbuf_dirty(db, tx);
}
@@ -2667,39 +2821,49 @@ dbuf_override_impl(dmu_buf_impl_t *db, const blkptr_t *bp, dmu_tx_t *tx)
dbuf_dirty_record_t *dr;
dr = list_head(&db->db_dirty_records);
+ ASSERT3P(dr, !=, NULL);
ASSERT3U(dr->dr_txg, ==, tx->tx_txg);
dl = &dr->dt.dl;
dl->dr_overridden_by = *bp;
dl->dr_override_state = DR_OVERRIDDEN;
- dl->dr_overridden_by.blk_birth = dr->dr_txg;
+ BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by, dr->dr_txg);
}
-void
-dmu_buf_fill_done(dmu_buf_t *dbuf, dmu_tx_t *tx)
+boolean_t
+dmu_buf_fill_done(dmu_buf_t *dbuf, dmu_tx_t *tx, boolean_t failed)
{
(void) tx;
dmu_buf_impl_t *db = (dmu_buf_impl_t *)dbuf;
- dbuf_states_t old_state;
mutex_enter(&db->db_mtx);
DBUF_VERIFY(db);
- old_state = db->db_state;
- db->db_state = DB_CACHED;
- if (old_state == DB_FILL) {
+ if (db->db_state == DB_FILL) {
if (db->db_level == 0 && db->db_freed_in_flight) {
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
/* we were freed while filling */
/* XXX dbuf_undirty? */
memset(db->db.db_data, 0, db->db.db_size);
db->db_freed_in_flight = FALSE;
+ db->db_state = DB_CACHED;
DTRACE_SET_STATE(db,
"fill done handling freed in flight");
+ failed = B_FALSE;
+ } else if (failed) {
+ VERIFY(!dbuf_undirty(db, tx));
+ db->db_buf = NULL;
+ dbuf_clear_data(db);
+ DTRACE_SET_STATE(db, "fill failed");
} else {
+ db->db_state = DB_CACHED;
DTRACE_SET_STATE(db, "fill done");
}
cv_broadcast(&db->db_changed);
+ } else {
+ db->db_state = DB_CACHED;
+ failed = B_FALSE;
}
mutex_exit(&db->db_mtx);
+ return (failed);
}
void
@@ -2728,6 +2892,7 @@ dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
dmu_buf_will_not_fill(dbuf, tx);
dr = list_head(&db->db_dirty_records);
+ ASSERT3P(dr, !=, NULL);
ASSERT3U(dr->dr_txg, ==, tx->tx_txg);
dl = &dr->dt.dl;
encode_embedded_bp_compressed(&dl->dr_overridden_by,
@@ -2738,7 +2903,7 @@ dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
BP_SET_BYTEORDER(&dl->dr_overridden_by, byteorder);
dl->dr_override_state = DR_OVERRIDDEN;
- dl->dr_overridden_by.blk_birth = dr->dr_txg;
+ BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by, dr->dr_txg);
}
void
@@ -2789,7 +2954,8 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
while (db->db_state == DB_READ || db->db_state == DB_FILL)
cv_wait(&db->db_changed, &db->db_mtx);
- ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED);
+ ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED ||
+ db->db_state == DB_NOFILL);
if (db->db_state == DB_CACHED &&
zfs_refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
@@ -2826,6 +2992,15 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
arc_buf_destroy(db->db_buf, db);
}
db->db_buf = NULL;
+ } else if (db->db_state == DB_NOFILL) {
+ /*
+ * We will be completely replacing the cloned block. In case
+ * it was cloned in this transaction group, let's undirty the
+ * pending clone and mark the block as uncached. This will be
+ * as if the clone was never done.
+ */
+ VERIFY(!dbuf_undirty(db, tx));
+ db->db_state = DB_UNCACHED;
}
ASSERT(db->db_buf == NULL);
dbuf_set_data(db, buf);
@@ -2833,7 +3008,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
DTRACE_SET_STATE(db, "filling assigned arcbuf");
mutex_exit(&db->db_mtx);
(void) dbuf_dirty(db, tx);
- dmu_buf_fill_done(&db->db, tx);
+ dmu_buf_fill_done(&db->db, tx, B_FALSE);
}
void
@@ -2869,6 +3044,8 @@ dbuf_destroy(dmu_buf_impl_t *db)
db->db_caching_status == DB_DBUF_METADATA_CACHE);
multilist_remove(&dbuf_caches[db->db_caching_status].cache, db);
+
+ ASSERT0(dmu_buf_user_size(&db->db));
(void) zfs_refcount_remove_many(
&dbuf_caches[db->db_caching_status].size,
db->db.db_size, db);
@@ -3053,7 +3230,7 @@ dbuf_findbp(dnode_t *dn, int level, uint64_t blkid, int fail_sparse,
static dmu_buf_impl_t *
dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid,
- dmu_buf_impl_t *parent, blkptr_t *blkptr)
+ dmu_buf_impl_t *parent, blkptr_t *blkptr, uint64_t hash)
{
objset_t *os = dn->dn_objset;
dmu_buf_impl_t *db, *odb;
@@ -3074,6 +3251,7 @@ dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid,
db->db_dnode_handle = dn->dn_handle;
db->db_parent = parent;
db->db_blkptr = blkptr;
+ db->db_hash = hash;
db->db_user = NULL;
db->db_user_immediate_evict = FALSE;
@@ -3157,6 +3335,7 @@ dbuf_dnode_findbp(dnode_t *dn, uint64_t level, uint64_t blkid,
err = dbuf_findbp(dn, level, blkid, B_FALSE, &dbp, &bp2);
if (err == 0) {
+ ASSERT3P(bp2, !=, NULL);
*bp = *bp2;
if (dbp != NULL)
dbuf_rele(dbp, NULL);
@@ -3254,7 +3433,8 @@ dbuf_prefetch_indirect_done(zio_t *zio, const zbookmark_phys_t *zb,
if (abuf == NULL) {
ASSERT(zio == NULL || zio->io_error != 0);
- return (dbuf_prefetch_fini(dpa, B_TRUE));
+ dbuf_prefetch_fini(dpa, B_TRUE);
+ return;
}
ASSERT(zio == NULL || zio->io_error == 0);
@@ -3287,7 +3467,8 @@ dbuf_prefetch_indirect_done(zio_t *zio, const zbookmark_phys_t *zb,
dpa->dpa_curlevel, curblkid, FTAG);
if (db == NULL) {
arc_buf_destroy(abuf, private);
- return (dbuf_prefetch_fini(dpa, B_TRUE));
+ dbuf_prefetch_fini(dpa, B_TRUE);
+ return;
}
(void) dbuf_read(db, NULL,
DB_RF_MUST_SUCCEED | DB_RF_NOPREFETCH | DB_RF_HAVESTRUCT);
@@ -3300,12 +3481,14 @@ 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)) {
+ arc_buf_destroy(abuf, private);
dbuf_prefetch_fini(dpa, B_TRUE);
+ return;
} else if (dpa->dpa_curlevel == dpa->dpa_zb.zb_level) {
ASSERT3U(nextblkid, ==, dpa->dpa_zb.zb_blkid);
dbuf_issue_final_prefetch(dpa, bp);
@@ -3370,7 +3553,7 @@ dbuf_prefetch_impl(dnode_t *dn, int64_t level, uint64_t blkid,
goto no_issue;
dmu_buf_impl_t *db = dbuf_find(dn->dn_objset, dn->dn_object,
- level, blkid);
+ level, blkid, NULL);
if (db != NULL) {
mutex_exit(&db->db_mtx);
/*
@@ -3434,8 +3617,9 @@ dbuf_prefetch_impl(dnode_t *dn, int64_t level, uint64_t blkid,
dpa->dpa_cb = cb;
dpa->dpa_arg = arg;
- /* flag if L2ARC eligible, l2arc_noprefetch then decides */
- if (dnode_level_is_l2cacheable(&bp, dn, level))
+ if (!DNODE_LEVEL_IS_CACHEABLE(dn, level))
+ dpa->dpa_aflags |= ARC_FLAG_UNCACHED;
+ else if (dnode_level_is_l2cacheable(&bp, dn, level))
dpa->dpa_aflags |= ARC_FLAG_L2CACHE;
/*
@@ -3535,6 +3719,7 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
const void *tag, dmu_buf_impl_t **dbp)
{
dmu_buf_impl_t *db, *parent = NULL;
+ uint64_t hv;
/* If the pool has been created, verify the tx_sync_lock is not held */
spa_t *spa = dn->dn_objset->os_spa;
@@ -3550,7 +3735,7 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
*dbp = NULL;
/* dbuf_find() returns with db_mtx held */
- db = dbuf_find(dn->dn_objset, dn->dn_object, level, blkid);
+ db = dbuf_find(dn->dn_objset, dn->dn_object, level, blkid, &hv);
if (db == NULL) {
blkptr_t *bp = NULL;
@@ -3572,7 +3757,7 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
}
if (err && err != ENOENT)
return (err);
- db = dbuf_create(dn, level, blkid, parent, bp);
+ db = dbuf_create(dn, level, blkid, parent, bp, hv);
}
if (fail_uncached && db->db_state != DB_CACHED) {
@@ -3596,8 +3781,10 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
dn->dn_object != DMU_META_DNODE_OBJECT &&
db->db_state == DB_CACHED && db->db_data_pending) {
dbuf_dirty_record_t *dr = db->db_data_pending;
- if (dr->dt.dl.dr_data == db->db_buf)
+ if (dr->dt.dl.dr_data == db->db_buf) {
+ ASSERT3P(db->db_buf, !=, NULL);
dbuf_hold_copy(dn, db);
+ }
}
if (multilist_link_active(&db->db_cache_link)) {
@@ -3606,17 +3793,17 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
db->db_caching_status == DB_DBUF_METADATA_CACHE);
multilist_remove(&dbuf_caches[db->db_caching_status].cache, db);
+
+ uint64_t size = db->db.db_size + dmu_buf_user_size(&db->db);
(void) zfs_refcount_remove_many(
- &dbuf_caches[db->db_caching_status].size,
- db->db.db_size, db);
+ &dbuf_caches[db->db_caching_status].size, size, db);
if (db->db_caching_status == DB_DBUF_METADATA_CACHE) {
DBUF_STAT_BUMPDOWN(metadata_cache_count);
} else {
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
DBUF_STAT_BUMPDOWN(cache_count);
- DBUF_STAT_DECR(cache_levels_bytes[db->db_level],
- db->db.db_size);
+ DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
}
db->db_caching_status = DB_NO_CACHE;
}
@@ -3656,7 +3843,8 @@ dbuf_create_bonus(dnode_t *dn)
ASSERT(RW_WRITE_HELD(&dn->dn_struct_rwlock));
ASSERT(dn->dn_bonus == NULL);
- dn->dn_bonus = dbuf_create(dn, 0, DMU_BONUS_BLKID, dn->dn_dbuf, NULL);
+ dn->dn_bonus = dbuf_create(dn, 0, DMU_BONUS_BLKID, dn->dn_dbuf, NULL,
+ dbuf_hash(dn->dn_objset, dn->dn_object, 0, DMU_BONUS_BLKID));
}
int
@@ -3702,7 +3890,7 @@ dbuf_try_add_ref(dmu_buf_t *db_fake, objset_t *os, uint64_t obj, uint64_t blkid,
if (blkid == DMU_BONUS_BLKID)
found_db = dbuf_find_bonus(os, obj);
else
- found_db = dbuf_find(os, obj, 0, blkid);
+ found_db = dbuf_find(os, obj, 0, blkid, NULL);
if (found_db != NULL) {
if (db == found_db && dbuf_refcount(db) > db->db_dirtycnt) {
@@ -3822,59 +4010,39 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, const void *tag, boolean_t evicting)
* This dbuf has anonymous data associated with it.
*/
dbuf_destroy(db);
- } else {
- boolean_t do_arc_evict = B_FALSE;
- blkptr_t bp;
- spa_t *spa = dmu_objset_spa(db->db_objset);
-
- if (!DBUF_IS_CACHEABLE(db) &&
- db->db_blkptr != NULL &&
- !BP_IS_HOLE(db->db_blkptr) &&
- !BP_IS_EMBEDDED(db->db_blkptr)) {
- do_arc_evict = B_TRUE;
- bp = *db->db_blkptr;
- }
-
- if (!DBUF_IS_CACHEABLE(db) ||
- db->db_pending_evict) {
- dbuf_destroy(db);
- } else if (!multilist_link_active(&db->db_cache_link)) {
- ASSERT3U(db->db_caching_status, ==,
- DB_NO_CACHE);
-
- dbuf_cached_state_t dcs =
- dbuf_include_in_metadata_cache(db) ?
- DB_DBUF_METADATA_CACHE : DB_DBUF_CACHE;
- db->db_caching_status = dcs;
-
- multilist_insert(&dbuf_caches[dcs].cache, db);
- uint64_t db_size = db->db.db_size;
- size = zfs_refcount_add_many(
- &dbuf_caches[dcs].size, db_size, db);
- uint8_t db_level = db->db_level;
- mutex_exit(&db->db_mtx);
-
- if (dcs == DB_DBUF_METADATA_CACHE) {
- DBUF_STAT_BUMP(metadata_cache_count);
- DBUF_STAT_MAX(
- metadata_cache_size_bytes_max,
- size);
- } else {
- DBUF_STAT_BUMP(cache_count);
- DBUF_STAT_MAX(cache_size_bytes_max,
- size);
- DBUF_STAT_BUMP(cache_levels[db_level]);
- DBUF_STAT_INCR(
- cache_levels_bytes[db_level],
- db_size);
- }
+ } else if (!(DBUF_IS_CACHEABLE(db) || db->db_partial_read) ||
+ db->db_pending_evict) {
+ dbuf_destroy(db);
+ } else if (!multilist_link_active(&db->db_cache_link)) {
+ ASSERT3U(db->db_caching_status, ==, DB_NO_CACHE);
+
+ dbuf_cached_state_t dcs =
+ dbuf_include_in_metadata_cache(db) ?
+ DB_DBUF_METADATA_CACHE : DB_DBUF_CACHE;
+ db->db_caching_status = dcs;
+
+ multilist_insert(&dbuf_caches[dcs].cache, db);
+ uint64_t db_size = db->db.db_size +
+ dmu_buf_user_size(&db->db);
+ size = zfs_refcount_add_many(
+ &dbuf_caches[dcs].size, db_size, db);
+ uint8_t db_level = db->db_level;
+ mutex_exit(&db->db_mtx);
- if (dcs == DB_DBUF_CACHE && !evicting)
- dbuf_evict_notify(size);
+ if (dcs == DB_DBUF_METADATA_CACHE) {
+ DBUF_STAT_BUMP(metadata_cache_count);
+ DBUF_STAT_MAX(metadata_cache_size_bytes_max,
+ size);
+ } else {
+ DBUF_STAT_BUMP(cache_count);
+ DBUF_STAT_MAX(cache_size_bytes_max, size);
+ DBUF_STAT_BUMP(cache_levels[db_level]);
+ DBUF_STAT_INCR(cache_levels_bytes[db_level],
+ db_size);
}
- if (do_arc_evict)
- arc_freed(spa, &bp);
+ if (dcs == DB_DBUF_CACHE && !evicting)
+ dbuf_evict_notify(size);
}
} else {
mutex_exit(&db->db_mtx);
@@ -3951,6 +4119,35 @@ dmu_buf_get_user(dmu_buf_t *db_fake)
return (db->db_user);
}
+uint64_t
+dmu_buf_user_size(dmu_buf_t *db_fake)
+{
+ dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+ if (db->db_user == NULL)
+ return (0);
+ return (atomic_load_64(&db->db_user->dbu_size));
+}
+
+void
+dmu_buf_add_user_size(dmu_buf_t *db_fake, uint64_t nadd)
+{
+ dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+ ASSERT3U(db->db_caching_status, ==, DB_NO_CACHE);
+ ASSERT3P(db->db_user, !=, NULL);
+ ASSERT3U(atomic_load_64(&db->db_user->dbu_size), <, UINT64_MAX - nadd);
+ atomic_add_64(&db->db_user->dbu_size, nadd);
+}
+
+void
+dmu_buf_sub_user_size(dmu_buf_t *db_fake, uint64_t nsub)
+{
+ dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
+ ASSERT3U(db->db_caching_status, ==, DB_NO_CACHE);
+ ASSERT3P(db->db_user, !=, NULL);
+ ASSERT3U(atomic_load_64(&db->db_user->dbu_size), >=, nsub);
+ atomic_sub_64(&db->db_user->dbu_size, nsub);
+}
+
void
dmu_buf_user_evict_wait(void)
{
@@ -3971,21 +4168,6 @@ dmu_buf_get_objset(dmu_buf_t *db)
return (dbi->db_objset);
}
-dnode_t *
-dmu_buf_dnode_enter(dmu_buf_t *db)
-{
- dmu_buf_impl_t *dbi = (dmu_buf_impl_t *)db;
- DB_DNODE_ENTER(dbi);
- return (DB_DNODE(dbi));
-}
-
-void
-dmu_buf_dnode_exit(dmu_buf_t *db)
-{
- dmu_buf_impl_t *dbi = (dmu_buf_impl_t *)db;
- DB_DNODE_EXIT(dbi);
-}
-
static void
dbuf_check_blkptr(dnode_t *dn, dmu_buf_impl_t *db)
{
@@ -4247,22 +4429,6 @@ dbuf_lightweight_ready(zio_t *zio)
}
static void
-dbuf_lightweight_physdone(zio_t *zio)
-{
- dbuf_dirty_record_t *dr = zio->io_private;
- dsl_pool_t *dp = spa_get_dsl(zio->io_spa);
- ASSERT3U(dr->dr_txg, ==, zio->io_txg);
-
- /*
- * The callback will be called io_phys_children times. Retire one
- * portion of our dirty space each time we are called. Any rounding
- * error will be cleaned up by dbuf_lightweight_done().
- */
- int delta = dr->dr_accounted / zio->io_phys_children;
- dsl_pool_undirty_space(dp, delta, zio->io_txg);
-}
-
-static void
dbuf_lightweight_done(zio_t *zio)
{
dbuf_dirty_record_t *dr = zio->io_private;
@@ -4280,16 +4446,8 @@ dbuf_lightweight_done(zio_t *zio)
dsl_dataset_block_born(ds, zio->io_bp, tx);
}
- /*
- * See comment in dbuf_write_done().
- */
- if (zio->io_phys_children == 0) {
- dsl_pool_undirty_space(dmu_objset_pool(os),
- dr->dr_accounted, zio->io_txg);
- } else {
- dsl_pool_undirty_space(dmu_objset_pool(os),
- dr->dr_accounted % zio->io_phys_children, zio->io_txg);
- }
+ dsl_pool_undirty_space(dmu_objset_pool(os), dr->dr_accounted,
+ zio->io_txg);
abd_free(dr->dt.dll.dr_abd);
kmem_free(dr, sizeof (*dr));
@@ -4323,8 +4481,7 @@ dbuf_sync_lightweight(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
dmu_tx_get_txg(tx), &dr->dr_bp_copy, dr->dt.dll.dr_abd,
dn->dn_datablksz, abd_get_size(dr->dt.dll.dr_abd),
&dr->dt.dll.dr_props, dbuf_lightweight_ready, NULL,
- dbuf_lightweight_physdone, dbuf_lightweight_done, dr,
- ZIO_PRIORITY_ASYNC_WRITE,
+ dbuf_lightweight_done, dr, ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_MUSTSUCCEED | dr->dt.dll.dr_flags, &zb);
zio_nowait(dr->dr_zio);
@@ -4359,6 +4516,15 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
} else if (db->db_state == DB_FILL) {
/* This buffer was freed and is now being re-filled */
ASSERT(db->db.db_data != dr->dt.dl.dr_data);
+ } else if (db->db_state == DB_READ) {
+ /*
+ * This buffer has a clone we need to write, and an in-flight
+ * read on the BP we're about to clone. Its safe to issue the
+ * write here because the read has already been issued and the
+ * contents won't change.
+ */
+ ASSERT(dr->dt.dl.dr_brtwrite &&
+ dr->dt.dl.dr_override_state == DR_OVERRIDDEN);
} else {
ASSERT(db->db_state == DB_CACHED || db->db_state == DB_NOFILL);
}
@@ -4415,7 +4581,6 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
while (dr->dt.dl.dr_override_state == DR_IN_DMU_SYNC) {
ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT);
cv_wait(&db->db_changed, &db->db_mtx);
- ASSERT(dr->dt.dl.dr_override_state != DR_NOT_OVERRIDDEN);
}
/*
@@ -4425,11 +4590,10 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
if (os->os_encrypted && dn->dn_object == DMU_META_DNODE_OBJECT)
dbuf_prepare_encrypted_dnode_leaf(dr);
- if (db->db_state != DB_NOFILL &&
+ if (*datap != NULL && *datap == db->db_buf &&
dn->dn_object != DMU_META_DNODE_OBJECT &&
zfs_refcount_count(&db->db_holds) > 1 &&
- dr->dt.dl.dr_override_state != DR_OVERRIDDEN &&
- *datap == db->db_buf) {
+ dr->dt.dl.dr_override_state != DR_OVERRIDDEN) {
/*
* If this buffer is currently "in use" (i.e., there
* are active holds and db_data still references it),
@@ -4481,6 +4645,10 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
}
}
+/*
+ * Syncs out a range of dirty records for indirect or leaf dbufs. May be
+ * called recursively from dbuf_sync_indirect().
+ */
void
dbuf_sync_list(list_t *list, int level, dmu_tx_t *tx)
{
@@ -4537,7 +4705,7 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
dnode_diduse_space(dn, delta - zio->io_prev_space_delta);
zio->io_prev_space_delta = delta;
- if (bp->blk_birth != 0) {
+ if (BP_GET_LOGICAL_BIRTH(bp) != 0) {
ASSERT((db->db_blkid != DMU_SPILL_BLKID &&
BP_GET_TYPE(bp) == dn->dn_type) ||
(db->db_blkid == DMU_SPILL_BLKID &&
@@ -4574,6 +4742,20 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
i += DNODE_MIN_SIZE;
if (dnp->dn_type != DMU_OT_NONE) {
fill++;
+ for (int j = 0; j < dnp->dn_nblkptr;
+ j++) {
+ (void) zfs_blkptr_verify(spa,
+ &dnp->dn_blkptr[j],
+ BLK_CONFIG_SKIP,
+ BLK_VERIFY_HALT);
+ }
+ if (dnp->dn_flags &
+ DNODE_FLAG_SPILL_BLKPTR) {
+ (void) zfs_blkptr_verify(spa,
+ DN_SPILL_BLKPTR(dnp),
+ BLK_CONFIG_SKIP,
+ BLK_VERIFY_HALT);
+ }
i += dnp->dn_extra_slots *
DNODE_MIN_SIZE;
}
@@ -4591,6 +4773,8 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
for (i = db->db.db_size >> SPA_BLKPTRSHIFT; i > 0; i--, ibp++) {
if (BP_IS_HOLE(ibp))
continue;
+ (void) zfs_blkptr_verify(spa, ibp,
+ BLK_CONFIG_SKIP, BLK_VERIFY_HALT);
fill += BP_GET_FILL(ibp);
}
}
@@ -4651,37 +4835,6 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
DB_DNODE_EXIT(db);
}
-/*
- * The SPA will call this callback several times for each zio - once
- * for every physical child i/o (zio->io_phys_children times). This
- * allows the DMU to monitor the progress of each logical i/o. For example,
- * there may be 2 copies of an indirect block, or many fragments of a RAID-Z
- * block. There may be a long delay before all copies/fragments are completed,
- * so this callback allows us to retire dirty space gradually, as the physical
- * i/os complete.
- */
-static void
-dbuf_write_physdone(zio_t *zio, arc_buf_t *buf, void *arg)
-{
- (void) buf;
- dmu_buf_impl_t *db = arg;
- objset_t *os = db->db_objset;
- dsl_pool_t *dp = dmu_objset_pool(os);
- dbuf_dirty_record_t *dr;
- int delta = 0;
-
- dr = db->db_data_pending;
- ASSERT3U(dr->dr_txg, ==, zio->io_txg);
-
- /*
- * The callback will be called io_phys_children times. Retire one
- * portion of our dirty space each time we are called. Any rounding
- * error will be cleaned up by dbuf_write_done().
- */
- delta = dr->dr_accounted / zio->io_phys_children;
- dsl_pool_undirty_space(dp, delta, zio->io_txg);
-}
-
static void
dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
{
@@ -4729,9 +4882,9 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
if (db->db_level == 0) {
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
ASSERT(dr->dt.dl.dr_override_state == DR_NOT_OVERRIDDEN);
- if (db->db_state != DB_NOFILL) {
- if (dr->dt.dl.dr_data != db->db_buf)
- arc_buf_destroy(dr->dt.dl.dr_data, db);
+ if (dr->dt.dl.dr_data != NULL &&
+ dr->dt.dl.dr_data != db->db_buf) {
+ arc_buf_destroy(dr->dt.dl.dr_data, db);
}
} else {
ASSERT(list_head(&dr->dt.di.dr_children) == NULL);
@@ -4754,27 +4907,8 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
db->db_data_pending = NULL;
dbuf_rele_and_unlock(db, (void *)(uintptr_t)tx->tx_txg, B_FALSE);
- /*
- * If we didn't do a physical write in this ZIO and we
- * still ended up here, it means that the space of the
- * dbuf that we just released (and undirtied) above hasn't
- * been marked as undirtied in the pool's accounting.
- *
- * Thus, we undirty that space in the pool's view of the
- * world here. For physical writes this type of update
- * happens in dbuf_write_physdone().
- *
- * If we did a physical write, cleanup any rounding errors
- * that came up due to writing multiple copies of a block
- * on disk [see dbuf_write_physdone()].
- */
- if (zio->io_phys_children == 0) {
- dsl_pool_undirty_space(dmu_objset_pool(os),
- dr->dr_accounted, zio->io_txg);
- } else {
- dsl_pool_undirty_space(dmu_objset_pool(os),
- dr->dr_accounted % zio->io_phys_children, zio->io_txg);
- }
+ dsl_pool_undirty_space(dmu_objset_pool(os), dr->dr_accounted,
+ zio->io_txg);
kmem_free(dr, sizeof (dbuf_dirty_record_t));
}
@@ -4856,7 +4990,7 @@ dbuf_remap_impl(dnode_t *dn, blkptr_t *bp, krwlock_t *rw, dmu_tx_t *tx)
ASSERT(dsl_pool_sync_context(spa_get_dsl(spa)));
drica.drica_os = dn->dn_objset;
- drica.drica_blk_birth = bp->blk_birth;
+ drica.drica_blk_birth = BP_GET_LOGICAL_BIRTH(bp);
drica.drica_tx = tx;
if (spa_remap_blkptr(spa, &bp_copy, dbuf_remap_impl_callback,
&drica)) {
@@ -4871,7 +5005,8 @@ dbuf_remap_impl(dnode_t *dn, blkptr_t *bp, krwlock_t *rw, dmu_tx_t *tx)
if (dn->dn_objset != spa_meta_objset(spa)) {
dsl_dataset_t *ds = dmu_objset_ds(dn->dn_objset);
if (dsl_deadlist_is_open(&ds->ds_dir->dd_livelist) &&
- bp->blk_birth > ds->ds_dir->dd_origin_txg) {
+ BP_GET_LOGICAL_BIRTH(bp) >
+ ds->ds_dir->dd_origin_txg) {
ASSERT(!BP_IS_EMBEDDED(bp));
ASSERT(dsl_dir_is_clone(ds->ds_dir));
ASSERT(spa_feature_is_enabled(spa,
@@ -4931,7 +5066,10 @@ dbuf_remap(dnode_t *dn, dmu_buf_impl_t *db, dmu_tx_t *tx)
}
-/* Issue I/O to commit a dirty buffer to disk. */
+/*
+ * Populate dr->dr_zio with a zio to commit a dirty buffer to disk.
+ * Caller is responsible for issuing the zio_[no]wait(dr->dr_zio).
+ */
static void
dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
{
@@ -4949,21 +5087,18 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
os = dn->dn_objset;
- if (db->db_state != DB_NOFILL) {
- if (db->db_level > 0 || dn->dn_type == DMU_OT_DNODE) {
- /*
- * Private object buffers are released here rather
- * than in dbuf_dirty() since they are only modified
- * in the syncing context and we don't want the
- * overhead of making multiple copies of the data.
- */
- if (BP_IS_HOLE(db->db_blkptr)) {
- arc_buf_thaw(data);
- } else {
- dbuf_release_bp(db);
- }
- dbuf_remap(dn, db, tx);
- }
+ if (db->db_level > 0 || dn->dn_type == DMU_OT_DNODE) {
+ /*
+ * Private object buffers are released here rather than in
+ * dbuf_dirty() since they are only modified in the syncing
+ * context and we don't want the overhead of making multiple
+ * copies of the data.
+ */
+ if (BP_IS_HOLE(db->db_blkptr))
+ arc_buf_thaw(data);
+ else
+ dbuf_release_bp(db);
+ dbuf_remap(dn, db, tx);
}
if (parent != dn->dn_dbuf) {
@@ -4990,7 +5125,7 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
}
ASSERT(db->db_level == 0 || data == db->db_buf);
- ASSERT3U(db->db_blkptr->blk_birth, <=, txg);
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(db->db_blkptr), <=, txg);
ASSERT(pio);
SET_BOOKMARK(&zb, os->os_dsl_dataset ?
@@ -4999,7 +5134,7 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
if (db->db_blkid == DMU_SPILL_BLKID)
wp_flag = WP_SPILL;
- wp_flag |= (db->db_state == DB_NOFILL) ? WP_NOFILL : 0;
+ wp_flag |= (data == NULL) ? WP_NOFILL : 0;
dmu_write_policy(os, dn, db->db_level, wp_flag, &zp);
@@ -5022,20 +5157,21 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
dr->dr_zio = zio_write(pio, os->os_spa, txg, &dr->dr_bp_copy,
contents, db->db.db_size, db->db.db_size, &zp,
- dbuf_write_override_ready, NULL, NULL,
+ dbuf_write_override_ready, NULL,
dbuf_write_override_done,
dr, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
mutex_enter(&db->db_mtx);
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
zio_write_override(dr->dr_zio, &dr->dt.dl.dr_overridden_by,
- dr->dt.dl.dr_copies, dr->dt.dl.dr_nopwrite);
+ dr->dt.dl.dr_copies, dr->dt.dl.dr_nopwrite,
+ dr->dt.dl.dr_brtwrite);
mutex_exit(&db->db_mtx);
- } else if (db->db_state == DB_NOFILL) {
+ } else if (data == NULL) {
ASSERT(zp.zp_checksum == ZIO_CHECKSUM_OFF ||
zp.zp_checksum == ZIO_CHECKSUM_NOPARITY);
dr->dr_zio = zio_write(pio, os->os_spa, txg,
&dr->dr_bp_copy, NULL, db->db.db_size, db->db.db_size, &zp,
- dbuf_write_nofill_ready, NULL, NULL,
+ dbuf_write_nofill_ready, NULL,
dbuf_write_nofill_done, db,
ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_MUSTSUCCEED | ZIO_FLAG_NODATA, &zb);
@@ -5052,11 +5188,10 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
children_ready_cb = dbuf_write_children_ready;
dr->dr_zio = arc_write(pio, os->os_spa, txg,
- &dr->dr_bp_copy, data, dbuf_is_l2cacheable(db),
- &zp, dbuf_write_ready,
- children_ready_cb, dbuf_write_physdone,
- dbuf_write_done, db, ZIO_PRIORITY_ASYNC_WRITE,
- ZIO_FLAG_MUSTSUCCEED, &zb);
+ &dr->dr_bp_copy, data, !DBUF_IS_CACHEABLE(db),
+ dbuf_is_l2cacheable(db), &zp, dbuf_write_ready,
+ children_ready_cb, dbuf_write_done, db,
+ ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
}
}
@@ -5074,6 +5209,7 @@ EXPORT_SYMBOL(dbuf_dirty);
EXPORT_SYMBOL(dmu_buf_set_crypt_params);
EXPORT_SYMBOL(dmu_buf_will_dirty);
EXPORT_SYMBOL(dmu_buf_is_dirty);
+EXPORT_SYMBOL(dmu_buf_will_clone);
EXPORT_SYMBOL(dmu_buf_will_not_fill);
EXPORT_SYMBOL(dmu_buf_will_fill);
EXPORT_SYMBOL(dmu_buf_fill_done);
@@ -5096,7 +5232,7 @@ EXPORT_SYMBOL(dmu_buf_set_user_ie);
EXPORT_SYMBOL(dmu_buf_get_user);
EXPORT_SYMBOL(dmu_buf_get_blkptr);
-ZFS_MODULE_PARAM(zfs_dbuf_cache, dbuf_cache_, max_bytes, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_dbuf_cache, dbuf_cache_, max_bytes, U64, ZMOD_RW,
"Maximum size in bytes of the dbuf cache.");
ZFS_MODULE_PARAM(zfs_dbuf_cache, dbuf_cache_, hiwater_pct, UINT, ZMOD_RW,
@@ -5105,11 +5241,14 @@ ZFS_MODULE_PARAM(zfs_dbuf_cache, dbuf_cache_, hiwater_pct, UINT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_dbuf_cache, dbuf_cache_, lowater_pct, UINT, ZMOD_RW,
"Percentage below dbuf_cache_max_bytes when dbuf eviction stops.");
-ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, metadata_cache_max_bytes, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, metadata_cache_max_bytes, U64, ZMOD_RW,
"Maximum size in bytes of dbuf metadata cache.");
-ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, cache_shift, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, cache_shift, UINT, ZMOD_RW,
"Set size of dbuf cache to log2 fraction of arc size.");
-ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, metadata_cache_shift, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, metadata_cache_shift, UINT, ZMOD_RW,
"Set size of dbuf metadata cache to log2 fraction of arc size.");
+
+ZFS_MODULE_PARAM(zfs_dbuf, dbuf_, mutex_cache_shift, UINT, ZMOD_RD,
+ "Set size of dbuf cache mutex array as log2 shift.");
diff --git a/module/zfs/dbuf_stats.c b/module/zfs/dbuf_stats.c
index a42750ac8e90..ccee8997e10e 100644
--- a/module/zfs/dbuf_stats.c
+++ b/module/zfs/dbuf_stats.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -46,14 +46,14 @@ static int
dbuf_stats_hash_table_headers(char *buf, size_t size)
{
(void) snprintf(buf, size,
- "%-96s | %-119s | %s\n"
- "%-16s %-8s %-8s %-8s %-8s %-10s %-8s %-5s %-5s %-7s %3s | "
+ "%-105s | %-119s | %s\n"
+ "%-16s %-8s %-8s %-8s %-8s %-10s %-8s %-8s %-5s %-5s %-7s %3s | "
"%-5s %-5s %-9s %-6s %-8s %-12s "
"%-6s %-6s %-6s %-6s %-6s %-8s %-8s %-8s %-6s | "
"%-6s %-6s %-8s %-8s %-6s %-6s %-6s %-8s %-8s\n",
"dbuf", "arcbuf", "dnode", "pool", "objset", "object", "level",
- "blkid", "offset", "dbsize", "meta", "state", "dbholds", "dbc",
- "list", "atype", "flags", "count", "asize", "access",
+ "blkid", "offset", "dbsize", "usize", "meta", "state", "dbholds",
+ "dbc", "list", "atype", "flags", "count", "asize", "access",
"mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
"l2_comp", "aholds", "dtype", "btype", "data_bs", "meta_bs",
"bsize", "lvls", "dholds", "blocks", "dsize");
@@ -75,8 +75,8 @@ __dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
__dmu_object_info_from_dnode(dn, &doi);
nwritten = snprintf(buf, size,
- "%-16s %-8llu %-8lld %-8lld %-8lld %-10llu %-8llu %-5d %-5d "
- "%-7lu %-3d | %-5d %-5d 0x%-7x %-6lu %-8llu %-12llu "
+ "%-16s %-8llu %-8lld %-8lld %-8lld %-10llu %-8llu %-8llu "
+ "%-5d %-5d %-7lu %-3d | %-5d %-5d 0x%-7x %-6lu %-8llu %-12llu "
"%-6lu %-6lu %-6lu %-6lu %-6lu %-8llu %-8llu %-8d %-6lu | "
"%-6d %-6d %-8lu %-8lu %-6llu %-6lu %-6lu %-8llu %-8llu\n",
/* dmu_buf_impl_t */
@@ -87,6 +87,7 @@ __dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
(longlong_t)db->db_blkid,
(u_longlong_t)db->db.db_offset,
(u_longlong_t)db->db.db_size,
+ (u_longlong_t)dmu_buf_user_size(&db->db),
!!dbuf_is_metadata(db),
db->db_state,
(ulong_t)zfs_refcount_count(&db->db_holds),
@@ -137,7 +138,7 @@ dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
if (size)
buf[0] = 0;
- rw_enter(DBUF_HASH_RWLOCK(h, dsh->idx), RW_READER);
+ mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
for (db = h->hash_table[dsh->idx]; db != NULL; db = db->db_hash_next) {
/*
* Returning ENOMEM will cause the data and header functions
@@ -158,7 +159,7 @@ dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
mutex_exit(&db->db_mtx);
}
- rw_exit(DBUF_HASH_RWLOCK(h, dsh->idx));
+ mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
return (error);
}
diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c
index 61a9c8f0eaed..4c53cb0a2f9b 100644
--- a/module/zfs/ddt.c
+++ b/module/zfs/ddt.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,8 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2022 by Pawel Jakub Dawidek
+ * Copyright (c) 2023, Klara Inc.
*/
#include <sys/zfs_context.h>
@@ -29,15 +31,119 @@
#include <sys/spa_impl.h>
#include <sys/zio.h>
#include <sys/ddt.h>
+#include <sys/ddt_impl.h>
#include <sys/zap.h>
#include <sys/dmu_tx.h>
#include <sys/arc.h>
#include <sys/dsl_pool.h>
#include <sys/zio_checksum.h>
-#include <sys/zio_compress.h>
#include <sys/dsl_scan.h>
#include <sys/abd.h>
+/*
+ * # DDT: Deduplication tables
+ *
+ * The dedup subsystem provides block-level deduplication. When enabled, blocks
+ * to be written will have the dedup (D) bit set, which causes them to be
+ * tracked in a "dedup table", or DDT. If a block has been seen before (exists
+ * in the DDT), instead of being written, it will instead be made to reference
+ * the existing on-disk data, and a refcount bumped in the DDT instead.
+ *
+ * ## Dedup tables and entries
+ *
+ * Conceptually, a DDT is a dictionary or map. Each entry has a "key"
+ * (ddt_key_t) made up a block's checksum and certian properties, and a "value"
+ * (one or more ddt_phys_t) containing valid DVAs for the block's data, birth
+ * time and refcount. Together these are enough to track references to a
+ * specific block, to build a valid block pointer to reference that block (for
+ * freeing, scrubbing, etc), and to fill a new block pointer with the missing
+ * pieces to make it seem like it was written.
+ *
+ * There's a single DDT (ddt_t) for each checksum type, held in spa_ddt[].
+ * Within each DDT, there can be multiple storage "types" (ddt_type_t, on-disk
+ * object data formats, each with their own implementations) and "classes"
+ * (ddt_class_t, instance of a storage type object, for entries with a specific
+ * characteristic). An entry (key) will only ever exist on one of these objects
+ * at any given time, but may be moved from one to another if their type or
+ * class changes.
+ *
+ * The DDT is driven by the write IO pipeline (zio_ddt_write()). When a block
+ * is to be written, before DVAs have been allocated, ddt_lookup() is called to
+ * see if the block has been seen before. If its not found, the write proceeds
+ * as normal, and after it succeeds, a new entry is created. If it is found, we
+ * fill the BP with the DVAs from the entry, increment the refcount and cause
+ * the write IO to return immediately.
+ *
+ * Each ddt_phys_t slot in the entry represents a separate dedup block for the
+ * same content/checksum. The slot is selected based on the zp_copies parameter
+ * the block is written with, that is, the number of DVAs in the block. The
+ * "ditto" slot (DDT_PHYS_DITTO) used to be used for now-removed "dedupditto"
+ * feature. These are no longer written, and will be freed if encountered on
+ * old pools.
+ *
+ * ## Lifetime of an entry
+ *
+ * A DDT can be enormous, and typically is not held in memory all at once.
+ * Instead, the changes to an entry are tracked in memory, and written down to
+ * disk at the end of each txg.
+ *
+ * A "live" in-memory entry (ddt_entry_t) is a node on the live tree
+ * (ddt_tree). At the start of a txg, ddt_tree is empty. When an entry is
+ * required for IO, ddt_lookup() is called. If an entry already exists on
+ * ddt_tree, it is returned. Otherwise, a new one is created, and the
+ * type/class objects for the DDT are searched for that key. If its found, its
+ * value is copied into the live entry. If not, an empty entry is created.
+ *
+ * The live entry will be modified during the txg, usually by modifying the
+ * refcount, but sometimes by adding or updating DVAs. At the end of the txg
+ * (during spa_sync()), type and class are recalculated for entry (see
+ * ddt_sync_entry()), and the entry is written to the appropriate storage
+ * object and (if necessary), removed from an old one. ddt_tree is cleared and
+ * the next txg can start.
+ *
+ * ## Repair IO
+ *
+ * If a read on a dedup block fails, but there are other copies of the block in
+ * the other ddt_phys_t slots, reads will be issued for those instead
+ * (zio_ddt_read_start()). If one of those succeeds, the read is returned to
+ * the caller, and a copy is stashed on the entry's dde_repair_abd.
+ *
+ * During the end-of-txg sync, any entries with a dde_repair_abd get a
+ * "rewrite" write issued for the original block pointer, with the data read
+ * from the alternate block. If the block is actually damaged, this will invoke
+ * the pool's "self-healing" mechanism, and repair the block.
+ *
+ * ## Scanning (scrub/resilver)
+ *
+ * If dedup is active, the scrub machinery will walk the dedup table first, and
+ * scrub all blocks with refcnt > 1 first. After that it will move on to the
+ * regular top-down scrub, and exclude the refcnt > 1 blocks when it sees them.
+ * In this way, heavily deduplicated blocks are only scrubbed once. See the
+ * commentary on dsl_scan_ddt() for more details.
+ *
+ * Walking the DDT is done via ddt_walk(). The current position is stored in a
+ * ddt_bookmark_t, which represents a stable position in the storage object.
+ * This bookmark is stored by the scan machinery, and must reference the same
+ * position on the object even if the object changes, the pool is exported, or
+ * OpenZFS is upgraded.
+ *
+ * ## Interaction with block cloning
+ *
+ * If block cloning and dedup are both enabled on a pool, BRT will look for the
+ * dedup bit on an incoming block pointer. If set, it will call into the DDT
+ * (ddt_addref()) to add a reference to the block, instead of adding a
+ * reference to the BRT. See brt_pending_apply().
+ */
+
+/*
+ * These are the only checksums valid for dedup. They must match the list
+ * from dedup_table in zfs_prop.c
+ */
+#define DDT_CHECKSUM_VALID(c) \
+ (c == ZIO_CHECKSUM_SHA256 || c == ZIO_CHECKSUM_SHA512 || \
+ c == ZIO_CHECKSUM_SKEIN || c == ZIO_CHECKSUM_EDONR || \
+ c == ZIO_CHECKSUM_BLAKE3)
+
static kmem_cache_t *ddt_cache;
static kmem_cache_t *ddt_entry_cache;
@@ -57,7 +163,7 @@ static const char *const ddt_class_name[DDT_CLASSES] = {
};
static void
-ddt_object_create(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_create(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
dmu_tx_t *tx)
{
spa_t *spa = ddt->ddt_spa;
@@ -69,20 +175,20 @@ ddt_object_create(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt_object_name(ddt, type, class, name);
- ASSERT(*objectp == 0);
- VERIFY(ddt_ops[type]->ddt_op_create(os, objectp, tx, prehash) == 0);
- ASSERT(*objectp != 0);
+ ASSERT3U(*objectp, ==, 0);
+ VERIFY0(ddt_ops[type]->ddt_op_create(os, objectp, tx, prehash));
+ ASSERT3U(*objectp, !=, 0);
- VERIFY(zap_add(os, DMU_POOL_DIRECTORY_OBJECT, name,
- sizeof (uint64_t), 1, objectp, tx) == 0);
+ VERIFY0(zap_add(os, DMU_POOL_DIRECTORY_OBJECT, name,
+ sizeof (uint64_t), 1, objectp, tx));
- VERIFY(zap_add(os, spa->spa_ddt_stat_object, name,
+ VERIFY0(zap_add(os, spa->spa_ddt_stat_object, name,
sizeof (uint64_t), sizeof (ddt_histogram_t) / sizeof (uint64_t),
- &ddt->ddt_histogram[type][class], tx) == 0);
+ &ddt->ddt_histogram[type][class], tx));
}
static void
-ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_destroy(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
dmu_tx_t *tx)
{
spa_t *spa = ddt->ddt_spa;
@@ -93,19 +199,20 @@ ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt_object_name(ddt, type, class, name);
- ASSERT(*objectp != 0);
+ ASSERT3U(*objectp, !=, 0);
ASSERT(ddt_histogram_empty(&ddt->ddt_histogram[type][class]));
- VERIFY(ddt_object_count(ddt, type, class, &count) == 0 && count == 0);
- VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0);
- VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0);
- VERIFY(ddt_ops[type]->ddt_op_destroy(os, *objectp, tx) == 0);
+ VERIFY0(ddt_object_count(ddt, type, class, &count));
+ VERIFY0(count);
+ VERIFY0(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx));
+ VERIFY0(zap_remove(os, spa->spa_ddt_stat_object, name, tx));
+ VERIFY0(ddt_ops[type]->ddt_op_destroy(os, *objectp, tx));
memset(&ddt->ddt_object_stats[type][class], 0, sizeof (ddt_object_t));
*objectp = 0;
}
static int
-ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
+ddt_object_load(ddt_t *ddt, ddt_type_t type, ddt_class_t class)
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
@@ -145,7 +252,7 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
}
static void
-ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_sync(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
dmu_tx_t *tx)
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
@@ -155,75 +262,95 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt_object_name(ddt, type, class, name);
- VERIFY(zap_update(ddt->ddt_os, ddt->ddt_spa->spa_ddt_stat_object, name,
+ VERIFY0(zap_update(ddt->ddt_os, ddt->ddt_spa->spa_ddt_stat_object, name,
sizeof (uint64_t), sizeof (ddt_histogram_t) / sizeof (uint64_t),
- &ddt->ddt_histogram[type][class], tx) == 0);
+ &ddt->ddt_histogram[type][class], tx));
/*
* Cache DDT statistics; this is the only time they'll change.
*/
- VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
- VERIFY(ddt_object_count(ddt, type, class, &count) == 0);
+ VERIFY0(ddt_object_info(ddt, type, class, &doi));
+ VERIFY0(ddt_object_count(ddt, type, class, &count));
ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
}
+static boolean_t
+ddt_object_exists(ddt_t *ddt, ddt_type_t type, ddt_class_t class)
+{
+ return (!!ddt->ddt_object[type][class]);
+}
+
static int
-ddt_object_lookup(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_lookup(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
ddt_entry_t *dde)
{
if (!ddt_object_exists(ddt, type, class))
return (SET_ERROR(ENOENT));
return (ddt_ops[type]->ddt_op_lookup(ddt->ddt_os,
- ddt->ddt_object[type][class], dde));
+ ddt->ddt_object[type][class], &dde->dde_key,
+ dde->dde_phys, sizeof (dde->dde_phys)));
+}
+
+static int
+ddt_object_contains(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
+ const ddt_key_t *ddk)
+{
+ if (!ddt_object_exists(ddt, type, class))
+ return (SET_ERROR(ENOENT));
+
+ return (ddt_ops[type]->ddt_op_contains(ddt->ddt_os,
+ ddt->ddt_object[type][class], ddk));
}
static void
-ddt_object_prefetch(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
- ddt_entry_t *dde)
+ddt_object_prefetch(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
+ const ddt_key_t *ddk)
{
if (!ddt_object_exists(ddt, type, class))
return;
ddt_ops[type]->ddt_op_prefetch(ddt->ddt_os,
- ddt->ddt_object[type][class], dde);
+ ddt->ddt_object[type][class], ddk);
}
-int
-ddt_object_update(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+static int
+ddt_object_update(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
ddt_entry_t *dde, dmu_tx_t *tx)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_update(ddt->ddt_os,
- ddt->ddt_object[type][class], dde, tx));
+ ddt->ddt_object[type][class], &dde->dde_key, dde->dde_phys,
+ sizeof (dde->dde_phys), tx));
}
static int
-ddt_object_remove(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
- ddt_entry_t *dde, dmu_tx_t *tx)
+ddt_object_remove(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
+ const ddt_key_t *ddk, dmu_tx_t *tx)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_remove(ddt->ddt_os,
- ddt->ddt_object[type][class], dde, tx));
+ ddt->ddt_object[type][class], ddk, tx));
}
int
-ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_walk(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
uint64_t *walk, ddt_entry_t *dde)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_walk(ddt->ddt_os,
- ddt->ddt_object[type][class], dde, walk));
+ ddt->ddt_object[type][class], walk, &dde->dde_key,
+ dde->dde_phys, sizeof (dde->dde_phys)));
}
int
-ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_count(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
uint64_t *count)
{
ASSERT(ddt_object_exists(ddt, type, class));
@@ -233,7 +360,7 @@ ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
}
int
-ddt_object_info(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_info(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
dmu_object_info_t *doi)
{
if (!ddt_object_exists(ddt, type, class))
@@ -243,14 +370,8 @@ ddt_object_info(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
doi));
}
-boolean_t
-ddt_object_exists(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
-{
- return (!!ddt->ddt_object[type][class]);
-}
-
void
-ddt_object_name(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
+ddt_object_name(ddt_t *ddt, ddt_type_t type, ddt_class_t class,
char *name)
{
(void) snprintf(name, DDT_NAMELEN, DMU_POOL_DDT,
@@ -261,7 +382,7 @@ ddt_object_name(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
void
ddt_bp_fill(const ddt_phys_t *ddp, blkptr_t *bp, uint64_t txg)
{
- ASSERT(txg != 0);
+ ASSERT3U(txg, !=, 0);
for (int d = 0; d < SPA_DVAS_PER_BP; d++)
bp->blk_dva[d] = ddp->ddp_dva[d];
@@ -312,11 +433,11 @@ ddt_key_fill(ddt_key_t *ddk, const blkptr_t *bp)
void
ddt_phys_fill(ddt_phys_t *ddp, const blkptr_t *bp)
{
- ASSERT(ddp->ddp_phys_birth == 0);
+ ASSERT0(ddp->ddp_phys_birth);
for (int d = 0; d < SPA_DVAS_PER_BP; d++)
ddp->ddp_dva[d] = bp->blk_dva[d];
- ddp->ddp_phys_birth = BP_PHYSICAL_BIRTH(bp);
+ ddp->ddp_phys_birth = BP_GET_BIRTH(bp);
}
void
@@ -335,12 +456,12 @@ void
ddt_phys_decref(ddt_phys_t *ddp)
{
if (ddp) {
- ASSERT(ddp->ddp_refcnt > 0);
+ ASSERT3U(ddp->ddp_refcnt, >, 0);
ddp->ddp_refcnt--;
}
}
-void
+static void
ddt_phys_free(ddt_t *ddt, ddt_key_t *ddk, ddt_phys_t *ddp, uint64_t txg)
{
blkptr_t blk;
@@ -364,7 +485,7 @@ ddt_phys_select(const ddt_entry_t *dde, const blkptr_t *bp)
for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
if (DVA_EQUAL(BP_IDENTITY(bp), &ddp->ddp_dva[0]) &&
- BP_PHYSICAL_BIRTH(bp) == ddp->ddp_phys_birth)
+ BP_GET_BIRTH(bp) == ddp->ddp_phys_birth)
return (ddp);
}
return (NULL);
@@ -381,221 +502,10 @@ ddt_phys_total_refcnt(const ddt_entry_t *dde)
return (refcnt);
}
-static void
-ddt_stat_generate(ddt_t *ddt, ddt_entry_t *dde, ddt_stat_t *dds)
-{
- spa_t *spa = ddt->ddt_spa;
- ddt_phys_t *ddp = dde->dde_phys;
- ddt_key_t *ddk = &dde->dde_key;
- uint64_t lsize = DDK_GET_LSIZE(ddk);
- uint64_t psize = DDK_GET_PSIZE(ddk);
-
- memset(dds, 0, sizeof (*dds));
-
- for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
- uint64_t dsize = 0;
- uint64_t refcnt = ddp->ddp_refcnt;
-
- if (ddp->ddp_phys_birth == 0)
- continue;
-
- for (int d = 0; d < DDE_GET_NDVAS(dde); d++)
- dsize += dva_get_dsize_sync(spa, &ddp->ddp_dva[d]);
-
- dds->dds_blocks += 1;
- dds->dds_lsize += lsize;
- dds->dds_psize += psize;
- dds->dds_dsize += dsize;
-
- dds->dds_ref_blocks += refcnt;
- dds->dds_ref_lsize += lsize * refcnt;
- dds->dds_ref_psize += psize * refcnt;
- dds->dds_ref_dsize += dsize * refcnt;
- }
-}
-
-void
-ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src, uint64_t neg)
-{
- const uint64_t *s = (const uint64_t *)src;
- uint64_t *d = (uint64_t *)dst;
- uint64_t *d_end = (uint64_t *)(dst + 1);
-
- ASSERT(neg == 0 || neg == -1ULL); /* add or subtract */
-
- for (int i = 0; i < d_end - d; i++)
- d[i] += (s[i] ^ neg) - neg;
-}
-
-static void
-ddt_stat_update(ddt_t *ddt, ddt_entry_t *dde, uint64_t neg)
-{
- ddt_stat_t dds;
- ddt_histogram_t *ddh;
- int bucket;
-
- ddt_stat_generate(ddt, dde, &dds);
-
- bucket = highbit64(dds.dds_ref_blocks) - 1;
- ASSERT(bucket >= 0);
-
- ddh = &ddt->ddt_histogram[dde->dde_type][dde->dde_class];
-
- ddt_stat_add(&ddh->ddh_stat[bucket], &dds, neg);
-}
-
-void
-ddt_histogram_add(ddt_histogram_t *dst, const ddt_histogram_t *src)
-{
- for (int h = 0; h < 64; h++)
- ddt_stat_add(&dst->ddh_stat[h], &src->ddh_stat[h], 0);
-}
-
-void
-ddt_histogram_stat(ddt_stat_t *dds, const ddt_histogram_t *ddh)
-{
- memset(dds, 0, sizeof (*dds));
-
- for (int h = 0; h < 64; h++)
- ddt_stat_add(dds, &ddh->ddh_stat[h], 0);
-}
-
-boolean_t
-ddt_histogram_empty(const ddt_histogram_t *ddh)
-{
- const uint64_t *s = (const uint64_t *)ddh;
- const uint64_t *s_end = (const uint64_t *)(ddh + 1);
-
- while (s < s_end)
- if (*s++ != 0)
- return (B_FALSE);
-
- return (B_TRUE);
-}
-
-void
-ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo_total)
-{
- /* Sum the statistics we cached in ddt_object_sync(). */
- for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
- ddt_t *ddt = spa->spa_ddt[c];
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES;
- class++) {
- ddt_object_t *ddo =
- &ddt->ddt_object_stats[type][class];
- ddo_total->ddo_count += ddo->ddo_count;
- ddo_total->ddo_dspace += ddo->ddo_dspace;
- ddo_total->ddo_mspace += ddo->ddo_mspace;
- }
- }
- }
-
- /* ... and compute the averages. */
- if (ddo_total->ddo_count != 0) {
- ddo_total->ddo_dspace /= ddo_total->ddo_count;
- ddo_total->ddo_mspace /= ddo_total->ddo_count;
- }
-}
-
-void
-ddt_get_dedup_histogram(spa_t *spa, ddt_histogram_t *ddh)
-{
- for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
- ddt_t *ddt = spa->spa_ddt[c];
- for (enum ddt_type type = 0; type < DDT_TYPES && ddt; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES;
- class++) {
- ddt_histogram_add(ddh,
- &ddt->ddt_histogram_cache[type][class]);
- }
- }
- }
-}
-
-void
-ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total)
-{
- ddt_histogram_t *ddh_total;
-
- ddh_total = kmem_zalloc(sizeof (ddt_histogram_t), KM_SLEEP);
- ddt_get_dedup_histogram(spa, ddh_total);
- ddt_histogram_stat(dds_total, ddh_total);
- kmem_free(ddh_total, sizeof (ddt_histogram_t));
-}
-
-uint64_t
-ddt_get_dedup_dspace(spa_t *spa)
-{
- ddt_stat_t dds_total;
-
- if (spa->spa_dedup_dspace != ~0ULL)
- return (spa->spa_dedup_dspace);
-
- memset(&dds_total, 0, sizeof (ddt_stat_t));
-
- /* Calculate and cache the stats */
- ddt_get_dedup_stats(spa, &dds_total);
- spa->spa_dedup_dspace = dds_total.dds_ref_dsize - dds_total.dds_dsize;
- return (spa->spa_dedup_dspace);
-}
-
-uint64_t
-ddt_get_pool_dedup_ratio(spa_t *spa)
-{
- ddt_stat_t dds_total = { 0 };
-
- ddt_get_dedup_stats(spa, &dds_total);
- if (dds_total.dds_dsize == 0)
- return (100);
-
- return (dds_total.dds_ref_dsize * 100 / dds_total.dds_dsize);
-}
-
-size_t
-ddt_compress(void *src, uchar_t *dst, size_t s_len, size_t d_len)
-{
- uchar_t *version = dst++;
- int cpfunc = ZIO_COMPRESS_ZLE;
- zio_compress_info_t *ci = &zio_compress_table[cpfunc];
- size_t c_len;
-
- ASSERT(d_len >= s_len + 1); /* no compression plus version byte */
-
- c_len = ci->ci_compress(src, dst, s_len, d_len - 1, ci->ci_level);
-
- if (c_len == s_len) {
- cpfunc = ZIO_COMPRESS_OFF;
- memcpy(dst, src, s_len);
- }
-
- *version = cpfunc;
- if (ZFS_HOST_BYTEORDER)
- *version |= DDT_COMPRESS_BYTEORDER_MASK;
-
- return (c_len + 1);
-}
-
-void
-ddt_decompress(uchar_t *src, void *dst, size_t s_len, size_t d_len)
-{
- uchar_t version = *src++;
- int cpfunc = version & DDT_COMPRESS_FUNCTION_MASK;
- zio_compress_info_t *ci = &zio_compress_table[cpfunc];
-
- if (ci->ci_decompress != NULL)
- (void) ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level);
- else
- memcpy(dst, src, d_len);
-
- if (((version & DDT_COMPRESS_BYTEORDER_MASK) != 0) !=
- (ZFS_HOST_BYTEORDER != 0))
- byteswap_uint64_array(dst, d_len);
-}
-
ddt_t *
ddt_select(spa_t *spa, const blkptr_t *bp)
{
+ ASSERT(DDT_CHECKSUM_VALID(BP_GET_CHECKSUM(bp)));
return (spa->spa_ddt[BP_GET_CHECKSUM(bp)]);
}
@@ -644,10 +554,10 @@ ddt_alloc(const ddt_key_t *ddk)
static void
ddt_free(ddt_entry_t *dde)
{
- ASSERT(!dde->dde_loading);
+ ASSERT(dde->dde_flags & DDE_FLAG_LOADED);
for (int p = 0; p < DDT_PHYS_TYPES; p++)
- ASSERT(dde->dde_lead_zio[p] == NULL);
+ ASSERT3P(dde->dde_lead_zio[p], ==, NULL);
if (dde->dde_repair_abd != NULL)
abd_free(dde->dde_repair_abd);
@@ -668,36 +578,48 @@ ddt_remove(ddt_t *ddt, ddt_entry_t *dde)
ddt_entry_t *
ddt_lookup(ddt_t *ddt, const blkptr_t *bp, boolean_t add)
{
- ddt_entry_t *dde, dde_search;
- enum ddt_type type;
- enum ddt_class class;
+ ddt_key_t search;
+ ddt_entry_t *dde;
+ ddt_type_t type;
+ ddt_class_t class;
avl_index_t where;
int error;
ASSERT(MUTEX_HELD(&ddt->ddt_lock));
- ddt_key_fill(&dde_search.dde_key, bp);
+ ddt_key_fill(&search, bp);
- dde = avl_find(&ddt->ddt_tree, &dde_search, &where);
- if (dde == NULL) {
- if (!add)
- return (NULL);
- dde = ddt_alloc(&dde_search.dde_key);
- avl_insert(&ddt->ddt_tree, dde, where);
- }
+ /* Find an existing live entry */
+ dde = avl_find(&ddt->ddt_tree, &search, &where);
+ if (dde != NULL) {
+ /* Found it. If it's already loaded, we can just return it. */
+ if (dde->dde_flags & DDE_FLAG_LOADED)
+ return (dde);
- while (dde->dde_loading)
- cv_wait(&dde->dde_cv, &ddt->ddt_lock);
+ /* Someone else is loading it, wait for it. */
+ while (!(dde->dde_flags & DDE_FLAG_LOADED))
+ cv_wait(&dde->dde_cv, &ddt->ddt_lock);
- if (dde->dde_loaded)
return (dde);
+ }
- dde->dde_loading = B_TRUE;
+ /* Not found. */
+ if (!add)
+ return (NULL);
+ /* Time to make a new entry. */
+ dde = ddt_alloc(&search);
+ avl_insert(&ddt->ddt_tree, dde, where);
+
+ /*
+ * ddt_tree is now stable, so unlock and let everyone else keep moving.
+ * Anyone landing on this entry will find it without DDE_FLAG_LOADED,
+ * and go to sleep waiting for it above.
+ */
ddt_exit(ddt);
+ /* Search all store objects for the entry. */
error = ENOENT;
-
for (type = 0; type < DDT_TYPES; type++) {
for (class = 0; class < DDT_CLASSES; class++) {
error = ddt_object_lookup(ddt, type, class, dde);
@@ -712,17 +634,16 @@ ddt_lookup(ddt_t *ddt, const blkptr_t *bp, boolean_t add)
ddt_enter(ddt);
- ASSERT(dde->dde_loaded == B_FALSE);
- ASSERT(dde->dde_loading == B_TRUE);
+ ASSERT(!(dde->dde_flags & DDE_FLAG_LOADED));
dde->dde_type = type; /* will be DDT_TYPES if no entry found */
dde->dde_class = class; /* will be DDT_CLASSES if no entry found */
- dde->dde_loaded = B_TRUE;
- dde->dde_loading = B_FALSE;
if (error == 0)
ddt_stat_update(ddt, dde, -1ULL);
+ /* Entry loaded, everyone can proceed now */
+ dde->dde_flags |= DDE_FLAG_LOADED;
cv_broadcast(&dde->dde_cv);
return (dde);
@@ -732,7 +653,7 @@ void
ddt_prefetch(spa_t *spa, const blkptr_t *bp)
{
ddt_t *ddt;
- ddt_entry_t dde;
+ ddt_key_t ddk;
if (!zfs_dedup_prefetch || bp == NULL || !BP_GET_DEDUP(bp))
return;
@@ -743,17 +664,18 @@ ddt_prefetch(spa_t *spa, const blkptr_t *bp)
* Thus no locking is required as the DDT can't disappear on us.
*/
ddt = ddt_select(spa, bp);
- ddt_key_fill(&dde.dde_key, bp);
+ ddt_key_fill(&ddk, bp);
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
- ddt_object_prefetch(ddt, type, class, &dde);
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES; class++) {
+ ddt_object_prefetch(ddt, type, class, &ddk);
}
}
}
/*
- * Opaque struct used for ddt_key comparison
+ * Key comparison. Any struct wanting to make use of this function must have
+ * the key as the first element.
*/
#define DDT_KEY_CMP_LEN (sizeof (ddt_key_t) / sizeof (uint16_t))
@@ -762,12 +684,10 @@ typedef struct ddt_key_cmp {
} ddt_key_cmp_t;
int
-ddt_entry_compare(const void *x1, const void *x2)
+ddt_key_compare(const void *x1, const void *x2)
{
- const ddt_entry_t *dde1 = x1;
- const ddt_entry_t *dde2 = x2;
- const ddt_key_cmp_t *k1 = (const ddt_key_cmp_t *)&dde1->dde_key;
- const ddt_key_cmp_t *k2 = (const ddt_key_cmp_t *)&dde2->dde_key;
+ const ddt_key_cmp_t *k1 = (const ddt_key_cmp_t *)x1;
+ const ddt_key_cmp_t *k2 = (const ddt_key_cmp_t *)x2;
int32_t cmp = 0;
for (int i = 0; i < DDT_KEY_CMP_LEN; i++) {
@@ -788,9 +708,9 @@ ddt_table_alloc(spa_t *spa, enum zio_checksum c)
memset(ddt, 0, sizeof (ddt_t));
mutex_init(&ddt->ddt_lock, NULL, MUTEX_DEFAULT, NULL);
- avl_create(&ddt->ddt_tree, ddt_entry_compare,
+ avl_create(&ddt->ddt_tree, ddt_key_compare,
sizeof (ddt_entry_t), offsetof(ddt_entry_t, dde_node));
- avl_create(&ddt->ddt_repair_tree, ddt_entry_compare,
+ avl_create(&ddt->ddt_repair_tree, ddt_key_compare,
sizeof (ddt_entry_t), offsetof(ddt_entry_t, dde_node));
ddt->ddt_checksum = c;
ddt->ddt_spa = spa;
@@ -802,8 +722,8 @@ ddt_table_alloc(spa_t *spa, enum zio_checksum c)
static void
ddt_table_free(ddt_t *ddt)
{
- ASSERT(avl_numnodes(&ddt->ddt_tree) == 0);
- ASSERT(avl_numnodes(&ddt->ddt_repair_tree) == 0);
+ ASSERT0(avl_numnodes(&ddt->ddt_tree));
+ ASSERT0(avl_numnodes(&ddt->ddt_repair_tree));
avl_destroy(&ddt->ddt_tree);
avl_destroy(&ddt->ddt_repair_tree);
mutex_destroy(&ddt->ddt_lock);
@@ -815,8 +735,10 @@ ddt_create(spa_t *spa)
{
spa->spa_dedup_checksum = ZIO_DEDUPCHECKSUM;
- for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++)
- spa->spa_ddt[c] = ddt_table_alloc(spa, c);
+ for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
+ if (DDT_CHECKSUM_VALID(c))
+ spa->spa_ddt[c] = ddt_table_alloc(spa, c);
+ }
}
int
@@ -834,9 +756,12 @@ ddt_load(spa_t *spa)
return (error == ENOENT ? 0 : error);
for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
+ if (!DDT_CHECKSUM_VALID(c))
+ continue;
+
ddt_t *ddt = spa->spa_ddt[c];
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES;
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES;
class++) {
error = ddt_object_load(ddt, type, class);
if (error != 0 && error != ENOENT)
@@ -867,10 +792,10 @@ ddt_unload(spa_t *spa)
}
boolean_t
-ddt_class_contains(spa_t *spa, enum ddt_class max_class, const blkptr_t *bp)
+ddt_class_contains(spa_t *spa, ddt_class_t max_class, const blkptr_t *bp)
{
ddt_t *ddt;
- ddt_entry_t *dde;
+ ddt_key_t ddk;
if (!BP_GET_DEDUP(bp))
return (B_FALSE);
@@ -879,20 +804,16 @@ ddt_class_contains(spa_t *spa, enum ddt_class max_class, const blkptr_t *bp)
return (B_TRUE);
ddt = spa->spa_ddt[BP_GET_CHECKSUM(bp)];
- dde = kmem_cache_alloc(ddt_entry_cache, KM_SLEEP);
- ddt_key_fill(&(dde->dde_key), bp);
+ ddt_key_fill(&ddk, bp);
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class <= max_class; class++) {
- if (ddt_object_lookup(ddt, type, class, dde) == 0) {
- kmem_cache_free(ddt_entry_cache, dde);
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class <= max_class; class++) {
+ if (ddt_object_contains(ddt, type, class, &ddk) == 0)
return (B_TRUE);
- }
}
}
- kmem_cache_free(ddt_entry_cache, dde);
return (B_FALSE);
}
@@ -906,8 +827,8 @@ ddt_repair_start(ddt_t *ddt, const blkptr_t *bp)
dde = ddt_alloc(&ddk);
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES; class++) {
/*
* We can only do repair if there are multiple copies
* of the block. For anything in the UNIQUE class,
@@ -1006,19 +927,18 @@ ddt_sync_entry(ddt_t *ddt, ddt_entry_t *dde, dmu_tx_t *tx, uint64_t txg)
dsl_pool_t *dp = ddt->ddt_spa->spa_dsl_pool;
ddt_phys_t *ddp = dde->dde_phys;
ddt_key_t *ddk = &dde->dde_key;
- enum ddt_type otype = dde->dde_type;
- enum ddt_type ntype = DDT_TYPE_CURRENT;
- enum ddt_class oclass = dde->dde_class;
- enum ddt_class nclass;
+ ddt_type_t otype = dde->dde_type;
+ ddt_type_t ntype = DDT_TYPE_DEFAULT;
+ ddt_class_t oclass = dde->dde_class;
+ ddt_class_t nclass;
uint64_t total_refcnt = 0;
- ASSERT(dde->dde_loaded);
- ASSERT(!dde->dde_loading);
+ ASSERT(dde->dde_flags & DDE_FLAG_LOADED);
for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
- ASSERT(dde->dde_lead_zio[p] == NULL);
+ ASSERT3P(dde->dde_lead_zio[p], ==, NULL);
if (ddp->ddp_phys_birth == 0) {
- ASSERT(ddp->ddp_refcnt == 0);
+ ASSERT0(ddp->ddp_refcnt);
continue;
}
if (p == DDT_PHYS_DITTO) {
@@ -1043,8 +963,9 @@ ddt_sync_entry(ddt_t *ddt, ddt_entry_t *dde, dmu_tx_t *tx, uint64_t txg)
if (otype != DDT_TYPES &&
(otype != ntype || oclass != nclass || total_refcnt == 0)) {
- VERIFY(ddt_object_remove(ddt, otype, oclass, dde, tx) == 0);
- ASSERT(ddt_object_lookup(ddt, otype, oclass, dde) == ENOENT);
+ VERIFY0(ddt_object_remove(ddt, otype, oclass, ddk, tx));
+ ASSERT3U(
+ ddt_object_contains(ddt, otype, oclass, ddk), ==, ENOENT);
}
if (total_refcnt != 0) {
@@ -1053,7 +974,7 @@ ddt_sync_entry(ddt_t *ddt, ddt_entry_t *dde, dmu_tx_t *tx, uint64_t txg)
ddt_stat_update(ddt, dde, 0);
if (!ddt_object_exists(ddt, ntype, nclass))
ddt_object_create(ddt, ntype, nclass, tx);
- VERIFY(ddt_object_update(ddt, ntype, nclass, dde, tx) == 0);
+ VERIFY0(ddt_object_update(ddt, ntype, nclass, dde, tx));
/*
* If the class changes, the order that we scan this bp
@@ -1079,7 +1000,7 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
if (avl_numnodes(&ddt->ddt_tree) == 0)
return;
- ASSERT(spa->spa_uberblock.ub_version >= SPA_VERSION_DEDUP);
+ ASSERT3U(spa->spa_uberblock.ub_version, >=, SPA_VERSION_DEDUP);
if (spa->spa_ddt_stat_object == 0) {
spa->spa_ddt_stat_object = zap_create_link(ddt->ddt_os,
@@ -1092,17 +1013,17 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
ddt_free(dde);
}
- for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
uint64_t add, count = 0;
- for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES; class++) {
if (ddt_object_exists(ddt, type, class)) {
ddt_object_sync(ddt, type, class, tx);
- VERIFY(ddt_object_count(ddt, type, class,
- &add) == 0);
+ VERIFY0(ddt_object_count(ddt, type, class,
+ &add));
count += add;
}
}
- for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES; class++) {
if (count == 0 && ddt_object_exists(ddt, type, class))
ddt_object_destroy(ddt, type, class, tx);
}
@@ -1120,7 +1041,7 @@ ddt_sync(spa_t *spa, uint64_t txg)
dmu_tx_t *tx;
zio_t *rio;
- ASSERT(spa_syncing_txg(spa) == txg);
+ ASSERT3U(spa_syncing_txg(spa), ==, txg);
tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
@@ -1157,6 +1078,8 @@ ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde)
do {
do {
ddt_t *ddt = spa->spa_ddt[ddb->ddb_checksum];
+ if (ddt == NULL)
+ continue;
int error = ENOENT;
if (ddt_object_exists(ddt, ddb->ddb_type,
ddb->ddb_class)) {
@@ -1180,5 +1103,68 @@ ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde)
return (SET_ERROR(ENOENT));
}
+/*
+ * This function is used by Block Cloning (brt.c) to increase reference
+ * counter for the DDT entry if the block is already in DDT.
+ *
+ * Return false if the block, despite having the D bit set, is not present
+ * in the DDT. Currently this is not possible but might be in the future.
+ * See the comment below.
+ */
+boolean_t
+ddt_addref(spa_t *spa, const blkptr_t *bp)
+{
+ ddt_t *ddt;
+ ddt_entry_t *dde;
+ boolean_t result;
+
+ spa_config_enter(spa, SCL_ZIO, FTAG, RW_READER);
+ ddt = ddt_select(spa, bp);
+ ddt_enter(ddt);
+
+ dde = ddt_lookup(ddt, bp, B_TRUE);
+ ASSERT3P(dde, !=, NULL);
+
+ if (dde->dde_type < DDT_TYPES) {
+ ddt_phys_t *ddp;
+
+ ASSERT3S(dde->dde_class, <, DDT_CLASSES);
+
+ ddp = &dde->dde_phys[BP_GET_NDVAS(bp)];
+
+ /*
+ * This entry already existed (dde_type is real), so it must
+ * have refcnt >0 at the start of this txg. We are called from
+ * brt_pending_apply(), before frees are issued, so the refcnt
+ * can't be lowered yet. Therefore, it must be >0. We assert
+ * this because if the order of BRT and DDT interactions were
+ * ever to change and the refcnt was ever zero here, then
+ * likely further action is required to fill out the DDT entry,
+ * and this is a place that is likely to be missed in testing.
+ */
+ ASSERT3U(ddp->ddp_refcnt, >, 0);
+
+ ddt_phys_addref(ddp);
+ result = B_TRUE;
+ } else {
+ /*
+ * At the time of implementating this if the block has the
+ * DEDUP flag set it must exist in the DEDUP table, but
+ * there are many advocates that want ability to remove
+ * entries from DDT with refcnt=1. If this will happen,
+ * we may have a block with the DEDUP set, but which doesn't
+ * have a corresponding entry in the DDT. Be ready.
+ */
+ ASSERT3S(dde->dde_class, ==, DDT_CLASSES);
+ ddt_remove(ddt, dde);
+ result = B_FALSE;
+ }
+
+ ddt_exit(ddt);
+ spa_config_exit(spa, SCL_ZIO, FTAG);
+
+ return (result);
+}
+
ZFS_MODULE_PARAM(zfs_dedup, zfs_dedup_, prefetch, INT, ZMOD_RW,
"Enable prefetching dedup-ed blks");
diff --git a/module/zfs/ddt_stats.c b/module/zfs/ddt_stats.c
new file mode 100644
index 000000000000..af5365a1d114
--- /dev/null
+++ b/module/zfs/ddt_stats.c
@@ -0,0 +1,212 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2022 by Pawel Jakub Dawidek
+ * Copyright (c) 2023, Klara Inc.
+ */
+
+#include <sys/zfs_context.h>
+#include <sys/spa.h>
+#include <sys/spa_impl.h>
+#include <sys/ddt.h>
+#include <sys/ddt_impl.h>
+
+static void
+ddt_stat_generate(ddt_t *ddt, ddt_entry_t *dde, ddt_stat_t *dds)
+{
+ spa_t *spa = ddt->ddt_spa;
+ ddt_phys_t *ddp = dde->dde_phys;
+ ddt_key_t *ddk = &dde->dde_key;
+ uint64_t lsize = DDK_GET_LSIZE(ddk);
+ uint64_t psize = DDK_GET_PSIZE(ddk);
+
+ memset(dds, 0, sizeof (*dds));
+
+ for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
+ uint64_t dsize = 0;
+ uint64_t refcnt = ddp->ddp_refcnt;
+
+ if (ddp->ddp_phys_birth == 0)
+ continue;
+
+ int ndvas = DDK_GET_CRYPT(&dde->dde_key) ?
+ SPA_DVAS_PER_BP - 1 : SPA_DVAS_PER_BP;
+ for (int d = 0; d < ndvas; d++)
+ dsize += dva_get_dsize_sync(spa, &ddp->ddp_dva[d]);
+
+ dds->dds_blocks += 1;
+ dds->dds_lsize += lsize;
+ dds->dds_psize += psize;
+ dds->dds_dsize += dsize;
+
+ dds->dds_ref_blocks += refcnt;
+ dds->dds_ref_lsize += lsize * refcnt;
+ dds->dds_ref_psize += psize * refcnt;
+ dds->dds_ref_dsize += dsize * refcnt;
+ }
+}
+
+void
+ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src, uint64_t neg)
+{
+ const uint64_t *s = (const uint64_t *)src;
+ uint64_t *d = (uint64_t *)dst;
+ uint64_t *d_end = (uint64_t *)(dst + 1);
+
+ ASSERT(neg == 0 || neg == -1ULL); /* add or subtract */
+
+ for (int i = 0; i < d_end - d; i++)
+ d[i] += (s[i] ^ neg) - neg;
+}
+
+void
+ddt_stat_update(ddt_t *ddt, ddt_entry_t *dde, uint64_t neg)
+{
+ ddt_stat_t dds;
+ ddt_histogram_t *ddh;
+ int bucket;
+
+ ddt_stat_generate(ddt, dde, &dds);
+
+ bucket = highbit64(dds.dds_ref_blocks) - 1;
+ ASSERT3U(bucket, >=, 0);
+
+ ddh = &ddt->ddt_histogram[dde->dde_type][dde->dde_class];
+
+ ddt_stat_add(&ddh->ddh_stat[bucket], &dds, neg);
+}
+
+void
+ddt_histogram_add(ddt_histogram_t *dst, const ddt_histogram_t *src)
+{
+ for (int h = 0; h < 64; h++)
+ ddt_stat_add(&dst->ddh_stat[h], &src->ddh_stat[h], 0);
+}
+
+void
+ddt_histogram_stat(ddt_stat_t *dds, const ddt_histogram_t *ddh)
+{
+ memset(dds, 0, sizeof (*dds));
+
+ for (int h = 0; h < 64; h++)
+ ddt_stat_add(dds, &ddh->ddh_stat[h], 0);
+}
+
+boolean_t
+ddt_histogram_empty(const ddt_histogram_t *ddh)
+{
+ const uint64_t *s = (const uint64_t *)ddh;
+ const uint64_t *s_end = (const uint64_t *)(ddh + 1);
+
+ while (s < s_end)
+ if (*s++ != 0)
+ return (B_FALSE);
+
+ return (B_TRUE);
+}
+
+void
+ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo_total)
+{
+ /* Sum the statistics we cached in ddt_object_sync(). */
+ for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
+ ddt_t *ddt = spa->spa_ddt[c];
+ if (!ddt)
+ continue;
+
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES;
+ class++) {
+ ddt_object_t *ddo =
+ &ddt->ddt_object_stats[type][class];
+ ddo_total->ddo_count += ddo->ddo_count;
+ ddo_total->ddo_dspace += ddo->ddo_dspace;
+ ddo_total->ddo_mspace += ddo->ddo_mspace;
+ }
+ }
+ }
+
+ /* ... and compute the averages. */
+ if (ddo_total->ddo_count != 0) {
+ ddo_total->ddo_dspace /= ddo_total->ddo_count;
+ ddo_total->ddo_mspace /= ddo_total->ddo_count;
+ }
+}
+
+void
+ddt_get_dedup_histogram(spa_t *spa, ddt_histogram_t *ddh)
+{
+ for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
+ ddt_t *ddt = spa->spa_ddt[c];
+ if (!ddt)
+ continue;
+
+ for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
+ for (ddt_class_t class = 0; class < DDT_CLASSES;
+ class++) {
+ ddt_histogram_add(ddh,
+ &ddt->ddt_histogram_cache[type][class]);
+ }
+ }
+ }
+}
+
+void
+ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total)
+{
+ ddt_histogram_t *ddh_total;
+
+ ddh_total = kmem_zalloc(sizeof (ddt_histogram_t), KM_SLEEP);
+ ddt_get_dedup_histogram(spa, ddh_total);
+ ddt_histogram_stat(dds_total, ddh_total);
+ kmem_free(ddh_total, sizeof (ddt_histogram_t));
+}
+
+uint64_t
+ddt_get_dedup_dspace(spa_t *spa)
+{
+ ddt_stat_t dds_total;
+
+ if (spa->spa_dedup_dspace != ~0ULL)
+ return (spa->spa_dedup_dspace);
+
+ memset(&dds_total, 0, sizeof (ddt_stat_t));
+
+ /* Calculate and cache the stats */
+ ddt_get_dedup_stats(spa, &dds_total);
+ spa->spa_dedup_dspace = dds_total.dds_ref_dsize - dds_total.dds_dsize;
+ return (spa->spa_dedup_dspace);
+}
+
+uint64_t
+ddt_get_pool_dedup_ratio(spa_t *spa)
+{
+ ddt_stat_t dds_total = { 0 };
+
+ ddt_get_dedup_stats(spa, &dds_total);
+ if (dds_total.dds_dsize == 0)
+ return (100);
+
+ return (dds_total.dds_ref_dsize * 100 / dds_total.dds_dsize);
+}
diff --git a/module/zfs/ddt_zap.c b/module/zfs/ddt_zap.c
index d0127f22e5ff..741554de3c60 100644
--- a/module/zfs/ddt_zap.c
+++ b/module/zfs/ddt_zap.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,11 +28,60 @@
#include <sys/spa.h>
#include <sys/zio.h>
#include <sys/ddt.h>
+#include <sys/ddt_impl.h>
#include <sys/zap.h>
#include <sys/dmu_tx.h>
+#include <sys/zio_compress.h>
-static const int ddt_zap_leaf_blockshift = 12;
-static const int ddt_zap_indirect_blockshift = 12;
+static unsigned int ddt_zap_default_bs = 15;
+static unsigned int ddt_zap_default_ibs = 15;
+
+#define DDT_ZAP_COMPRESS_BYTEORDER_MASK 0x80
+#define DDT_ZAP_COMPRESS_FUNCTION_MASK 0x7f
+
+#define DDT_KEY_WORDS (sizeof (ddt_key_t) / sizeof (uint64_t))
+
+static size_t
+ddt_zap_compress(const void *src, uchar_t *dst, size_t s_len, size_t d_len)
+{
+ uchar_t *version = dst++;
+ int cpfunc = ZIO_COMPRESS_ZLE;
+ zio_compress_info_t *ci = &zio_compress_table[cpfunc];
+ size_t c_len;
+
+ ASSERT3U(d_len, >=, s_len + 1); /* no compression plus version byte */
+
+ c_len = ci->ci_compress((void *)src, dst, s_len, d_len - 1,
+ ci->ci_level);
+
+ if (c_len == s_len) {
+ cpfunc = ZIO_COMPRESS_OFF;
+ memcpy(dst, src, s_len);
+ }
+
+ *version = cpfunc;
+ if (ZFS_HOST_BYTEORDER)
+ *version |= DDT_ZAP_COMPRESS_BYTEORDER_MASK;
+
+ return (c_len + 1);
+}
+
+static void
+ddt_zap_decompress(uchar_t *src, void *dst, size_t s_len, size_t d_len)
+{
+ uchar_t version = *src++;
+ int cpfunc = version & DDT_ZAP_COMPRESS_FUNCTION_MASK;
+ zio_compress_info_t *ci = &zio_compress_table[cpfunc];
+
+ if (ci->ci_decompress != NULL)
+ (void) ci->ci_decompress(src, dst, s_len, d_len, ci->ci_level);
+ else
+ memcpy(dst, src, d_len);
+
+ if (((version & DDT_ZAP_COMPRESS_BYTEORDER_MASK) != 0) !=
+ (ZFS_HOST_BYTEORDER != 0))
+ byteswap_uint64_array(dst, d_len);
+}
static int
ddt_zap_create(objset_t *os, uint64_t *objectp, dmu_tx_t *tx, boolean_t prehash)
@@ -43,10 +92,12 @@ ddt_zap_create(objset_t *os, uint64_t *objectp, dmu_tx_t *tx, boolean_t prehash)
flags |= ZAP_FLAG_PRE_HASHED_KEY;
*objectp = zap_create_flags(os, 0, flags, DMU_OT_DDT_ZAP,
- ddt_zap_leaf_blockshift, ddt_zap_indirect_blockshift,
+ ddt_zap_default_bs, ddt_zap_default_ibs,
DMU_OT_NONE, 0, tx);
+ if (*objectp == 0)
+ return (SET_ERROR(ENOTSUP));
- return (*objectp == 0 ? SET_ERROR(ENOTSUP) : 0);
+ return (0);
}
static int
@@ -56,63 +107,75 @@ ddt_zap_destroy(objset_t *os, uint64_t object, dmu_tx_t *tx)
}
static int
-ddt_zap_lookup(objset_t *os, uint64_t object, ddt_entry_t *dde)
+ddt_zap_lookup(objset_t *os, uint64_t object,
+ const ddt_key_t *ddk, ddt_phys_t *phys, size_t psize)
{
uchar_t *cbuf;
uint64_t one, csize;
int error;
- cbuf = kmem_alloc(sizeof (dde->dde_phys) + 1, KM_SLEEP);
-
- error = zap_length_uint64(os, object, (uint64_t *)&dde->dde_key,
+ error = zap_length_uint64(os, object, (uint64_t *)ddk,
DDT_KEY_WORDS, &one, &csize);
if (error)
- goto out;
+ return (error);
- ASSERT(one == 1);
- ASSERT(csize <= (sizeof (dde->dde_phys) + 1));
+ ASSERT3U(one, ==, 1);
+ ASSERT3U(csize, <=, psize + 1);
- error = zap_lookup_uint64(os, object, (uint64_t *)&dde->dde_key,
+ cbuf = kmem_alloc(csize, KM_SLEEP);
+
+ error = zap_lookup_uint64(os, object, (uint64_t *)ddk,
DDT_KEY_WORDS, 1, csize, cbuf);
- if (error)
- goto out;
+ if (error == 0)
+ ddt_zap_decompress(cbuf, phys, csize, psize);
- ddt_decompress(cbuf, dde->dde_phys, csize, sizeof (dde->dde_phys));
-out:
- kmem_free(cbuf, sizeof (dde->dde_phys) + 1);
+ kmem_free(cbuf, csize);
return (error);
}
+static int
+ddt_zap_contains(objset_t *os, uint64_t object, const ddt_key_t *ddk)
+{
+ return (zap_length_uint64(os, object, (uint64_t *)ddk, DDT_KEY_WORDS,
+ NULL, NULL));
+}
+
static void
-ddt_zap_prefetch(objset_t *os, uint64_t object, ddt_entry_t *dde)
+ddt_zap_prefetch(objset_t *os, uint64_t object, const ddt_key_t *ddk)
{
- (void) zap_prefetch_uint64(os, object, (uint64_t *)&dde->dde_key,
- DDT_KEY_WORDS);
+ (void) zap_prefetch_uint64(os, object, (uint64_t *)ddk, DDT_KEY_WORDS);
}
static int
-ddt_zap_update(objset_t *os, uint64_t object, ddt_entry_t *dde, dmu_tx_t *tx)
+ddt_zap_update(objset_t *os, uint64_t object, const ddt_key_t *ddk,
+ const ddt_phys_t *phys, size_t psize, dmu_tx_t *tx)
{
- uchar_t cbuf[sizeof (dde->dde_phys) + 1];
- uint64_t csize;
+ const size_t cbuf_size = psize + 1;
+
+ uchar_t *cbuf = kmem_alloc(cbuf_size, KM_SLEEP);
+
+ uint64_t csize = ddt_zap_compress(phys, cbuf, psize, cbuf_size);
- csize = ddt_compress(dde->dde_phys, cbuf,
- sizeof (dde->dde_phys), sizeof (cbuf));
+ int error = zap_update_uint64(os, object, (uint64_t *)ddk,
+ DDT_KEY_WORDS, 1, csize, cbuf, tx);
- return (zap_update_uint64(os, object, (uint64_t *)&dde->dde_key,
- DDT_KEY_WORDS, 1, csize, cbuf, tx));
+ kmem_free(cbuf, cbuf_size);
+
+ return (error);
}
static int
-ddt_zap_remove(objset_t *os, uint64_t object, ddt_entry_t *dde, dmu_tx_t *tx)
+ddt_zap_remove(objset_t *os, uint64_t object, const ddt_key_t *ddk,
+ dmu_tx_t *tx)
{
- return (zap_remove_uint64(os, object, (uint64_t *)&dde->dde_key,
+ return (zap_remove_uint64(os, object, (uint64_t *)ddk,
DDT_KEY_WORDS, tx));
}
static int
-ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
+ddt_zap_walk(objset_t *os, uint64_t object, uint64_t *walk, ddt_key_t *ddk,
+ ddt_phys_t *phys, size_t psize)
{
zap_cursor_t zc;
zap_attribute_t za;
@@ -131,17 +194,23 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
zap_cursor_init_serialized(&zc, os, object, *walk);
}
if ((error = zap_cursor_retrieve(&zc, &za)) == 0) {
- uchar_t cbuf[sizeof (dde->dde_phys) + 1];
uint64_t csize = za.za_num_integers;
- ASSERT(za.za_integer_length == 1);
+
+ ASSERT3U(za.za_integer_length, ==, 1);
+ ASSERT3U(csize, <=, psize + 1);
+
+ uchar_t *cbuf = kmem_alloc(csize, KM_SLEEP);
+
error = zap_lookup_uint64(os, object, (uint64_t *)za.za_name,
DDT_KEY_WORDS, 1, csize, cbuf);
- ASSERT(error == 0);
+ ASSERT0(error);
if (error == 0) {
- ddt_decompress(cbuf, dde->dde_phys, csize,
- sizeof (dde->dde_phys));
- dde->dde_key = *(ddt_key_t *)za.za_name;
+ ddt_zap_decompress(cbuf, phys, csize, psize);
+ *ddk = *(ddt_key_t *)za.za_name;
}
+
+ kmem_free(cbuf, csize);
+
zap_cursor_advance(&zc);
*walk = zap_cursor_serialize(&zc);
}
@@ -160,9 +229,17 @@ const ddt_ops_t ddt_zap_ops = {
ddt_zap_create,
ddt_zap_destroy,
ddt_zap_lookup,
+ ddt_zap_contains,
ddt_zap_prefetch,
ddt_zap_update,
ddt_zap_remove,
ddt_zap_walk,
ddt_zap_count,
};
+
+/* BEGIN CSTYLED */
+ZFS_MODULE_PARAM(zfs_dedup, , ddt_zap_default_bs, UINT, ZMOD_RW,
+ "DDT ZAP leaf blockshift");
+ZFS_MODULE_PARAM(zfs_dedup, , ddt_zap_default_ibs, UINT, ZMOD_RW,
+ "DDT ZAP indirect blockshift");
+/* END CSTYLED */
diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c
index e6008b3bf178..6ef149aab9a6 100644
--- a/module/zfs/dmu.c
+++ b/module/zfs/dmu.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,6 +28,8 @@
* Copyright (c) 2019 Datto Inc.
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
+ * Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
+ * Copyright (c) 2021, 2022 by Pawel Jakub Dawidek
*/
#include <sys/dmu.h>
@@ -51,6 +53,7 @@
#include <sys/sa.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
+#include <sys/brt.h>
#include <sys/trace_zfs.h>
#include <sys/zfs_racct.h>
#include <sys/zfs_rlock.h>
@@ -70,7 +73,7 @@ static int zfs_nopwrite_enabled = 1;
* will wait until the next TXG.
* A value of zero will disable this throttle.
*/
-static unsigned long zfs_per_txg_dirty_frees_percent = 5;
+static uint_t zfs_per_txg_dirty_frees_percent = 30;
/*
* Enable/disable forcing txg sync when dirty checking for holes with lseek().
@@ -86,7 +89,11 @@ static int zfs_dmu_offset_next_sync = 1;
* helps to limit the amount of memory that can be used by prefetching.
* Larger objects should be prefetched a bit at a time.
*/
-int dmu_prefetch_max = 8 * SPA_MAXBLOCKSIZE;
+#ifdef _ILP32
+uint_t dmu_prefetch_max = 8 * 1024 * 1024;
+#else
+uint_t dmu_prefetch_max = 8 * SPA_MAXBLOCKSIZE;
+#endif
const dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES] = {
{DMU_BSWAP_UINT8, TRUE, FALSE, FALSE, "unallocated" },
@@ -145,7 +152,7 @@ const dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES] = {
{DMU_BSWAP_UINT64, TRUE, FALSE, FALSE, "bpobj subobj" }
};
-const dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS] = {
+dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS] = {
{ byteswap_uint8_array, "uint8" },
{ byteswap_uint16_array, "uint16" },
{ byteswap_uint32_array, "uint32" },
@@ -158,7 +165,7 @@ const dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS] = {
{ zfs_acl_byteswap, "acl" }
};
-static int
+int
dmu_buf_hold_noread_by_dnode(dnode_t *dn, uint64_t offset,
const void *tag, dmu_buf_t **dbp)
{
@@ -178,6 +185,7 @@ dmu_buf_hold_noread_by_dnode(dnode_t *dn, uint64_t offset,
*dbp = &db->db;
return (0);
}
+
int
dmu_buf_hold_noread(objset_t *os, uint64_t object, uint64_t offset,
const void *tag, dmu_buf_t **dbp)
@@ -356,8 +364,10 @@ int dmu_bonus_hold_by_dnode(dnode_t *dn, const void *tag, dmu_buf_t **dbp,
rw_enter(&dn->dn_struct_rwlock, RW_READER);
if (dn->dn_bonus == NULL) {
- rw_exit(&dn->dn_struct_rwlock);
- rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
+ if (!rw_tryupgrade(&dn->dn_struct_rwlock)) {
+ rw_exit(&dn->dn_struct_rwlock);
+ rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
+ }
if (dn->dn_bonus == NULL)
dbuf_create_bonus(dn);
}
@@ -510,7 +520,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
zio_t *zio = NULL;
boolean_t missed = B_FALSE;
- ASSERT(length <= DMU_MAX_ACCESS);
+ ASSERT(!read || length <= DMU_MAX_ACCESS);
/*
* Note: We directly notify the prefetch code of this read, so that
@@ -520,6 +530,9 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT |
DB_RF_NOPREFETCH;
+ if ((flags & DMU_READ_NO_DECRYPT) != 0)
+ dbuf_flags |= DB_RF_NO_DECRYPT;
+
rw_enter(&dn->dn_struct_rwlock, RW_READER);
if (dn->dn_datablkshift) {
int blkshift = dn->dn_datablkshift;
@@ -544,21 +557,22 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
zio = zio_root(dn->dn_objset->os_spa, NULL, NULL,
ZIO_FLAG_CANFAIL);
blkid = dbuf_whichblock(dn, 0, offset);
- if ((flags & DMU_READ_NO_PREFETCH) == 0 &&
- DNODE_META_IS_CACHEABLE(dn) && length <= zfetch_array_rd_sz) {
+ if ((flags & DMU_READ_NO_PREFETCH) == 0) {
/*
* Prepare the zfetch before initiating the demand reads, so
* that if multiple threads block on same indirect block, we
* base predictions on the original less racy request order.
*/
- zs = dmu_zfetch_prepare(&dn->dn_zfetch, blkid, nblks,
- read && DNODE_IS_CACHEABLE(dn), B_TRUE);
+ zs = dmu_zfetch_prepare(&dn->dn_zfetch, blkid, nblks, read,
+ B_TRUE);
}
for (i = 0; i < nblks; i++) {
dmu_buf_impl_t *db = dbuf_hold(dn, blkid + i, tag);
if (db == NULL) {
- if (zs)
- dmu_zfetch_run(zs, missed, B_TRUE);
+ if (zs) {
+ dmu_zfetch_run(&dn->dn_zfetch, zs, missed,
+ B_TRUE);
+ }
rw_exit(&dn->dn_struct_rwlock);
dmu_buf_rele_array(dbp, nblks, tag);
if (read)
@@ -575,6 +589,14 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
* state will not yet be CACHED.
*/
if (read) {
+ if (i == nblks - 1 && blkid + i < dn->dn_maxblkid &&
+ offset + length < db->db.db_offset +
+ db->db.db_size) {
+ if (offset <= db->db.db_offset)
+ dbuf_flags |= DB_RF_PARTIAL_FIRST;
+ else
+ dbuf_flags |= DB_RF_PARTIAL_MORE;
+ }
(void) dbuf_read(db, zio, dbuf_flags);
if (db->db_state != DB_CACHED)
missed = B_TRUE;
@@ -586,7 +608,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
zfs_racct_write(length, nblks);
if (zs)
- dmu_zfetch_run(zs, missed, B_TRUE);
+ dmu_zfetch_run(&dn->dn_zfetch, zs, missed, B_TRUE);
rw_exit(&dn->dn_struct_rwlock);
if (read) {
@@ -675,72 +697,99 @@ dmu_buf_rele_array(dmu_buf_t **dbp_fake, int numbufs, const void *tag)
}
/*
- * Issue prefetch i/os for the given blocks. If level is greater than 0, the
+ * Issue prefetch I/Os for the given blocks. If level is greater than 0, the
* indirect blocks prefetched will be those that point to the blocks containing
- * the data starting at offset, and continuing to offset + len.
+ * the data starting at offset, and continuing to offset + len. If the range
+ * it too long, prefetch the first dmu_prefetch_max bytes as requested, while
+ * for the rest only a higher level, also fitting within dmu_prefetch_max. It
+ * should primarily help random reads, since for long sequential reads there is
+ * a speculative prefetcher.
*
* Note that if the indirect blocks above the blocks being prefetched are not
- * in cache, they will be asynchronously read in.
+ * in cache, they will be asynchronously read in. Dnode read by dnode_hold()
+ * is currently synchronous.
*/
void
dmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
uint64_t len, zio_priority_t pri)
{
dnode_t *dn;
- uint64_t blkid;
- int nblks, err;
-
- if (len == 0) { /* they're interested in the bonus buffer */
- dn = DMU_META_DNODE(os);
- if (object == 0 || object >= DN_MAX_OBJECT)
- return;
-
- rw_enter(&dn->dn_struct_rwlock, RW_READER);
- blkid = dbuf_whichblock(dn, level,
- object * sizeof (dnode_phys_t));
- dbuf_prefetch(dn, level, blkid, pri, 0);
- rw_exit(&dn->dn_struct_rwlock);
+ if (dmu_prefetch_max == 0 || len == 0) {
+ dmu_prefetch_dnode(os, object, pri);
return;
}
- /*
- * See comment before the definition of dmu_prefetch_max.
- */
- len = MIN(len, dmu_prefetch_max);
-
- /*
- * XXX - Note, if the dnode for the requested object is not
- * already cached, we will do a *synchronous* read in the
- * dnode_hold() call. The same is true for any indirects.
- */
- err = dnode_hold(os, object, FTAG, &dn);
- if (err != 0)
+ if (dnode_hold(os, object, FTAG, &dn) != 0)
return;
+ dmu_prefetch_by_dnode(dn, level, offset, len, pri);
+
+ dnode_rele(dn, FTAG);
+}
+
+void
+dmu_prefetch_by_dnode(dnode_t *dn, int64_t level, uint64_t offset,
+ uint64_t len, zio_priority_t pri)
+{
+ int64_t level2 = level;
+ uint64_t start, end, start2, end2;
+
/*
- * offset + len - 1 is the last byte we want to prefetch for, and offset
- * is the first. Then dbuf_whichblk(dn, level, off + len - 1) is the
- * last block we want to prefetch, and dbuf_whichblock(dn, level,
- * offset) is the first. Then the number we need to prefetch is the
- * last - first + 1.
+ * Depending on len we may do two prefetches: blocks [start, end) at
+ * level, and following blocks [start2, end2) at higher level2.
*/
rw_enter(&dn->dn_struct_rwlock, RW_READER);
- if (level > 0 || dn->dn_datablkshift != 0) {
- nblks = dbuf_whichblock(dn, level, offset + len - 1) -
- dbuf_whichblock(dn, level, offset) + 1;
+ if (dn->dn_datablkshift != 0) {
+ /*
+ * The object has multiple blocks. Calculate the full range
+ * of blocks [start, end2) and then split it into two parts,
+ * so that the first [start, end) fits into dmu_prefetch_max.
+ */
+ start = dbuf_whichblock(dn, level, offset);
+ end2 = dbuf_whichblock(dn, level, offset + len - 1) + 1;
+ uint8_t ibs = dn->dn_indblkshift;
+ uint8_t bs = (level == 0) ? dn->dn_datablkshift : ibs;
+ uint_t limit = P2ROUNDUP(dmu_prefetch_max, 1 << bs) >> bs;
+ start2 = end = MIN(end2, start + limit);
+
+ /*
+ * Find level2 where [start2, end2) fits into dmu_prefetch_max.
+ */
+ uint8_t ibps = ibs - SPA_BLKPTRSHIFT;
+ limit = P2ROUNDUP(dmu_prefetch_max, 1 << ibs) >> ibs;
+ do {
+ level2++;
+ start2 = P2ROUNDUP(start2, 1 << ibps) >> ibps;
+ end2 = P2ROUNDUP(end2, 1 << ibps) >> ibps;
+ } while (end2 - start2 > limit);
} else {
- nblks = (offset < dn->dn_datablksz);
+ /* There is only one block. Prefetch it or nothing. */
+ start = start2 = end2 = 0;
+ end = start + (level == 0 && offset < dn->dn_datablksz);
}
- if (nblks != 0) {
- blkid = dbuf_whichblock(dn, level, offset);
- for (int i = 0; i < nblks; i++)
- dbuf_prefetch(dn, level, blkid + i, pri, 0);
- }
+ for (uint64_t i = start; i < end; i++)
+ dbuf_prefetch(dn, level, i, pri, 0);
+ for (uint64_t i = start2; i < end2; i++)
+ dbuf_prefetch(dn, level2, i, pri, 0);
rw_exit(&dn->dn_struct_rwlock);
+}
- dnode_rele(dn, FTAG);
+/*
+ * Issue prefetch I/Os for the given object's dnode.
+ */
+void
+dmu_prefetch_dnode(objset_t *os, uint64_t object, zio_priority_t pri)
+{
+ if (object == 0 || object >= DN_MAX_OBJECT)
+ return;
+
+ dnode_t *dn = DMU_META_DNODE(os);
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
+ uint64_t blkid = dbuf_whichblock(dn, 0, object * sizeof (dnode_phys_t));
+ dbuf_prefetch(dn, 0, blkid, pri, 0);
+ rw_exit(&dn->dn_struct_rwlock);
}
/*
@@ -1095,14 +1144,14 @@ dmu_write_impl(dmu_buf_t **dbp, int numbufs, uint64_t offset, uint64_t size,
ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
if (tocpy == db->db_size)
- dmu_buf_will_fill(db, tx);
+ dmu_buf_will_fill(db, tx, B_FALSE);
else
dmu_buf_will_dirty(db, tx);
(void) memcpy((char *)db->db_data + bufoff, buf, tocpy);
if (tocpy == db->db_size)
- dmu_buf_fill_done(db, tx);
+ dmu_buf_fill_done(db, tx, B_FALSE);
offset += tocpy;
size -= tocpy;
@@ -1310,27 +1359,24 @@ dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx)
ASSERT(size > 0);
- bufoff = zfs_uio_offset(uio) - db->db_offset;
+ offset_t off = zfs_uio_offset(uio);
+ bufoff = off - db->db_offset;
tocpy = MIN(db->db_size - bufoff, size);
ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
if (tocpy == db->db_size)
- dmu_buf_will_fill(db, tx);
+ dmu_buf_will_fill(db, tx, B_TRUE);
else
dmu_buf_will_dirty(db, tx);
- /*
- * XXX zfs_uiomove could block forever (eg.nfs-backed
- * pages). There needs to be a uiolockdown() function
- * to lock the pages in memory, so that zfs_uiomove won't
- * block.
- */
err = zfs_uio_fault_move((char *)db->db_data + bufoff,
tocpy, UIO_WRITE, uio);
- if (tocpy == db->db_size)
- dmu_buf_fill_done(db, tx);
+ if (tocpy == db->db_size && dmu_buf_fill_done(db, tx, err)) {
+ /* The fill was reverted. Undo any uio progress. */
+ zfs_uio_advance(uio, off - zfs_uio_offset(uio));
+ }
if (err)
break;
@@ -1432,7 +1478,7 @@ dmu_return_arcbuf(arc_buf_t *buf)
*/
int
dmu_lightweight_write_by_dnode(dnode_t *dn, uint64_t offset, abd_t *abd,
- const zio_prop_t *zp, enum zio_flag flags, dmu_tx_t *tx)
+ const zio_prop_t *zp, zio_flag_t flags, dmu_tx_t *tx)
{
dbuf_dirty_record_t *dr =
dbuf_dirty_lightweight(dn, dbuf_whichblock(dn, 0, offset), tx);
@@ -1462,9 +1508,9 @@ dmu_assign_arcbuf_by_dnode(dnode_t *dn, uint64_t offset, arc_buf_t *buf,
rw_enter(&dn->dn_struct_rwlock, RW_READER);
blkid = dbuf_whichblock(dn, 0, offset);
db = dbuf_hold(dn, blkid, FTAG);
+ rw_exit(&dn->dn_struct_rwlock);
if (db == NULL)
return (SET_ERROR(EIO));
- rw_exit(&dn->dn_struct_rwlock);
/*
* We can only assign if the offset is aligned and the arc buf is the
@@ -1583,7 +1629,7 @@ dmu_sync_done(zio_t *zio, arc_buf_t *buf, void *varg)
* it's an old style hole.
*/
if (BP_IS_HOLE(&dr->dt.dl.dr_overridden_by) &&
- dr->dt.dl.dr_overridden_by.blk_birth == 0)
+ BP_GET_LOGICAL_BIRTH(&dr->dt.dl.dr_overridden_by) == 0)
BP_ZERO(&dr->dt.dl.dr_overridden_by);
} else {
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
@@ -1614,7 +1660,7 @@ dmu_sync_late_arrival_done(zio_t *zio)
blkptr_t *bp_orig __maybe_unused = &zio->io_bp_orig;
ASSERT(!(zio->io_flags & ZIO_FLAG_NOPWRITE));
ASSERT(BP_IS_HOLE(bp_orig) || !BP_EQUAL(bp, bp_orig));
- ASSERT(zio->io_bp->blk_birth == zio->io_txg);
+ ASSERT(BP_GET_LOGICAL_BIRTH(zio->io_bp) == zio->io_txg);
ASSERT(zio->io_txg > spa_syncing_txg(zio->io_spa));
zio_free(zio->io_spa, zio->io_txg, zio->io_bp);
}
@@ -1634,10 +1680,22 @@ dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
{
dmu_sync_arg_t *dsa;
dmu_tx_t *tx;
+ int error;
+
+ error = dbuf_read((dmu_buf_impl_t *)zgd->zgd_db, NULL,
+ DB_RF_CANFAIL | DB_RF_NOPREFETCH);
+ if (error != 0)
+ return (error);
tx = dmu_tx_create(os);
dmu_tx_hold_space(tx, zgd->zgd_db->db_size);
- if (dmu_tx_assign(tx, TXG_WAIT) != 0) {
+ /*
+ * This transaction does not produce any dirty data or log blocks, so
+ * it should not be throttled. All other cases wait for TXG sync, by
+ * which time the log block we are writing will be obsolete, so we can
+ * skip waiting and just return error here instead.
+ */
+ if (dmu_tx_assign(tx, TXG_NOWAIT | TXG_NOTHROTTLE) != 0) {
dmu_tx_abort(tx);
/* Make zl_get_data do txg_waited_synced() */
return (SET_ERROR(EIO));
@@ -1682,7 +1740,7 @@ dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx), zgd->zgd_bp,
abd_get_from_buf(zgd->zgd_db->db_data, zgd->zgd_db->db_size),
zgd->zgd_db->db_size, zgd->zgd_db->db_size, zp,
- dmu_sync_late_arrival_ready, NULL, NULL, dmu_sync_late_arrival_done,
+ dmu_sync_late_arrival_ready, NULL, dmu_sync_late_arrival_done,
dsa, ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, zb));
return (0);
@@ -1846,9 +1904,9 @@ dmu_sync(zio_t *pio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd)
dsa->dsa_zgd = zgd;
dsa->dsa_tx = NULL;
- zio_nowait(arc_write(pio, os->os_spa, txg,
- zgd->zgd_bp, dr->dt.dl.dr_data, dbuf_is_l2cacheable(db),
- &zp, dmu_sync_ready, NULL, NULL, dmu_sync_done, dsa,
+ zio_nowait(arc_write(pio, os->os_spa, txg, zgd->zgd_bp,
+ dr->dt.dl.dr_data, !DBUF_IS_CACHEABLE(db), dbuf_is_l2cacheable(db),
+ &zp, dmu_sync_ready, NULL, dmu_sync_done, dsa,
ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
return (0);
@@ -1989,12 +2047,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);
@@ -2090,18 +2158,18 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp)
}
/*
- * This function is only called from zfs_holey_common() for zpl_llseek()
- * in order to determine the location of holes. In order to accurately
- * report holes all dirty data must be synced to disk. This causes extremely
- * poor performance when seeking for holes in a dirty file. As a compromise,
- * only provide hole data when the dnode is clean. When a dnode is dirty
- * report the dnode as having no holes which is always a safe thing to do.
+ * Reports the location of data and holes in an object. In order to
+ * accurately report holes all dirty data must be synced to disk. This
+ * causes extremely poor performance when seeking for holes in a dirty file.
+ * As a compromise, only provide hole data when the dnode is clean. When
+ * a dnode is dirty report the dnode as having no holes by returning EBUSY
+ * which is always safe to do.
*/
int
dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
{
dnode_t *dn;
- int err;
+ int restarted = 0, err;
restart:
err = dnode_hold(os, object, FTAG, &dn);
@@ -2113,19 +2181,23 @@ restart:
if (dnode_is_dirty(dn)) {
/*
* If the zfs_dmu_offset_next_sync module option is enabled
- * then strict hole reporting has been requested. Dirty
- * dnodes must be synced to disk to accurately report all
- * holes. When disabled dirty dnodes are reported to not
- * have any holes which is always safe.
+ * then hole reporting has been requested. Dirty dnodes
+ * must be synced to disk to accurately report holes.
*
- * When called by zfs_holey_common() the zp->z_rangelock
- * is held to prevent zfs_write() and mmap writeback from
- * re-dirtying the dnode after txg_wait_synced().
+ * Provided a RL_READER rangelock spanning 0-UINT64_MAX is
+ * held by the caller only a single restart will be required.
+ * We tolerate callers which do not hold the rangelock by
+ * returning EBUSY and not reporting holes after one restart.
*/
if (zfs_dmu_offset_next_sync) {
rw_exit(&dn->dn_struct_rwlock);
dnode_rele(dn, FTAG);
+
+ if (restarted)
+ return (SET_ERROR(EBUSY));
+
txg_wait_synced(dmu_objset_pool(os), 0);
+ restarted = 1;
goto restart;
}
@@ -2141,6 +2213,187 @@ restart:
return (err);
}
+int
+dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
+ blkptr_t *bps, size_t *nbpsp)
+{
+ dmu_buf_t **dbp, *dbuf;
+ dmu_buf_impl_t *db;
+ blkptr_t *bp;
+ int error, numbufs;
+
+ error = dmu_buf_hold_array(os, object, offset, length, FALSE, FTAG,
+ &numbufs, &dbp);
+ if (error != 0) {
+ if (error == ESRCH) {
+ error = SET_ERROR(ENXIO);
+ }
+ return (error);
+ }
+
+ ASSERT3U(numbufs, <=, *nbpsp);
+
+ for (int i = 0; i < numbufs; i++) {
+ dbuf = dbp[i];
+ db = (dmu_buf_impl_t *)dbuf;
+
+ mutex_enter(&db->db_mtx);
+
+ if (!list_is_empty(&db->db_dirty_records)) {
+ dbuf_dirty_record_t *dr;
+
+ dr = list_head(&db->db_dirty_records);
+ if (dr->dt.dl.dr_brtwrite) {
+ /*
+ * This is very special case where we clone a
+ * block and in the same transaction group we
+ * read its BP (most likely to clone the clone).
+ */
+ bp = &dr->dt.dl.dr_overridden_by;
+ } else {
+ /*
+ * The block was modified in the same
+ * transaction group.
+ */
+ mutex_exit(&db->db_mtx);
+ error = SET_ERROR(EAGAIN);
+ goto out;
+ }
+ } else {
+ bp = db->db_blkptr;
+ }
+
+ mutex_exit(&db->db_mtx);
+
+ if (bp == NULL) {
+ /*
+ * The file size was increased, but the block was never
+ * written, otherwise we would either have the block
+ * pointer or the dirty record and would not get here.
+ * It is effectively a hole, so report it as such.
+ */
+ BP_ZERO(&bps[i]);
+ continue;
+ }
+ /*
+ * Make sure we clone only data blocks.
+ */
+ if (BP_IS_METADATA(bp) && !BP_IS_HOLE(bp)) {
+ error = SET_ERROR(EINVAL);
+ goto out;
+ }
+
+ /*
+ * If the block was allocated in transaction group that is not
+ * yet synced, we could clone it, but we couldn't write this
+ * operation into ZIL, or it may be impossible to replay, since
+ * the block may appear not yet allocated at that point.
+ */
+ if (BP_GET_BIRTH(bp) > spa_freeze_txg(os->os_spa)) {
+ error = SET_ERROR(EINVAL);
+ goto out;
+ }
+ if (BP_GET_BIRTH(bp) > spa_last_synced_txg(os->os_spa)) {
+ error = SET_ERROR(EAGAIN);
+ goto out;
+ }
+
+ bps[i] = *bp;
+ }
+
+ *nbpsp = numbufs;
+out:
+ dmu_buf_rele_array(dbp, numbufs, FTAG);
+
+ return (error);
+}
+
+int
+dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
+ dmu_tx_t *tx, const blkptr_t *bps, size_t nbps)
+{
+ spa_t *spa;
+ dmu_buf_t **dbp, *dbuf;
+ dmu_buf_impl_t *db;
+ struct dirty_leaf *dl;
+ dbuf_dirty_record_t *dr;
+ const blkptr_t *bp;
+ int error = 0, i, numbufs;
+
+ spa = os->os_spa;
+
+ VERIFY0(dmu_buf_hold_array(os, object, offset, length, FALSE, FTAG,
+ &numbufs, &dbp));
+ ASSERT3U(nbps, ==, numbufs);
+
+ /*
+ * Before we start cloning make sure that the dbufs sizes match new BPs
+ * sizes. If they don't, that's a no-go, as we are not able to shrink
+ * dbufs.
+ */
+ for (i = 0; i < numbufs; i++) {
+ dbuf = dbp[i];
+ db = (dmu_buf_impl_t *)dbuf;
+ bp = &bps[i];
+
+ ASSERT0(db->db_level);
+ ASSERT(db->db_blkid != DMU_BONUS_BLKID);
+ ASSERT(db->db_blkid != DMU_SPILL_BLKID);
+
+ if (!BP_IS_HOLE(bp) && BP_GET_LSIZE(bp) != dbuf->db_size) {
+ error = SET_ERROR(EXDEV);
+ goto out;
+ }
+ }
+
+ for (i = 0; i < numbufs; i++) {
+ dbuf = dbp[i];
+ db = (dmu_buf_impl_t *)dbuf;
+ bp = &bps[i];
+
+ ASSERT0(db->db_level);
+ ASSERT(db->db_blkid != DMU_BONUS_BLKID);
+ ASSERT(db->db_blkid != DMU_SPILL_BLKID);
+ ASSERT(BP_IS_HOLE(bp) || dbuf->db_size == BP_GET_LSIZE(bp));
+
+ dmu_buf_will_clone(dbuf, tx);
+
+ mutex_enter(&db->db_mtx);
+
+ dr = list_head(&db->db_dirty_records);
+ VERIFY(dr != NULL);
+ ASSERT3U(dr->dr_txg, ==, tx->tx_txg);
+ dl = &dr->dt.dl;
+ dl->dr_overridden_by = *bp;
+ if (!BP_IS_HOLE(bp) || BP_GET_LOGICAL_BIRTH(bp) != 0) {
+ if (!BP_IS_EMBEDDED(bp)) {
+ BP_SET_BIRTH(&dl->dr_overridden_by, dr->dr_txg,
+ BP_GET_BIRTH(bp));
+ } else {
+ BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by,
+ dr->dr_txg);
+ }
+ }
+ dl->dr_brtwrite = B_TRUE;
+ dl->dr_override_state = DR_OVERRIDDEN;
+
+ mutex_exit(&db->db_mtx);
+
+ /*
+ * When data in embedded into BP there is no need to create
+ * BRT entry as there is no data block. Just copy the BP as
+ * it contains the data.
+ */
+ if (!BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp)) {
+ brt_pending_add(spa, bp, tx);
+ }
+ }
+out:
+ dmu_buf_rele_array(dbp, numbufs, FTAG);
+
+ return (error);
+}
+
void
__dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
{
@@ -2321,6 +2574,8 @@ EXPORT_SYMBOL(dmu_bonus_hold_by_dnode);
EXPORT_SYMBOL(dmu_buf_hold_array_by_bonus);
EXPORT_SYMBOL(dmu_buf_rele_array);
EXPORT_SYMBOL(dmu_prefetch);
+EXPORT_SYMBOL(dmu_prefetch_by_dnode);
+EXPORT_SYMBOL(dmu_prefetch_dnode);
EXPORT_SYMBOL(dmu_free_range);
EXPORT_SYMBOL(dmu_free_long_range);
EXPORT_SYMBOL(dmu_free_long_object);
@@ -2352,12 +2607,12 @@ EXPORT_SYMBOL(dmu_ot);
ZFS_MODULE_PARAM(zfs, zfs_, nopwrite_enabled, INT, ZMOD_RW,
"Enable NOP writes");
-ZFS_MODULE_PARAM(zfs, zfs_, per_txg_dirty_frees_percent, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, per_txg_dirty_frees_percent, UINT, ZMOD_RW,
"Percentage of dirtied blocks from frees in one TXG");
ZFS_MODULE_PARAM(zfs, zfs_, dmu_offset_next_sync, INT, ZMOD_RW,
"Enable forcing txg sync to find holes");
/* CSTYLED */
-ZFS_MODULE_PARAM(zfs, , dmu_prefetch_max, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, , dmu_prefetch_max, UINT, ZMOD_RW,
"Limit one prefetch call to this size");
diff --git a/module/zfs/dmu_diff.c b/module/zfs/dmu_diff.c
index 1382da267d8a..a2b1a27c88e9 100644
--- a/module/zfs/dmu_diff.c
+++ b/module/zfs/dmu_diff.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/dmu_object.c b/module/zfs/dmu_object.c
index d954c7d9b6bc..d0e39a423bb0 100644
--- a/module/zfs/dmu_object.c
+++ b/module/zfs/dmu_object.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,7 +41,7 @@
* determined to be the lowest value that eliminates the measurable effect
* of lock contention from this code path.
*/
-int dmu_object_alloc_chunk_shift = 7;
+uint_t dmu_object_alloc_chunk_shift = 7;
static uint64_t
dmu_object_alloc_impl(objset_t *os, dmu_object_type_t ot, int blocksize,
@@ -55,7 +55,7 @@ dmu_object_alloc_impl(objset_t *os, dmu_object_type_t ot, int blocksize,
int dn_slots = dnodesize >> DNODE_SHIFT;
boolean_t restarted = B_FALSE;
uint64_t *cpuobj = NULL;
- int dnodes_per_chunk = 1 << dmu_object_alloc_chunk_shift;
+ uint_t dnodes_per_chunk = 1 << dmu_object_alloc_chunk_shift;
int error;
cpuobj = &os->os_obj_next_percpu[CPU_SEQID_UNSTABLE %
@@ -409,6 +409,8 @@ dmu_object_next(objset_t *os, uint64_t *objectp, boolean_t hole, uint64_t txg)
* hand off to dnode_next_offset() for further scanning.
*/
while (i <= last_obj) {
+ if (i == 0)
+ return (SET_ERROR(ESRCH));
error = dmu_object_info(os, i, &doi);
if (error == ENOENT) {
if (hole) {
@@ -518,6 +520,6 @@ EXPORT_SYMBOL(dmu_object_zapify);
EXPORT_SYMBOL(dmu_object_free_zapified);
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs, , dmu_object_alloc_chunk_shift, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, , dmu_object_alloc_chunk_shift, UINT, ZMOD_RW,
"CPU-specific allocator grabs 2^N objects at once");
/* END CSTYLED */
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index 324ee8d8342f..f1818ae155bd 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -32,6 +32,7 @@
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. 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 */
@@ -263,6 +264,19 @@ secondary_cache_changed_cb(void *arg, uint64_t newval)
}
static void
+prefetch_changed_cb(void *arg, uint64_t newval)
+{
+ objset_t *os = arg;
+
+ /*
+ * Inheritance should have been done by now.
+ */
+ ASSERT(newval == ZFS_PREFETCH_ALL || newval == ZFS_PREFETCH_NONE ||
+ newval == ZFS_PREFETCH_METADATA);
+ os->os_prefetch = newval;
+}
+
+static void
sync_changed_cb(void *arg, uint64_t newval)
{
objset_t *os = arg;
@@ -287,7 +301,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;
}
@@ -384,10 +400,10 @@ dnode_hash(const objset_t *os, uint64_t obj)
ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY);
/*
- * The low 6 bits of the pointer don't have much entropy, because
- * the objset_t is larger than 2^6 bytes long.
+ * The lower 11 bits of the pointer don't have much entropy, because
+ * the objset_t is more than 1KB long and so likely aligned to 2KB.
*/
- crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (osv >> 6)) & 0xFF];
+ crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (osv >> 11)) & 0xFF];
crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (obj >> 0)) & 0xFF];
crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (obj >> 8)) & 0xFF];
crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (obj >> 16)) & 0xFF];
@@ -416,28 +432,28 @@ dnode_multilist_index_func(multilist_t *ml, void *obj)
static inline boolean_t
dmu_os_is_l2cacheable(objset_t *os)
{
- vdev_t *vd = NULL;
- zfs_cache_type_t cache = os->os_secondary_cache;
- blkptr_t *bp = os->os_rootbp;
+ if (os->os_secondary_cache == ZFS_CACHE_ALL ||
+ os->os_secondary_cache == ZFS_CACHE_METADATA) {
+ if (l2arc_exclude_special == 0)
+ return (B_TRUE);
- if (bp != NULL && !BP_IS_HOLE(bp)) {
+ blkptr_t *bp = os->os_rootbp;
+ if (bp == NULL || BP_IS_HOLE(bp))
+ return (B_FALSE);
uint64_t vdev = DVA_GET_VDEV(bp->blk_dva);
vdev_t *rvd = os->os_spa->spa_root_vdev;
+ vdev_t *vd = NULL;
if (vdev < rvd->vdev_children)
vd = rvd->vdev_child[vdev];
- if (cache == ZFS_CACHE_ALL || cache == ZFS_CACHE_METADATA) {
- if (vd == NULL)
- return (B_TRUE);
+ if (vd == NULL)
+ return (B_TRUE);
- if ((vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
- vd->vdev_alloc_bias != VDEV_BIAS_DEDUP) ||
- l2arc_exclude_special == 0)
- return (B_TRUE);
- }
+ if (vd->vdev_alloc_bias != VDEV_BIAS_SPECIAL &&
+ vd->vdev_alloc_bias != VDEV_BIAS_DEDUP)
+ return (B_TRUE);
}
-
return (B_FALSE);
}
@@ -479,7 +495,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
arc_flags_t aflags = ARC_FLAG_WAIT;
zbookmark_phys_t zb;
int size;
- enum zio_flag zio_flags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zio_flags = ZIO_FLAG_CANFAIL;
SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET,
ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
@@ -559,6 +575,11 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
secondary_cache_changed_cb, os);
}
+ if (err == 0) {
+ err = dsl_prop_register(ds,
+ zfs_prop_to_name(ZFS_PROP_PREFETCH),
+ prefetch_changed_cb, os);
+ }
if (!ds->ds_is_snapshot) {
if (err == 0) {
err = dsl_prop_register(ds,
@@ -632,6 +653,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
os->os_primary_cache = ZFS_CACHE_ALL;
os->os_secondary_cache = ZFS_CACHE_ALL;
os->os_dnodesize = DNODE_MIN_SIZE;
+ os->os_prefetch = ZFS_PREFETCH_ALL;
}
if (ds == NULL || !ds->ds_is_snapshot)
@@ -1118,12 +1140,14 @@ dmu_objset_create_impl_dnstats(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
(!os->os_encrypted || !dmu_objset_is_receiving(os))) {
os->os_phys->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE;
if (dmu_objset_userobjused_enabled(os)) {
+ ASSERT3P(ds, !=, NULL);
ds->ds_feature_activation[
SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE;
os->os_phys->os_flags |=
OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE;
}
if (dmu_objset_projectquota_enabled(os)) {
+ ASSERT3P(ds, !=, NULL);
ds->ds_feature_activation[
SPA_FEATURE_PROJECT_QUOTA] = (void *)B_TRUE;
os->os_phys->os_flags |=
@@ -1298,6 +1322,7 @@ dmu_objset_create_sync(void *arg, dmu_tx_t *tx)
ASSERT3P(ds->ds_key_mapping, !=, NULL);
key_mapping_rele(spa, ds->ds_key_mapping, ds);
dsl_dataset_sync_done(ds, tx);
+ dmu_buf_rele(ds->ds_dbuf, ds);
}
mutex_enter(&ds->ds_lock);
@@ -1614,28 +1639,92 @@ dmu_objset_write_done(zio_t *zio, arc_buf_t *abuf, void *arg)
kmem_free(bp, sizeof (*bp));
}
+typedef struct sync_objset_arg {
+ zio_t *soa_zio;
+ objset_t *soa_os;
+ dmu_tx_t *soa_tx;
+ kmutex_t soa_mutex;
+ int soa_count;
+ taskq_ent_t soa_tq_ent;
+} sync_objset_arg_t;
+
typedef struct sync_dnodes_arg {
- multilist_t *sda_list;
- int sda_sublist_idx;
- multilist_t *sda_newlist;
- dmu_tx_t *sda_tx;
+ multilist_t *sda_list;
+ int sda_sublist_idx;
+ multilist_t *sda_newlist;
+ sync_objset_arg_t *sda_soa;
} sync_dnodes_arg_t;
+static void sync_meta_dnode_task(void *arg);
+
static void
sync_dnodes_task(void *arg)
{
sync_dnodes_arg_t *sda = arg;
+ sync_objset_arg_t *soa = sda->sda_soa;
+ objset_t *os = soa->soa_os;
+ uint_t allocator = spa_acq_allocator(os->os_spa);
multilist_sublist_t *ms =
- multilist_sublist_lock(sda->sda_list, sda->sda_sublist_idx);
+ multilist_sublist_lock_idx(sda->sda_list, sda->sda_sublist_idx);
- dmu_objset_sync_dnodes(ms, sda->sda_tx);
+ dmu_objset_sync_dnodes(ms, soa->soa_tx);
multilist_sublist_unlock(ms);
+ spa_rel_allocator(os->os_spa, allocator);
kmem_free(sda, sizeof (*sda));
+
+ mutex_enter(&soa->soa_mutex);
+ ASSERT(soa->soa_count != 0);
+ if (--soa->soa_count != 0) {
+ mutex_exit(&soa->soa_mutex);
+ return;
+ }
+ mutex_exit(&soa->soa_mutex);
+
+ taskq_dispatch_ent(dmu_objset_pool(os)->dp_sync_taskq,
+ sync_meta_dnode_task, soa, TQ_FRONT, &soa->soa_tq_ent);
}
+/*
+ * Issue the zio_nowait() for all dirty record zios on the meta dnode,
+ * then trigger the callback for the zil_sync. This runs once for each
+ * objset, only after any/all sublists in the objset have been synced.
+ */
+static void
+sync_meta_dnode_task(void *arg)
+{
+ sync_objset_arg_t *soa = arg;
+ objset_t *os = soa->soa_os;
+ dmu_tx_t *tx = soa->soa_tx;
+ int txgoff = tx->tx_txg & TXG_MASK;
+ dbuf_dirty_record_t *dr;
+
+ ASSERT0(soa->soa_count);
+
+ list_t *list = &DMU_META_DNODE(os)->dn_dirty_records[txgoff];
+ while ((dr = list_remove_head(list)) != NULL) {
+ ASSERT0(dr->dr_dbuf->db_level);
+ zio_nowait(dr->dr_zio);
+ }
+
+ /* Enable dnode backfill if enough objects have been freed. */
+ if (os->os_freed_dnodes >= dmu_rescan_dnode_threshold) {
+ os->os_rescan_dnodes = B_TRUE;
+ os->os_freed_dnodes = 0;
+ }
+
+ /*
+ * Free intent log blocks up to this tx.
+ */
+ zil_sync(os->os_zil, tx);
+ os->os_phys->os_zil_header = os->os_zil_header;
+ zio_nowait(soa->soa_zio);
+
+ mutex_destroy(&soa->soa_mutex);
+ kmem_free(soa, sizeof (*soa));
+}
/* called from dsl */
void
@@ -1645,8 +1734,6 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
zbookmark_phys_t zb;
zio_prop_t zp;
zio_t *zio;
- list_t *list;
- dbuf_dirty_record_t *dr;
int num_sublists;
multilist_t *ml;
blkptr_t *blkptr_copy = kmem_alloc(sizeof (*os->os_rootbp), KM_SLEEP);
@@ -1691,21 +1778,11 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
}
zio = arc_write(pio, os->os_spa, tx->tx_txg,
- blkptr_copy, os->os_phys_buf, dmu_os_is_l2cacheable(os),
- &zp, dmu_objset_write_ready, NULL, NULL, dmu_objset_write_done,
+ blkptr_copy, os->os_phys_buf, B_FALSE, dmu_os_is_l2cacheable(os),
+ &zp, dmu_objset_write_ready, NULL, dmu_objset_write_done,
os, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
/*
- * In the codepath dsl_dataset_sync()->dmu_objset_sync() we cannot
- * rely on the zio above completing and calling back
- * dmu_objset_write_done()->dsl_dataset_block_born() before
- * dsl_dataset_sync() actually activates feature flags near its end.
- * Decide here if any features need to be activated, before
- * dsl_dataset_sync() completes its run.
- */
- dsl_dataset_feature_set_activation(blkptr_copy, os->os_dsl_dataset);
-
- /*
* Sync special dnodes - the parent IO for the sync is the root block
*/
DMU_META_DNODE(os)->dn_zio = zio;
@@ -1743,40 +1820,49 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
offsetof(dnode_t, dn_dirty_link[txgoff]));
}
+ /*
+ * zio_nowait(zio) is done after any/all sublist and meta dnode
+ * zios have been nowaited, and the zil_sync() has been performed.
+ * The soa is freed at the end of sync_meta_dnode_task.
+ */
+ sync_objset_arg_t *soa = kmem_alloc(sizeof (*soa), KM_SLEEP);
+ soa->soa_zio = zio;
+ soa->soa_os = os;
+ soa->soa_tx = tx;
+ taskq_init_ent(&soa->soa_tq_ent);
+ mutex_init(&soa->soa_mutex, NULL, MUTEX_DEFAULT, NULL);
+
ml = &os->os_dirty_dnodes[txgoff];
- num_sublists = multilist_get_num_sublists(ml);
+ soa->soa_count = num_sublists = multilist_get_num_sublists(ml);
+
for (int i = 0; i < num_sublists; i++) {
if (multilist_sublist_is_empty_idx(ml, i))
- continue;
- sync_dnodes_arg_t *sda = kmem_alloc(sizeof (*sda), KM_SLEEP);
- sda->sda_list = ml;
- sda->sda_sublist_idx = i;
- sda->sda_tx = tx;
- (void) taskq_dispatch(dmu_objset_pool(os)->dp_sync_taskq,
- sync_dnodes_task, sda, 0);
- /* callback frees sda */
+ soa->soa_count--;
}
- taskq_wait(dmu_objset_pool(os)->dp_sync_taskq);
- list = &DMU_META_DNODE(os)->dn_dirty_records[txgoff];
- while ((dr = list_head(list)) != NULL) {
- ASSERT0(dr->dr_dbuf->db_level);
- list_remove(list, dr);
- zio_nowait(dr->dr_zio);
- }
-
- /* Enable dnode backfill if enough objects have been freed. */
- if (os->os_freed_dnodes >= dmu_rescan_dnode_threshold) {
- os->os_rescan_dnodes = B_TRUE;
- os->os_freed_dnodes = 0;
+ if (soa->soa_count == 0) {
+ taskq_dispatch_ent(dmu_objset_pool(os)->dp_sync_taskq,
+ sync_meta_dnode_task, soa, TQ_FRONT, &soa->soa_tq_ent);
+ } else {
+ /*
+ * Sync sublists in parallel. The last to finish
+ * (i.e., when soa->soa_count reaches zero) must
+ * dispatch sync_meta_dnode_task.
+ */
+ for (int i = 0; i < num_sublists; i++) {
+ if (multilist_sublist_is_empty_idx(ml, i))
+ continue;
+ sync_dnodes_arg_t *sda =
+ kmem_alloc(sizeof (*sda), KM_SLEEP);
+ sda->sda_list = ml;
+ sda->sda_sublist_idx = i;
+ sda->sda_soa = soa;
+ (void) taskq_dispatch(
+ dmu_objset_pool(os)->dp_sync_taskq,
+ sync_dnodes_task, sda, 0);
+ /* sync_dnodes_task frees sda */
+ }
}
-
- /*
- * Free intent log blocks up to this tx.
- */
- zil_sync(os->os_zil, tx);
- os->os_phys->os_zil_header = os->os_zil_header;
- zio_nowait(zio);
}
boolean_t
@@ -1992,8 +2078,8 @@ userquota_updates_task(void *arg)
dnode_t *dn;
userquota_cache_t cache = { { 0 } };
- multilist_sublist_t *list =
- multilist_sublist_lock(&os->os_synced_dnodes, uua->uua_sublist_idx);
+ multilist_sublist_t *list = multilist_sublist_lock_idx(
+ &os->os_synced_dnodes, uua->uua_sublist_idx);
ASSERT(multilist_sublist_head(list) == NULL ||
dmu_objset_userused_enabled(os));
@@ -2075,8 +2161,8 @@ dnode_rele_task(void *arg)
userquota_updates_arg_t *uua = arg;
objset_t *os = uua->uua_os;
- multilist_sublist_t *list =
- multilist_sublist_lock(&os->os_synced_dnodes, uua->uua_sublist_idx);
+ multilist_sublist_t *list = multilist_sublist_lock_idx(
+ &os->os_synced_dnodes, uua->uua_sublist_idx);
dnode_t *dn;
while ((dn = multilist_sublist_head(list)) != NULL) {
diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c
index 5ac862519166..680aed4513bc 100644
--- a/module/zfs/dmu_recv.c
+++ b/module/zfs/dmu_recv.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,8 +27,12 @@
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
* Copyright (c) 2019, Klara Inc.
* Copyright (c) 2019, Allan Jude
+ * Copyright (c) 2019 Datto Inc.
+ * Copyright (c) 2022 Axcient.
*/
+#include <sys/arc.h>
+#include <sys/spa_impl.h>
#include <sys/dmu.h>
#include <sys/dmu_impl.h>
#include <sys/dmu_send.h>
@@ -64,13 +68,20 @@
#endif
#include <sys/zfs_file.h>
-static int zfs_recv_queue_length = SPA_MAXBLOCKSIZE;
-static int zfs_recv_queue_ff = 20;
-static int zfs_recv_write_batch_size = 1024 * 1024;
+static uint_t zfs_recv_queue_length = SPA_MAXBLOCKSIZE;
+static uint_t zfs_recv_queue_ff = 20;
+static uint_t zfs_recv_write_batch_size = 1024 * 1024;
+static int zfs_recv_best_effort_corrective = 0;
static const void *const dmu_recv_tag = "dmu_recv_tag";
const char *const recv_clone_name = "%recv";
+typedef enum {
+ ORNS_NO,
+ ORNS_YES,
+ ORNS_MAYBE
+} or_need_sync_t;
+
static int receive_read_payload_and_next_header(dmu_recv_cookie_t *ra, int len,
void *buf);
@@ -102,6 +113,8 @@ struct receive_writer_arg {
boolean_t done;
int err;
+ const char *tofs;
+ boolean_t heal;
boolean_t resumable;
boolean_t raw; /* DMU_BACKUP_FEATURE_RAW set */
boolean_t spill; /* DRR_FLAG_SPILL_BLOCK set */
@@ -121,6 +134,10 @@ struct receive_writer_arg {
uint8_t or_iv[ZIO_DATA_IV_LEN];
uint8_t or_mac[ZIO_DATA_MAC_LEN];
boolean_t or_byteorder;
+ zio_t *heal_pio;
+
+ /* Keep track of DRR_FREEOBJECTS right after DRR_OBJECT_RANGE */
+ or_need_sync_t or_need_sync;
};
typedef struct dmu_recv_begin_arg {
@@ -343,9 +360,10 @@ static int
recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
uint64_t fromguid, uint64_t featureflags)
{
- uint64_t val;
+ uint64_t obj;
uint64_t children;
int error;
+ dsl_dataset_t *snap;
dsl_pool_t *dp = ds->ds_dir->dd_pool;
boolean_t encrypted = ds->ds_dir->dd_crypto_obj != 0;
boolean_t raw = (featureflags & DMU_BACKUP_FEATURE_RAW) != 0;
@@ -354,7 +372,7 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
/* Temporary clone name must not exist. */
error = zap_lookup(dp->dp_meta_objset,
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
- 8, 1, &val);
+ 8, 1, &obj);
if (error != ENOENT)
return (error == 0 ? SET_ERROR(EBUSY) : error);
@@ -362,12 +380,16 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
if (dsl_dataset_has_resume_receive_state(ds))
return (SET_ERROR(EBUSY));
- /* New snapshot name must not exist. */
+ /* New snapshot name must not exist if we're not healing it. */
error = zap_lookup(dp->dp_meta_objset,
dsl_dataset_phys(ds)->ds_snapnames_zapobj,
- drba->drba_cookie->drc_tosnap, 8, 1, &val);
- if (error != ENOENT)
+ drba->drba_cookie->drc_tosnap, 8, 1, &obj);
+ if (drba->drba_cookie->drc_heal) {
+ if (error != 0)
+ return (error);
+ } else if (error != ENOENT) {
return (error == 0 ? SET_ERROR(EEXIST) : error);
+ }
/* Must not have children if receiving a ZVOL. */
error = zap_count(dp->dp_meta_objset,
@@ -392,8 +414,40 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
if (error != 0)
return (error);
- if (fromguid != 0) {
- dsl_dataset_t *snap;
+ if (drba->drba_cookie->drc_heal) {
+ /* Encryption is incompatible with embedded data. */
+ if (encrypted && embed)
+ return (SET_ERROR(EINVAL));
+
+ /* Healing is not supported when in 'force' mode. */
+ if (drba->drba_cookie->drc_force)
+ return (SET_ERROR(EINVAL));
+
+ /* Must have keys loaded if doing encrypted non-raw recv. */
+ if (encrypted && !raw) {
+ if (spa_keystore_lookup_key(dp->dp_spa, ds->ds_object,
+ NULL, NULL) != 0)
+ return (SET_ERROR(EACCES));
+ }
+
+ error = dsl_dataset_hold_obj(dp, obj, FTAG, &snap);
+ if (error != 0)
+ return (error);
+
+ /*
+ * When not doing best effort corrective recv healing can only
+ * be done if the send stream is for the same snapshot as the
+ * one we are trying to heal.
+ */
+ if (zfs_recv_best_effort_corrective == 0 &&
+ drba->drba_cookie->drc_drrb->drr_toguid !=
+ dsl_dataset_phys(snap)->ds_guid) {
+ dsl_dataset_rele(snap, FTAG);
+ return (SET_ERROR(ENOTSUP));
+ }
+ dsl_dataset_rele(snap, FTAG);
+ } else if (fromguid != 0) {
+ /* Sanity check the incremental recv */
uint64_t obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
/* Can't perform a raw receive on top of a non-raw receive */
@@ -459,7 +513,7 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
dsl_dataset_rele(snap, FTAG);
} else {
- /* if full, then must be forced */
+ /* If full and not healing then must be forced. */
if (!drba->drba_cookie->drc_force)
return (SET_ERROR(EEXIST));
@@ -602,7 +656,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;
}
@@ -626,6 +680,10 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
char buf[ZFS_MAX_DATASET_NAME_LEN];
objset_t *os;
+ /* healing recv must be done "into" an existing snapshot */
+ if (drba->drba_cookie->drc_heal == B_TRUE)
+ return (SET_ERROR(ENOTSUP));
+
/*
* If it's a non-clone incremental, we are missing the
* target fs, so fail the recv.
@@ -807,7 +865,7 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
error = dsl_dataset_hold_flags(dp, tofs, dsflags, FTAG, &ds);
if (error == 0) {
- /* create temporary clone */
+ /* Create temporary clone unless we're doing corrective recv */
dsl_dataset_t *snap = NULL;
if (drba->drba_cookie->drc_fromsnapobj != 0) {
@@ -815,8 +873,15 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
drba->drba_cookie->drc_fromsnapobj, FTAG, &snap));
ASSERT3P(dcp, ==, NULL);
}
- dsobj = dsl_dataset_create_sync(ds->ds_dir, recv_clone_name,
- snap, crflags, drba->drba_cred, dcp, tx);
+ if (drc->drc_heal) {
+ /* When healing we want to use the provided snapshot */
+ VERIFY0(dsl_dataset_snap_lookup(ds, drc->drc_tosnap,
+ &dsobj));
+ } else {
+ dsobj = dsl_dataset_create_sync(ds->ds_dir,
+ recv_clone_name, snap, crflags, drba->drba_cred,
+ dcp, tx);
+ }
if (drba->drba_cookie->drc_fromsnapobj != 0)
dsl_dataset_rele(snap, FTAG);
dsl_dataset_rele_flags(ds, dsflags, FTAG);
@@ -933,7 +998,8 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
*/
rrw_enter(&newds->ds_bp_rwlock, RW_READER, FTAG);
if (BP_IS_HOLE(dsl_dataset_get_blkptr(newds)) &&
- (featureflags & DMU_BACKUP_FEATURE_RAW) == 0) {
+ (featureflags & DMU_BACKUP_FEATURE_RAW) == 0 &&
+ !drc->drc_heal) {
(void) dmu_objset_create_impl(dp->dp_spa,
newds, dsl_dataset_get_blkptr(newds), drrb->drr_type, tx);
}
@@ -989,13 +1055,24 @@ dmu_recv_resume_begin_check(void *arg, dmu_tx_t *tx)
dsflags |= DS_HOLD_FLAG_DECRYPT;
}
+ boolean_t recvexist = B_TRUE;
if (dsl_dataset_hold_flags(dp, recvname, dsflags, FTAG, &ds) != 0) {
/* %recv does not exist; continue in tofs */
+ recvexist = B_FALSE;
error = dsl_dataset_hold_flags(dp, tofs, dsflags, FTAG, &ds);
if (error != 0)
return (error);
}
+ /*
+ * Resume of full/newfs recv on existing dataset should be done with
+ * force flag
+ */
+ if (recvexist && drrb->drr_fromguid == 0 && !drc->drc_force) {
+ dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ return (SET_ERROR(ZFS_ERR_RESUME_EXISTS));
+ }
+
/* check that ds is marked inconsistent */
if (!DS_IS_INCONSISTENT(ds)) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
@@ -1140,13 +1217,14 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx)
* succeeds; otherwise we will leak the holds on the datasets.
*/
int
-dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
- boolean_t force, boolean_t resumable, nvlist_t *localprops,
- nvlist_t *hidden_args, char *origin, dmu_recv_cookie_t *drc,
- zfs_file_t *fp, offset_t *voffp)
+dmu_recv_begin(const char *tofs, const char *tosnap,
+ dmu_replay_record_t *drr_begin, boolean_t force, boolean_t heal,
+ boolean_t resumable, nvlist_t *localprops, nvlist_t *hidden_args,
+ const char *origin, dmu_recv_cookie_t *drc, zfs_file_t *fp,
+ offset_t *voffp)
{
dmu_recv_begin_arg_t drba = { 0 };
- int err;
+ int err = 0;
memset(drc, 0, sizeof (dmu_recv_cookie_t));
drc->drc_drr_begin = drr_begin;
@@ -1154,6 +1232,7 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
drc->drc_tosnap = tosnap;
drc->drc_tofs = tofs;
drc->drc_force = force;
+ drc->drc_heal = heal;
drc->drc_resumable = resumable;
drc->drc_cred = CRED();
drc->drc_proc = curproc;
@@ -1177,20 +1256,36 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
uint32_t payloadlen = drc->drc_drr_begin->drr_payloadlen;
- void *payload = NULL;
- if (payloadlen != 0)
- payload = kmem_alloc(payloadlen, KM_SLEEP);
- err = receive_read_payload_and_next_header(drc, payloadlen,
- payload);
- if (err != 0) {
- kmem_free(payload, payloadlen);
- return (err);
- }
+ /*
+ * Since OpenZFS 2.0.0, we have enforced a 64MB limit in userspace
+ * configurable via ZFS_SENDRECV_MAX_NVLIST. We enforce 256MB as a hard
+ * upper limit. Systems with less than 1GB of RAM will see a lower
+ * limit from `arc_all_memory() / 4`.
+ */
+ if (payloadlen > (MIN((1U << 28), arc_all_memory() / 4)))
+ return (E2BIG);
+
+
if (payloadlen != 0) {
+ void *payload = vmem_alloc(payloadlen, KM_SLEEP);
+ /*
+ * For compatibility with recursive send streams, we don't do
+ * this here if the stream could be part of a package. Instead,
+ * we'll do it in dmu_recv_stream. If we pull the next header
+ * too early, and it's the END record, we break the `recv_skip`
+ * logic.
+ */
+
+ err = receive_read_payload_and_next_header(drc, payloadlen,
+ payload);
+ if (err != 0) {
+ vmem_free(payload, payloadlen);
+ return (err);
+ }
err = nvlist_unpack(payload, payloadlen, &drc->drc_begin_nvl,
KM_SLEEP);
- kmem_free(payload, payloadlen);
+ vmem_free(payload, payloadlen);
if (err != 0) {
kmem_free(drc->drc_next_rrd,
sizeof (*drc->drc_next_rrd));
@@ -1243,6 +1338,186 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
return (err);
}
+/*
+ * Holds data need for corrective recv callback
+ */
+typedef struct cr_cb_data {
+ uint64_t size;
+ zbookmark_phys_t zb;
+ spa_t *spa;
+} cr_cb_data_t;
+
+static void
+corrective_read_done(zio_t *zio)
+{
+ cr_cb_data_t *data = zio->io_private;
+ /* Corruption corrected; update error log if needed */
+ if (zio->io_error == 0) {
+ spa_remove_error(data->spa, &data->zb,
+ BP_GET_LOGICAL_BIRTH(zio->io_bp));
+ }
+ kmem_free(data, sizeof (cr_cb_data_t));
+ abd_free(zio->io_abd);
+}
+
+/*
+ * zio_rewrite the data pointed to by bp with the data from the rrd's abd.
+ */
+static int
+do_corrective_recv(struct receive_writer_arg *rwa, struct drr_write *drrw,
+ struct receive_record_arg *rrd, blkptr_t *bp)
+{
+ int err;
+ zio_t *io;
+ zbookmark_phys_t zb;
+ dnode_t *dn;
+ abd_t *abd = rrd->abd;
+ zio_cksum_t bp_cksum = bp->blk_cksum;
+ zio_flag_t flags = ZIO_FLAG_SPECULATIVE | ZIO_FLAG_DONT_RETRY |
+ ZIO_FLAG_CANFAIL;
+
+ if (rwa->raw)
+ flags |= ZIO_FLAG_RAW;
+
+ err = dnode_hold(rwa->os, drrw->drr_object, FTAG, &dn);
+ if (err != 0)
+ return (err);
+ SET_BOOKMARK(&zb, dmu_objset_id(rwa->os), drrw->drr_object, 0,
+ dbuf_whichblock(dn, 0, drrw->drr_offset));
+ dnode_rele(dn, FTAG);
+
+ if (!rwa->raw && DRR_WRITE_COMPRESSED(drrw)) {
+ /* Decompress the stream data */
+ abd_t *dabd = abd_alloc_linear(
+ drrw->drr_logical_size, B_FALSE);
+ err = zio_decompress_data(drrw->drr_compressiontype,
+ abd, abd_to_buf(dabd), abd_get_size(abd),
+ abd_get_size(dabd), NULL);
+
+ if (err != 0) {
+ abd_free(dabd);
+ return (err);
+ }
+ /* Swap in the newly decompressed data into the abd */
+ abd_free(abd);
+ abd = dabd;
+ }
+
+ if (!rwa->raw && BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF) {
+ /* Recompress the data */
+ abd_t *cabd = abd_alloc_linear(BP_GET_PSIZE(bp),
+ B_FALSE);
+ void *buf = abd_to_buf(cabd);
+ uint64_t csize = zio_compress_data(BP_GET_COMPRESS(bp),
+ abd, &buf, abd_get_size(abd),
+ rwa->os->os_complevel);
+ abd_zero_off(cabd, csize, BP_GET_PSIZE(bp) - csize);
+ /* Swap in newly compressed data into the abd */
+ abd_free(abd);
+ abd = cabd;
+ flags |= ZIO_FLAG_RAW_COMPRESS;
+ }
+
+ /*
+ * The stream is not encrypted but the data on-disk is.
+ * We need to re-encrypt the buf using the same
+ * encryption type, salt, iv, and mac that was used to encrypt
+ * the block previosly.
+ */
+ if (!rwa->raw && BP_USES_CRYPT(bp)) {
+ dsl_dataset_t *ds;
+ dsl_crypto_key_t *dck = NULL;
+ uint8_t salt[ZIO_DATA_SALT_LEN];
+ uint8_t iv[ZIO_DATA_IV_LEN];
+ uint8_t mac[ZIO_DATA_MAC_LEN];
+ boolean_t no_crypt = B_FALSE;
+ dsl_pool_t *dp = dmu_objset_pool(rwa->os);
+ abd_t *eabd = abd_alloc_linear(BP_GET_PSIZE(bp), B_FALSE);
+
+ zio_crypt_decode_params_bp(bp, salt, iv);
+ zio_crypt_decode_mac_bp(bp, mac);
+
+ dsl_pool_config_enter(dp, FTAG);
+ err = dsl_dataset_hold_flags(dp, rwa->tofs,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
+ if (err != 0) {
+ dsl_pool_config_exit(dp, FTAG);
+ abd_free(eabd);
+ return (SET_ERROR(EACCES));
+ }
+
+ /* Look up the key from the spa's keystore */
+ err = spa_keystore_lookup_key(rwa->os->os_spa,
+ zb.zb_objset, FTAG, &dck);
+ if (err != 0) {
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT,
+ FTAG);
+ dsl_pool_config_exit(dp, FTAG);
+ abd_free(eabd);
+ return (SET_ERROR(EACCES));
+ }
+
+ err = zio_do_crypt_abd(B_TRUE, &dck->dck_key,
+ BP_GET_TYPE(bp), BP_SHOULD_BYTESWAP(bp), salt, iv,
+ mac, abd_get_size(abd), abd, eabd, &no_crypt);
+
+ spa_keystore_dsl_key_rele(rwa->os->os_spa, dck, FTAG);
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ dsl_pool_config_exit(dp, FTAG);
+
+ ASSERT0(no_crypt);
+ if (err != 0) {
+ abd_free(eabd);
+ return (err);
+ }
+ /* Swap in the newly encrypted data into the abd */
+ abd_free(abd);
+ abd = eabd;
+
+ /*
+ * We want to prevent zio_rewrite() from trying to
+ * encrypt the data again
+ */
+ flags |= ZIO_FLAG_RAW_ENCRYPT;
+ }
+ rrd->abd = abd;
+
+ io = zio_rewrite(NULL, rwa->os->os_spa, BP_GET_LOGICAL_BIRTH(bp), bp,
+ abd, BP_GET_PSIZE(bp), NULL, NULL, ZIO_PRIORITY_SYNC_WRITE, flags,
+ &zb);
+
+ ASSERT(abd_get_size(abd) == BP_GET_LSIZE(bp) ||
+ abd_get_size(abd) == BP_GET_PSIZE(bp));
+
+ /* compute new bp checksum value and make sure it matches the old one */
+ zio_checksum_compute(io, BP_GET_CHECKSUM(bp), abd, abd_get_size(abd));
+ if (!ZIO_CHECKSUM_EQUAL(bp_cksum, io->io_bp->blk_cksum)) {
+ zio_destroy(io);
+ if (zfs_recv_best_effort_corrective != 0)
+ return (0);
+ return (SET_ERROR(ECKSUM));
+ }
+
+ /* Correct the corruption in place */
+ err = zio_wait(io);
+ if (err == 0) {
+ cr_cb_data_t *cb_data =
+ kmem_alloc(sizeof (cr_cb_data_t), KM_SLEEP);
+ cb_data->spa = rwa->os->os_spa;
+ cb_data->size = drrw->drr_logical_size;
+ cb_data->zb = zb;
+ /* Test if healing worked by re-reading the bp */
+ err = zio_wait(zio_read(rwa->heal_pio, rwa->os->os_spa, bp,
+ abd_alloc_for_io(drrw->drr_logical_size, B_FALSE),
+ drrw->drr_logical_size, corrective_read_done,
+ cb_data, ZIO_PRIORITY_ASYNC_READ, flags, NULL));
+ }
+ if (err != 0 && zfs_recv_best_effort_corrective != 0)
+ err = 0;
+
+ return (err);
+}
+
static int
receive_read(dmu_recv_cookie_t *drc, int len, void *buf)
{
@@ -1256,11 +1531,11 @@ receive_read(dmu_recv_cookie_t *drc, int len, void *buf)
(drc->drc_featureflags & DMU_BACKUP_FEATURE_RAW) != 0);
while (done < len) {
- ssize_t resid;
+ ssize_t resid = len - done;
zfs_file_t *fp = drc->drc_fp;
int err = zfs_file_read(fp, (char *)buf + done,
len - done, &resid);
- if (resid == len - done) {
+ if (err == 0 && resid == len - done) {
/*
* Note: ECKSUM or ZFS_ERR_STREAM_TRUNCATED indicates
* that the receive was interrupted and can
@@ -1523,17 +1798,19 @@ receive_handle_existing_object(const struct receive_writer_arg *rwa,
}
/*
- * The dmu does not currently support decreasing nlevels
- * or changing the number of dnode slots on an object. For
- * non-raw sends, this does not matter and the new object
- * can just use the previous one's nlevels. For raw sends,
- * however, the structure of the received dnode (including
- * nlevels and dnode slots) must match that of the send
- * side. Therefore, instead of using dmu_object_reclaim(),
- * we must free the object completely and call
- * dmu_object_claim_dnsize() instead.
+ * The dmu does not currently support decreasing nlevels or changing
+ * indirect block size if there is already one, same as changing the
+ * number of of dnode slots on an object. For non-raw sends this
+ * does not matter and the new object can just use the previous one's
+ * parameters. For raw sends, however, the structure of the received
+ * dnode (including indirects and dnode slots) must match that of the
+ * send side. Therefore, instead of using dmu_object_reclaim(), we
+ * must free the object completely and call dmu_object_claim_dnsize()
+ * instead.
*/
- if ((rwa->raw && drro->drr_nlevels < doi->doi_indirection) ||
+ if ((rwa->raw && ((doi->doi_indirection > 1 &&
+ indblksz != doi->doi_metadata_block_size) ||
+ drro->drr_nlevels < doi->doi_indirection)) ||
dn_slots != doi->doi_dnodesize >> DNODE_SHIFT) {
err = dmu_free_long_object(rwa->os, drro->drr_object);
if (err != 0)
@@ -1641,6 +1918,8 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
if (err == 0) {
err = receive_handle_existing_object(rwa, drro, &doi, data,
&object_to_hold, &new_blksz);
+ if (err != 0)
+ return (err);
} else if (err == EEXIST) {
/*
* The object requested is currently an interior slot of a
@@ -1657,10 +1936,22 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
/* object was freed and we are about to allocate a new one */
object_to_hold = DMU_NEW_OBJECT;
} else {
+ /*
+ * If the only record in this range so far was DRR_FREEOBJECTS
+ * with at least one actually freed object, it's possible that
+ * the block will now be converted to a hole. We need to wait
+ * for the txg to sync to prevent races.
+ */
+ if (rwa->or_need_sync == ORNS_YES)
+ txg_wait_synced(dmu_objset_pool(rwa->os), 0);
+
/* object is free and we are about to allocate a new one */
object_to_hold = DMU_NEW_OBJECT;
}
+ /* Only relevant for the first object in the range */
+ rwa->or_need_sync = ORNS_NO;
+
/*
* If this is a multi-slot dnode there is a chance that this
* object will expand into a slot that is already used by
@@ -1822,6 +2113,16 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
dmu_buf_rele(db, FTAG);
dnode_rele(dn, FTAG);
}
+
+ /*
+ * If the receive fails, we want the resume stream to start with the
+ * same record that we last successfully received. There is no way to
+ * request resume from the object record, but we can benefit from the
+ * fact that sender always sends object record before anything else,
+ * after which it will "resend" data at offset 0 and resume normally.
+ */
+ save_resume_state(rwa, drro->drr_object, 0, tx);
+
dmu_tx_commit(tx);
return (0);
@@ -1854,6 +2155,9 @@ receive_freeobjects(struct receive_writer_arg *rwa,
if (err != 0)
return (err);
+
+ if (rwa->or_need_sync == ORNS_MAYBE)
+ rwa->or_need_sync = ORNS_YES;
}
if (next_err != ESRCH)
return (next_err);
@@ -1937,10 +2241,10 @@ flush_write_batch_impl(struct receive_writer_arg *rwa)
if (err == 0)
abd_free(abd);
} else {
- zio_prop_t zp;
+ zio_prop_t zp = {0};
dmu_write_policy(rwa->os, dn, 0, 0, &zp);
- enum zio_flag zio_flags = 0;
+ zio_flag_t zio_flags = 0;
if (rwa->raw) {
zp.zp_encrypt = B_TRUE;
@@ -2049,6 +2353,53 @@ receive_process_write_record(struct receive_writer_arg *rwa,
!DMU_OT_IS_VALID(drrw->drr_type))
return (SET_ERROR(EINVAL));
+ if (rwa->heal) {
+ blkptr_t *bp;
+ dmu_buf_t *dbp;
+ int flags = DB_RF_CANFAIL;
+
+ if (rwa->raw)
+ flags |= DB_RF_NO_DECRYPT;
+
+ if (rwa->byteswap) {
+ dmu_object_byteswap_t byteswap =
+ DMU_OT_BYTESWAP(drrw->drr_type);
+ dmu_ot_byteswap[byteswap].ob_func(abd_to_buf(rrd->abd),
+ DRR_WRITE_PAYLOAD_SIZE(drrw));
+ }
+
+ err = dmu_buf_hold_noread(rwa->os, drrw->drr_object,
+ drrw->drr_offset, FTAG, &dbp);
+ if (err != 0)
+ return (err);
+
+ /* Try to read the object to see if it needs healing */
+ err = dbuf_read((dmu_buf_impl_t *)dbp, NULL, flags);
+ /*
+ * We only try to heal when dbuf_read() returns a ECKSUMs.
+ * Other errors (even EIO) get returned to caller.
+ * EIO indicates that the device is not present/accessible,
+ * so writing to it will likely fail.
+ * If the block is healthy, we don't want to overwrite it
+ * unnecessarily.
+ */
+ if (err != ECKSUM) {
+ dmu_buf_rele(dbp, FTAG);
+ return (err);
+ }
+ /* Make sure the on-disk block and recv record sizes match */
+ if (drrw->drr_logical_size != dbp->db_size) {
+ err = ENOTSUP;
+ dmu_buf_rele(dbp, FTAG);
+ return (err);
+ }
+ /* Get the block pointer for the corrupted block */
+ bp = dmu_buf_get_blkptr(dbp);
+ err = do_corrective_recv(rwa, drrw, rrd, bp);
+ dmu_buf_rele(dbp, FTAG);
+ return (err);
+ }
+
/*
* For resuming to work, records must be in increasing order
* by (object, offset).
@@ -2189,7 +2540,7 @@ receive_spill(struct receive_writer_arg *rwa, struct drr_spill *drrs,
* size of the provided arc_buf_t.
*/
if (db_spill->db_size != drrs->drr_length) {
- dmu_buf_will_fill(db_spill, tx);
+ dmu_buf_will_fill(db_spill, tx, B_FALSE);
VERIFY0(dbuf_spill_set_blksz(db_spill,
drrs->drr_length, tx));
}
@@ -2295,6 +2646,8 @@ receive_object_range(struct receive_writer_arg *rwa,
memcpy(rwa->or_mac, drror->drr_mac, ZIO_DATA_MAC_LEN);
rwa->or_byteorder = byteorder;
+ rwa->or_need_sync = ORNS_MAYBE;
+
return (0);
}
@@ -2341,7 +2694,8 @@ dmu_recv_cleanup_ds(dmu_recv_cookie_t *drc)
rrw_exit(&ds->ds_bp_rwlock, FTAG);
dsl_dataset_name(ds, name);
dsl_dataset_disown(ds, dsflags, dmu_recv_tag);
- (void) dsl_destroy_head(name);
+ if (!drc->drc_heal)
+ (void) dsl_destroy_head(name);
}
}
@@ -2702,7 +3056,19 @@ receive_process_record(struct receive_writer_arg *rwa,
ASSERT3U(rrd->bytes_read, >=, rwa->bytes_read);
rwa->bytes_read = rrd->bytes_read;
- if (rrd->header.drr_type != DRR_WRITE) {
+ /* We can only heal write records; other ones get ignored */
+ if (rwa->heal && rrd->header.drr_type != DRR_WRITE) {
+ if (rrd->abd != NULL) {
+ abd_free(rrd->abd);
+ rrd->abd = NULL;
+ } else if (rrd->payload != NULL) {
+ kmem_free(rrd->payload, rrd->payload_size);
+ rrd->payload = NULL;
+ }
+ return (0);
+ }
+
+ if (!rwa->heal && rrd->header.drr_type != DRR_WRITE) {
err = flush_write_batch(rwa);
if (err != 0) {
if (rrd->abd != NULL) {
@@ -2737,9 +3103,16 @@ receive_process_record(struct receive_writer_arg *rwa,
case DRR_WRITE:
{
err = receive_process_write_record(rwa, rrd);
- if (err != EAGAIN) {
+ if (rwa->heal) {
/*
- * On success, receive_process_write_record() returns
+ * If healing - always free the abd after processing
+ */
+ abd_free(rrd->abd);
+ rrd->abd = NULL;
+ } else if (err != EAGAIN) {
+ /*
+ * On success, a non-healing
+ * receive_process_write_record() returns
* EAGAIN to indicate that we do not want to free
* the rrd or arc_buf.
*/
@@ -2830,8 +3203,9 @@ receive_writer_thread(void *arg)
* EAGAIN indicates that this record has been saved (on
* raw->write_batch), and will be used again, so we don't
* free it.
+ * When healing data we always need to free the record.
*/
- if (err != EAGAIN) {
+ if (err != EAGAIN || rwa->heal) {
if (rwa->err == 0)
rwa->err = err;
kmem_free(rrd, sizeof (*rrd));
@@ -2839,10 +3213,13 @@ receive_writer_thread(void *arg)
}
kmem_free(rrd, sizeof (*rrd));
- int err = flush_write_batch(rwa);
- if (rwa->err == 0)
- rwa->err = err;
-
+ if (rwa->heal) {
+ zio_wait(rwa->heal_pio);
+ } else {
+ int err = flush_write_batch(rwa);
+ if (rwa->err == 0)
+ rwa->err = err;
+ }
mutex_enter(&rwa->mutex);
rwa->done = B_TRUE;
cv_signal(&rwa->cv);
@@ -2926,17 +3303,19 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
if (err != 0)
goto out;
- /*
- * If this is a new dataset we set the key immediately.
- * Otherwise we don't want to change the key until we
- * are sure the rest of the receive succeeded so we stash
- * the keynvl away until then.
- */
- err = dsl_crypto_recv_raw(spa_name(drc->drc_os->os_spa),
- drc->drc_ds->ds_object, drc->drc_fromsnapobj,
- drc->drc_drrb->drr_type, keynvl, drc->drc_newfs);
- if (err != 0)
- goto out;
+ if (!drc->drc_heal) {
+ /*
+ * If this is a new dataset we set the key immediately.
+ * Otherwise we don't want to change the key until we
+ * are sure the rest of the receive succeeded so we
+ * stash the keynvl away until then.
+ */
+ err = dsl_crypto_recv_raw(spa_name(drc->drc_os->os_spa),
+ drc->drc_ds->ds_object, drc->drc_fromsnapobj,
+ drc->drc_drrb->drr_type, keynvl, drc->drc_newfs);
+ if (err != 0)
+ goto out;
+ }
/* see comment in dmu_recv_end_sync() */
drc->drc_ivset_guid = 0;
@@ -2954,6 +3333,17 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
}
/*
+ * For compatibility with recursive send streams, we do this here,
+ * rather than in dmu_recv_begin. If we pull the next header too
+ * early, and it's the END record, we break the `recv_skip` logic.
+ */
+ if (drc->drc_drr_begin->drr_payloadlen == 0) {
+ err = receive_read_payload_and_next_header(drc, 0, NULL);
+ if (err != 0)
+ goto out;
+ }
+
+ /*
* If we failed before this point we will clean up any new resume
* state that was created. Now that we've gotten past the initial
* checks we are ok to retain that resume state.
@@ -2967,11 +3357,17 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
mutex_init(&rwa->mutex, NULL, MUTEX_DEFAULT, NULL);
rwa->os = drc->drc_os;
rwa->byteswap = drc->drc_byteswap;
+ rwa->heal = drc->drc_heal;
+ rwa->tofs = drc->drc_tofs;
rwa->resumable = drc->drc_resumable;
rwa->raw = drc->drc_raw;
rwa->spill = drc->drc_spill;
rwa->full = (drc->drc_drr_begin->drr_u.drr_begin.drr_fromguid == 0);
rwa->os->os_raw_receive = drc->drc_raw;
+ if (drc->drc_heal) {
+ rwa->heal_pio = zio_root(drc->drc_os->os_spa, NULL, NULL,
+ ZIO_FLAG_GODFATHER);
+ }
list_create(&rwa->write_batch, sizeof (struct receive_record_arg),
offsetof(struct receive_record_arg, node.bqn_node));
@@ -3107,7 +3503,9 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
ASSERT3P(drc->drc_ds->ds_owner, ==, dmu_recv_tag);
- if (!drc->drc_newfs) {
+ if (drc->drc_heal) {
+ error = 0;
+ } else if (!drc->drc_newfs) {
dsl_dataset_t *origin_head;
error = dsl_dataset_hold(dp, drc->drc_tofs, FTAG, &origin_head);
@@ -3183,13 +3581,18 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
dmu_recv_cookie_t *drc = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
boolean_t encrypted = drc->drc_ds->ds_dir->dd_crypto_obj != 0;
- uint64_t newsnapobj;
+ uint64_t newsnapobj = 0;
spa_history_log_internal_ds(drc->drc_ds, "finish receiving",
tx, "snap=%s", drc->drc_tosnap);
drc->drc_ds->ds_objset->os_raw_receive = B_FALSE;
- if (!drc->drc_newfs) {
+ if (drc->drc_heal) {
+ if (drc->drc_keynvl != NULL) {
+ nvlist_free(drc->drc_keynvl);
+ drc->drc_keynvl = NULL;
+ }
+ } else if (!drc->drc_newfs) {
dsl_dataset_t *origin_head;
VERIFY0(dsl_dataset_hold(dp, drc->drc_tofs, FTAG,
@@ -3303,7 +3706,7 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
* tunable is set, in which case we will leave the newly-generated
* value.
*/
- if (drc->drc_raw && drc->drc_ivset_guid != 0) {
+ if (!drc->drc_heal && drc->drc_raw && drc->drc_ivset_guid != 0) {
dmu_object_zapify(dp->dp_meta_objset, newsnapobj,
DMU_OT_DSL_DATASET, tx);
VERIFY0(zap_update(dp->dp_meta_objset, newsnapobj,
@@ -3370,7 +3773,7 @@ dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
if (error != 0) {
dmu_recv_cleanup_ds(drc);
nvlist_free(drc->drc_keynvl);
- } else {
+ } else if (!drc->drc_heal) {
if (drc->drc_newfs) {
zvol_create_minor(drc->drc_tofs);
}
@@ -3392,11 +3795,15 @@ dmu_objset_is_receiving(objset_t *os)
os->os_dsl_dataset->ds_owner == dmu_recv_tag);
}
-ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, queue_length, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, queue_length, UINT, ZMOD_RW,
"Maximum receive queue length");
-ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, queue_ff, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, queue_ff, UINT, ZMOD_RW,
"Receive queue fill fraction");
-ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, write_batch_size, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, write_batch_size, UINT, ZMOD_RW,
"Maximum amount of writes to batch into one transaction");
+
+ZFS_MODULE_PARAM(zfs_recv, zfs_recv_, best_effort_corrective, INT, ZMOD_RW,
+ "Ignore errors during corrective receive");
+/* END CSTYLED */
diff --git a/module/zfs/dmu_redact.c b/module/zfs/dmu_redact.c
index ae2e65d5c4b8..5ac14edfca12 100644
--- a/module/zfs/dmu_redact.c
+++ b/module/zfs/dmu_redact.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -142,7 +142,7 @@ record_merge_enqueue(bqueue_t *q, struct redact_record **build,
{
if (new->eos_marker) {
if (*build != NULL)
- bqueue_enqueue(q, *build, sizeof (*build));
+ bqueue_enqueue(q, *build, sizeof (**build));
bqueue_enqueue_flush(q, new, sizeof (*new));
return;
}
@@ -746,10 +746,8 @@ perform_thread_merge(bqueue_t *q, uint32_t num_threads,
bqueue_enqueue(q, record, sizeof (*record));
return (0);
}
- if (num_threads > 0) {
- redact_nodes = kmem_zalloc(num_threads *
- sizeof (*redact_nodes), KM_SLEEP);
- }
+ redact_nodes = vmem_zalloc(num_threads *
+ sizeof (*redact_nodes), KM_SLEEP);
avl_create(&start_tree, redact_node_compare_start,
sizeof (struct redact_node),
@@ -822,9 +820,9 @@ perform_thread_merge(bqueue_t *q, uint32_t num_threads,
avl_destroy(&start_tree);
avl_destroy(&end_tree);
- kmem_free(redact_nodes, num_threads * sizeof (*redact_nodes));
+ vmem_free(redact_nodes, num_threads * sizeof (*redact_nodes));
if (current_record != NULL)
- bqueue_enqueue(q, current_record, sizeof (current_record));
+ bqueue_enqueue(q, current_record, sizeof (*current_record));
return (err);
}
@@ -1032,7 +1030,7 @@ dmu_redact_snap(const char *snapname, nvlist_t *redactnvl,
numsnaps = fnvlist_num_pairs(redactnvl);
if (numsnaps > 0)
- args = kmem_zalloc(numsnaps * sizeof (*args), KM_SLEEP);
+ args = vmem_zalloc(numsnaps * sizeof (*args), KM_SLEEP);
nvpair_t *pair = NULL;
for (int i = 0; i < numsnaps; i++) {
@@ -1081,7 +1079,7 @@ dmu_redact_snap(const char *snapname, nvlist_t *redactnvl,
kmem_free(newredactbook,
sizeof (char) * ZFS_MAX_DATASET_NAME_LEN);
if (args != NULL)
- kmem_free(args, numsnaps * sizeof (*args));
+ vmem_free(args, numsnaps * sizeof (*args));
return (SET_ERROR(ENAMETOOLONG));
}
err = dsl_bookmark_lookup(dp, newredactbook, NULL, &bookmark);
@@ -1121,7 +1119,7 @@ dmu_redact_snap(const char *snapname, nvlist_t *redactnvl,
} else {
uint64_t *guids = NULL;
if (numsnaps > 0) {
- guids = kmem_zalloc(numsnaps * sizeof (uint64_t),
+ guids = vmem_zalloc(numsnaps * sizeof (uint64_t),
KM_SLEEP);
}
for (int i = 0; i < numsnaps; i++) {
@@ -1133,10 +1131,9 @@ dmu_redact_snap(const char *snapname, nvlist_t *redactnvl,
dp = NULL;
err = dsl_bookmark_create_redacted(newredactbook, snapname,
numsnaps, guids, FTAG, &new_rl);
- kmem_free(guids, numsnaps * sizeof (uint64_t));
- if (err != 0) {
+ vmem_free(guids, numsnaps * sizeof (uint64_t));
+ if (err != 0)
goto out;
- }
}
for (int i = 0; i < numsnaps; i++) {
@@ -1190,7 +1187,7 @@ out:
}
if (args != NULL)
- kmem_free(args, numsnaps * sizeof (*args));
+ vmem_free(args, numsnaps * sizeof (*args));
if (dp != NULL)
dsl_pool_rele(dp, FTAG);
if (ds != NULL) {
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c
index ca0163891c07..b6cc2f0a5e91 100644
--- a/module/zfs/dmu_send.c
+++ b/module/zfs/dmu_send.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -75,7 +75,7 @@ static int zfs_send_corrupt_data = B_FALSE;
* thread is issuing new reads because the prefetches have fallen out of the
* cache, this may need to be decreased.
*/
-static int zfs_send_queue_length = SPA_MAXBLOCKSIZE;
+static uint_t zfs_send_queue_length = SPA_MAXBLOCKSIZE;
/*
* This tunable controls the length of the queues that zfs send worker threads
* use to communicate. If the send_main_thread is blocking on these queues,
@@ -83,7 +83,7 @@ static int zfs_send_queue_length = SPA_MAXBLOCKSIZE;
* at the start of a send as these threads consume all the available IO
* resources, this variable may need to be decreased.
*/
-static int zfs_send_no_prefetch_queue_length = 1024 * 1024;
+static uint_t zfs_send_no_prefetch_queue_length = 1024 * 1024;
/*
* These tunables control the fill fraction of the queues by zfs send. The fill
* fraction controls the frequency with which threads have to be cv_signaled.
@@ -91,13 +91,13 @@ static int zfs_send_no_prefetch_queue_length = 1024 * 1024;
* down. If the queues empty before the signalled thread can catch up, then
* these should be tuned up.
*/
-static int zfs_send_queue_ff = 20;
-static int zfs_send_no_prefetch_queue_ff = 20;
+static uint_t zfs_send_queue_ff = 20;
+static uint_t zfs_send_no_prefetch_queue_ff = 20;
/*
* Use this to override the recordsize calculation for fast zfs send estimates.
*/
-static int zfs_override_estimate_recordsize = 0;
+static uint_t zfs_override_estimate_recordsize = 0;
/* Set this tunable to FALSE to disable setting of DRR_FLAG_FREERECORDS */
static const boolean_t zfs_send_set_freerecords_bit = B_TRUE;
@@ -585,7 +585,13 @@ dump_write_embedded(dmu_send_cookie_t *dscp, uint64_t object, uint64_t offset,
decode_embedded_bp_compressed(bp, buf);
- if (dump_record(dscp, buf, P2ROUNDUP(drrw->drr_psize, 8)) != 0)
+ uint32_t psize = drrw->drr_psize;
+ uint32_t rsize = P2ROUNDUP(psize, 8);
+
+ if (psize != rsize)
+ memset(buf + psize, 0, rsize - psize);
+
+ if (dump_record(dscp, buf, rsize) != 0)
return (SET_ERROR(EINTR));
return (0);
}
@@ -613,7 +619,7 @@ dump_spill(dmu_send_cookie_t *dscp, const blkptr_t *bp, uint64_t object,
/* See comment in dump_dnode() for full details */
if (zfs_send_unmodified_spill_blocks &&
- (bp->blk_birth <= dscp->dsc_fromtxg)) {
+ (BP_GET_LOGICAL_BIRTH(bp) <= dscp->dsc_fromtxg)) {
drrs->drr_flags |= DRR_SPILL_UNMODIFIED;
}
@@ -798,7 +804,7 @@ dump_dnode(dmu_send_cookie_t *dscp, const blkptr_t *bp, uint64_t object,
*/
if (zfs_send_unmodified_spill_blocks &&
(dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) &&
- (DN_SPILL_BLKPTR(dnp)->blk_birth <= dscp->dsc_fromtxg)) {
+ (BP_GET_LOGICAL_BIRTH(DN_SPILL_BLKPTR(dnp)) <= dscp->dsc_fromtxg)) {
struct send_range record;
blkptr_t *bp = DN_SPILL_BLKPTR(dnp);
@@ -935,7 +941,7 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
ASSERT3U(range->start_blkid + 1, ==, range->end_blkid);
if (BP_GET_TYPE(bp) == DMU_OT_SA) {
arc_flags_t aflags = ARC_FLAG_WAIT;
- enum zio_flag zioflags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zioflags = ZIO_FLAG_CANFAIL;
if (dscp->dsc_featureflags & DMU_BACKUP_FEATURE_RAW) {
ASSERT(BP_IS_PROTECTED(bp));
@@ -1018,9 +1024,6 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
if (srdp->datablksz > SPA_OLD_MAXBLOCKSIZE &&
!(dscp->dsc_featureflags &
DMU_BACKUP_FEATURE_LARGE_BLOCKS)) {
- if (dscp->dsc_featureflags & DMU_BACKUP_FEATURE_RAW)
- return (SET_ERROR(ENOTSUP));
-
while (srdp->datablksz > 0 && err == 0) {
int n = MIN(srdp->datablksz,
SPA_OLD_MAXBLOCKSIZE);
@@ -1120,9 +1123,7 @@ send_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
*/
if (sta->os->os_encrypted &&
!BP_IS_HOLE(bp) && !BP_USES_CRYPT(bp)) {
- spa_log_error(spa, zb);
- zfs_panic_recover("unencrypted block in encrypted "
- "object set %llu", dmu_objset_id(sta->os));
+ spa_log_error(spa, zb, BP_GET_LOGICAL_BIRTH(bp));
return (SET_ERROR(EIO));
}
@@ -1590,8 +1591,6 @@ send_merge_thread(void *arg)
}
range_free(front_ranges[i]);
}
- if (range == NULL)
- range = kmem_zalloc(sizeof (*range), KM_SLEEP);
range->eos_marker = B_TRUE;
bqueue_enqueue_flush(&smt_arg->q, range, 1);
spl_fstrans_unmark(cookie);
@@ -1658,7 +1657,7 @@ issue_data_read(struct send_reader_thread_arg *srta, struct send_range *range)
!split_large_blocks && !BP_SHOULD_BYTESWAP(bp) &&
!BP_IS_EMBEDDED(bp) && !DMU_OT_IS_METADATA(BP_GET_TYPE(bp));
- enum zio_flag zioflags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zioflags = ZIO_FLAG_CANFAIL;
if (srta->featureflags & DMU_BACKUP_FEATURE_RAW) {
zioflags |= ZIO_FLAG_RAW;
@@ -1718,8 +1717,10 @@ enqueue_range(struct send_reader_thread_arg *srta, bqueue_t *q, dnode_t *dn,
struct send_range *range = range_alloc(range_type, dn->dn_object,
blkid, blkid + count, B_FALSE);
- if (blkid == DMU_SPILL_BLKID)
+ if (blkid == DMU_SPILL_BLKID) {
+ ASSERT3P(bp, !=, NULL);
ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_SA);
+ }
switch (range_type) {
case HOLE:
@@ -1840,8 +1841,7 @@ send_reader_thread(void *arg)
continue;
}
uint64_t file_max =
- (dn->dn_maxblkid < range->end_blkid ?
- dn->dn_maxblkid : range->end_blkid);
+ MIN(dn->dn_maxblkid, range->end_blkid);
/*
* The object exists, so we need to try to find the
* blkptr for each block in the range we're processing.
@@ -1953,7 +1953,7 @@ setup_featureflags(struct dmu_send_params *dspp, objset_t *os,
{
dsl_dataset_t *to_ds = dspp->to_ds;
dsl_pool_t *dp = dspp->dp;
-#ifdef _KERNEL
+
if (dmu_objset_type(os) == DMU_OST_ZFS) {
uint64_t version;
if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &version) != 0)
@@ -1962,7 +1962,6 @@ setup_featureflags(struct dmu_send_params *dspp, objset_t *os,
if (version >= ZPL_VERSION_SA)
*featureflags |= DMU_BACKUP_FEATURE_SA_SPILL;
}
-#endif
/* raw sends imply large_block_ok */
if ((dspp->rawok || dspp->large_block_ok) &&
@@ -2515,8 +2514,7 @@ dmu_send_impl(struct dmu_send_params *dspp)
}
if (featureflags & DMU_BACKUP_FEATURE_RAW) {
- uint64_t ivset_guid = (ancestor_zb != NULL) ?
- ancestor_zb->zbm_ivset_guid : 0;
+ uint64_t ivset_guid = ancestor_zb->zbm_ivset_guid;
nvlist_t *keynvl = NULL;
ASSERT(os->os_encrypted);
@@ -2720,6 +2718,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);
}
@@ -2788,6 +2790,7 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
}
if (err == 0) {
+ owned = B_TRUE;
err = zap_lookup(dspp.dp->dp_meta_objset,
dspp.to_ds->ds_object,
DS_FIELD_RESUME_TOGUID, 8, 1,
@@ -2801,21 +2804,24 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
sizeof (dspp.saved_toname),
dspp.saved_toname);
}
- if (err != 0)
+ /* Only disown if there was an error in the lookups */
+ if (owned && (err != 0))
dsl_dataset_disown(dspp.to_ds, dsflags, FTAG);
kmem_strfree(name);
} else {
err = dsl_dataset_own(dspp.dp, tosnap, dsflags,
FTAG, &dspp.to_ds);
+ if (err == 0)
+ owned = B_TRUE;
}
- owned = B_TRUE;
} else {
err = dsl_dataset_hold_flags(dspp.dp, tosnap, dsflags, FTAG,
&dspp.to_ds);
}
if (err != 0) {
+ /* Note: dsl dataset is not owned at this point */
dsl_pool_rele(dspp.dp, FTAG);
return (err);
}
@@ -2928,6 +2934,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 {
@@ -3020,7 +3030,7 @@ dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds,
dsl_dataset_name(origds, dsname);
(void) strcat(dsname, "/");
- (void) strcat(dsname, recv_clone_name);
+ (void) strlcat(dsname, recv_clone_name, sizeof (dsname));
err = dsl_dataset_hold(origds->ds_dir->dd_pool,
dsname, FTAG, &ds);
@@ -3093,20 +3103,20 @@ out:
ZFS_MODULE_PARAM(zfs_send, zfs_send_, corrupt_data, INT, ZMOD_RW,
"Allow sending corrupt data");
-ZFS_MODULE_PARAM(zfs_send, zfs_send_, queue_length, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_send, zfs_send_, queue_length, UINT, ZMOD_RW,
"Maximum send queue length");
ZFS_MODULE_PARAM(zfs_send, zfs_send_, unmodified_spill_blocks, INT, ZMOD_RW,
"Send unmodified spill blocks");
-ZFS_MODULE_PARAM(zfs_send, zfs_send_, no_prefetch_queue_length, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_send, zfs_send_, no_prefetch_queue_length, UINT, ZMOD_RW,
"Maximum send queue length for non-prefetch queues");
-ZFS_MODULE_PARAM(zfs_send, zfs_send_, queue_ff, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_send, zfs_send_, queue_ff, UINT, ZMOD_RW,
"Send queue fill fraction");
-ZFS_MODULE_PARAM(zfs_send, zfs_send_, no_prefetch_queue_ff, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_send, zfs_send_, no_prefetch_queue_ff, UINT, ZMOD_RW,
"Send queue fill fraction for non-prefetch queues");
-ZFS_MODULE_PARAM(zfs_send, zfs_, override_estimate_recordsize, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_send, zfs_, override_estimate_recordsize, UINT, ZMOD_RW,
"Override block size estimate with fixed size");
diff --git a/module/zfs/dmu_traverse.c b/module/zfs/dmu_traverse.c
index 41baff73a172..15cc2885e805 100644
--- a/module/zfs/dmu_traverse.c
+++ b/module/zfs/dmu_traverse.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,7 +41,7 @@
static int32_t zfs_pd_bytes_max = 50 * 1024 * 1024; /* 50MB */
static int32_t send_holes_without_birth_time = 1;
-static int32_t zfs_traverse_indirect_prefetch_limit = 32;
+static uint_t zfs_traverse_indirect_prefetch_limit = 32;
typedef struct prefetch_data {
kmutex_t pd_mtx;
@@ -83,7 +83,8 @@ traverse_zil_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
if (BP_IS_HOLE(bp))
return (0);
- if (claim_txg == 0 && bp->blk_birth >= spa_min_claim_txg(td->td_spa))
+ if (claim_txg == 0 &&
+ BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(td->td_spa))
return (-1);
SET_BOOKMARK(&zb, td->td_objset, ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
@@ -108,9 +109,10 @@ traverse_zil_record(zilog_t *zilog, const lr_t *lrc, void *arg,
if (BP_IS_HOLE(bp))
return (0);
- if (claim_txg == 0 || bp->blk_birth < claim_txg)
+ if (claim_txg == 0 || BP_GET_LOGICAL_BIRTH(bp) < claim_txg)
return (0);
+ ASSERT3U(BP_GET_LSIZE(bp), !=, 0);
SET_BOOKMARK(&zb, td->td_objset, lr->lr_foid,
ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp));
@@ -153,10 +155,10 @@ typedef enum resume_skip {
* Otherwise returns RESUME_SKIP_NONE.
*/
static resume_skip_t
-resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
+resume_skip_check(const traverse_data_t *td, const dnode_phys_t *dnp,
const zbookmark_phys_t *zb)
{
- if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume)) {
+ if (td->td_resume != NULL) {
/*
* If we already visited this bp & everything below,
* don't bother doing it again.
@@ -164,12 +166,7 @@ resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
if (zbookmark_subtree_completed(dnp, zb, td->td_resume))
return (RESUME_SKIP_ALL);
- /*
- * If we found the block we're trying to resume from, zero
- * the bookmark out to indicate that we have resumed.
- */
if (memcmp(zb, td->td_resume, sizeof (*zb)) == 0) {
- memset(td->td_resume, 0, sizeof (*zb));
if (td->td_flags & TRAVERSE_POST)
return (RESUME_SKIP_CHILDREN);
}
@@ -181,22 +178,22 @@ resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
* Returns B_TRUE, if prefetch read is issued, otherwise B_FALSE.
*/
static boolean_t
-traverse_prefetch_metadata(traverse_data_t *td,
+traverse_prefetch_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
const blkptr_t *bp, const zbookmark_phys_t *zb)
{
- arc_flags_t flags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH;
+ arc_flags_t flags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH |
+ ARC_FLAG_PRESCIENT_PREFETCH;
int zio_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE;
if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA))
return (B_FALSE);
/*
- * If we are in the process of resuming, don't prefetch, because
- * some children will not be needed (and in fact may have already
- * been freed).
+ * If this bp is before the resume point, it may have already been
+ * freed.
*/
- if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume))
+ if (resume_skip_check(td, dnp, zb) != RESUME_SKIP_NONE)
return (B_FALSE);
- if (BP_IS_HOLE(bp) || bp->blk_birth <= td->td_min_txg)
+ if (BP_IS_HOLE(bp) || BP_GET_LOGICAL_BIRTH(bp) <= td->td_min_txg)
return (B_FALSE);
if (BP_GET_LEVEL(bp) == 0 && BP_GET_TYPE(bp) != DMU_OT_DNODE)
return (B_FALSE);
@@ -239,7 +236,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
ASSERT(0);
}
- if (bp->blk_birth == 0) {
+ if (BP_GET_LOGICAL_BIRTH(bp) == 0) {
/*
* Since this block has a birth time of 0 it must be one of
* two things: a hole created before the
@@ -267,7 +264,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
zb->zb_object == DMU_META_DNODE_OBJECT) &&
td->td_hole_birth_enabled_txg <= td->td_min_txg)
return (0);
- } else if (bp->blk_birth <= td->td_min_txg) {
+ } else if (BP_GET_LOGICAL_BIRTH(bp) <= td->td_min_txg) {
return (0);
}
@@ -342,7 +339,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
SET_BOOKMARK(czb, zb->zb_objset,
zb->zb_object, zb->zb_level - 1,
zb->zb_blkid * epb + pidx);
- if (traverse_prefetch_metadata(td,
+ if (traverse_prefetch_metadata(td, dnp,
&((blkptr_t *)buf->b_data)[pidx],
czb) == B_TRUE) {
prefetched++;
@@ -504,12 +501,12 @@ prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
for (j = 0; j < dnp->dn_nblkptr; j++) {
SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
- traverse_prefetch_metadata(td, &dnp->dn_blkptr[j], &czb);
+ traverse_prefetch_metadata(td, dnp, &dnp->dn_blkptr[j], &czb);
}
if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
- traverse_prefetch_metadata(td, DN_SPILL_BLKPTR(dnp), &czb);
+ traverse_prefetch_metadata(td, dnp, DN_SPILL_BLKPTR(dnp), &czb);
}
}
@@ -670,7 +667,7 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
/* See comment on ZIL traversal in dsl_scan_visitds. */
if (ds != NULL && !ds->ds_is_snapshot && !BP_IS_HOLE(rootbp)) {
- enum zio_flag zio_flags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zio_flags = ZIO_FLAG_CANFAIL;
uint32_t flags = ARC_FLAG_WAIT;
objset_phys_t *osp;
arc_buf_t *buf;
@@ -812,7 +809,7 @@ EXPORT_SYMBOL(traverse_pool);
ZFS_MODULE_PARAM(zfs, zfs_, pd_bytes_max, INT, ZMOD_RW,
"Max number of bytes to prefetch");
-ZFS_MODULE_PARAM(zfs, zfs_, traverse_indirect_prefetch_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, traverse_indirect_prefetch_limit, UINT, ZMOD_RW,
"Traverse prefetch number of blocks pointed by indirect block");
#if defined(_KERNEL)
diff --git a/module/zfs/dmu_tx.c b/module/zfs/dmu_tx.c
index e7bd53136b85..8451b5082e86 100644
--- a/module/zfs/dmu_tx.c
+++ b/module/zfs/dmu_tx.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -210,11 +210,18 @@ dmu_tx_check_ioerr(zio_t *zio, dnode_t *dn, int level, uint64_t blkid)
dmu_buf_impl_t *db;
rw_enter(&dn->dn_struct_rwlock, RW_READER);
- db = dbuf_hold_level(dn, level, blkid, FTAG);
+ err = dbuf_hold_impl(dn, level, blkid, TRUE, FALSE, FTAG, &db);
rw_exit(&dn->dn_struct_rwlock);
- if (db == NULL)
- return (SET_ERROR(EIO));
- err = dbuf_read(db, zio, DB_RF_CANFAIL | DB_RF_NOPREFETCH);
+ if (err == ENOENT)
+ return (0);
+ if (err != 0)
+ return (err);
+ /*
+ * PARTIAL_FIRST allows caching for uncacheable blocks. It will
+ * be cleared after dmu_buf_will_dirty() call dbuf_read() again.
+ */
+ err = dbuf_read(db, zio, DB_RF_CANFAIL | DB_RF_NOPREFETCH |
+ (level == 0 ? DB_RF_PARTIAL_FIRST : 0));
dbuf_rele(db, FTAG);
return (err);
}
@@ -290,6 +297,53 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
}
static void
+dmu_tx_count_append(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
+{
+ dnode_t *dn = txh->txh_dnode;
+ int err = 0;
+
+ if (len == 0)
+ return;
+
+ (void) zfs_refcount_add_many(&txh->txh_space_towrite, len, FTAG);
+
+ if (dn == NULL)
+ return;
+
+ /*
+ * For i/o error checking, read the blocks that will be needed
+ * to perform the append; first level-0 block (if not aligned, i.e.
+ * if they are partial-block writes), no additional blocks are read.
+ */
+ if (dn->dn_maxblkid == 0) {
+ if (off < dn->dn_datablksz &&
+ (off > 0 || len < dn->dn_datablksz)) {
+ err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
+ if (err != 0) {
+ txh->txh_tx->tx_err = err;
+ }
+ }
+ } else {
+ zio_t *zio = zio_root(dn->dn_objset->os_spa,
+ NULL, NULL, ZIO_FLAG_CANFAIL);
+
+ /* first level-0 block */
+ uint64_t start = off >> dn->dn_datablkshift;
+ if (P2PHASE(off, dn->dn_datablksz) || len < dn->dn_datablksz) {
+ err = dmu_tx_check_ioerr(zio, dn, 0, start);
+ if (err != 0) {
+ txh->txh_tx->tx_err = err;
+ }
+ }
+
+ err = zio_wait(zio);
+ if (err != 0) {
+ txh->txh_tx->tx_err = err;
+ }
+ }
+}
+
+static void
dmu_tx_count_dnode(dmu_tx_hold_t *txh)
{
(void) zfs_refcount_add_many(&txh->txh_space_towrite,
@@ -330,6 +384,42 @@ dmu_tx_hold_write_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
}
/*
+ * Should be used when appending to an object and the exact offset is unknown.
+ * The write must occur at or beyond the specified offset. Only the L0 block
+ * at provided offset will be prefetched.
+ */
+void
+dmu_tx_hold_append(dmu_tx_t *tx, uint64_t object, uint64_t off, int len)
+{
+ dmu_tx_hold_t *txh;
+
+ ASSERT0(tx->tx_txg);
+ ASSERT3U(len, <=, DMU_MAX_ACCESS);
+
+ txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
+ object, THT_APPEND, off, DMU_OBJECT_END);
+ if (txh != NULL) {
+ dmu_tx_count_append(txh, off, len);
+ dmu_tx_count_dnode(txh);
+ }
+}
+
+void
+dmu_tx_hold_append_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
+{
+ dmu_tx_hold_t *txh;
+
+ ASSERT0(tx->tx_txg);
+ ASSERT3U(len, <=, DMU_MAX_ACCESS);
+
+ txh = dmu_tx_hold_dnode_impl(tx, dn, THT_APPEND, off, DMU_OBJECT_END);
+ if (txh != NULL) {
+ dmu_tx_count_append(txh, off, len);
+ dmu_tx_count_dnode(txh);
+ }
+}
+
+/*
* This function marks the transaction as being a "net free". The end
* result is that refquotas will be disabled for this transaction, and
* this transaction will be able to use half of the pool space overhead
@@ -344,7 +434,7 @@ dmu_tx_mark_netfree(dmu_tx_t *tx)
}
static void
-dmu_tx_hold_free_impl(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
+dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
{
dmu_tx_t *tx = txh->txh_tx;
dnode_t *dn = txh->txh_dnode;
@@ -352,15 +442,11 @@ dmu_tx_hold_free_impl(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
ASSERT(tx->tx_txg == 0);
- dmu_tx_count_dnode(txh);
-
if (off >= (dn->dn_maxblkid + 1) * dn->dn_datablksz)
return;
if (len == DMU_OBJECT_END)
len = (dn->dn_maxblkid + 1) * dn->dn_datablksz - off;
- dmu_tx_count_dnode(txh);
-
/*
* For i/o error checking, we read the first and last level-0
* blocks if they are not aligned, and all the level-1 blocks.
@@ -440,8 +526,10 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len)
txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
object, THT_FREE, off, len);
- if (txh != NULL)
- (void) dmu_tx_hold_free_impl(txh, off, len);
+ if (txh != NULL) {
+ dmu_tx_count_dnode(txh);
+ dmu_tx_count_free(txh, off, len);
+ }
}
void
@@ -450,8 +538,35 @@ dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
dmu_tx_hold_t *txh;
txh = dmu_tx_hold_dnode_impl(tx, dn, THT_FREE, off, len);
- if (txh != NULL)
- (void) dmu_tx_hold_free_impl(txh, off, len);
+ if (txh != NULL) {
+ dmu_tx_count_dnode(txh);
+ dmu_tx_count_free(txh, off, len);
+ }
+}
+
+static void
+dmu_tx_count_clone(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
+{
+
+ /*
+ * Reuse dmu_tx_count_free(), it does exactly what we need for clone.
+ */
+ dmu_tx_count_free(txh, off, len);
+}
+
+void
+dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
+{
+ dmu_tx_hold_t *txh;
+
+ ASSERT0(tx->tx_txg);
+ ASSERT(len == 0 || UINT64_MAX - off >= len - 1);
+
+ txh = dmu_tx_hold_dnode_impl(tx, dn, THT_CLONE, off, len);
+ if (txh != NULL) {
+ dmu_tx_count_dnode(txh);
+ dmu_tx_count_clone(txh, off, len);
+ }
}
static void
@@ -460,6 +575,7 @@ dmu_tx_hold_zap_impl(dmu_tx_hold_t *txh, const char *name)
dmu_tx_t *tx = txh->txh_tx;
dnode_t *dn = txh->txh_dnode;
int err;
+ extern int zap_micro_max_size;
ASSERT(tx->tx_txg == 0);
@@ -475,7 +591,7 @@ dmu_tx_hold_zap_impl(dmu_tx_hold_t *txh, const char *name)
* - 2 grown ptrtbl blocks
*/
(void) zfs_refcount_add_many(&txh->txh_space_towrite,
- MZAP_MAX_BLKSZ, FTAG);
+ zap_micro_max_size, FTAG);
if (dn == NULL)
return;
@@ -637,6 +753,26 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
if (blkid == 0)
match_offset = TRUE;
break;
+ case THT_APPEND:
+ if (blkid >= beginblk && (blkid <= endblk ||
+ txh->txh_arg2 == DMU_OBJECT_END))
+ match_offset = TRUE;
+
+ /*
+ * THT_WRITE used for bonus and spill blocks.
+ */
+ ASSERT(blkid != DMU_BONUS_BLKID &&
+ blkid != DMU_SPILL_BLKID);
+
+ /*
+ * They might have to increase nlevels,
+ * thus dirtying the new TLIBs. Or the
+ * might have to change the block size,
+ * thus dirying the new lvl=0 blk=0.
+ */
+ if (blkid == 0)
+ match_offset = TRUE;
+ break;
case THT_FREE:
/*
* We will dirty all the level 1 blocks in
@@ -661,6 +797,10 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
case THT_NEWOBJECT:
match_object = TRUE;
break;
+ case THT_CLONE:
+ if (blkid >= beginblk && blkid <= endblk)
+ match_offset = TRUE;
+ break;
default:
cmn_err(CE_PANIC, "bad txh_type %d",
txh->txh_type);
@@ -1258,8 +1398,7 @@ dmu_tx_do_callbacks(list_t *cb_list, int error)
{
dmu_tx_callback_t *dcb;
- while ((dcb = list_tail(cb_list)) != NULL) {
- list_remove(cb_list, dcb);
+ while ((dcb = list_remove_tail(cb_list)) != NULL) {
dcb->dcb_func(dcb->dcb_data, error);
kmem_free(dcb, sizeof (dmu_tx_callback_t));
}
@@ -1419,6 +1558,8 @@ dmu_tx_fini(void)
EXPORT_SYMBOL(dmu_tx_create);
EXPORT_SYMBOL(dmu_tx_hold_write);
EXPORT_SYMBOL(dmu_tx_hold_write_by_dnode);
+EXPORT_SYMBOL(dmu_tx_hold_append);
+EXPORT_SYMBOL(dmu_tx_hold_append_by_dnode);
EXPORT_SYMBOL(dmu_tx_hold_free);
EXPORT_SYMBOL(dmu_tx_hold_free_by_dnode);
EXPORT_SYMBOL(dmu_tx_hold_zap);
diff --git a/module/zfs/dmu_zfetch.c b/module/zfs/dmu_zfetch.c
index d00a48159aeb..ed50f1889b59 100644
--- a/module/zfs/dmu_zfetch.c
+++ b/module/zfs/dmu_zfetch.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,6 +28,7 @@
*/
#include <sys/zfs_context.h>
+#include <sys/arc_impl.h>
#include <sys/dnode.h>
#include <sys/dmu_objset.h>
#include <sys/dmu_zfetch.h>
@@ -51,34 +52,55 @@ static unsigned int zfetch_max_streams = 8;
static unsigned int zfetch_min_sec_reap = 1;
/* max time before stream delete */
static unsigned int zfetch_max_sec_reap = 2;
+#ifdef _ILP32
+/* min bytes to prefetch per stream (default 2MB) */
+static unsigned int zfetch_min_distance = 2 * 1024 * 1024;
+/* max bytes to prefetch per stream (default 8MB) */
+unsigned int zfetch_max_distance = 8 * 1024 * 1024;
+#else
/* min bytes to prefetch per stream (default 4MB) */
static unsigned int zfetch_min_distance = 4 * 1024 * 1024;
/* max bytes to prefetch per stream (default 64MB) */
unsigned int zfetch_max_distance = 64 * 1024 * 1024;
+#endif
/* max bytes to prefetch indirects for per stream (default 64MB) */
unsigned int zfetch_max_idistance = 64 * 1024 * 1024;
-/* max number of bytes in an array_read in which we allow prefetching (1MB) */
-unsigned long zfetch_array_rd_sz = 1024 * 1024;
+/* max request reorder distance within a stream (default 16MB) */
+unsigned int zfetch_max_reorder = 16 * 1024 * 1024;
+/* Max log2 fraction of holes in a stream */
+unsigned int zfetch_hole_shift = 2;
typedef struct zfetch_stats {
kstat_named_t zfetchstat_hits;
+ kstat_named_t zfetchstat_future;
+ kstat_named_t zfetchstat_stride;
+ kstat_named_t zfetchstat_past;
kstat_named_t zfetchstat_misses;
kstat_named_t zfetchstat_max_streams;
kstat_named_t zfetchstat_io_issued;
+ kstat_named_t zfetchstat_io_active;
} zfetch_stats_t;
static zfetch_stats_t zfetch_stats = {
{ "hits", KSTAT_DATA_UINT64 },
+ { "future", KSTAT_DATA_UINT64 },
+ { "stride", KSTAT_DATA_UINT64 },
+ { "past", KSTAT_DATA_UINT64 },
{ "misses", KSTAT_DATA_UINT64 },
{ "max_streams", KSTAT_DATA_UINT64 },
- { "io_issued", KSTAT_DATA_UINT64 },
+ { "io_issued", KSTAT_DATA_UINT64 },
+ { "io_active", KSTAT_DATA_UINT64 },
};
struct {
wmsum_t zfetchstat_hits;
+ wmsum_t zfetchstat_future;
+ wmsum_t zfetchstat_stride;
+ wmsum_t zfetchstat_past;
wmsum_t zfetchstat_misses;
wmsum_t zfetchstat_max_streams;
wmsum_t zfetchstat_io_issued;
+ aggsum_t zfetchstat_io_active;
} zfetch_sums;
#define ZFETCHSTAT_BUMP(stat) \
@@ -98,12 +120,20 @@ zfetch_kstats_update(kstat_t *ksp, int rw)
return (EACCES);
zs->zfetchstat_hits.value.ui64 =
wmsum_value(&zfetch_sums.zfetchstat_hits);
+ zs->zfetchstat_future.value.ui64 =
+ wmsum_value(&zfetch_sums.zfetchstat_future);
+ zs->zfetchstat_stride.value.ui64 =
+ wmsum_value(&zfetch_sums.zfetchstat_stride);
+ zs->zfetchstat_past.value.ui64 =
+ wmsum_value(&zfetch_sums.zfetchstat_past);
zs->zfetchstat_misses.value.ui64 =
wmsum_value(&zfetch_sums.zfetchstat_misses);
zs->zfetchstat_max_streams.value.ui64 =
wmsum_value(&zfetch_sums.zfetchstat_max_streams);
zs->zfetchstat_io_issued.value.ui64 =
wmsum_value(&zfetch_sums.zfetchstat_io_issued);
+ zs->zfetchstat_io_active.value.ui64 =
+ aggsum_value(&zfetch_sums.zfetchstat_io_active);
return (0);
}
@@ -111,9 +141,13 @@ void
zfetch_init(void)
{
wmsum_init(&zfetch_sums.zfetchstat_hits, 0);
+ wmsum_init(&zfetch_sums.zfetchstat_future, 0);
+ wmsum_init(&zfetch_sums.zfetchstat_stride, 0);
+ wmsum_init(&zfetch_sums.zfetchstat_past, 0);
wmsum_init(&zfetch_sums.zfetchstat_misses, 0);
wmsum_init(&zfetch_sums.zfetchstat_max_streams, 0);
wmsum_init(&zfetch_sums.zfetchstat_io_issued, 0);
+ aggsum_init(&zfetch_sums.zfetchstat_io_active, 0);
zfetch_ksp = kstat_create("zfs", 0, "zfetchstats", "misc",
KSTAT_TYPE_NAMED, sizeof (zfetch_stats) / sizeof (kstat_named_t),
@@ -135,9 +169,14 @@ zfetch_fini(void)
}
wmsum_fini(&zfetch_sums.zfetchstat_hits);
+ wmsum_fini(&zfetch_sums.zfetchstat_future);
+ wmsum_fini(&zfetch_sums.zfetchstat_stride);
+ wmsum_fini(&zfetch_sums.zfetchstat_past);
wmsum_fini(&zfetch_sums.zfetchstat_misses);
wmsum_fini(&zfetch_sums.zfetchstat_max_streams);
wmsum_fini(&zfetch_sums.zfetchstat_io_issued);
+ ASSERT0(aggsum_value(&zfetch_sums.zfetchstat_io_active));
+ aggsum_fini(&zfetch_sums.zfetchstat_io_active);
}
/*
@@ -208,22 +247,22 @@ static void
dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
{
zstream_t *zs, *zs_next, *zs_old = NULL;
- hrtime_t now = gethrtime(), t;
+ uint_t now = gethrestime_sec(), t;
ASSERT(MUTEX_HELD(&zf->zf_lock));
/*
* Delete too old streams, reusing the first found one.
*/
- t = now - SEC2NSEC(zfetch_max_sec_reap);
+ t = now - zfetch_max_sec_reap;
for (zs = list_head(&zf->zf_stream); zs != NULL; zs = zs_next) {
zs_next = list_next(&zf->zf_stream, zs);
/*
* Skip if still active. 1 -- zf_stream reference.
*/
- if (zfs_refcount_count(&zs->zs_refs) != 1)
+ if ((int)(zs->zs_atime - t) >= 0)
continue;
- if (zs->zs_atime > t)
+ if (zfs_refcount_count(&zs->zs_refs) != 1)
continue;
if (zs_old)
dmu_zfetch_stream_remove(zf, zs);
@@ -232,6 +271,7 @@ dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
}
if (zs_old) {
zs = zs_old;
+ list_remove(&zf->zf_stream, zs);
goto reuse;
}
@@ -241,21 +281,23 @@ dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
* for all the streams to be non-overlapping.
*/
uint32_t max_streams = MAX(1, MIN(zfetch_max_streams,
- zf->zf_dnode->dn_maxblkid * zf->zf_dnode->dn_datablksz /
+ (zf->zf_dnode->dn_maxblkid << zf->zf_dnode->dn_datablkshift) /
zfetch_max_distance));
if (zf->zf_numstreams >= max_streams) {
- t = now - SEC2NSEC(zfetch_min_sec_reap);
+ t = now - zfetch_min_sec_reap;
for (zs = list_head(&zf->zf_stream); zs != NULL;
zs = list_next(&zf->zf_stream, zs)) {
- if (zfs_refcount_count(&zs->zs_refs) != 1)
+ if ((int)(zs->zs_atime - t) >= 0)
continue;
- if (zs->zs_atime > t)
+ if (zfs_refcount_count(&zs->zs_refs) != 1)
continue;
- if (zs_old == NULL || zs->zs_atime < zs_old->zs_atime)
+ if (zs_old == NULL ||
+ (int)(zs_old->zs_atime - zs->zs_atime) >= 0)
zs_old = zs;
}
if (zs_old) {
zs = zs_old;
+ list_remove(&zf->zf_stream, zs);
goto reuse;
}
ZFETCHSTAT_BUMP(zfetchstat_max_streams);
@@ -263,24 +305,24 @@ dmu_zfetch_stream_create(zfetch_t *zf, uint64_t blkid)
}
zs = kmem_zalloc(sizeof (*zs), KM_SLEEP);
- zs->zs_fetch = zf;
zfs_refcount_create(&zs->zs_callers);
zfs_refcount_create(&zs->zs_refs);
/* One reference for zf_stream. */
zfs_refcount_add(&zs->zs_refs, NULL);
zf->zf_numstreams++;
- list_insert_head(&zf->zf_stream, zs);
reuse:
+ list_insert_head(&zf->zf_stream, zs);
zs->zs_blkid = blkid;
+ /* Allow immediate stream reuse until first hit. */
+ zs->zs_atime = now - zfetch_min_sec_reap;
+ memset(zs->zs_ranges, 0, sizeof (zs->zs_ranges));
zs->zs_pf_dist = 0;
+ zs->zs_ipf_dist = 0;
zs->zs_pf_start = blkid;
zs->zs_pf_end = blkid;
- zs->zs_ipf_dist = 0;
zs->zs_ipf_start = blkid;
zs->zs_ipf_end = blkid;
- /* Allow immediate stream reuse until first hit. */
- zs->zs_atime = now - SEC2NSEC(zfetch_min_sec_reap);
zs->zs_missed = B_FALSE;
zs->zs_more = B_FALSE;
}
@@ -294,6 +336,121 @@ dmu_zfetch_done(void *arg, uint64_t level, uint64_t blkid, boolean_t io_issued)
zs->zs_more = B_TRUE;
if (zfs_refcount_remove(&zs->zs_refs, NULL) == 0)
dmu_zfetch_stream_fini(zs);
+ aggsum_add(&zfetch_sums.zfetchstat_io_active, -1);
+}
+
+/*
+ * Process stream hit access for nblks blocks starting at zs_blkid. Return
+ * number of blocks to proceed for after aggregation with future ranges.
+ */
+static uint64_t
+dmu_zfetch_hit(zstream_t *zs, uint64_t nblks)
+{
+ uint_t i, j;
+
+ /* Optimize sequential accesses (no future ranges). */
+ if (zs->zs_ranges[0].start == 0)
+ goto done;
+
+ /* Look for intersections with further ranges. */
+ for (i = 0; i < ZFETCH_RANGES; i++) {
+ zsrange_t *r = &zs->zs_ranges[i];
+ if (r->start == 0 || r->start > nblks)
+ break;
+ if (r->end >= nblks) {
+ nblks = r->end;
+ i++;
+ break;
+ }
+ }
+
+ /* Delete all found intersecting ranges, updates remaining. */
+ for (j = 0; i < ZFETCH_RANGES; i++, j++) {
+ if (zs->zs_ranges[i].start == 0)
+ break;
+ ASSERT3U(zs->zs_ranges[i].start, >, nblks);
+ ASSERT3U(zs->zs_ranges[i].end, >, nblks);
+ zs->zs_ranges[j].start = zs->zs_ranges[i].start - nblks;
+ zs->zs_ranges[j].end = zs->zs_ranges[i].end - nblks;
+ }
+ if (j < ZFETCH_RANGES) {
+ zs->zs_ranges[j].start = 0;
+ zs->zs_ranges[j].end = 0;
+ }
+
+done:
+ zs->zs_blkid += nblks;
+ return (nblks);
+}
+
+/*
+ * Process future stream access for nblks blocks starting at blkid. Return
+ * number of blocks to proceed for if future ranges reach fill threshold.
+ */
+static uint64_t
+dmu_zfetch_future(zstream_t *zs, uint64_t blkid, uint64_t nblks)
+{
+ ASSERT3U(blkid, >, zs->zs_blkid);
+ blkid -= zs->zs_blkid;
+ ASSERT3U(blkid + nblks, <=, UINT16_MAX);
+
+ /* Search for first and last intersection or insert point. */
+ uint_t f = ZFETCH_RANGES, l = 0, i;
+ for (i = 0; i < ZFETCH_RANGES; i++) {
+ zsrange_t *r = &zs->zs_ranges[i];
+ if (r->start == 0 || r->start > blkid + nblks)
+ break;
+ if (r->end < blkid)
+ continue;
+ if (f > i)
+ f = i;
+ if (l < i)
+ l = i;
+ }
+ if (f <= l) {
+ /* Got some intersecting range, expand it if needed. */
+ if (zs->zs_ranges[f].start > blkid)
+ zs->zs_ranges[f].start = blkid;
+ zs->zs_ranges[f].end = MAX(zs->zs_ranges[l].end, blkid + nblks);
+ if (f < l) {
+ /* Got more than one intersection, remove others. */
+ for (f++, l++; l < ZFETCH_RANGES; f++, l++) {
+ zs->zs_ranges[f].start = zs->zs_ranges[l].start;
+ zs->zs_ranges[f].end = zs->zs_ranges[l].end;
+ }
+ zs->zs_ranges[f].start = 0;
+ zs->zs_ranges[f].end = 0;
+ }
+ } else if (i < ZFETCH_RANGES) {
+ /* Got no intersecting ranges, insert new one. */
+ for (l = ZFETCH_RANGES - 1; l > i; l--) {
+ zs->zs_ranges[l].start = zs->zs_ranges[l - 1].start;
+ zs->zs_ranges[l].end = zs->zs_ranges[l - 1].end;
+ }
+ zs->zs_ranges[i].start = blkid;
+ zs->zs_ranges[i].end = blkid + nblks;
+ } else {
+ /* No space left to insert. Drop the range. */
+ return (0);
+ }
+
+ /* Check if with the new access addition we reached fill threshold. */
+ if (zfetch_hole_shift >= 16)
+ return (0);
+ uint_t hole = 0;
+ for (i = f = l = 0; i < ZFETCH_RANGES; i++) {
+ zsrange_t *r = &zs->zs_ranges[i];
+ if (r->start == 0)
+ break;
+ hole += r->start - f;
+ f = r->end;
+ if (hole <= r->end >> zfetch_hole_shift)
+ l = r->end;
+ }
+ if (l > 0)
+ return (dmu_zfetch_hit(zs, l));
+
+ return (0);
}
/*
@@ -314,9 +471,14 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
{
zstream_t *zs;
spa_t *spa = zf->zf_dnode->dn_objset->os_spa;
+ zfs_prefetch_type_t os_prefetch = zf->zf_dnode->dn_objset->os_prefetch;
- if (zfs_prefetch_disable)
+ if (zfs_prefetch_disable || os_prefetch == ZFS_PREFETCH_NONE)
return (NULL);
+
+ if (os_prefetch == ZFS_PREFETCH_METADATA)
+ fetch_data = B_FALSE;
+
/*
* If we haven't yet loaded the indirect vdevs' mappings, we
* can only read from blocks that we carefully ensure are on
@@ -350,53 +512,92 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
mutex_enter(&zf->zf_lock);
/*
- * Find matching prefetch stream. Depending on whether the accesses
+ * Find perfect prefetch stream. Depending on whether the accesses
* are block-aligned, first block of the new access may either follow
* the last block of the previous access, or be equal to it.
*/
+ unsigned int dbs = zf->zf_dnode->dn_datablkshift;
+ uint64_t end_blkid = blkid + nblks;
for (zs = list_head(&zf->zf_stream); zs != NULL;
zs = list_next(&zf->zf_stream, zs)) {
if (blkid == zs->zs_blkid) {
- break;
+ goto hit;
} else if (blkid + 1 == zs->zs_blkid) {
blkid++;
nblks--;
- break;
+ goto hit;
}
}
/*
- * If the file is ending, remove the matching stream if found.
- * If not found then it is too late to create a new one now.
+ * Find close enough prefetch stream. Access crossing stream position
+ * is a hit in its new part. Access ahead of stream position considered
+ * a hit for metadata prefetch, since we do not care about fill percent,
+ * or stored for future otherwise. Access behind stream position is
+ * silently ignored, since we already skipped it reaching fill percent.
*/
- uint64_t end_of_access_blkid = blkid + nblks;
- if (end_of_access_blkid >= maxblkid) {
- if (zs != NULL)
- dmu_zfetch_stream_remove(zf, zs);
- mutex_exit(&zf->zf_lock);
- if (!have_lock)
- rw_exit(&zf->zf_dnode->dn_struct_rwlock);
- return (NULL);
+ uint_t max_reorder = MIN((zfetch_max_reorder >> dbs) + 1, UINT16_MAX);
+ uint_t t = gethrestime_sec() - zfetch_max_sec_reap;
+ for (zs = list_head(&zf->zf_stream); zs != NULL;
+ zs = list_next(&zf->zf_stream, zs)) {
+ if (blkid > zs->zs_blkid) {
+ if (end_blkid <= zs->zs_blkid + max_reorder) {
+ if (!fetch_data) {
+ nblks = dmu_zfetch_hit(zs,
+ end_blkid - zs->zs_blkid);
+ ZFETCHSTAT_BUMP(zfetchstat_stride);
+ goto future;
+ }
+ nblks = dmu_zfetch_future(zs, blkid, nblks);
+ if (nblks > 0)
+ ZFETCHSTAT_BUMP(zfetchstat_stride);
+ else
+ ZFETCHSTAT_BUMP(zfetchstat_future);
+ goto future;
+ }
+ } else if (end_blkid >= zs->zs_blkid) {
+ nblks -= zs->zs_blkid - blkid;
+ blkid += zs->zs_blkid - blkid;
+ goto hit;
+ } else if (end_blkid + max_reorder > zs->zs_blkid &&
+ (int)(zs->zs_atime - t) >= 0) {
+ ZFETCHSTAT_BUMP(zfetchstat_past);
+ zs->zs_atime = gethrestime_sec();
+ goto out;
+ }
}
- /* Exit if we already prefetched this block before. */
- if (nblks == 0) {
- mutex_exit(&zf->zf_lock);
- if (!have_lock)
- rw_exit(&zf->zf_dnode->dn_struct_rwlock);
- return (NULL);
- }
+ /*
+ * This access is not part of any existing stream. Create a new
+ * stream for it unless we are at the end of file.
+ */
+ if (end_blkid < maxblkid)
+ dmu_zfetch_stream_create(zf, end_blkid);
+ mutex_exit(&zf->zf_lock);
+ if (!have_lock)
+ rw_exit(&zf->zf_dnode->dn_struct_rwlock);
+ ZFETCHSTAT_BUMP(zfetchstat_misses);
+ return (NULL);
- if (zs == NULL) {
- /*
- * This access is not part of any existing stream. Create
- * a new stream for it.
- */
- dmu_zfetch_stream_create(zf, end_of_access_blkid);
+hit:
+ nblks = dmu_zfetch_hit(zs, nblks);
+ ZFETCHSTAT_BUMP(zfetchstat_hits);
+
+future:
+ zs->zs_atime = gethrestime_sec();
+
+ /* Exit if we already prefetched for this position before. */
+ if (nblks == 0)
+ goto out;
+
+ /* If the file is ending, remove the stream. */
+ end_blkid = zs->zs_blkid;
+ if (end_blkid >= maxblkid) {
+ dmu_zfetch_stream_remove(zf, zs);
+out:
mutex_exit(&zf->zf_lock);
if (!have_lock)
rw_exit(&zf->zf_dnode->dn_struct_rwlock);
- ZFETCHSTAT_BUMP(zfetchstat_misses);
return (NULL);
}
@@ -407,27 +608,34 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
* Start prefetch from the demand access size (nblks). Double the
* distance every access up to zfetch_min_distance. After that only
* if needed increase the distance by 1/8 up to zfetch_max_distance.
+ *
+ * Don't double the distance beyond single block if we have more
+ * than ~6% of ARC held by active prefetches. It should help with
+ * getting out of RAM on some badly mispredicted read patterns.
*/
- unsigned int nbytes = nblks << zf->zf_dnode->dn_datablkshift;
+ unsigned int nbytes = nblks << dbs;
unsigned int pf_nblks;
if (fetch_data) {
if (unlikely(zs->zs_pf_dist < nbytes))
zs->zs_pf_dist = nbytes;
- else if (zs->zs_pf_dist < zfetch_min_distance)
+ else if (zs->zs_pf_dist < zfetch_min_distance &&
+ (zs->zs_pf_dist < (1 << dbs) ||
+ aggsum_compare(&zfetch_sums.zfetchstat_io_active,
+ arc_c_max >> (4 + dbs)) < 0))
zs->zs_pf_dist *= 2;
else if (zs->zs_more)
zs->zs_pf_dist += zs->zs_pf_dist / 8;
zs->zs_more = B_FALSE;
if (zs->zs_pf_dist > zfetch_max_distance)
zs->zs_pf_dist = zfetch_max_distance;
- pf_nblks = zs->zs_pf_dist >> zf->zf_dnode->dn_datablkshift;
+ pf_nblks = zs->zs_pf_dist >> dbs;
} else {
pf_nblks = 0;
}
- if (zs->zs_pf_start < end_of_access_blkid)
- zs->zs_pf_start = end_of_access_blkid;
- if (zs->zs_pf_end < end_of_access_blkid + pf_nblks)
- zs->zs_pf_end = end_of_access_blkid + pf_nblks;
+ if (zs->zs_pf_start < end_blkid)
+ zs->zs_pf_start = end_blkid;
+ if (zs->zs_pf_end < end_blkid + pf_nblks)
+ zs->zs_pf_end = end_blkid + pf_nblks;
/*
* Do the same for indirects, starting where we will stop reading
@@ -439,15 +647,12 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
zs->zs_ipf_dist *= 2;
if (zs->zs_ipf_dist > zfetch_max_idistance)
zs->zs_ipf_dist = zfetch_max_idistance;
- pf_nblks = zs->zs_ipf_dist >> zf->zf_dnode->dn_datablkshift;
+ pf_nblks = zs->zs_ipf_dist >> dbs;
if (zs->zs_ipf_start < zs->zs_pf_end)
zs->zs_ipf_start = zs->zs_pf_end;
if (zs->zs_ipf_end < zs->zs_pf_end + pf_nblks)
zs->zs_ipf_end = zs->zs_pf_end + pf_nblks;
- zs->zs_blkid = end_of_access_blkid;
- /* Protect the stream from reclamation. */
- zs->zs_atime = gethrtime();
zfs_refcount_add(&zs->zs_refs, NULL);
/* Count concurrent callers. */
zfs_refcount_add(&zs->zs_callers, NULL);
@@ -455,15 +660,13 @@ dmu_zfetch_prepare(zfetch_t *zf, uint64_t blkid, uint64_t nblks,
if (!have_lock)
rw_exit(&zf->zf_dnode->dn_struct_rwlock);
-
- ZFETCHSTAT_BUMP(zfetchstat_hits);
return (zs);
}
void
-dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock)
+dmu_zfetch_run(zfetch_t *zf, zstream_t *zs, boolean_t missed,
+ boolean_t have_lock)
{
- zfetch_t *zf = zs->zs_fetch;
int64_t pf_start, pf_end, ipf_start, ipf_end;
int epbs, issued;
@@ -502,14 +705,14 @@ dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock)
issued = pf_end - pf_start + ipf_end - ipf_start;
if (issued > 1) {
/* More references on top of taken in dmu_zfetch_prepare(). */
- for (int i = 0; i < issued - 1; i++)
- zfs_refcount_add(&zs->zs_refs, NULL);
+ zfs_refcount_add_few(&zs->zs_refs, issued - 1, NULL);
} else if (issued == 0) {
/* Some other thread has done our work, so drop the ref. */
if (zfs_refcount_remove(&zs->zs_refs, NULL) == 0)
dmu_zfetch_stream_fini(zs);
return;
}
+ aggsum_add(&zfetch_sums.zfetchstat_io_active, issued);
if (!have_lock)
rw_enter(&zf->zf_dnode->dn_struct_rwlock, RW_READER);
@@ -517,13 +720,11 @@ dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock)
issued = 0;
for (int64_t blk = pf_start; blk < pf_end; blk++) {
issued += dbuf_prefetch_impl(zf->zf_dnode, 0, blk,
- ZIO_PRIORITY_ASYNC_READ, ARC_FLAG_PREDICTIVE_PREFETCH,
- dmu_zfetch_done, zs);
+ ZIO_PRIORITY_ASYNC_READ, 0, dmu_zfetch_done, zs);
}
for (int64_t iblk = ipf_start; iblk < ipf_end; iblk++) {
issued += dbuf_prefetch_impl(zf->zf_dnode, 1, iblk,
- ZIO_PRIORITY_ASYNC_READ, ARC_FLAG_PREDICTIVE_PREFETCH,
- dmu_zfetch_done, zs);
+ ZIO_PRIORITY_ASYNC_READ, 0, dmu_zfetch_done, zs);
}
if (!have_lock)
@@ -541,7 +742,7 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data,
zs = dmu_zfetch_prepare(zf, blkid, nblks, fetch_data, have_lock);
if (zs)
- dmu_zfetch_run(zs, missed, have_lock);
+ dmu_zfetch_run(zf, zs, missed, have_lock);
}
ZFS_MODULE_PARAM(zfs_prefetch, zfs_prefetch_, disable, INT, ZMOD_RW,
@@ -565,5 +766,8 @@ ZFS_MODULE_PARAM(zfs_prefetch, zfetch_, max_distance, UINT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_prefetch, zfetch_, max_idistance, UINT, ZMOD_RW,
"Max bytes to prefetch indirects for per stream");
-ZFS_MODULE_PARAM(zfs_prefetch, zfetch_, array_rd_sz, ULONG, ZMOD_RW,
- "Number of bytes in a array_read");
+ZFS_MODULE_PARAM(zfs_prefetch, zfetch_, max_reorder, UINT, ZMOD_RW,
+ "Max request reorder distance within a stream");
+
+ZFS_MODULE_PARAM(zfs_prefetch, zfetch_, hole_shift, UINT, ZMOD_RW,
+ "Max log2 fraction of holes in a stream");
diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c
index 7157d8c8a920..a703fd414f87 100644
--- a/module/zfs/dnode.c
+++ b/module/zfs/dnode.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -71,6 +71,8 @@ dnode_stats_t dnode_stats = {
{ "dnode_move_active", KSTAT_DATA_UINT64 },
};
+dnode_sums_t dnode_sums;
+
static kstat_t *dnode_ksp;
static kmem_cache_t *dnode_cache;
@@ -97,6 +99,14 @@ dbuf_compare(const void *x1, const void *x2)
if (likely(cmp))
return (cmp);
+ if (d1->db_state == DB_MARKER) {
+ ASSERT3S(d2->db_state, !=, DB_MARKER);
+ return (TREE_PCMP(d1->db_parent, d2));
+ } else if (d2->db_state == DB_MARKER) {
+ ASSERT3S(d1->db_state, !=, DB_MARKER);
+ return (TREE_PCMP(d1, d2->db_parent));
+ }
+
if (d1->db_state == DB_SEARCH) {
ASSERT3S(d2->db_state, !=, DB_SEARCH);
return (-1);
@@ -225,6 +235,72 @@ dnode_dest(void *arg, void *unused)
avl_destroy(&dn->dn_dbufs);
}
+static int
+dnode_kstats_update(kstat_t *ksp, int rw)
+{
+ dnode_stats_t *ds = ksp->ks_data;
+
+ if (rw == KSTAT_WRITE)
+ return (EACCES);
+ ds->dnode_hold_dbuf_hold.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_dbuf_hold);
+ ds->dnode_hold_dbuf_read.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_dbuf_read);
+ ds->dnode_hold_alloc_hits.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_hits);
+ ds->dnode_hold_alloc_misses.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_misses);
+ ds->dnode_hold_alloc_interior.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_interior);
+ ds->dnode_hold_alloc_lock_retry.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_lock_retry);
+ ds->dnode_hold_alloc_lock_misses.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_lock_misses);
+ ds->dnode_hold_alloc_type_none.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_alloc_type_none);
+ ds->dnode_hold_free_hits.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_hits);
+ ds->dnode_hold_free_misses.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_misses);
+ ds->dnode_hold_free_lock_misses.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_lock_misses);
+ ds->dnode_hold_free_lock_retry.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_lock_retry);
+ ds->dnode_hold_free_refcount.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_refcount);
+ ds->dnode_hold_free_overflow.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_hold_free_overflow);
+ ds->dnode_free_interior_lock_retry.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_free_interior_lock_retry);
+ ds->dnode_allocate.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_allocate);
+ ds->dnode_reallocate.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_reallocate);
+ ds->dnode_buf_evict.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_buf_evict);
+ ds->dnode_alloc_next_chunk.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_alloc_next_chunk);
+ ds->dnode_alloc_race.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_alloc_race);
+ ds->dnode_alloc_next_block.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_alloc_next_block);
+ ds->dnode_move_invalid.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_invalid);
+ ds->dnode_move_recheck1.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_recheck1);
+ ds->dnode_move_recheck2.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_recheck2);
+ ds->dnode_move_special.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_special);
+ ds->dnode_move_handle.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_handle);
+ ds->dnode_move_rwlock.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_rwlock);
+ ds->dnode_move_active.value.ui64 =
+ wmsum_value(&dnode_sums.dnode_move_active);
+ return (0);
+}
+
void
dnode_init(void)
{
@@ -233,11 +309,41 @@ dnode_init(void)
0, dnode_cons, dnode_dest, NULL, NULL, NULL, 0);
kmem_cache_set_move(dnode_cache, dnode_move);
+ wmsum_init(&dnode_sums.dnode_hold_dbuf_hold, 0);
+ wmsum_init(&dnode_sums.dnode_hold_dbuf_read, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_hits, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_misses, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_interior, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_lock_retry, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_lock_misses, 0);
+ wmsum_init(&dnode_sums.dnode_hold_alloc_type_none, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_hits, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_misses, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_lock_misses, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_lock_retry, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_refcount, 0);
+ wmsum_init(&dnode_sums.dnode_hold_free_overflow, 0);
+ wmsum_init(&dnode_sums.dnode_free_interior_lock_retry, 0);
+ wmsum_init(&dnode_sums.dnode_allocate, 0);
+ wmsum_init(&dnode_sums.dnode_reallocate, 0);
+ wmsum_init(&dnode_sums.dnode_buf_evict, 0);
+ wmsum_init(&dnode_sums.dnode_alloc_next_chunk, 0);
+ wmsum_init(&dnode_sums.dnode_alloc_race, 0);
+ wmsum_init(&dnode_sums.dnode_alloc_next_block, 0);
+ wmsum_init(&dnode_sums.dnode_move_invalid, 0);
+ wmsum_init(&dnode_sums.dnode_move_recheck1, 0);
+ wmsum_init(&dnode_sums.dnode_move_recheck2, 0);
+ wmsum_init(&dnode_sums.dnode_move_special, 0);
+ wmsum_init(&dnode_sums.dnode_move_handle, 0);
+ wmsum_init(&dnode_sums.dnode_move_rwlock, 0);
+ wmsum_init(&dnode_sums.dnode_move_active, 0);
+
dnode_ksp = kstat_create("zfs", 0, "dnodestats", "misc",
KSTAT_TYPE_NAMED, sizeof (dnode_stats) / sizeof (kstat_named_t),
KSTAT_FLAG_VIRTUAL);
if (dnode_ksp != NULL) {
dnode_ksp->ks_data = &dnode_stats;
+ dnode_ksp->ks_update = dnode_kstats_update;
kstat_install(dnode_ksp);
}
}
@@ -250,6 +356,35 @@ dnode_fini(void)
dnode_ksp = NULL;
}
+ wmsum_fini(&dnode_sums.dnode_hold_dbuf_hold);
+ wmsum_fini(&dnode_sums.dnode_hold_dbuf_read);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_hits);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_misses);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_interior);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_lock_retry);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_lock_misses);
+ wmsum_fini(&dnode_sums.dnode_hold_alloc_type_none);
+ wmsum_fini(&dnode_sums.dnode_hold_free_hits);
+ wmsum_fini(&dnode_sums.dnode_hold_free_misses);
+ wmsum_fini(&dnode_sums.dnode_hold_free_lock_misses);
+ wmsum_fini(&dnode_sums.dnode_hold_free_lock_retry);
+ wmsum_fini(&dnode_sums.dnode_hold_free_refcount);
+ wmsum_fini(&dnode_sums.dnode_hold_free_overflow);
+ wmsum_fini(&dnode_sums.dnode_free_interior_lock_retry);
+ wmsum_fini(&dnode_sums.dnode_allocate);
+ wmsum_fini(&dnode_sums.dnode_reallocate);
+ wmsum_fini(&dnode_sums.dnode_buf_evict);
+ wmsum_fini(&dnode_sums.dnode_alloc_next_chunk);
+ wmsum_fini(&dnode_sums.dnode_alloc_race);
+ wmsum_fini(&dnode_sums.dnode_alloc_next_block);
+ wmsum_fini(&dnode_sums.dnode_move_invalid);
+ wmsum_fini(&dnode_sums.dnode_move_recheck1);
+ wmsum_fini(&dnode_sums.dnode_move_recheck2);
+ wmsum_fini(&dnode_sums.dnode_move_special);
+ wmsum_fini(&dnode_sums.dnode_move_handle);
+ wmsum_fini(&dnode_sums.dnode_move_rwlock);
+ wmsum_fini(&dnode_sums.dnode_move_active);
+
kmem_cache_destroy(dnode_cache);
dnode_cache = NULL;
}
@@ -593,6 +728,7 @@ dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
ASSERT(DMU_OT_IS_VALID(ot));
ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
(bonustype == DMU_OT_SA && bonuslen == 0) ||
+ (bonustype == DMU_OTN_UINT64_METADATA && bonuslen == 0) ||
(bonustype != DMU_OT_NONE && bonuslen != 0));
ASSERT(DMU_OT_IS_VALID(bonustype));
ASSERT3U(bonuslen, <=, DN_SLOTS_TO_BONUSLEN(dn_slots));
@@ -1109,9 +1245,11 @@ dnode_check_slots_free(dnode_children_t *children, int idx, int slots)
return (B_TRUE);
}
-static void
+static uint_t
dnode_reclaim_slots(dnode_children_t *children, int idx, int slots)
{
+ uint_t reclaimed = 0;
+
ASSERT3S(idx + slots, <=, DNODES_PER_BLOCK);
for (int i = idx; i < idx + slots; i++) {
@@ -1123,8 +1261,11 @@ dnode_reclaim_slots(dnode_children_t *children, int idx, int slots)
ASSERT3S(dnh->dnh_dnode->dn_type, ==, DMU_OT_NONE);
dnode_destroy(dnh->dnh_dnode);
dnh->dnh_dnode = DN_SLOT_FREE;
+ reclaimed++;
}
}
+
+ return (reclaimed);
}
void
@@ -1142,7 +1283,7 @@ dnode_free_interior_slots(dnode_t *dn)
while (!dnode_slots_tryenter(children, idx, slots)) {
DNODE_STAT_BUMP(dnode_free_interior_lock_retry);
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
}
dnode_set_slots(children, idx, slots, DN_SLOT_FREE);
@@ -1423,7 +1564,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
dnode_slots_rele(dnc, idx, slots);
while (!dnode_slots_tryenter(dnc, idx, slots)) {
DNODE_STAT_BUMP(dnode_hold_alloc_lock_retry);
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
}
/*
@@ -1437,6 +1578,8 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
} else {
dn = dnode_create(os, dn_block + idx, db,
object, dnh);
+ dmu_buf_add_user_size(&db->db,
+ sizeof (dnode_t));
}
}
@@ -1478,7 +1621,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
dnode_slots_rele(dnc, idx, slots);
while (!dnode_slots_tryenter(dnc, idx, slots)) {
DNODE_STAT_BUMP(dnode_hold_free_lock_retry);
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
}
if (!dnode_check_slots_free(dnc, idx, slots)) {
@@ -1494,8 +1637,13 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
* to be freed. Single slot dnodes can be safely
* re-purposed as a performance optimization.
*/
- if (slots > 1)
- dnode_reclaim_slots(dnc, idx + 1, slots - 1);
+ if (slots > 1) {
+ uint_t reclaimed =
+ dnode_reclaim_slots(dnc, idx + 1, slots - 1);
+ if (reclaimed > 0)
+ dmu_buf_sub_user_size(&db->db,
+ reclaimed * sizeof (dnode_t));
+ }
dnh = &dnc->dnc_children[idx];
if (DN_SLOT_IS_PTR(dnh->dnh_dnode)) {
@@ -1503,6 +1651,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
} else {
dn = dnode_create(os, dn_block + idx, db,
object, dnh);
+ dmu_buf_add_user_size(&db->db, sizeof (dnode_t));
}
mutex_enter(&dn->dn_mtx);
@@ -1637,7 +1786,14 @@ dnode_try_claim(objset_t *os, uint64_t object, int slots)
}
/*
- * Checks if the dnode contains any uncommitted dirty records.
+ * Checks if the dnode itself is dirty, or is carrying any uncommitted records.
+ * It is important to check both conditions, as some operations (eg appending
+ * to a file) can dirty both as a single logical unit, but they are not synced
+ * out atomically, so checking one and not the other can result in an object
+ * appearing to be clean mid-way through a commit.
+ *
+ * Do not change this lightly! If you get it wrong, dmu_offset_next() can
+ * detect a hole where there is really data, leading to silent corruption.
*/
boolean_t
dnode_is_dirty(dnode_t *dn)
@@ -1645,7 +1801,8 @@ dnode_is_dirty(dnode_t *dn)
mutex_enter(&dn->dn_mtx);
for (int i = 0; i < TXG_SIZE; i++) {
- if (multilist_link_active(&dn->dn_dirty_link[i])) {
+ if (multilist_link_active(&dn->dn_dirty_link[i]) ||
+ !list_is_empty(&dn->dn_dirty_records[i])) {
mutex_exit(&dn->dn_mtx);
return (B_TRUE);
}
@@ -1755,7 +1912,7 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
if (ibs == dn->dn_indblkshift)
ibs = 0;
- if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec && ibs == 0)
+ if (size == dn->dn_datablksz && ibs == 0)
return (0);
rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
@@ -1778,24 +1935,25 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
if (ibs && dn->dn_nlevels != 1)
goto fail;
- /* resize the old block */
- err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
- if (err == 0) {
- dbuf_new_size(db, size, tx);
- } else if (err != ENOENT) {
- goto fail;
- }
-
- dnode_setdblksz(dn, size);
dnode_setdirty(dn, tx);
- dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = size;
+ if (size != dn->dn_datablksz) {
+ /* resize the old block */
+ err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
+ if (err == 0) {
+ dbuf_new_size(db, size, tx);
+ } else if (err != ENOENT) {
+ goto fail;
+ }
+
+ dnode_setdblksz(dn, size);
+ dn->dn_next_blksz[tx->tx_txg & TXG_MASK] = size;
+ if (db)
+ dbuf_rele(db, FTAG);
+ }
if (ibs) {
dn->dn_indblkshift = ibs;
- dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
+ dn->dn_next_indblkshift[tx->tx_txg & TXG_MASK] = ibs;
}
- /* release after we have fixed the blocksize in the dnode */
- if (db)
- dbuf_rele(db, FTAG);
rw_exit(&dn->dn_struct_rwlock);
return (0);
@@ -2280,19 +2438,11 @@ dnode_spill_freed(dnode_t *dn)
uint64_t
dnode_block_freed(dnode_t *dn, uint64_t blkid)
{
- void *dp = spa_get_dsl(dn->dn_objset->os_spa);
int i;
if (blkid == DMU_BONUS_BLKID)
return (FALSE);
- /*
- * If we're in the process of opening the pool, dp will not be
- * set yet, but there shouldn't be anything dirty.
- */
- if (dp == NULL)
- return (FALSE);
-
if (dn->dn_free_txg)
return (TRUE);
@@ -2407,7 +2557,7 @@ dnode_next_offset_level(dnode_t *dn, int flags, uint64_t *offset,
}
if (db != NULL && txg != 0 && (db->db_blkptr == NULL ||
- db->db_blkptr->blk_birth <= txg ||
+ BP_GET_LOGICAL_BIRTH(db->db_blkptr) <= txg ||
BP_IS_HOLE(db->db_blkptr))) {
/*
* This can only happen when we are searching up the tree
@@ -2455,7 +2605,7 @@ dnode_next_offset_level(dnode_t *dn, int flags, uint64_t *offset,
i >= 0 && i < epb; i += inc) {
if (BP_GET_FILL(&bp[i]) >= minfill &&
BP_GET_FILL(&bp[i]) <= maxfill &&
- (hole || bp[i].blk_birth > txg))
+ (hole || BP_GET_LOGICAL_BIRTH(&bp[i]) > txg))
break;
if (inc > 0 || *offset > 0)
*offset += inc;
@@ -2469,8 +2619,9 @@ dnode_next_offset_level(dnode_t *dn, int flags, uint64_t *offset,
if (inc < 0) {
/* traversing backwards; position offset at the end */
- ASSERT3U(*offset, <=, start);
- *offset = MIN(*offset + (1ULL << span) - 1, start);
+ if (span < 8 * sizeof (*offset))
+ *offset = MIN(*offset + (1ULL << span) - 1,
+ start);
} else if (*offset < start) {
*offset = start;
}
@@ -2577,3 +2728,8 @@ EXPORT_SYMBOL(dnode_free_range);
EXPORT_SYMBOL(dnode_evict_dbufs);
EXPORT_SYMBOL(dnode_evict_bonus);
#endif
+
+ZFS_MODULE_PARAM(zfs, zfs_, default_bs, INT, ZMOD_RW,
+ "Default dnode block shift");
+ZFS_MODULE_PARAM(zfs, zfs_, default_ibs, INT, ZMOD_RW,
+ "Default dnode indirect block shift");
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index 973f93c4ec01..f67dad002319 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -70,8 +70,8 @@ dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
dmu_buf_impl_t *children[DN_MAX_NBLKPTR];
ASSERT3U(nblkptr, <=, DN_MAX_NBLKPTR);
for (i = 0; i < nblkptr; i++) {
- children[i] =
- dbuf_find(dn->dn_objset, dn->dn_object, old_toplvl, i);
+ children[i] = dbuf_find(dn->dn_objset, dn->dn_object,
+ old_toplvl, i, NULL);
}
/* transfer dnode's block pointers to new indirect block */
@@ -175,19 +175,21 @@ free_blocks(dnode_t *dn, blkptr_t *bp, int num, dmu_tx_t *tx)
static void
free_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
{
- int off, num;
- int i, err, epbs;
+ uint64_t off, num, i, j;
+ unsigned int epbs;
+ int err;
uint64_t txg = tx->tx_txg;
dnode_t *dn;
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
- off = start - (db->db_blkid * 1<<epbs);
+ off = start - (db->db_blkid << epbs);
num = end - start + 1;
- ASSERT3U(off, >=, 0);
- ASSERT3U(num, >=, 0);
+ ASSERT3U(dn->dn_phys->dn_indblkshift, >=, SPA_BLKPTRSHIFT);
+ ASSERT3U(end + 1, >=, start);
+ ASSERT3U(start, >=, (db->db_blkid << epbs));
ASSERT3U(db->db_level, >, 0);
ASSERT3U(db->db.db_size, ==, 1 << dn->dn_phys->dn_indblkshift);
ASSERT3U(off+num, <=, db->db.db_size >> SPA_BLKPTRSHIFT);
@@ -197,7 +199,6 @@ free_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
uint64_t *buf;
dmu_buf_impl_t *child;
dbuf_dirty_record_t *dr;
- int j;
ASSERT(db->db_level == 1);
@@ -217,8 +218,11 @@ free_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
for (j = 0; j < child->db.db_size >> 3; j++) {
if (buf[j] != 0) {
panic("freed data not zero: "
- "child=%p i=%d off=%d num=%d\n",
- (void *)child, i, off, num);
+ "child=%p i=%llu off=%llu "
+ "num=%llu\n",
+ (void *)child, (u_longlong_t)i,
+ (u_longlong_t)off,
+ (u_longlong_t)num);
}
}
}
@@ -234,8 +238,11 @@ free_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
for (j = 0; j < child->db.db_size >> 3; j++) {
if (buf[j] != 0) {
panic("freed data not zero: "
- "child=%p i=%d off=%d num=%d\n",
- (void *)child, i, off, num);
+ "child=%p i=%llu off=%llu "
+ "num=%llu\n",
+ (void *)child, (u_longlong_t)i,
+ (u_longlong_t)off,
+ (u_longlong_t)num);
}
}
}
@@ -475,7 +482,14 @@ dnode_evict_dbufs(dnode_t *dn)
zfs_refcount_is_zero(&db->db_holds)) {
db_marker->db_level = db->db_level;
db_marker->db_blkid = db->db_blkid;
- db_marker->db_state = DB_SEARCH;
+ /*
+ * Insert a MARKER node with the same level and blkid.
+ * And to resolve any ties in dbuf_compare() use the
+ * pointer of the dbuf that we are evicting. Pass the
+ * address in db_parent.
+ */
+ db_marker->db_state = DB_MARKER;
+ db_marker->db_parent = (void *)((uintptr_t)db - 1);
avl_insert_here(&dn->dn_dbufs, db_marker, db,
AVL_BEFORE);
@@ -620,6 +634,7 @@ dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
/*
* Write out the dnode's dirty buffers.
+ * Does not wait for zio completions.
*/
void
dnode_sync(dnode_t *dn, dmu_tx_t *tx)
diff --git a/module/zfs/dsl_bookmark.c b/module/zfs/dsl_bookmark.c
index 8ca7ba8957aa..5fd8bc2a2682 100644
--- a/module/zfs/dsl_bookmark.c
+++ b/module/zfs/dsl_bookmark.c
@@ -34,6 +34,7 @@
#include <sys/dsl_bookmark.h>
#include <zfs_namecheck.h>
#include <sys/dmu_send.h>
+#include <sys/dbuf.h>
static int
dsl_bookmark_hold_ds(dsl_pool_t *dp, const char *fullname,
@@ -160,14 +161,14 @@ dsl_bookmark_create_nvl_validate_pair(const char *bmark, const char *source)
int
dsl_bookmark_create_nvl_validate(nvlist_t *bmarks)
{
- char *first = NULL;
+ const char *first = NULL;
size_t first_len = 0;
for (nvpair_t *pair = nvlist_next_nvpair(bmarks, NULL);
pair != NULL; pair = nvlist_next_nvpair(bmarks, pair)) {
- char *bmark = nvpair_name(pair);
- char *source;
+ const char *bmark = nvpair_name(pair);
+ const char *source;
/* list structure: values must be snapshots XOR bookmarks */
if (nvpair_value_string(pair, &source) != 0)
@@ -177,7 +178,7 @@ dsl_bookmark_create_nvl_validate(nvlist_t *bmarks)
/* same pool check */
if (first == NULL) {
- char *cp = strpbrk(bmark, "/#");
+ const char *cp = strpbrk(bmark, "/#");
if (cp == NULL)
return (-1);
first = bmark;
@@ -229,7 +230,6 @@ dsl_bookmark_create_check_impl(dsl_pool_t *dp,
switch (error) {
case ESRCH:
/* happy path: new bmark doesn't exist, proceed after switch */
- error = 0;
break;
case 0:
error = SET_ERROR(EEXIST);
@@ -306,11 +306,11 @@ dsl_bookmark_create_check(void *arg, dmu_tx_t *tx)
for (nvpair_t *pair = nvlist_next_nvpair(dbca->dbca_bmarks, NULL);
pair != NULL; pair = nvlist_next_nvpair(dbca->dbca_bmarks, pair)) {
- char *new = nvpair_name(pair);
+ const char *new = nvpair_name(pair);
int error = schema_err;
if (error == 0) {
- char *source = fnvpair_value_string(pair);
+ const char *source = fnvpair_value_string(pair);
error = dsl_bookmark_create_check_impl(dp, new, source);
if (error != 0)
error = SET_ERROR(error);
@@ -460,25 +460,42 @@ dsl_bookmark_create_sync_impl_snap(const char *bookmark, const char *snapshot,
SPA_FEATURE_REDACTED_DATASETS, &dsnumsnaps, &dsredactsnaps);
if (redaction_list != NULL || bookmark_redacted) {
redaction_list_t *local_rl;
+ boolean_t spill = B_FALSE;
if (bookmark_redacted) {
redact_snaps = dsredactsnaps;
num_redact_snaps = dsnumsnaps;
}
+ int bonuslen = sizeof (redaction_list_phys_t) +
+ num_redact_snaps * sizeof (uint64_t);
+ if (bonuslen > dmu_bonus_max())
+ spill = B_TRUE;
dbn->dbn_phys.zbm_redaction_obj = dmu_object_alloc(mos,
DMU_OTN_UINT64_METADATA, SPA_OLD_MAXBLOCKSIZE,
- DMU_OTN_UINT64_METADATA, sizeof (redaction_list_phys_t) +
- num_redact_snaps * sizeof (uint64_t), tx);
+ DMU_OTN_UINT64_METADATA, spill ? 0 : bonuslen, tx);
spa_feature_incr(dp->dp_spa,
SPA_FEATURE_REDACTION_BOOKMARKS, tx);
+ if (spill) {
+ spa_feature_incr(dp->dp_spa,
+ SPA_FEATURE_REDACTION_LIST_SPILL, tx);
+ }
VERIFY0(dsl_redaction_list_hold_obj(dp,
dbn->dbn_phys.zbm_redaction_obj, tag, &local_rl));
dsl_redaction_list_long_hold(dp, local_rl, tag);
- ASSERT3U((local_rl)->rl_dbuf->db_size, >=,
- sizeof (redaction_list_phys_t) + num_redact_snaps *
- sizeof (uint64_t));
- dmu_buf_will_dirty(local_rl->rl_dbuf, tx);
+ if (!spill) {
+ ASSERT3U(local_rl->rl_bonus->db_size, >=, bonuslen);
+ dmu_buf_will_dirty(local_rl->rl_bonus, tx);
+ } else {
+ dmu_buf_t *db;
+ VERIFY0(dmu_spill_hold_by_bonus(local_rl->rl_bonus,
+ DB_RF_MUST_SUCCEED, FTAG, &db));
+ dmu_buf_will_fill(db, tx, B_FALSE);
+ VERIFY0(dbuf_spill_set_blksz(db, P2ROUNDUP(bonuslen,
+ SPA_MINBLOCKSIZE), tx));
+ local_rl->rl_phys = db->db_data;
+ local_rl->rl_dbuf = db;
+ }
memcpy(local_rl->rl_phys->rlp_snaps, redact_snaps,
sizeof (uint64_t) * num_redact_snaps);
local_rl->rl_phys->rlp_num_snaps = num_redact_snaps;
@@ -590,8 +607,8 @@ dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx)
for (nvpair_t *pair = nvlist_next_nvpair(dbca->dbca_bmarks, NULL);
pair != NULL; pair = nvlist_next_nvpair(dbca->dbca_bmarks, pair)) {
- char *new = nvpair_name(pair);
- char *source = fnvpair_value_string(pair);
+ const char *new = nvpair_name(pair);
+ const char *source = fnvpair_value_string(pair);
if (strchr(source, '@') != NULL) {
dsl_bookmark_create_sync_impl_snap(new, source, tx,
@@ -637,11 +654,15 @@ dsl_bookmark_create_redacted_check(void *arg, dmu_tx_t *tx)
SPA_FEATURE_REDACTION_BOOKMARKS))
return (SET_ERROR(ENOTSUP));
/*
- * If the list of redact snaps will not fit in the bonus buffer with
- * the furthest reached object and offset, fail.
+ * If the list of redact snaps will not fit in the bonus buffer (or
+ * spill block, with the REDACTION_LIST_SPILL feature) with the
+ * furthest reached object and offset, fail.
*/
- if (dbcra->dbcra_numsnaps > (dmu_bonus_max() -
- sizeof (redaction_list_phys_t)) / sizeof (uint64_t))
+ uint64_t snaplimit = ((spa_feature_is_enabled(dp->dp_spa,
+ SPA_FEATURE_REDACTION_LIST_SPILL) ? spa_maxblocksize(dp->dp_spa) :
+ dmu_bonus_max()) -
+ sizeof (redaction_list_phys_t)) / sizeof (uint64_t);
+ if (dbcra->dbcra_numsnaps > snaplimit)
return (SET_ERROR(E2BIG));
if (dsl_bookmark_create_nvl_validate_pair(
@@ -1041,6 +1062,14 @@ dsl_bookmark_destroy_sync_impl(dsl_dataset_t *ds, const char *name,
}
if (dbn->dbn_phys.zbm_redaction_obj != 0) {
+ dnode_t *rl;
+ VERIFY0(dnode_hold(mos,
+ dbn->dbn_phys.zbm_redaction_obj, FTAG, &rl));
+ if (rl->dn_have_spill) {
+ spa_feature_decr(dmu_objset_spa(mos),
+ SPA_FEATURE_REDACTION_LIST_SPILL, tx);
+ }
+ dnode_rele(rl, FTAG);
VERIFY0(dmu_object_free(mos,
dbn->dbn_phys.zbm_redaction_obj, tx));
spa_feature_decr(dmu_objset_spa(mos),
@@ -1214,7 +1243,9 @@ redaction_list_evict_sync(void *rlu)
void
dsl_redaction_list_rele(redaction_list_t *rl, const void *tag)
{
- dmu_buf_rele(rl->rl_dbuf, tag);
+ if (rl->rl_bonus != rl->rl_dbuf)
+ dmu_buf_rele(rl->rl_dbuf, tag);
+ dmu_buf_rele(rl->rl_bonus, tag);
}
int
@@ -1222,7 +1253,7 @@ dsl_redaction_list_hold_obj(dsl_pool_t *dp, uint64_t rlobj, const void *tag,
redaction_list_t **rlp)
{
objset_t *mos = dp->dp_meta_objset;
- dmu_buf_t *dbuf;
+ dmu_buf_t *dbuf, *spill_dbuf;
redaction_list_t *rl;
int err;
@@ -1237,13 +1268,18 @@ dsl_redaction_list_hold_obj(dsl_pool_t *dp, uint64_t rlobj, const void *tag,
redaction_list_t *winner = NULL;
rl = kmem_zalloc(sizeof (redaction_list_t), KM_SLEEP);
- rl->rl_dbuf = dbuf;
+ rl->rl_bonus = dbuf;
+ if (dmu_spill_hold_existing(dbuf, tag, &spill_dbuf) == 0) {
+ rl->rl_dbuf = spill_dbuf;
+ } else {
+ rl->rl_dbuf = dbuf;
+ }
rl->rl_object = rlobj;
- rl->rl_phys = dbuf->db_data;
+ rl->rl_phys = rl->rl_dbuf->db_data;
rl->rl_mos = dp->dp_meta_objset;
zfs_refcount_create(&rl->rl_longholds);
dmu_buf_init_user(&rl->rl_dbu, redaction_list_evict_sync, NULL,
- &rl->rl_dbuf);
+ &rl->rl_bonus);
if ((winner = dmu_buf_set_user_ie(dbuf, &rl->rl_dbu)) != NULL) {
kmem_free(rl, sizeof (*rl));
rl = winner;
@@ -1484,7 +1520,8 @@ dsl_bookmark_block_killed(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
* If the block was live (referenced) at the time of this
* bookmark, add its space to the bookmark's FBN.
*/
- if (bp->blk_birth <= dbn->dbn_phys.zbm_creation_txg &&
+ if (BP_GET_LOGICAL_BIRTH(bp) <=
+ dbn->dbn_phys.zbm_creation_txg &&
(dbn->dbn_phys.zbm_flags & ZBM_FLAG_HAS_FBN)) {
mutex_enter(&dbn->dbn_lock);
dbn->dbn_phys.zbm_referenced_freed_before_next_snap +=
diff --git a/module/zfs/dsl_crypt.c b/module/zfs/dsl_crypt.c
index 25cb4f6ab1ad..8e1055d9bcb1 100644
--- a/module/zfs/dsl_crypt.c
+++ b/module/zfs/dsl_crypt.c
@@ -143,7 +143,7 @@ dsl_crypto_params_create_nvlist(dcp_cmd_t cmd, nvlist_t *props,
dsl_wrapping_key_t *wkey = NULL;
uint8_t *wkeydata = NULL;
uint_t wkeydata_len = 0;
- char *keylocation = NULL;
+ const char *keylocation = NULL;
dcp = kmem_zalloc(sizeof (dsl_crypto_params_t), KM_SLEEP);
dcp->cp_cmd = cmd;
@@ -266,6 +266,40 @@ spa_crypto_key_compare(const void *a, const void *b)
return (0);
}
+/*
+ * this compares a crypto key based on zk_guid. See comment on
+ * spa_crypto_key_compare for more information.
+ */
+boolean_t
+dmu_objset_crypto_key_equal(objset_t *osa, objset_t *osb)
+{
+ dsl_crypto_key_t *dcka = NULL;
+ dsl_crypto_key_t *dckb = NULL;
+ uint64_t obja, objb;
+ boolean_t equal;
+ spa_t *spa;
+
+ spa = dmu_objset_spa(osa);
+ if (spa != dmu_objset_spa(osb))
+ return (B_FALSE);
+ obja = dmu_objset_ds(osa)->ds_object;
+ objb = dmu_objset_ds(osb)->ds_object;
+
+ if (spa_keystore_lookup_key(spa, obja, FTAG, &dcka) != 0)
+ return (B_FALSE);
+ if (spa_keystore_lookup_key(spa, objb, FTAG, &dckb) != 0) {
+ spa_keystore_dsl_key_rele(spa, dcka, FTAG);
+ return (B_FALSE);
+ }
+
+ equal = (dcka->dck_key.zk_guid == dckb->dck_key.zk_guid);
+
+ spa_keystore_dsl_key_rele(spa, dcka, FTAG);
+ spa_keystore_dsl_key_rele(spa, dckb, FTAG);
+
+ return (equal);
+}
+
static int
spa_key_mapping_compare(const void *a, const void *b)
{
@@ -541,6 +575,12 @@ dsl_crypto_key_open(objset_t *mos, dsl_wrapping_key_t *wkey,
if (ret != 0)
goto error;
+ /* handle a future crypto suite that we don't support */
+ if (crypt >= ZIO_CRYPT_FUNCTIONS) {
+ ret = (SET_ERROR(ZFS_ERR_CRYPTO_NOTSUP));
+ goto error;
+ }
+
ret = zap_lookup(mos, dckobj, DSL_CRYPTO_KEY_GUID, 8, 1, &guid);
if (ret != 0)
goto error;
@@ -1137,7 +1177,7 @@ dmu_objset_check_wkey_loaded(dsl_dir_t *dd)
return (0);
}
-static zfs_keystatus_t
+zfs_keystatus_t
dsl_dataset_get_keystatus(dsl_dir_t *dd)
{
/* check if this dd has a has a dsl key */
@@ -2119,9 +2159,6 @@ dsl_crypto_recv_raw_objset_sync(dsl_dataset_t *ds, dmu_objset_type_t ostype,
zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
dsl_dataset_sync(ds, zio, tx);
VERIFY0(zio_wait(zio));
-
- /* dsl_dataset_sync_done will drop this reference. */
- dmu_buf_add_ref(ds->ds_dbuf, ds);
dsl_dataset_sync_done(ds, tx);
}
}
@@ -2144,10 +2181,16 @@ dsl_crypto_recv_raw_key_check(dsl_dataset_t *ds, nvlist_t *nvl, dmu_tx_t *tx)
* wrapping key.
*/
ret = nvlist_lookup_uint64(nvl, DSL_CRYPTO_KEY_CRYPTO_SUITE, &intval);
- if (ret != 0 || intval >= ZIO_CRYPT_FUNCTIONS ||
- intval <= ZIO_CRYPT_OFF)
+ if (ret != 0 || intval <= ZIO_CRYPT_OFF)
return (SET_ERROR(EINVAL));
+ /*
+ * Flag a future crypto suite that we don't support differently, so
+ * we can return a more useful error to the user.
+ */
+ if (intval >= ZIO_CRYPT_FUNCTIONS)
+ return (SET_ERROR(ZFS_ERR_CRYPTO_NOTSUP));
+
ret = nvlist_lookup_uint64(nvl, DSL_CRYPTO_KEY_GUID, &intval);
if (ret != 0)
return (SET_ERROR(EINVAL));
@@ -2671,6 +2714,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);
@@ -2696,8 +2740,21 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj,
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) {
- abd_return_buf(abd, buf, datalen);
- return (SET_ERROR(ECKSUM));
+ /*
+ * 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 1067218948d0..b4de0e7ff073 100644
--- a/module/zfs/dsl_dataset.c
+++ b/module/zfs/dsl_dataset.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -82,12 +82,14 @@
* 3/1 memory split doesn't leave much room for 16M chunks.
*/
#ifdef _ILP32
-int zfs_max_recordsize = 1 * 1024 * 1024;
+uint_t zfs_max_recordsize = 1 * 1024 * 1024;
#else
-int zfs_max_recordsize = 16 * 1024 * 1024;
+uint_t zfs_max_recordsize = 16 * 1024 * 1024;
#endif
static int zfs_allow_redacted_dataset_mount = 0;
+int zfs_snapshot_history_enabled = 1;
+
#define SWITCH64(x, y) \
{ \
uint64_t __tmp = (x); \
@@ -104,7 +106,7 @@ static void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
static void unload_zfeature(dsl_dataset_t *ds, spa_feature_t f);
-extern int spa_asize_inflation;
+extern uint_t spa_asize_inflation;
static zil_header_t zero_zil;
@@ -131,30 +133,6 @@ parent_delta(dsl_dataset_t *ds, int64_t delta)
}
void
-dsl_dataset_feature_set_activation(const blkptr_t *bp, dsl_dataset_t *ds)
-{
- spa_feature_t f;
- if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
- ds->ds_feature_activation[SPA_FEATURE_LARGE_BLOCKS] =
- (void *)B_TRUE;
- }
-
- f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
- if (f != SPA_FEATURE_NONE) {
- ASSERT3S(spa_feature_table[f].fi_type, ==,
- ZFEATURE_TYPE_BOOLEAN);
- ds->ds_feature_activation[f] = (void *)B_TRUE;
- }
-
- f = zio_compress_to_feature(BP_GET_COMPRESS(bp));
- if (f != SPA_FEATURE_NONE) {
- ASSERT3S(spa_feature_table[f].fi_type, ==,
- ZFEATURE_TYPE_BOOLEAN);
- ds->ds_feature_activation[f] = (void *)B_TRUE;
- }
-}
-
-void
dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
@@ -162,6 +140,7 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
int compressed = BP_GET_PSIZE(bp);
int uncompressed = BP_GET_UCSIZE(bp);
int64_t delta;
+ spa_feature_t f;
dprintf_bp(bp, "ds=%p", ds);
@@ -177,7 +156,8 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
return;
}
- ASSERT3U(bp->blk_birth, >, dsl_dataset_phys(ds)->ds_prev_snap_txg);
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(bp), >,
+ dsl_dataset_phys(ds)->ds_prev_snap_txg);
dmu_buf_will_dirty(ds->ds_dbuf, tx);
mutex_enter(&ds->ds_lock);
delta = parent_delta(ds, used);
@@ -186,14 +166,32 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed;
dsl_dataset_phys(ds)->ds_unique_bytes += used;
- dsl_dataset_feature_set_activation(bp, ds);
+ if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
+ ds->ds_feature_activation[SPA_FEATURE_LARGE_BLOCKS] =
+ (void *)B_TRUE;
+ }
+
+
+ f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
+ if (f != SPA_FEATURE_NONE) {
+ ASSERT3S(spa_feature_table[f].fi_type, ==,
+ ZFEATURE_TYPE_BOOLEAN);
+ ds->ds_feature_activation[f] = (void *)B_TRUE;
+ }
+
+ f = zio_compress_to_feature(BP_GET_COMPRESS(bp));
+ if (f != SPA_FEATURE_NONE) {
+ ASSERT3S(spa_feature_table[f].fi_type, ==,
+ ZFEATURE_TYPE_BOOLEAN);
+ ds->ds_feature_activation[f] = (void *)B_TRUE;
+ }
/*
* Track block for livelist, but ignore embedded blocks because
* they do not need to be freed.
*/
if (dsl_deadlist_is_open(&ds->ds_dir->dd_livelist) &&
- bp->blk_birth > ds->ds_dir->dd_origin_txg &&
+ BP_GET_LOGICAL_BIRTH(bp) > ds->ds_dir->dd_origin_txg &&
!(BP_IS_EMBEDDED(bp))) {
ASSERT(dsl_dir_is_clone(ds->ds_dir));
ASSERT(spa_feature_is_enabled(spa,
@@ -239,7 +237,7 @@ dsl_dataset_block_remapped(dsl_dataset_t *ds, uint64_t vdev, uint64_t offset,
mutex_exit(&ds->ds_remap_deadlist_lock);
BP_ZERO(&fakebp);
- fakebp.blk_birth = birth;
+ BP_SET_LOGICAL_BIRTH(&fakebp, birth);
DVA_SET_VDEV(dva, vdev);
DVA_SET_OFFSET(dva, offset);
DVA_SET_ASIZE(dva, size);
@@ -262,7 +260,7 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
return (0);
ASSERT(dmu_tx_is_syncing(tx));
- ASSERT(bp->blk_birth <= tx->tx_txg);
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) <= tx->tx_txg);
if (ds == NULL) {
dsl_free(tx->tx_pool, tx->tx_txg, bp);
@@ -280,7 +278,7 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
* they do not need to be freed.
*/
if (dsl_deadlist_is_open(&ds->ds_dir->dd_livelist) &&
- bp->blk_birth > ds->ds_dir->dd_origin_txg &&
+ BP_GET_LOGICAL_BIRTH(bp) > ds->ds_dir->dd_origin_txg &&
!(BP_IS_EMBEDDED(bp))) {
ASSERT(dsl_dir_is_clone(ds->ds_dir));
ASSERT(spa_feature_is_enabled(spa,
@@ -288,7 +286,7 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
bplist_append(&ds->ds_dir->dd_pending_frees, bp);
}
- if (bp->blk_birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
int64_t delta;
dprintf_bp(bp, "freeing ds=%llu", (u_longlong_t)ds->ds_object);
@@ -320,16 +318,16 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
ASSERT3U(ds->ds_prev->ds_object, ==,
dsl_dataset_phys(ds)->ds_prev_snap_obj);
ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_num_children > 0);
- /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
+ /* if (logical birth > prev prev snap txg) prev unique += bs */
if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj ==
- ds->ds_object && bp->blk_birth >
+ ds->ds_object && BP_GET_LOGICAL_BIRTH(bp) >
dsl_dataset_phys(ds->ds_prev)->ds_prev_snap_txg) {
dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
mutex_enter(&ds->ds_prev->ds_lock);
dsl_dataset_phys(ds->ds_prev)->ds_unique_bytes += used;
mutex_exit(&ds->ds_prev->ds_lock);
}
- if (bp->blk_birth > ds->ds_dir->dd_origin_txg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) > ds->ds_dir->dd_origin_txg) {
dsl_dir_transfer_space(ds->ds_dir, used,
DD_USED_HEAD, DD_USED_SNAP, tx);
}
@@ -534,7 +532,7 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
matchtype_t mt = 0;
int err;
- dsl_dir_snap_cmtime_update(ds->ds_dir);
+ dsl_dir_snap_cmtime_update(ds->ds_dir, tx);
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
mt = MT_NORMALIZE;
@@ -643,6 +641,8 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, const void *tag,
dsl_dataset_phys(ds)->ds_prev_snap_obj,
ds, &ds->ds_prev);
}
+ if (err != 0)
+ goto after_dsl_bookmark_fini;
err = dsl_bookmark_init_ds(ds);
} else {
if (zfs_flags & ZFS_DEBUG_SNAPNAMES)
@@ -691,11 +691,11 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, const void *tag,
winner = dmu_buf_set_user_ie(dbuf, &ds->ds_dbu);
if (err != 0 || winner != NULL) {
- bplist_destroy(&ds->ds_pending_deadlist);
dsl_deadlist_close(&ds->ds_deadlist);
if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
dsl_deadlist_close(&ds->ds_remap_deadlist);
dsl_bookmark_fini_ds(ds);
+after_dsl_bookmark_fini:
if (ds->ds_prev)
dsl_dataset_rele(ds->ds_prev, ds);
dsl_dir_rele(ds->ds_dir, ds);
@@ -706,6 +706,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, const void *tag,
list_destroy(&ds->ds_prop_cbs);
list_destroy(&ds->ds_sendstreams);
+ bplist_destroy(&ds->ds_pending_deadlist);
mutex_destroy(&ds->ds_lock);
mutex_destroy(&ds->ds_opening_lock);
mutex_destroy(&ds->ds_sendstream_lock);
@@ -1272,9 +1273,6 @@ dsl_dataset_zero_zil(dsl_dataset_t *ds, dmu_tx_t *tx)
zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
dsl_dataset_sync(ds, zio, tx);
VERIFY0(zio_wait(zio));
-
- /* dsl_dataset_sync_done will drop this reference. */
- dmu_buf_add_ref(ds->ds_dbuf, ds);
dsl_dataset_sync_done(ds, tx);
}
}
@@ -1623,7 +1621,7 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
for (pair = nvlist_next_nvpair(cnt_track, NULL);
pair != NULL; pair = nvlist_next_nvpair(cnt_track, pair)) {
int error = 0;
- char *name;
+ const char *name;
uint64_t cnt = 0;
dsl_dataset_t *ds;
@@ -1655,7 +1653,7 @@ dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
int error = 0;
dsl_dataset_t *ds;
- char *name, *atp = NULL;
+ const char *name, *atp = NULL;
char dsname[ZFS_MAX_DATASET_NAME_LEN];
name = nvpair_name(pair);
@@ -1698,7 +1696,6 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dsl_dataset_phys_t *dsphys;
uint64_t dsobj, crtxg;
objset_t *mos = dp->dp_meta_objset;
- static zil_header_t zero_zil __maybe_unused;
objset_t *os __maybe_unused;
ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
@@ -1865,9 +1862,10 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dsl_scan_ds_snapshotted(ds, tx);
- dsl_dir_snap_cmtime_update(ds->ds_dir);
+ dsl_dir_snap_cmtime_update(ds->ds_dir, tx);
- spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, " ");
+ if (zfs_snapshot_history_enabled)
+ spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, " ");
}
void
@@ -1880,7 +1878,7 @@ dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
dsl_dataset_t *ds;
- char *name, *atp;
+ const char *name, *atp;
char dsname[ZFS_MAX_DATASET_NAME_LEN];
name = nvpair_name(pair);
@@ -1909,7 +1907,7 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
boolean_t needsuspend;
int error;
spa_t *spa;
- char *firstname;
+ const char *firstname;
nvlist_t *suspended = NULL;
pair = nvlist_next_nvpair(snaps, NULL);
@@ -1928,8 +1926,8 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
pair = nvlist_next_nvpair(snaps, pair)) {
char fsname[ZFS_MAX_DATASET_NAME_LEN];
- char *snapname = nvpair_name(pair);
- char *atp;
+ const char *snapname = nvpair_name(pair);
+ const char *atp;
void *cookie;
atp = strchr(snapname, '@');
@@ -2072,8 +2070,9 @@ dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
return (error);
}
+/* Nonblocking dataset sync. Assumes dataset:objset is always 1:1 */
void
-dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
+dsl_dataset_sync(dsl_dataset_t *ds, zio_t *rio, dmu_tx_t *tx)
{
ASSERT(dmu_tx_is_syncing(tx));
ASSERT(ds->ds_objset != NULL);
@@ -2101,17 +2100,7 @@ dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
ds->ds_resume_bytes[tx->tx_txg & TXG_MASK] = 0;
}
- dmu_objset_sync(ds->ds_objset, zio, tx);
-
- for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
- if (zfeature_active(f, ds->ds_feature_activation[f])) {
- if (zfeature_active(f, ds->ds_feature[f]))
- continue;
- dsl_dataset_activate_feature(ds->ds_object, f,
- ds->ds_feature_activation[f], tx);
- ds->ds_feature[f] = ds->ds_feature_activation[f];
- }
- }
+ dmu_objset_sync(ds->ds_objset, rio, tx);
}
/*
@@ -2127,8 +2116,6 @@ dsl_livelist_should_disable(dsl_dataset_t *ds)
used = dsl_dir_get_usedds(ds->ds_dir);
referenced = dsl_get_referenced(ds);
- ASSERT3U(referenced, >=, 0);
- ASSERT3U(used, >=, 0);
if (referenced == 0)
return (B_FALSE);
percent_shared = (100 * (referenced - used)) / referenced;
@@ -2283,9 +2270,18 @@ dsl_dataset_sync_done(dsl_dataset_t *ds, dmu_tx_t *tx)
else
ASSERT0(os->os_next_write_raw[tx->tx_txg & TXG_MASK]);
- ASSERT(!dmu_objset_is_dirty(os, dmu_tx_get_txg(tx)));
+ for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
+ if (zfeature_active(f,
+ ds->ds_feature_activation[f])) {
+ if (zfeature_active(f, ds->ds_feature[f]))
+ continue;
+ dsl_dataset_activate_feature(ds->ds_object, f,
+ ds->ds_feature_activation[f], tx);
+ ds->ds_feature[f] = ds->ds_feature_activation[f];
+ }
+ }
- dmu_buf_rele(ds->ds_dbuf, ds);
+ ASSERT(!dmu_objset_is_dirty(os, dmu_tx_get_txg(tx)));
}
int
@@ -2741,6 +2737,8 @@ dsl_get_mountpoint(dsl_dataset_t *ds, const char *dsname, char *value,
relpath[0] != '\0'))
mnt = value + 1;
+ mnt = kmem_strdup(mnt);
+
if (relpath[0] == '\0') {
(void) snprintf(value, ZAP_MAXVALUELEN, "%s%s",
root, mnt);
@@ -2750,6 +2748,7 @@ dsl_get_mountpoint(dsl_dataset_t *ds, const char *dsname, char *value,
relpath);
}
kmem_free(buf, ZAP_MAXVALUELEN);
+ kmem_strfree(mnt);
}
return (0);
@@ -2809,6 +2808,8 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
dsl_get_userrefs(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
dsl_get_defer_destroy(ds));
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOTS_CHANGED,
+ dsl_dir_snap_cmtime(ds->ds_dir).tv_sec);
dsl_dataset_crypt_stats(ds, nv);
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
@@ -2895,7 +2896,7 @@ dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
if (snap == NULL)
return (B_FALSE);
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
- birth = dsl_dataset_get_blkptr(ds)->blk_birth;
+ birth = BP_GET_LOGICAL_BIRTH(dsl_dataset_get_blkptr(ds));
rrw_exit(&ds->ds_bp_rwlock, FTAG);
if (birth > dsl_dataset_phys(snap)->ds_creation_txg) {
objset_t *os, *os_snap;
@@ -2915,14 +2916,6 @@ dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
return (B_FALSE);
}
-typedef struct dsl_dataset_rename_snapshot_arg {
- const char *ddrsa_fsname;
- const char *ddrsa_oldsnapname;
- const char *ddrsa_newsnapname;
- boolean_t ddrsa_recursive;
- dmu_tx_t *ddrsa_tx;
-} dsl_dataset_rename_snapshot_arg_t;
-
static int
dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
dsl_dataset_t *hds, void *arg)
@@ -2953,7 +2946,7 @@ dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
return (error);
}
-static int
+int
dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx)
{
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
@@ -3015,7 +3008,7 @@ dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
return (0);
}
-static void
+void
dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
@@ -3289,7 +3282,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;
@@ -3309,12 +3301,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.
@@ -3410,10 +3401,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;
@@ -3427,7 +3418,8 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
conflicting_snaps = B_TRUE;
} else if (err == ESRCH) {
err = 0;
- } else if (err != 0) {
+ }
+ if (err != 0) {
goto out;
}
}
@@ -3792,8 +3784,7 @@ snaplist_destroy(list_t *l, const void *tag)
if (l == NULL || !list_link_active(&l->list_head))
return;
- while ((snap = list_tail(l)) != NULL) {
- list_remove(l, snap);
+ while ((snap = list_remove_tail(l)) != NULL) {
dsl_dataset_rele(snap->ds, tag);
kmem_free(snap, sizeof (*snap));
}
@@ -4527,6 +4518,7 @@ dsl_dataset_set_compression_sync(void *arg, dmu_tx_t *tx)
uint64_t compval = ZIO_COMPRESS_ALGO(ddsca->ddsca_value);
spa_feature_t f = zio_compress_to_feature(compval);
+ ASSERT3S(f, !=, SPA_FEATURE_NONE);
ASSERT3S(spa_feature_table[f].fi_type, ==, ZFEATURE_TYPE_BOOLEAN);
VERIFY0(dsl_dataset_hold(dp, ddsca->ddsca_name, FTAG, &ds));
@@ -4977,12 +4969,15 @@ dsl_dataset_oldest_snapshot(spa_t *spa, uint64_t head_ds, uint64_t min_txg,
return (0);
}
-ZFS_MODULE_PARAM(zfs, zfs_, max_recordsize, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_recordsize, UINT, ZMOD_RW,
"Max allowed record size");
ZFS_MODULE_PARAM(zfs, zfs_, allow_redacted_dataset_mount, INT, ZMOD_RW,
"Allow mounting of redacted datasets");
+ZFS_MODULE_PARAM(zfs, zfs_, snapshot_history_enabled, INT, ZMOD_RW,
+ "Include snapshot events in pool history/events");
+
EXPORT_SYMBOL(dsl_dataset_hold);
EXPORT_SYMBOL(dsl_dataset_hold_flags);
EXPORT_SYMBOL(dsl_dataset_hold_obj);
@@ -5019,4 +5014,3 @@ EXPORT_SYMBOL(dsl_dsobj_to_dsname);
EXPORT_SYMBOL(dsl_dataset_check_quota);
EXPORT_SYMBOL(dsl_dataset_clone_swap_check_impl);
EXPORT_SYMBOL(dsl_dataset_clone_swap_sync_impl);
-EXPORT_SYMBOL(dsl_dataset_feature_set_activation);
diff --git a/module/zfs/dsl_deadlist.c b/module/zfs/dsl_deadlist.c
index f516b1c3111e..eff1f7de7731 100644
--- a/module/zfs/dsl_deadlist.c
+++ b/module/zfs/dsl_deadlist.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -92,7 +92,7 @@
* will be loaded into memory and shouldn't take up an inordinate amount of
* space. We settled on ~500000 entries, corresponding to roughly 128M.
*/
-unsigned long zfs_livelist_max_entries = 500000;
+uint64_t zfs_livelist_max_entries = 500000;
/*
* We can approximate how much of a performance gain a livelist will give us
@@ -173,8 +173,8 @@ dsl_deadlist_load_tree(dsl_deadlist_t *dl)
* in parallel. Then open them all in a second pass.
*/
dle->dle_bpobj.bpo_object = za.za_first_integer;
- dmu_prefetch(dl->dl_os, dle->dle_bpobj.bpo_object,
- 0, 0, 0, ZIO_PRIORITY_SYNC_READ);
+ dmu_prefetch_dnode(dl->dl_os, dle->dle_bpobj.bpo_object,
+ ZIO_PRIORITY_SYNC_READ);
avl_add(&dl->dl_tree, dle);
}
@@ -235,8 +235,8 @@ dsl_deadlist_load_cache(dsl_deadlist_t *dl)
* in parallel. Then open them all in a second pass.
*/
dlce->dlce_bpobj = za.za_first_integer;
- dmu_prefetch(dl->dl_os, dlce->dlce_bpobj,
- 0, 0, 0, ZIO_PRIORITY_SYNC_READ);
+ dmu_prefetch_dnode(dl->dl_os, dlce->dlce_bpobj,
+ ZIO_PRIORITY_SYNC_READ);
avl_add(&dl->dl_cache, dlce);
}
VERIFY3U(error, ==, ENOENT);
@@ -438,6 +438,18 @@ dle_enqueue_subobj(dsl_deadlist_t *dl, dsl_deadlist_entry_t *dle,
}
}
+/*
+ * Prefetch metadata required for dle_enqueue_subobj().
+ */
+static void
+dle_prefetch_subobj(dsl_deadlist_t *dl, dsl_deadlist_entry_t *dle,
+ uint64_t obj)
+{
+ if (dle->dle_bpobj.bpo_object !=
+ dmu_objset_pool(dl->dl_os)->dp_empty_bpobj)
+ bpobj_prefetch_subobj(&dle->dle_bpobj, obj);
+}
+
void
dsl_deadlist_insert(dsl_deadlist_t *dl, const blkptr_t *bp, boolean_t bp_freed,
dmu_tx_t *tx)
@@ -462,7 +474,7 @@ dsl_deadlist_insert(dsl_deadlist_t *dl, const blkptr_t *bp, boolean_t bp_freed,
dl->dl_phys->dl_comp += sign * BP_GET_PSIZE(bp);
dl->dl_phys->dl_uncomp += sign * BP_GET_UCSIZE(bp);
- dle_tofind.dle_mintxg = bp->blk_birth;
+ dle_tofind.dle_mintxg = BP_GET_LOGICAL_BIRTH(bp);
dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
if (dle == NULL)
dle = avl_nearest(&dl->dl_tree, where, AVL_BEFORE);
@@ -471,7 +483,7 @@ dsl_deadlist_insert(dsl_deadlist_t *dl, const blkptr_t *bp, boolean_t bp_freed,
if (dle == NULL) {
zfs_panic_recover("blkptr at %p has invalid BLK_BIRTH %llu",
- bp, (longlong_t)bp->blk_birth);
+ bp, (longlong_t)BP_GET_LOGICAL_BIRTH(bp));
dle = avl_first(&dl->dl_tree);
}
@@ -542,6 +554,7 @@ dsl_deadlist_remove_key(dsl_deadlist_t *dl, uint64_t mintxg, dmu_tx_t *tx)
dle = avl_find(&dl->dl_tree, &dle_tofind, NULL);
ASSERT3P(dle, !=, NULL);
dle_prev = AVL_PREV(&dl->dl_tree, dle);
+ ASSERT3P(dle_prev, !=, NULL);
dle_enqueue_subobj(dl, dle_prev, dle->dle_bpobj.bpo_object, tx);
@@ -809,6 +822,27 @@ dsl_deadlist_insert_bpobj(dsl_deadlist_t *dl, uint64_t obj, uint64_t birth,
dle_enqueue_subobj(dl, dle, obj, tx);
}
+/*
+ * Prefetch metadata required for dsl_deadlist_insert_bpobj().
+ */
+static void
+dsl_deadlist_prefetch_bpobj(dsl_deadlist_t *dl, uint64_t obj, uint64_t birth)
+{
+ dsl_deadlist_entry_t dle_tofind;
+ dsl_deadlist_entry_t *dle;
+ avl_index_t where;
+
+ ASSERT(MUTEX_HELD(&dl->dl_lock));
+
+ dsl_deadlist_load_tree(dl);
+
+ dle_tofind.dle_mintxg = birth;
+ dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
+ if (dle == NULL)
+ dle = avl_nearest(&dl->dl_tree, where, AVL_BEFORE);
+ dle_prefetch_subobj(dl, dle, obj);
+}
+
static int
dsl_deadlist_insert_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed,
dmu_tx_t *tx)
@@ -825,12 +859,12 @@ dsl_deadlist_insert_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed,
void
dsl_deadlist_merge(dsl_deadlist_t *dl, uint64_t obj, dmu_tx_t *tx)
{
- zap_cursor_t zc;
- zap_attribute_t za;
+ zap_cursor_t zc, pzc;
+ zap_attribute_t *za, *pza;
dmu_buf_t *bonus;
dsl_deadlist_phys_t *dlp;
dmu_object_info_t doi;
- int error;
+ int error, perror, i;
VERIFY0(dmu_object_info(dl->dl_os, obj, &doi));
if (doi.doi_type == DMU_OT_BPOBJ) {
@@ -841,16 +875,36 @@ dsl_deadlist_merge(dsl_deadlist_t *dl, uint64_t obj, dmu_tx_t *tx)
return;
}
+ za = kmem_alloc(sizeof (*za), KM_SLEEP);
+ pza = kmem_alloc(sizeof (*pza), KM_SLEEP);
+
mutex_enter(&dl->dl_lock);
+ /*
+ * Prefetch up to 128 deadlists first and then more as we progress.
+ * The limit is a balance between ARC use and diminishing returns.
+ */
+ for (zap_cursor_init(&pzc, dl->dl_os, obj), i = 0;
+ (perror = zap_cursor_retrieve(&pzc, pza)) == 0 && i < 128;
+ zap_cursor_advance(&pzc), i++) {
+ dsl_deadlist_prefetch_bpobj(dl, pza->za_first_integer,
+ zfs_strtonum(pza->za_name, NULL));
+ }
for (zap_cursor_init(&zc, dl->dl_os, obj);
- (error = zap_cursor_retrieve(&zc, &za)) == 0;
+ (error = zap_cursor_retrieve(&zc, za)) == 0;
zap_cursor_advance(&zc)) {
- uint64_t mintxg = zfs_strtonum(za.za_name, NULL);
- dsl_deadlist_insert_bpobj(dl, za.za_first_integer, mintxg, tx);
- VERIFY0(zap_remove_int(dl->dl_os, obj, mintxg, tx));
+ dsl_deadlist_insert_bpobj(dl, za->za_first_integer,
+ zfs_strtonum(za->za_name, NULL), tx);
+ VERIFY0(zap_remove(dl->dl_os, obj, za->za_name, tx));
+ if (perror == 0) {
+ dsl_deadlist_prefetch_bpobj(dl, pza->za_first_integer,
+ zfs_strtonum(pza->za_name, NULL));
+ zap_cursor_advance(&pzc);
+ perror = zap_cursor_retrieve(&pzc, pza);
+ }
}
VERIFY3U(error, ==, ENOENT);
zap_cursor_fini(&zc);
+ zap_cursor_fini(&pzc);
VERIFY0(dmu_bonus_hold(dl->dl_os, obj, FTAG, &bonus));
dlp = bonus->db_data;
@@ -858,6 +912,9 @@ dsl_deadlist_merge(dsl_deadlist_t *dl, uint64_t obj, dmu_tx_t *tx)
memset(dlp, 0, sizeof (*dlp));
dmu_buf_rele(bonus, FTAG);
mutex_exit(&dl->dl_lock);
+
+ kmem_free(za, sizeof (*za));
+ kmem_free(pza, sizeof (*pza));
}
/*
@@ -868,8 +925,9 @@ dsl_deadlist_move_bpobj(dsl_deadlist_t *dl, bpobj_t *bpo, uint64_t mintxg,
dmu_tx_t *tx)
{
dsl_deadlist_entry_t dle_tofind;
- dsl_deadlist_entry_t *dle;
+ dsl_deadlist_entry_t *dle, *pdle;
avl_index_t where;
+ int i;
ASSERT(!dl->dl_oldfmt);
@@ -881,11 +939,23 @@ dsl_deadlist_move_bpobj(dsl_deadlist_t *dl, bpobj_t *bpo, uint64_t mintxg,
dle = avl_find(&dl->dl_tree, &dle_tofind, &where);
if (dle == NULL)
dle = avl_nearest(&dl->dl_tree, where, AVL_AFTER);
+ /*
+ * Prefetch up to 128 deadlists first and then more as we progress.
+ * The limit is a balance between ARC use and diminishing returns.
+ */
+ for (pdle = dle, i = 0; pdle && i < 128; i++) {
+ bpobj_prefetch_subobj(bpo, pdle->dle_bpobj.bpo_object);
+ pdle = AVL_NEXT(&dl->dl_tree, pdle);
+ }
while (dle) {
uint64_t used, comp, uncomp;
dsl_deadlist_entry_t *dle_next;
bpobj_enqueue_subobj(bpo, dle->dle_bpobj.bpo_object, tx);
+ if (pdle) {
+ bpobj_prefetch_subobj(bpo, pdle->dle_bpobj.bpo_object);
+ pdle = AVL_NEXT(&dl->dl_tree, pdle);
+ }
VERIFY0(bpobj_space(&dle->dle_bpobj,
&used, &comp, &uncomp));
@@ -930,8 +1000,6 @@ livelist_compare(const void *larg, const void *rarg)
/* if vdevs are equal, sort by offsets. */
uint64_t l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
uint64_t r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
- if (l_dva0_offset == r_dva0_offset)
- ASSERT3U(l->blk_birth, ==, r->blk_birth);
return (TREE_CMP(l_dva0_offset, r_dva0_offset));
}
@@ -946,9 +1014,9 @@ struct livelist_iter_arg {
* and used to match up ALLOC/FREE pairs. ALLOC'd blkptrs without a
* corresponding FREE are stored in the supplied bplist.
*
- * Note that multiple FREE and ALLOC entries for the same blkptr may
- * be encountered when dedup is involved. For this reason we keep a
- * refcount for all the FREE entries of each blkptr and ensure that
+ * Note that multiple FREE and ALLOC entries for the same blkptr may be
+ * encountered when dedup or block cloning is involved. For this reason we
+ * keep a refcount for all the FREE entries of each blkptr and ensure that
* each of those FREE entries has a corresponding ALLOC preceding it.
*/
static int
@@ -967,6 +1035,12 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
livelist_entry_t node;
node.le_bp = *bp;
livelist_entry_t *found = avl_find(avl, &node, NULL);
+ if (found) {
+ ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(&found->le_bp));
+ ASSERT3U(BP_GET_CHECKSUM(bp), ==,
+ BP_GET_CHECKSUM(&found->le_bp));
+ ASSERT3U(BP_GET_BIRTH(bp), ==, BP_GET_BIRTH(&found->le_bp));
+ }
if (bp_freed) {
if (found == NULL) {
/* first free entry for this blkptr */
@@ -976,10 +1050,10 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
e->le_refcnt = 1;
avl_add(avl, e);
} else {
- /* dedup block free */
- ASSERT(BP_GET_DEDUP(bp));
- ASSERT3U(BP_GET_CHECKSUM(bp), ==,
- BP_GET_CHECKSUM(&found->le_bp));
+ /*
+ * Deduped or cloned block free. We could assert D bit
+ * for dedup, but there is no such one for cloning.
+ */
ASSERT3U(found->le_refcnt + 1, >, found->le_refcnt);
found->le_refcnt++;
}
@@ -995,14 +1069,6 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed,
/* all tracked free pairs have been matched */
avl_remove(avl, found);
kmem_free(found, sizeof (livelist_entry_t));
- } else {
- /*
- * This is definitely a deduped blkptr so
- * let's validate it.
- */
- ASSERT(BP_GET_DEDUP(bp));
- ASSERT3U(BP_GET_CHECKSUM(bp), ==,
- BP_GET_CHECKSUM(&found->le_bp));
}
}
}
@@ -1028,13 +1094,18 @@ 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);
}
-ZFS_MODULE_PARAM(zfs_livelist, zfs_livelist_, max_entries, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_livelist, zfs_livelist_, max_entries, U64, ZMOD_RW,
"Size to start the next sub-livelist in a livelist");
ZFS_MODULE_PARAM(zfs_livelist, zfs_livelist_, min_percent_shared, INT, ZMOD_RW,
diff --git a/module/zfs/dsl_deleg.c b/module/zfs/dsl_deleg.c
index cf8a3c9bbdfb..645ad8e5b8dc 100644
--- a/module/zfs/dsl_deleg.c
+++ b/module/zfs/dsl_deleg.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/dsl_destroy.c b/module/zfs/dsl_destroy.c
index f44de67f4693..d4a6e5b6e9fd 100644
--- a/module/zfs/dsl_destroy.c
+++ b/module/zfs/dsl_destroy.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -49,6 +49,8 @@
#include <sys/zthr.h>
#include <sys/spa_impl.h>
+extern int zfs_snapshot_history_enabled;
+
int
dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
{
@@ -130,10 +132,11 @@ process_old_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
ASSERT(!BP_IS_HOLE(bp));
- if (bp->blk_birth <= dsl_dataset_phys(poa->ds)->ds_prev_snap_txg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) <=
+ dsl_dataset_phys(poa->ds)->ds_prev_snap_txg) {
dsl_deadlist_insert(&poa->ds->ds_deadlist, bp, bp_freed, tx);
if (poa->ds_prev && !poa->after_branch_point &&
- bp->blk_birth >
+ BP_GET_LOGICAL_BIRTH(bp) >
dsl_dataset_phys(poa->ds_prev)->ds_prev_snap_txg) {
dsl_dataset_phys(poa->ds_prev)->ds_unique_bytes +=
bp_get_dsize_sync(dp->dp_spa, bp);
@@ -311,7 +314,8 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
- ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(&dsl_dataset_phys(ds)->ds_bp), <=,
+ tx->tx_txg);
rrw_exit(&ds->ds_bp_rwlock, FTAG);
ASSERT(zfs_refcount_is_zero(&ds->ds_longholds));
@@ -321,14 +325,19 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
dmu_buf_will_dirty(ds->ds_dbuf, tx);
dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_DEFER_DESTROY;
- spa_history_log_internal_ds(ds, "defer_destroy", tx, " ");
+ if (zfs_snapshot_history_enabled) {
+ spa_history_log_internal_ds(ds, "defer_destroy", tx,
+ " ");
+ }
return;
}
ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1);
- /* We need to log before removing it from the namespace. */
- spa_history_log_internal_ds(ds, "destroy", tx, " ");
+ if (zfs_snapshot_history_enabled) {
+ /* We need to log before removing it from the namespace. */
+ spa_history_log_internal_ds(ds, "destroy", tx, " ");
+ }
dsl_scan_ds_destroyed(ds, tx);
@@ -651,7 +660,7 @@ dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,
zfs_lua_max_memlimit,
fnvlist_lookup_nvpair(wrapper, ZCP_ARG_ARGLIST), result);
if (error != 0) {
- char *errorstr = NULL;
+ const char *errorstr = NULL;
(void) nvlist_lookup_string(result, ZCP_RET_ERROR, &errorstr);
if (errorstr != NULL) {
zfs_dbgmsg("%s", errorstr);
@@ -720,7 +729,7 @@ kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
} else {
ASSERT(zilog == NULL);
- ASSERT3U(bp->blk_birth, >,
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(bp), >,
dsl_dataset_phys(ka->ds)->ds_prev_snap_txg);
(void) dsl_dataset_block_kill(ka->ds, bp, tx, B_FALSE);
}
@@ -1010,7 +1019,8 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
ASSERT(ds->ds_prev == NULL ||
dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj != ds->ds_object);
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
- ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(&dsl_dataset_phys(ds)->ds_bp), <=,
+ tx->tx_txg);
rrw_exit(&ds->ds_bp_rwlock, FTAG);
ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
@@ -1118,6 +1128,16 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
while ((dbn = avl_destroy_nodes(&ds->ds_bookmarks, &cookie)) !=
NULL) {
if (dbn->dbn_phys.zbm_redaction_obj != 0) {
+ dnode_t *rl;
+ VERIFY0(dnode_hold(mos,
+ dbn->dbn_phys.zbm_redaction_obj, FTAG,
+ &rl));
+ if (rl->dn_have_spill) {
+ spa_feature_decr(dmu_objset_spa(mos),
+ SPA_FEATURE_REDACTION_LIST_SPILL,
+ tx);
+ }
+ dnode_rele(rl, FTAG);
VERIFY0(dmu_object_free(mos,
dbn->dbn_phys.zbm_redaction_obj, tx));
spa_feature_decr(dmu_objset_spa(mos),
diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c
index b5f50c9bde1d..baf970121a61 100644
--- a/module/zfs/dsl_dir.c
+++ b/module/zfs/dsl_dir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,6 +26,7 @@
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+ * Copyright (c) 2023 Hewlett Packard Enterprise Development LP.
*/
#include <sys/dmu.h>
@@ -54,6 +55,15 @@
#include "zfs_prop.h"
/*
+ * This controls if we verify the ZVOL quota or not.
+ * Currently, quotas are not implemented for ZVOLs.
+ * The quota size is the size of the ZVOL.
+ * The size of the volume already implies the ZVOL size quota.
+ * The quota mechanism can introduce a significant performance drop.
+ */
+static int zvol_enforce_quotas = B_TRUE;
+
+/*
* Filesystem and Snapshot Limits
* ------------------------------
*
@@ -207,8 +217,6 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
}
}
- dsl_dir_snap_cmtime_update(dd);
-
if (dsl_dir_phys(dd)->dd_parent_obj) {
err = dsl_dir_hold_obj(dp,
dsl_dir_phys(dd)->dd_parent_obj, NULL, dd,
@@ -270,6 +278,16 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
}
}
+ if (dsl_dir_is_zapified(dd)) {
+ inode_timespec_t t = {0};
+ (void) zap_lookup(dp->dp_meta_objset, ddobj,
+ DD_FIELD_SNAPSHOTS_CHANGED,
+ sizeof (uint64_t),
+ sizeof (inode_timespec_t) / sizeof (uint64_t),
+ &t);
+ dd->dd_snap_cmtime = t;
+ }
+
dmu_buf_init_user(&dd->dd_dbu, NULL, dsl_dir_evict_async,
&dd->dd_dbuf);
winner = dmu_buf_set_user_ie(dbuf, &dd->dd_dbu);
@@ -420,8 +438,7 @@ getcomponent(const char *path, char *component, const char **nextp)
} else if (p[0] == '/') {
if (p - path >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
- (void) strncpy(component, path, p - path);
- component[p - path] = '\0';
+ (void) strlcpy(component, path, p - path + 1);
p++;
} else if (p[0] == '@') {
/*
@@ -432,8 +449,7 @@ getcomponent(const char *path, char *component, const char **nextp)
return (SET_ERROR(EINVAL));
if (p - path >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
- (void) strncpy(component, path, p - path);
- component[p - path] = '\0';
+ (void) strlcpy(component, path, p - path + 1);
} else {
panic("invalid p=%p", (void *)p);
}
@@ -809,6 +825,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
@@ -828,19 +856,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
@@ -1172,10 +1187,9 @@ dsl_dir_space_towrite(dsl_dir_t *dd)
ASSERT(MUTEX_HELD(&dd->dd_lock));
- for (int i = 0; i < TXG_SIZE; i++) {
+ for (int i = 0; i < TXG_SIZE; i++)
space += dd->dd_space_towrite[i & TXG_MASK];
- ASSERT3U(dd->dd_space_towrite[i & TXG_MASK], >=, 0);
- }
+
return (space);
}
@@ -1262,6 +1276,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:
@@ -1305,7 +1320,9 @@ top_of_function:
* If this transaction will result in a net free of space,
* we want to let it through.
*/
- if (ignorequota || netfree || dsl_dir_phys(dd)->dd_quota == 0)
+ if (ignorequota || netfree || dsl_dir_phys(dd)->dd_quota == 0 ||
+ (tx->tx_objset && dmu_objset_type(tx->tx_objset) == DMU_OST_ZVOL &&
+ zvol_enforce_quotas == B_FALSE))
quota = UINT64_MAX;
else
quota = dsl_dir_phys(dd)->dd_quota;
@@ -1337,26 +1354,28 @@ top_of_function:
* 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) {
- if (est_inflight > 0 || used_on_disk < quota) {
- retval = SET_ERROR(ERESTART);
- } else {
- ASSERT3U(used_on_disk, >=, quota);
+ ext_quota = quota >> 5;
+ if (quota == UINT64_MAX)
+ ext_quota = 0;
- if (retval == ENOSPC && (used_on_disk - quota) <
- dsl_pool_deferred_space(dd->dd_pool)) {
- retval = SET_ERROR(ERESTART);
- }
+ if (used_on_disk >= quota) {
+ if (retval == ENOSPC && (used_on_disk - quota) <
+ dsl_pool_deferred_space(dd->dd_pool)) {
+ retval = SET_ERROR(ERESTART);
}
-
+ /* 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) {
dprintf_dd(dd, "failing: used=%lluK inflight = %lluK "
- "quota=%lluK tr=%lluK err=%d\n",
+ "quota=%lluK tr=%lluK\n",
(u_longlong_t)used_on_disk>>10,
(u_longlong_t)est_inflight>>10,
- (u_longlong_t)quota>>10, (u_longlong_t)asize>>10, retval);
+ (u_longlong_t)quota>>10, (u_longlong_t)asize>>10);
mutex_exit(&dd->dd_lock);
DMU_TX_STAT_BUMP(dmu_tx_quota);
- return (retval);
+ return (SET_ERROR(ERESTART));
}
/* We need to up our estimated delta before dropping dd_lock */
@@ -1384,10 +1403,9 @@ top_of_function:
ignorequota = (dsl_dir_phys(dd)->dd_head_dataset_obj == 0);
first = B_FALSE;
goto top_of_function;
-
- } else {
- return (0);
}
+
+ return (0);
}
/*
@@ -1466,7 +1484,7 @@ dsl_dir_tempreserve_clear(void *tr_cookie, dmu_tx_t *tx)
if (tr_cookie == NULL)
return;
- while ((tr = list_head(tr_list)) != NULL) {
+ while ((tr = list_remove_head(tr_list)) != NULL) {
if (tr->tr_ds) {
mutex_enter(&tr->tr_ds->dd_lock);
ASSERT3U(tr->tr_ds->dd_tempreserved[txgidx], >=,
@@ -1476,7 +1494,6 @@ dsl_dir_tempreserve_clear(void *tr_cookie, dmu_tx_t *tx)
} else {
arc_tempreserve_clear(tr->tr_size);
}
- list_remove(tr_list, tr);
kmem_free(tr, sizeof (struct tempreserve));
}
@@ -2101,6 +2118,8 @@ dsl_dir_rename_sync(void *arg, dmu_tx_t *tx)
VERIFY0(dsl_dir_hold(dp, ddra->ddra_newname, FTAG, &newparent,
&mynewname));
+ ASSERT3P(mynewname, !=, NULL);
+
/* Log this before we change the name. */
spa_history_log_internal_dd(dd, "rename", tx,
"-> %s", ddra->ddra_newname);
@@ -2243,13 +2262,25 @@ dsl_dir_snap_cmtime(dsl_dir_t *dd)
}
void
-dsl_dir_snap_cmtime_update(dsl_dir_t *dd)
+dsl_dir_snap_cmtime_update(dsl_dir_t *dd, dmu_tx_t *tx)
{
+ dsl_pool_t *dp = dmu_tx_pool(tx);
inode_timespec_t t;
-
gethrestime(&t);
+
mutex_enter(&dd->dd_lock);
dd->dd_snap_cmtime = t;
+ if (spa_feature_is_enabled(dp->dp_spa,
+ SPA_FEATURE_EXTENSIBLE_DATASET)) {
+ objset_t *mos = dd->dd_pool->dp_meta_objset;
+ uint64_t ddobj = dd->dd_object;
+ dsl_dir_zapify(dd, tx);
+ VERIFY0(zap_update(mos, ddobj,
+ DD_FIELD_SNAPSHOTS_CHANGED,
+ sizeof (uint64_t),
+ sizeof (inode_timespec_t) / sizeof (uint64_t),
+ &t, tx));
+ }
mutex_exit(&dd->dd_lock);
}
@@ -2456,3 +2487,7 @@ dsl_dir_cancel_waiters(dsl_dir_t *dd)
EXPORT_SYMBOL(dsl_dir_set_quota);
EXPORT_SYMBOL(dsl_dir_set_reservation);
#endif
+
+/* CSTYLED */
+ZFS_MODULE_PARAM(zfs, , zvol_enforce_quotas, INT, ZMOD_RW,
+ "Enable strict ZVOL quota enforcment");
diff --git a/module/zfs/dsl_pool.c b/module/zfs/dsl_pool.c
index 3c2fefcfb085..342ec5c15c79 100644
--- a/module/zfs/dsl_pool.c
+++ b/module/zfs/dsl_pool.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -99,31 +99,31 @@
* capped at zfs_dirty_data_max_max. It can also be overridden with a module
* parameter.
*/
-unsigned long zfs_dirty_data_max = 0;
-unsigned long zfs_dirty_data_max_max = 0;
-int zfs_dirty_data_max_percent = 10;
-int zfs_dirty_data_max_max_percent = 25;
+uint64_t zfs_dirty_data_max = 0;
+uint64_t zfs_dirty_data_max_max = 0;
+uint_t zfs_dirty_data_max_percent = 10;
+uint_t zfs_dirty_data_max_max_percent = 25;
/*
* The upper limit of TX_WRITE log data. Write operations are throttled
* when approaching the limit until log data is cleared out after txg sync.
* It only counts TX_WRITE log with WR_COPIED or WR_NEED_COPY.
*/
-unsigned long zfs_wrlog_data_max = 0;
+uint64_t zfs_wrlog_data_max = 0;
/*
* If there's at least this much dirty data (as a percentage of
* zfs_dirty_data_max), push out a txg. This should be less than
* zfs_vdev_async_write_active_min_dirty_percent.
*/
-static int zfs_dirty_data_sync_percent = 20;
+static uint_t zfs_dirty_data_sync_percent = 20;
/*
* Once there is this amount of dirty data, the dmu_tx_delay() will kick in
* and delay each transaction.
* This value should be >= zfs_vdev_async_write_active_max_dirty_percent.
*/
-int zfs_delay_min_dirty_percent = 60;
+uint_t zfs_delay_min_dirty_percent = 60;
/*
* This controls how quickly the delay approaches infinity.
@@ -138,12 +138,7 @@ int zfs_delay_min_dirty_percent = 60;
* Note: zfs_delay_scale * zfs_dirty_data_max must be < 2^64, due to the
* multiply in dmu_tx_delay().
*/
-unsigned long zfs_delay_scale = 1000 * 1000 * 1000 / 2000;
-
-/*
- * This determines the number of threads used by the dp_sync_taskq.
- */
-static int zfs_sync_taskq_batch_pct = 75;
+uint64_t zfs_delay_scale = 1000 * 1000 * 1000 / 2000;
/*
* These tunables determine the behavior of how zil_itxg_clean() is
@@ -214,9 +209,7 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
txg_list_create(&dp->dp_early_sync_tasks, spa,
offsetof(dsl_sync_task_t, dst_node));
- dp->dp_sync_taskq = taskq_create("dp_sync_taskq",
- zfs_sync_taskq_batch_pct, minclsyspri, 1, INT_MAX,
- TASKQ_THREADS_CPU_PCT);
+ dp->dp_sync_taskq = spa_sync_tq_create(spa, "dp_sync_taskq");
dp->dp_zil_clean_taskq = taskq_create("dp_zil_clean_taskq",
zfs_zil_clean_taskq_nthr_pct, minclsyspri,
@@ -331,7 +324,6 @@ dsl_pool_open(dsl_pool_t *dp)
/*
* We might not have created the remap bpobj yet.
*/
- err = 0;
} else {
goto out;
}
@@ -410,7 +402,7 @@ dsl_pool_close(dsl_pool_t *dp)
txg_list_destroy(&dp->dp_dirty_dirs);
taskq_destroy(dp->dp_zil_clean_taskq);
- taskq_destroy(dp->dp_sync_taskq);
+ spa_sync_tq_destroy(dp->dp_spa);
/*
* We can't set retry to TRUE since we're explicitly specifying
@@ -675,7 +667,7 @@ dsl_early_sync_task_verify(dsl_pool_t *dp, uint64_t txg)
void
dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
{
- zio_t *zio;
+ zio_t *rio; /* root zio for all dirty dataset syncs */
dmu_tx_t *tx;
dsl_dir_t *dd;
dsl_dataset_t *ds;
@@ -705,9 +697,10 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
}
/*
- * Write out all dirty blocks of dirty datasets.
+ * Write out all dirty blocks of dirty datasets. Note, this could
+ * create a very large (+10k) zio tree.
*/
- zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
+ rio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) != NULL) {
/*
* We must not sync any non-MOS datasets twice, because
@@ -716,9 +709,9 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
*/
ASSERT(!list_link_active(&ds->ds_synced_link));
list_insert_tail(&synced_datasets, ds);
- dsl_dataset_sync(ds, zio, tx);
+ dsl_dataset_sync(ds, rio, tx);
}
- VERIFY0(zio_wait(zio));
+ VERIFY0(zio_wait(rio));
/*
* Update the long range free counter after
@@ -749,13 +742,13 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
* user accounting information (and we won't get confused
* about which blocks are part of the snapshot).
*/
- zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
+ rio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) != NULL) {
objset_t *os = ds->ds_objset;
ASSERT(list_link_active(&ds->ds_synced_link));
dmu_buf_rele(ds->ds_dbuf, ds);
- dsl_dataset_sync(ds, zio, tx);
+ dsl_dataset_sync(ds, rio, tx);
/*
* Release any key mappings created by calls to
@@ -768,7 +761,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
key_mapping_rele(dp->dp_spa, ds->ds_key_mapping, ds);
}
}
- VERIFY0(zio_wait(zio));
+ VERIFY0(zio_wait(rio));
/*
* Now that the datasets have been completely synced, we can
@@ -789,6 +782,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
}
dsl_dataset_sync_done(ds, tx);
+ dmu_buf_rele(ds->ds_dbuf, ds);
}
while ((dd = txg_list_remove(&dp->dp_dirty_dirs, txg)) != NULL) {
@@ -965,18 +959,18 @@ dsl_pool_need_dirty_delay(dsl_pool_t *dp)
uint64_t delay_min_bytes =
zfs_dirty_data_max * zfs_delay_min_dirty_percent / 100;
- mutex_enter(&dp->dp_lock);
- uint64_t dirty = dp->dp_dirty_total;
- mutex_exit(&dp->dp_lock);
-
- return (dirty > delay_min_bytes);
+ /*
+ * We are not taking the dp_lock here and few other places, since torn
+ * reads are unlikely: on 64-bit systems due to register size and on
+ * 32-bit due to memory constraints. Pool-wide locks in hot path may
+ * be too expensive, while we do not need a precise result here.
+ */
+ return (dp->dp_dirty_total > delay_min_bytes);
}
static boolean_t
dsl_pool_need_dirty_sync(dsl_pool_t *dp, uint64_t txg)
{
- ASSERT(MUTEX_HELD(&dp->dp_lock));
-
uint64_t dirty_min_bytes =
zfs_dirty_data_max * zfs_dirty_data_sync_percent / 100;
uint64_t dirty = dp->dp_dirty_pertxg[txg & TXG_MASK];
@@ -1053,7 +1047,7 @@ upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
* will be wrong.
*/
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
- ASSERT0(dsl_dataset_phys(prev)->ds_bp.blk_birth);
+ ASSERT0(BP_GET_LOGICAL_BIRTH(&dsl_dataset_phys(prev)->ds_bp));
rrw_exit(&ds->ds_bp_rwlock, FTAG);
/* The origin doesn't get attached to itself */
@@ -1455,35 +1449,32 @@ EXPORT_SYMBOL(dsl_pool_config_enter);
EXPORT_SYMBOL(dsl_pool_config_exit);
/* zfs_dirty_data_max_percent only applied at module load in arc_init(). */
-ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_percent, INT, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_percent, UINT, ZMOD_RD,
"Max percent of RAM allowed to be dirty");
/* zfs_dirty_data_max_max_percent only applied at module load in arc_init(). */
-ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_max_percent, INT, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_max_percent, UINT, ZMOD_RD,
"zfs_dirty_data_max upper bound as % of RAM");
-ZFS_MODULE_PARAM(zfs, zfs_, delay_min_dirty_percent, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, delay_min_dirty_percent, UINT, ZMOD_RW,
"Transaction delay threshold");
-ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max, U64, ZMOD_RW,
"Determines the dirty space limit");
-ZFS_MODULE_PARAM(zfs, zfs_, wrlog_data_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, wrlog_data_max, U64, ZMOD_RW,
"The size limit of write-transaction zil log data");
/* zfs_dirty_data_max_max only applied at module load in arc_init(). */
-ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_max, ULONG, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_max_max, U64, ZMOD_RD,
"zfs_dirty_data_max upper bound in bytes");
-ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_sync_percent, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, dirty_data_sync_percent, UINT, ZMOD_RW,
"Dirty data txg sync threshold as a percentage of zfs_dirty_data_max");
-ZFS_MODULE_PARAM(zfs, zfs_, delay_scale, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, delay_scale, U64, ZMOD_RW,
"How quickly delay approaches infinity");
-ZFS_MODULE_PARAM(zfs, zfs_, sync_taskq_batch_pct, INT, ZMOD_RW,
- "Max percent of CPUs that are used to sync dirty data");
-
ZFS_MODULE_PARAM(zfs_zil, zfs_zil_, clean_taskq_nthr_pct, INT, ZMOD_RW,
"Max percent of CPUs that are used per dp_sync_taskq");
diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c
index 51d689355ef0..99f931cd8632 100644
--- a/module/zfs/dsl_prop.c
+++ b/module/zfs/dsl_prop.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -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 <sys/zfs_context.h>
@@ -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)
@@ -57,7 +59,7 @@ dodefault(zfs_prop_t prop, int intsz, int numints, void *buf)
if (zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
if (intsz != 1)
return (SET_ERROR(EOVERFLOW));
- (void) strncpy(buf, zfs_prop_default_string(prop),
+ (void) strlcpy(buf, zfs_prop_default_string(prop),
numints);
} else {
if (intsz != 8 || numints < 1)
@@ -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_USERPROP || 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 (err == 0 && dsl_prop_known_index(prop,
+ *(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.
@@ -881,7 +956,7 @@ dsl_props_set_check(void *arg, dmu_tx_t *tx)
return (SET_ERROR(ENAMETOOLONG));
}
if (nvpair_type(elem) == DATA_TYPE_STRING) {
- char *valstr = fnvpair_value_string(elem);
+ const char *valstr = fnvpair_value_string(elem);
if (strlen(valstr) >= (version <
SPA_VERSION_STMF_PROP ?
ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) {
@@ -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;
@@ -1019,8 +1102,8 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj,
if (flags & DSL_PROP_GET_LOCAL)
continue;
- (void) strncpy(buf, za.za_name, (suffix - za.za_name));
- buf[suffix - za.za_name] = '\0';
+ (void) strlcpy(buf, za.za_name,
+ MIN(sizeof (buf), suffix - za.za_name + 1));
propname = buf;
if (!(flags & DSL_PROP_GET_RECEIVED)) {
@@ -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/dsl_scan.c b/module/zfs/dsl_scan.c
index e8b581390c07..55e89b89f06a 100644
--- a/module/zfs/dsl_scan.c
+++ b/module/zfs/dsl_scan.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -37,6 +37,7 @@
#include <sys/dmu_tx.h>
#include <sys/dmu_objset.h>
#include <sys/arc.h>
+#include <sys/arc_impl.h>
#include <sys/zap.h>
#include <sys/zio.h>
#include <sys/zfs_context.h>
@@ -46,12 +47,14 @@
#include <sys/vdev_impl.h>
#include <sys/zil_impl.h>
#include <sys/zio_checksum.h>
+#include <sys/brt.h>
#include <sys/ddt.h>
#include <sys/sa.h>
#include <sys/sa_impl.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/range_tree.h>
+#include <sys/dbuf.h>
#ifdef _KERNEL
#include <sys/zfs_vfsops.h>
#endif
@@ -126,12 +129,22 @@ static boolean_t scan_ds_queue_contains(dsl_scan_t *scn, uint64_t dsobj,
static void scan_ds_queue_insert(dsl_scan_t *scn, uint64_t dsobj, uint64_t txg);
static void scan_ds_queue_remove(dsl_scan_t *scn, uint64_t dsobj);
static void scan_ds_queue_sync(dsl_scan_t *scn, dmu_tx_t *tx);
-static uint64_t dsl_scan_count_data_disks(vdev_t *vd);
+static uint64_t dsl_scan_count_data_disks(spa_t *spa);
+static void read_by_block_level(dsl_scan_t *scn, zbookmark_phys_t zb);
-extern int zfs_vdev_async_write_active_min_dirty_percent;
+extern uint_t zfs_vdev_async_write_active_min_dirty_percent;
static int zfs_scan_blkstats = 0;
/*
+ * 'zpool status' uses bytes processed per pass to report throughput and
+ * estimate time remaining. We define a pass to start when the scanning
+ * phase completes for a sequential resilver. Optionally, this value
+ * may be used to reset the pass statistics every N txgs to provide an
+ * estimated completion time based on currently observed performance.
+ */
+static uint_t zfs_scan_report_txgs = 0;
+
+/*
* By default zfs will check to ensure it is not over the hard memory
* limit before each txg. If finer-grained control of this is needed
* this value can be set to 1 to enable checking before scanning each
@@ -147,39 +160,54 @@ static int zfs_scan_strict_mem_lim = B_FALSE;
* overload the drives with I/O, since that is protected by
* zfs_vdev_scrub_max_active.
*/
-static unsigned long zfs_scan_vdev_limit = 4 << 20;
+static uint64_t zfs_scan_vdev_limit = 16 << 20;
-static int zfs_scan_issue_strategy = 0;
-static int zfs_scan_legacy = B_FALSE; /* don't queue & sort zios, go direct */
-static unsigned long zfs_scan_max_ext_gap = 2 << 20; /* in bytes */
+static uint_t zfs_scan_issue_strategy = 0;
+
+/* don't queue & sort zios, go direct */
+static int zfs_scan_legacy = B_FALSE;
+static uint64_t zfs_scan_max_ext_gap = 2 << 20; /* in bytes */
/*
* fill_weight is non-tunable at runtime, so we copy it at module init from
* zfs_scan_fill_weight. Runtime adjustments to zfs_scan_fill_weight would
* break queue sorting.
*/
-static int zfs_scan_fill_weight = 3;
+static uint_t zfs_scan_fill_weight = 3;
static uint64_t fill_weight;
/* See dsl_scan_should_clear() for details on the memory limit tunables */
static const uint64_t zfs_scan_mem_lim_min = 16 << 20; /* bytes */
static const uint64_t zfs_scan_mem_lim_soft_max = 128 << 20; /* bytes */
-static int zfs_scan_mem_lim_fact = 20; /* fraction of physmem */
-static int zfs_scan_mem_lim_soft_fact = 20; /* fraction of mem lim above */
-
-static int zfs_scrub_min_time_ms = 1000; /* min millis to scrub per txg */
-static int zfs_obsolete_min_time_ms = 500; /* min millis to obsolete per txg */
-static int zfs_free_min_time_ms = 1000; /* min millis to free per txg */
-static int zfs_resilver_min_time_ms = 3000; /* min millis to resilver per txg */
-static int zfs_scan_checkpoint_intval = 7200; /* in seconds */
+
+
+/* fraction of physmem */
+static uint_t zfs_scan_mem_lim_fact = 20;
+
+/* fraction of mem lim above */
+static uint_t zfs_scan_mem_lim_soft_fact = 20;
+
+/* minimum milliseconds to scrub per txg */
+static uint_t zfs_scrub_min_time_ms = 1000;
+
+/* minimum milliseconds to obsolete per txg */
+static uint_t zfs_obsolete_min_time_ms = 500;
+
+/* minimum milliseconds to free per txg */
+static uint_t zfs_free_min_time_ms = 1000;
+
+/* minimum milliseconds to resilver per txg */
+static uint_t zfs_resilver_min_time_ms = 3000;
+
+static uint_t zfs_scan_checkpoint_intval = 7200; /* in seconds */
int zfs_scan_suspend_progress = 0; /* set to prevent scans from progressing */
static int zfs_no_scrub_io = B_FALSE; /* set to disable scrub i/o */
static int zfs_no_scrub_prefetch = B_FALSE; /* set to disable scrub prefetch */
-static const enum ddt_class zfs_scrub_ddt_class_max = DDT_CLASS_DUPLICATE;
+static const ddt_class_t zfs_scrub_ddt_class_max = DDT_CLASS_DUPLICATE;
/* max number of blocks to free in a single TXG */
-static unsigned long zfs_async_block_max_blocks = ULONG_MAX;
+static uint64_t zfs_async_block_max_blocks = UINT64_MAX;
/* max number of dedup blocks to free in a single TXG */
-static unsigned long zfs_max_async_dedup_frees = 100000;
+static uint64_t zfs_max_async_dedup_frees = 100000;
/* set to disable resilver deferring */
static int zfs_resilver_disable_defer = B_FALSE;
@@ -205,6 +233,9 @@ static int zfs_resilver_disable_defer = B_FALSE;
*/
static int zfs_free_bpobj_enabled = 1;
+/* Error blocks to be scrubbed in one txg. */
+static uint_t zfs_scrub_error_blocks_per_txg = 1 << 12;
+
/* the order has to match pool_scan_type */
static scan_cb_t *scan_funcs[POOL_SCAN_FUNCS] = {
NULL,
@@ -266,7 +297,7 @@ typedef struct scan_io {
* event of an error. This array must go at the end of the
* struct to allow this for the variable number of elements.
*/
- dva_t sio_dva[0];
+ dva_t sio_dva[];
} scan_io_t;
#define SIO_SET_OFFSET(sio, x) DVA_SET_OFFSET(&(sio)->sio_dva[0], x)
@@ -398,8 +429,8 @@ sio2bp(const scan_io_t *sio, blkptr_t *bp)
{
memset(bp, 0, sizeof (*bp));
bp->blk_prop = sio->sio_blk_prop;
- bp->blk_phys_birth = sio->sio_phys_birth;
- bp->blk_birth = sio->sio_birth;
+ BP_SET_PHYSICAL_BIRTH(bp, sio->sio_phys_birth);
+ BP_SET_LOGICAL_BIRTH(bp, sio->sio_birth);
bp->blk_fill = 1; /* we always only work with data pointers */
bp->blk_cksum = sio->sio_cksum;
@@ -413,8 +444,8 @@ static inline void
bp2sio(const blkptr_t *bp, scan_io_t *sio, int dva_i)
{
sio->sio_blk_prop = bp->blk_prop;
- sio->sio_phys_birth = bp->blk_phys_birth;
- sio->sio_birth = bp->blk_birth;
+ sio->sio_phys_birth = BP_GET_PHYSICAL_BIRTH(bp);
+ sio->sio_birth = BP_GET_LOGICAL_BIRTH(bp);
sio->sio_cksum = bp->blk_cksum;
sio->sio_nr_dvas = BP_GET_NDVAS(bp);
@@ -451,11 +482,12 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
/*
* Calculate the max number of in-flight bytes for pool-wide
- * scanning operations (minimum 1MB). Limits for the issuing
- * phase are done per top-level vdev and are handled separately.
+ * scanning operations (minimum 1MB, maximum 1/4 of arc_c_max).
+ * Limits for the issuing phase are done per top-level vdev and
+ * are handled separately.
*/
- scn->scn_maxinflight_bytes = MAX(zfs_scan_vdev_limit *
- dsl_scan_count_data_disks(spa->spa_root_vdev), 1ULL << 20);
+ scn->scn_maxinflight_bytes = MIN(arc_c_max / 4, MAX(1ULL << 20,
+ zfs_scan_vdev_limit * dsl_scan_count_data_disks(spa)));
avl_create(&scn->scn_queue, scan_ds_queue_compare, sizeof (scan_ds_t),
offsetof(scan_ds_t, sds_node));
@@ -485,8 +517,16 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
&scn->scn_phys.scn_queue_obj);
} else {
err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
+ DMU_POOL_ERRORSCRUB, sizeof (uint64_t),
+ ERRORSCRUB_PHYS_NUMINTS, &scn->errorscrub_phys);
+
+ if (err != 0 && err != ENOENT)
+ return (err);
+
+ err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
DMU_POOL_SCAN, sizeof (uint64_t), SCAN_PHYS_NUMINTS,
&scn->scn_phys);
+
/*
* Detect if the pool contains the signature of #2094. If it
* does properly update the scn->scn_phys structure and notify
@@ -533,7 +573,8 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
* counter to how far we've scanned. We know we're consistent
* up to here.
*/
- scn->scn_issued_before_pass = scn->scn_phys.scn_examined;
+ scn->scn_issued_before_pass = scn->scn_phys.scn_examined -
+ scn->scn_phys.scn_skipped;
if (dsl_scan_is_running(scn) &&
spa_prev_software_version(dp->dp_spa) < SPA_VERSION_SCAN) {
@@ -589,6 +630,8 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
}
spa_scan_stat_init(spa);
+ vdev_scan_stat_init(spa->spa_root_vdev);
+
return (0);
}
@@ -635,12 +678,90 @@ dsl_scan_scrubbing(const dsl_pool_t *dp)
}
boolean_t
+dsl_errorscrubbing(const dsl_pool_t *dp)
+{
+ dsl_errorscrub_phys_t *errorscrub_phys = &dp->dp_scan->errorscrub_phys;
+
+ return (errorscrub_phys->dep_state == DSS_ERRORSCRUBBING &&
+ errorscrub_phys->dep_func == POOL_SCAN_ERRORSCRUB);
+}
+
+boolean_t
+dsl_errorscrub_is_paused(const dsl_scan_t *scn)
+{
+ return (dsl_errorscrubbing(scn->scn_dp) &&
+ scn->errorscrub_phys.dep_paused_flags);
+}
+
+boolean_t
dsl_scan_is_paused_scrub(const dsl_scan_t *scn)
{
return (dsl_scan_scrubbing(scn->scn_dp) &&
scn->scn_phys.scn_flags & DSF_SCRUB_PAUSED);
}
+static void
+dsl_errorscrub_sync_state(dsl_scan_t *scn, dmu_tx_t *tx)
+{
+ scn->errorscrub_phys.dep_cursor =
+ zap_cursor_serialize(&scn->errorscrub_cursor);
+
+ VERIFY0(zap_update(scn->scn_dp->dp_meta_objset,
+ DMU_POOL_DIRECTORY_OBJECT,
+ DMU_POOL_ERRORSCRUB, sizeof (uint64_t), ERRORSCRUB_PHYS_NUMINTS,
+ &scn->errorscrub_phys, tx));
+}
+
+static void
+dsl_errorscrub_setup_sync(void *arg, dmu_tx_t *tx)
+{
+ dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
+ pool_scan_func_t *funcp = arg;
+ dsl_pool_t *dp = scn->scn_dp;
+ spa_t *spa = dp->dp_spa;
+
+ ASSERT(!dsl_scan_is_running(scn));
+ ASSERT(!dsl_errorscrubbing(scn->scn_dp));
+ ASSERT(*funcp > POOL_SCAN_NONE && *funcp < POOL_SCAN_FUNCS);
+
+ memset(&scn->errorscrub_phys, 0, sizeof (scn->errorscrub_phys));
+ scn->errorscrub_phys.dep_func = *funcp;
+ scn->errorscrub_phys.dep_state = DSS_ERRORSCRUBBING;
+ scn->errorscrub_phys.dep_start_time = gethrestime_sec();
+ scn->errorscrub_phys.dep_to_examine = spa_get_last_errlog_size(spa);
+ scn->errorscrub_phys.dep_examined = 0;
+ scn->errorscrub_phys.dep_errors = 0;
+ scn->errorscrub_phys.dep_cursor = 0;
+ zap_cursor_init_serialized(&scn->errorscrub_cursor,
+ spa->spa_meta_objset, spa->spa_errlog_last,
+ scn->errorscrub_phys.dep_cursor);
+
+ vdev_config_dirty(spa->spa_root_vdev);
+ spa_event_notify(spa, NULL, NULL, ESC_ZFS_ERRORSCRUB_START);
+
+ dsl_errorscrub_sync_state(scn, tx);
+
+ spa_history_log_internal(spa, "error scrub setup", tx,
+ "func=%u mintxg=%u maxtxg=%llu",
+ *funcp, 0, (u_longlong_t)tx->tx_txg);
+}
+
+static int
+dsl_errorscrub_setup_check(void *arg, dmu_tx_t *tx)
+{
+ (void) arg;
+ dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
+
+ if (dsl_scan_is_running(scn) || (dsl_errorscrubbing(scn->scn_dp))) {
+ return (SET_ERROR(EBUSY));
+ }
+
+ if (spa_get_last_errlog_size(scn->scn_dp->dp_spa) == 0) {
+ return (ECANCELED);
+ }
+ return (0);
+}
+
/*
* Writes out a persistent dsl_scan_phys_t record to the pool directory.
* Because we can be running in the block sorting algorithm, we do not always
@@ -716,7 +837,8 @@ dsl_scan_setup_check(void *arg, dmu_tx_t *tx)
dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
vdev_t *rvd = scn->scn_dp->dp_spa->spa_root_vdev;
- if (dsl_scan_is_running(scn) || vdev_rebuild_active(rvd))
+ if (dsl_scan_is_running(scn) || vdev_rebuild_active(rvd) ||
+ dsl_errorscrubbing(scn->scn_dp))
return (SET_ERROR(EBUSY));
return (0);
@@ -725,6 +847,7 @@ dsl_scan_setup_check(void *arg, dmu_tx_t *tx)
void
dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
pool_scan_func_t *funcp = arg;
dmu_object_type_t ot = 0;
@@ -734,6 +857,14 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
ASSERT(!dsl_scan_is_running(scn));
ASSERT(*funcp > POOL_SCAN_NONE && *funcp < POOL_SCAN_FUNCS);
memset(&scn->scn_phys, 0, sizeof (scn->scn_phys));
+
+ /*
+ * If we are starting a fresh scrub, we erase the error scrub
+ * information from disk.
+ */
+ memset(&scn->errorscrub_phys, 0, sizeof (scn->errorscrub_phys));
+ dsl_errorscrub_sync_state(scn, tx);
+
scn->scn_phys.scn_func = *funcp;
scn->scn_phys.scn_state = DSS_SCANNING;
scn->scn_phys.scn_min_txg = 0;
@@ -748,6 +879,7 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
scn->scn_last_checkpoint = 0;
scn->scn_checkpointing = B_FALSE;
spa_scan_stat_init(spa);
+ vdev_scan_stat_init(spa->spa_root_vdev);
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
scn->scn_phys.scn_ddt_class_max = zfs_scrub_ddt_class_max;
@@ -826,8 +958,9 @@ dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
}
/*
- * Called by the ZFS_IOC_POOL_SCAN ioctl to start a scrub or resilver.
- * Can also be called to resume a paused scrub.
+ * Called by ZFS_IOC_POOL_SCRUB and ZFS_IOC_POOL_SCAN ioctl to start a scrub,
+ * error scrub or resilver. Can also be called to resume a paused scrub or
+ * error scrub.
*/
int
dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
@@ -853,6 +986,26 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
return (0);
}
+ if (func == POOL_SCAN_ERRORSCRUB) {
+ if (dsl_errorscrub_is_paused(dp->dp_scan)) {
+ /*
+ * got error scrub start cmd, resume paused error scrub.
+ */
+ int err = dsl_scrub_set_pause_resume(scn->scn_dp,
+ POOL_SCRUB_NORMAL);
+ if (err == 0) {
+ spa_event_notify(spa, NULL, NULL,
+ ESC_ZFS_ERRORSCRUB_RESUME);
+ return (ECANCELED);
+ }
+ return (SET_ERROR(err));
+ }
+
+ return (dsl_sync_task(spa_name(dp->dp_spa),
+ dsl_errorscrub_setup_check, dsl_errorscrub_setup_sync,
+ &func, 0, ZFS_SPACE_CHECK_RESERVED));
+ }
+
if (func == POOL_SCAN_SCRUB && dsl_scan_is_paused_scrub(scn)) {
/* got scrub start cmd, resume paused scrub */
int err = dsl_scrub_set_pause_resume(scn->scn_dp,
@@ -861,7 +1014,6 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
spa_event_notify(spa, NULL, NULL, ESC_ZFS_SCRUB_RESUME);
return (SET_ERROR(ECANCELED));
}
-
return (SET_ERROR(err));
}
@@ -870,6 +1022,33 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
}
static void
+dsl_errorscrub_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
+{
+ dsl_pool_t *dp = scn->scn_dp;
+ spa_t *spa = dp->dp_spa;
+
+ if (complete) {
+ spa_event_notify(spa, NULL, NULL, ESC_ZFS_ERRORSCRUB_FINISH);
+ spa_history_log_internal(spa, "error scrub done", tx,
+ "errors=%llu", (u_longlong_t)spa_approx_errlog_size(spa));
+ } else {
+ spa_history_log_internal(spa, "error scrub canceled", tx,
+ "errors=%llu", (u_longlong_t)spa_approx_errlog_size(spa));
+ }
+
+ scn->errorscrub_phys.dep_state = complete ? DSS_FINISHED : DSS_CANCELED;
+ spa->spa_scrub_active = B_FALSE;
+ spa_errlog_rotate(spa);
+ scn->errorscrub_phys.dep_end_time = gethrestime_sec();
+ zap_cursor_fini(&scn->errorscrub_cursor);
+
+ if (spa->spa_errata == ZPOOL_ERRATA_ZOL_2094_SCRUB)
+ spa->spa_errata = 0;
+
+ ASSERT(!dsl_errorscrubbing(scn->scn_dp));
+}
+
+static void
dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
{
static const char *old_names[] = {
@@ -929,13 +1108,13 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
if (dsl_scan_restarting(scn, tx))
spa_history_log_internal(spa, "scan aborted, restarting", tx,
- "errors=%llu", (u_longlong_t)spa_get_errlog_size(spa));
+ "errors=%llu", (u_longlong_t)spa_approx_errlog_size(spa));
else if (!complete)
spa_history_log_internal(spa, "scan cancelled", tx,
- "errors=%llu", (u_longlong_t)spa_get_errlog_size(spa));
+ "errors=%llu", (u_longlong_t)spa_approx_errlog_size(spa));
else
spa_history_log_internal(spa, "scan done", tx,
- "errors=%llu", (u_longlong_t)spa_get_errlog_size(spa));
+ "errors=%llu", (u_longlong_t)spa_approx_errlog_size(spa));
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
spa->spa_scrub_active = B_FALSE;
@@ -998,7 +1177,7 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
vdev_clear_resilver_deferred(spa->spa_root_vdev, tx)) {
spa_history_log_internal(spa,
"starting deferred resilver", tx, "errors=%llu",
- (u_longlong_t)spa_get_errlog_size(spa));
+ (u_longlong_t)spa_approx_errlog_size(spa));
spa_async_request(spa, SPA_ASYNC_RESILVER);
}
@@ -1016,6 +1195,92 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
}
static int
+dsl_errorscrub_pause_resume_check(void *arg, dmu_tx_t *tx)
+{
+ pool_scrub_cmd_t *cmd = arg;
+ dsl_pool_t *dp = dmu_tx_pool(tx);
+ dsl_scan_t *scn = dp->dp_scan;
+
+ if (*cmd == POOL_SCRUB_PAUSE) {
+ /*
+ * can't pause a error scrub when there is no in-progress
+ * error scrub.
+ */
+ if (!dsl_errorscrubbing(dp))
+ return (SET_ERROR(ENOENT));
+
+ /* can't pause a paused error scrub */
+ if (dsl_errorscrub_is_paused(scn))
+ return (SET_ERROR(EBUSY));
+ } else if (*cmd != POOL_SCRUB_NORMAL) {
+ return (SET_ERROR(ENOTSUP));
+ }
+
+ return (0);
+}
+
+static void
+dsl_errorscrub_pause_resume_sync(void *arg, dmu_tx_t *tx)
+{
+ pool_scrub_cmd_t *cmd = arg;
+ dsl_pool_t *dp = dmu_tx_pool(tx);
+ spa_t *spa = dp->dp_spa;
+ dsl_scan_t *scn = dp->dp_scan;
+
+ if (*cmd == POOL_SCRUB_PAUSE) {
+ spa->spa_scan_pass_errorscrub_pause = gethrestime_sec();
+ scn->errorscrub_phys.dep_paused_flags = B_TRUE;
+ dsl_errorscrub_sync_state(scn, tx);
+ spa_event_notify(spa, NULL, NULL, ESC_ZFS_ERRORSCRUB_PAUSED);
+ } else {
+ ASSERT3U(*cmd, ==, POOL_SCRUB_NORMAL);
+ if (dsl_errorscrub_is_paused(scn)) {
+ /*
+ * We need to keep track of how much time we spend
+ * paused per pass so that we can adjust the error scrub
+ * rate shown in the output of 'zpool status'.
+ */
+ spa->spa_scan_pass_errorscrub_spent_paused +=
+ gethrestime_sec() -
+ spa->spa_scan_pass_errorscrub_pause;
+
+ spa->spa_scan_pass_errorscrub_pause = 0;
+ scn->errorscrub_phys.dep_paused_flags = B_FALSE;
+
+ zap_cursor_init_serialized(
+ &scn->errorscrub_cursor,
+ spa->spa_meta_objset, spa->spa_errlog_last,
+ scn->errorscrub_phys.dep_cursor);
+
+ dsl_errorscrub_sync_state(scn, tx);
+ }
+ }
+}
+
+static int
+dsl_errorscrub_cancel_check(void *arg, dmu_tx_t *tx)
+{
+ (void) arg;
+ dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
+ /* can't cancel a error scrub when there is no one in-progress */
+ if (!dsl_errorscrubbing(scn->scn_dp))
+ return (SET_ERROR(ENOENT));
+ return (0);
+}
+
+static void
+dsl_errorscrub_cancel_sync(void *arg, dmu_tx_t *tx)
+{
+ (void) arg;
+ dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
+
+ dsl_errorscrub_done(scn, B_FALSE, tx);
+ dsl_errorscrub_sync_state(scn, tx);
+ spa_event_notify(scn->scn_dp->dp_spa, NULL, NULL,
+ ESC_ZFS_ERRORSCRUB_ABORT);
+}
+
+static int
dsl_scan_cancel_check(void *arg, dmu_tx_t *tx)
{
(void) arg;
@@ -1040,6 +1305,11 @@ dsl_scan_cancel_sync(void *arg, dmu_tx_t *tx)
int
dsl_scan_cancel(dsl_pool_t *dp)
{
+ if (dsl_errorscrubbing(dp)) {
+ return (dsl_sync_task(spa_name(dp->dp_spa),
+ dsl_errorscrub_cancel_check, dsl_errorscrub_cancel_sync,
+ NULL, 3, ZFS_SPACE_CHECK_RESERVED));
+ }
return (dsl_sync_task(spa_name(dp->dp_spa), dsl_scan_cancel_check,
dsl_scan_cancel_sync, NULL, 3, ZFS_SPACE_CHECK_RESERVED));
}
@@ -1106,6 +1376,12 @@ dsl_scrub_pause_resume_sync(void *arg, dmu_tx_t *tx)
int
dsl_scrub_set_pause_resume(const dsl_pool_t *dp, pool_scrub_cmd_t cmd)
{
+ if (dsl_errorscrubbing(dp)) {
+ return (dsl_sync_task(spa_name(dp->dp_spa),
+ dsl_errorscrub_pause_resume_check,
+ dsl_errorscrub_pause_resume_sync, &cmd, 3,
+ ZFS_SPACE_CHECK_RESERVED));
+ }
return (dsl_sync_task(spa_name(dp->dp_spa),
dsl_scrub_pause_resume_check, dsl_scrub_pause_resume_sync, &cmd, 3,
ZFS_SPACE_CHECK_RESERVED));
@@ -1350,7 +1626,7 @@ dsl_scan_check_suspend(dsl_scan_t *scn, const zbookmark_phys_t *zb)
scn->scn_dp->dp_spa->spa_sync_starttime;
uint64_t dirty_min_bytes = zfs_dirty_data_max *
zfs_vdev_async_write_active_min_dirty_percent / 100;
- int mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
+ uint_t mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
zfs_resilver_min_time_ms : zfs_scrub_min_time_ms;
if ((NSEC2MSEC(scan_time_ns) > mintime &&
@@ -1392,6 +1668,42 @@ dsl_scan_check_suspend(dsl_scan_t *scn, const zbookmark_phys_t *zb)
return (B_FALSE);
}
+static boolean_t
+dsl_error_scrub_check_suspend(dsl_scan_t *scn, const zbookmark_phys_t *zb)
+{
+ /*
+ * We suspend if:
+ * - we have scrubbed for at least the minimum time (default 1 sec
+ * for error scrub), someone is explicitly waiting for this txg
+ * to complete, or we have used up all of the time in the txg
+ * timeout (default 5 sec).
+ * or
+ * - the spa is shutting down because this pool is being exported
+ * or the machine is rebooting.
+ */
+ uint64_t curr_time_ns = gethrtime();
+ uint64_t error_scrub_time_ns = curr_time_ns - scn->scn_sync_start_time;
+ uint64_t sync_time_ns = curr_time_ns -
+ scn->scn_dp->dp_spa->spa_sync_starttime;
+ int mintime = zfs_scrub_min_time_ms;
+
+ if ((NSEC2MSEC(error_scrub_time_ns) > mintime &&
+ (txg_sync_waiting(scn->scn_dp) ||
+ NSEC2SEC(sync_time_ns) >= zfs_txg_timeout)) ||
+ spa_shutting_down(scn->scn_dp->dp_spa)) {
+ if (zb) {
+ dprintf("error scrub suspending at bookmark "
+ "%llx/%llx/%llx/%llx\n",
+ (longlong_t)zb->zb_objset,
+ (longlong_t)zb->zb_object,
+ (longlong_t)zb->zb_level,
+ (longlong_t)zb->zb_blkid);
+ }
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
typedef struct zil_scan_arg {
dsl_pool_t *zsa_dp;
zil_header_t *zsa_zh;
@@ -1409,7 +1721,8 @@ dsl_scan_zil_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
zbookmark_phys_t zb;
ASSERT(!BP_IS_REDACTED(bp));
- if (BP_IS_HOLE(bp) || bp->blk_birth <= scn->scn_phys.scn_cur_min_txg)
+ if (BP_IS_HOLE(bp) ||
+ BP_GET_LOGICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_min_txg)
return (0);
/*
@@ -1418,7 +1731,8 @@ dsl_scan_zil_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
* (on-disk) even if it hasn't been claimed (even though for
* scrub there's nothing to do to it).
*/
- if (claim_txg == 0 && bp->blk_birth >= spa_min_claim_txg(dp->dp_spa))
+ if (claim_txg == 0 &&
+ BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(dp->dp_spa))
return (0);
SET_BOOKMARK(&zb, zh->zh_log.blk_cksum.zc_word[ZIL_ZC_OBJSET],
@@ -1444,7 +1758,7 @@ dsl_scan_zil_record(zilog_t *zilog, const lr_t *lrc, void *arg,
ASSERT(!BP_IS_REDACTED(bp));
if (BP_IS_HOLE(bp) ||
- bp->blk_birth <= scn->scn_phys.scn_cur_min_txg)
+ BP_GET_LOGICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_min_txg)
return (0);
/*
@@ -1452,9 +1766,10 @@ dsl_scan_zil_record(zilog_t *zilog, const lr_t *lrc, void *arg,
* already txg sync'ed (but this log block contains
* other records that are not synced)
*/
- if (claim_txg == 0 || bp->blk_birth < claim_txg)
+ if (claim_txg == 0 || BP_GET_LOGICAL_BIRTH(bp) < claim_txg)
return (0);
+ ASSERT3U(BP_GET_LSIZE(bp), !=, 0);
SET_BOOKMARK(&zb, zh->zh_log.blk_cksum.zc_word[ZIL_ZC_OBJSET],
lr->lr_foid, ZB_ZIL_LEVEL,
lr->lr_offset / BP_GET_LSIZE(bp));
@@ -1590,7 +1905,8 @@ dsl_scan_prefetch(scan_prefetch_ctx_t *spc, blkptr_t *bp, zbookmark_phys_t *zb)
if (zfs_no_scrub_prefetch || BP_IS_REDACTED(bp))
return;
- if (BP_IS_HOLE(bp) || bp->blk_birth <= scn->scn_phys.scn_cur_min_txg ||
+ if (BP_IS_HOLE(bp) ||
+ BP_GET_LOGICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_min_txg ||
(BP_GET_LEVEL(bp) == 0 && BP_GET_TYPE(bp) != DMU_OT_DNODE &&
BP_GET_TYPE(bp) != DMU_OT_OBJSET))
return;
@@ -1702,6 +2018,11 @@ dsl_scan_prefetch_cb(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
zb->zb_objset, DMU_META_DNODE_OBJECT);
if (OBJSET_BUF_HAS_USERUSED(buf)) {
+ if (OBJSET_BUF_HAS_PROJECTUSED(buf)) {
+ dsl_scan_prefetch_dnode(scn,
+ &osp->os_projectused_dnode, zb->zb_objset,
+ DMU_PROJECTUSED_OBJECT);
+ }
dsl_scan_prefetch_dnode(scn,
&osp->os_groupused_dnode, zb->zb_objset,
DMU_GROUPUSED_OBJECT);
@@ -1762,10 +2083,16 @@ dsl_scan_prefetch_thread(void *arg)
zio_flags |= ZIO_FLAG_RAW;
}
+ /* We don't need data L1 buffer since we do not prefetch L0. */
+ blkptr_t *bp = &spic->spic_bp;
+ if (BP_GET_LEVEL(bp) == 1 && BP_GET_TYPE(bp) != DMU_OT_DNODE &&
+ BP_GET_TYPE(bp) != DMU_OT_OBJSET)
+ flags |= ARC_FLAG_NO_BUF;
+
/* issue the prefetch asynchronously */
- (void) arc_read(scn->scn_zio_root, scn->scn_dp->dp_spa,
- &spic->spic_bp, dsl_scan_prefetch_cb, spic->spic_spc,
- ZIO_PRIORITY_SCRUB, zio_flags, &flags, &spic->spic_zb);
+ (void) arc_read(scn->scn_zio_root, spa, bp,
+ dsl_scan_prefetch_cb, spic->spic_spc, ZIO_PRIORITY_SCRUB,
+ zio_flags, &flags, &spic->spic_zb);
kmem_free(spic, sizeof (scan_prefetch_issue_ctx_t));
}
@@ -1802,13 +2129,11 @@ dsl_scan_check_resume(dsl_scan_t *scn, const dnode_phys_t *dnp,
/*
* If we found the block we're trying to resume from, or
- * we went past it to a different object, zero it out to
- * indicate that it's OK to start checking for suspending
- * again.
+ * we went past it, zero it out to indicate that it's OK
+ * to start checking for suspending again.
*/
- if (memcmp(zb, &scn->scn_phys.scn_bookmark,
- sizeof (*zb)) == 0 ||
- zb->zb_object > scn->scn_phys.scn_bookmark.zb_object) {
+ if (zbookmark_subtree_tbd(dnp, zb,
+ &scn->scn_phys.scn_bookmark)) {
dprintf("resuming at %llx/%llx/%llx/%llx\n",
(longlong_t)zb->zb_objset,
(longlong_t)zb->zb_object,
@@ -1820,7 +2145,7 @@ dsl_scan_check_resume(dsl_scan_t *scn, const dnode_phys_t *dnp,
return (B_FALSE);
}
-static void dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
+static void dsl_scan_visitbp(const blkptr_t *bp, const zbookmark_phys_t *zb,
dnode_phys_t *dnp, dsl_dataset_t *ds, dsl_scan_t *scn,
dmu_objset_type_t ostype, dmu_tx_t *tx);
inline __attribute__((always_inline)) static void dsl_scan_visitdnode(
@@ -1852,7 +2177,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
if (dnp != NULL &&
dnp->dn_bonuslen > DN_MAX_BONUS_LEN(dnp)) {
scn->scn_phys.scn_errors++;
- spa_log_error(spa, zb);
+ spa_log_error(spa, zb, BP_GET_LOGICAL_BIRTH(bp));
return (SET_ERROR(EINVAL));
}
@@ -1941,13 +2266,14 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
DMU_USERUSED_OBJECT, tx);
}
arc_buf_destroy(buf, &buf);
- } else if (!zfs_blkptr_verify(spa, bp, B_FALSE, BLK_VERIFY_LOG)) {
+ } else if (!zfs_blkptr_verify(spa, bp,
+ BLK_CONFIG_NEEDED, BLK_VERIFY_LOG)) {
/*
* Sanity check the block pointer contents, this is handled
* by arc_read() for the cases above.
*/
scn->scn_phys.scn_errors++;
- spa_log_error(spa, zb);
+ spa_log_error(spa, zb, BP_GET_LOGICAL_BIRTH(bp));
return (SET_ERROR(EINVAL));
}
@@ -1984,12 +2310,11 @@ dsl_scan_visitdnode(dsl_scan_t *scn, dsl_dataset_t *ds,
* first 5; we want them to be useful.
*/
static void
-dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
+dsl_scan_visitbp(const blkptr_t *bp, const zbookmark_phys_t *zb,
dnode_phys_t *dnp, dsl_dataset_t *ds, dsl_scan_t *scn,
dmu_objset_type_t ostype, dmu_tx_t *tx)
{
dsl_pool_t *dp = scn->scn_dp;
- blkptr_t *bp_toread = NULL;
if (dsl_scan_check_suspend(scn, zb))
return;
@@ -2015,26 +2340,23 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
*/
spa_feature_t f = SPA_FEATURE_LARGE_BLOCKS;
if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE)
- ASSERT3B(dsl_dataset_feature_is_active(ds, f), ==, B_TRUE);
+ ASSERT(dsl_dataset_feature_is_active(ds, f));
f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
if (f != SPA_FEATURE_NONE)
- ASSERT3B(dsl_dataset_feature_is_active(ds, f), ==, B_TRUE);
+ ASSERT(dsl_dataset_feature_is_active(ds, f));
f = zio_compress_to_feature(BP_GET_COMPRESS(bp));
if (f != SPA_FEATURE_NONE)
- ASSERT3B(dsl_dataset_feature_is_active(ds, f), ==, B_TRUE);
+ ASSERT(dsl_dataset_feature_is_active(ds, f));
- if (bp->blk_birth <= scn->scn_phys.scn_cur_min_txg) {
+ if (BP_GET_LOGICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_min_txg) {
scn->scn_lt_min_this_txg++;
return;
}
- bp_toread = kmem_alloc(sizeof (blkptr_t), KM_SLEEP);
- *bp_toread = *bp;
-
- if (dsl_scan_recurse(scn, ds, ostype, dnp, bp_toread, zb, tx) != 0)
- goto out;
+ if (dsl_scan_recurse(scn, ds, ostype, dnp, bp, zb, tx) != 0)
+ return;
/*
* If dsl_scan_ddt() has already visited this block, it will have
@@ -2044,7 +2366,7 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
if (ddt_class_contains(dp->dp_spa,
scn->scn_phys.scn_ddt_class_max, bp)) {
scn->scn_ddt_contained_this_txg++;
- goto out;
+ return;
}
/*
@@ -2054,15 +2376,12 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
* Don't scan it now unless we need to because something
* under it was modified.
*/
- if (BP_PHYSICAL_BIRTH(bp) > scn->scn_phys.scn_cur_max_txg) {
+ if (BP_GET_BIRTH(bp) > scn->scn_phys.scn_cur_max_txg) {
scn->scn_gt_max_this_txg++;
- goto out;
+ return;
}
scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
-
-out:
- kmem_free(bp_toread, sizeof (blkptr_t));
}
static void
@@ -2646,7 +2965,7 @@ dsl_scan_ddt_entry(dsl_scan_t *scn, enum zio_checksum checksum,
* If there are N references to a deduped block, we don't want to scrub it
* N times -- ideally, we should scrub it exactly once.
*
- * We leverage the fact that the dde's replication class (enum ddt_class)
+ * We leverage the fact that the dde's replication class (ddt_class_t)
* is ordered from highest replication class (DDT_CLASS_DITTO) to lowest
* (DDT_CLASS_UNIQUE) so that we may walk the DDT in that order.
*
@@ -2743,7 +3062,6 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
scn->scn_phys.scn_cur_max_txg = scn->scn_phys.scn_max_txg;
dsl_scan_visit_rootbp(scn, NULL,
&dp->dp_meta_rootbp, tx);
- spa_set_rootblkptr(dp->dp_spa, &dp->dp_meta_rootbp);
if (scn->scn_suspending)
return;
@@ -2812,8 +3130,9 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
}
static uint64_t
-dsl_scan_count_data_disks(vdev_t *rvd)
+dsl_scan_count_data_disks(spa_t *spa)
{
+ vdev_t *rvd = spa->spa_root_vdev;
uint64_t i, leaves = 0;
for (i = 0; i < rvd->vdev_children; i++) {
@@ -2857,7 +3176,7 @@ scan_io_queue_check_suspend(dsl_scan_t *scn)
scn->scn_dp->dp_spa->spa_sync_starttime;
uint64_t dirty_min_bytes = zfs_dirty_data_max *
zfs_vdev_async_write_active_min_dirty_percent / 100;
- int mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
+ uint_t mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
zfs_resilver_min_time_ms : zfs_scrub_min_time_ms;
return ((NSEC2MSEC(scan_time_ns) > mintime &&
@@ -3017,7 +3336,7 @@ scan_io_queue_fetch_ext(dsl_scan_io_queue_t *queue)
* otherwise we leave shorter remnant every txg.
*/
uint64_t start;
- uint64_t size = 1 << rt->rt_shift;
+ uint64_t size = 1ULL << rt->rt_shift;
range_seg_t *addr_rs;
if (queue->q_last_ext_addr != -1) {
start = queue->q_last_ext_addr;
@@ -3125,10 +3444,8 @@ scan_io_queues_run_one(void *arg)
* If we were suspended in the middle of processing,
* requeue any unfinished sios and exit.
*/
- while ((sio = list_head(&sio_list)) != NULL) {
- list_remove(&sio_list, sio);
+ while ((sio = list_remove_head(&sio_list)) != NULL)
scan_io_queue_insert_impl(queue, sio);
- }
queue->q_zio = NULL;
mutex_exit(q_lock);
@@ -3321,6 +3638,19 @@ dsl_scan_active(dsl_scan_t *scn)
return ((used != 0) || (clones_left));
}
+boolean_t
+dsl_errorscrub_active(dsl_scan_t *scn)
+{
+ spa_t *spa = scn->scn_dp->dp_spa;
+ if (spa->spa_load_state != SPA_LOAD_NONE)
+ return (B_FALSE);
+ if (spa_shutting_down(spa))
+ return (B_FALSE);
+ if (dsl_errorscrubbing(scn->scn_dp))
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
static boolean_t
dsl_scan_check_deferred(vdev_t *vd)
{
@@ -3470,11 +3800,12 @@ dsl_process_async_destroys(dsl_pool_t *dp, dmu_tx_t *tx)
scn->scn_dedup_frees_this_txg = 0;
/*
- * Write out changes to the DDT that may be required as a
- * result of the blocks freed. This ensures that the DDT
- * is clean when a scrub/resilver runs.
+ * Write out changes to the DDT and the BRT that may be required
+ * as a result of the blocks freed. This ensures that the DDT
+ * and the BRT are clean when a scrub/resilver runs.
*/
ddt_sync(spa, tx->tx_txg);
+ brt_sync(spa, tx->tx_txg);
}
if (err != 0)
return (err);
@@ -3536,6 +3867,387 @@ dsl_process_async_destroys(dsl_pool_t *dp, dmu_tx_t *tx)
return (0);
}
+static void
+name_to_bookmark(char *buf, zbookmark_phys_t *zb)
+{
+ zb->zb_objset = zfs_strtonum(buf, &buf);
+ ASSERT(*buf == ':');
+ zb->zb_object = zfs_strtonum(buf + 1, &buf);
+ ASSERT(*buf == ':');
+ zb->zb_level = (int)zfs_strtonum(buf + 1, &buf);
+ ASSERT(*buf == ':');
+ zb->zb_blkid = zfs_strtonum(buf + 1, &buf);
+ ASSERT(*buf == '\0');
+}
+
+static void
+name_to_object(char *buf, uint64_t *obj)
+{
+ *obj = zfs_strtonum(buf, &buf);
+ ASSERT(*buf == '\0');
+}
+
+static void
+read_by_block_level(dsl_scan_t *scn, zbookmark_phys_t zb)
+{
+ dsl_pool_t *dp = scn->scn_dp;
+ dsl_dataset_t *ds;
+ objset_t *os;
+ if (dsl_dataset_hold_obj(dp, zb.zb_objset, FTAG, &ds) != 0)
+ return;
+
+ if (dmu_objset_from_ds(ds, &os) != 0) {
+ dsl_dataset_rele(ds, FTAG);
+ return;
+ }
+
+ /*
+ * If the key is not loaded dbuf_dnode_findbp() will error out with
+ * EACCES. However in that case dnode_hold() will eventually call
+ * dbuf_read()->zio_wait() which may call spa_log_error(). This will
+ * lead to a deadlock due to us holding the mutex spa_errlist_lock.
+ * Avoid this by checking here if the keys are loaded, if not return.
+ * If the keys are not loaded the head_errlog feature is meaningless
+ * as we cannot figure out the birth txg of the block pointer.
+ */
+ if (dsl_dataset_get_keystatus(ds->ds_dir) ==
+ ZFS_KEYSTATUS_UNAVAILABLE) {
+ dsl_dataset_rele(ds, FTAG);
+ return;
+ }
+
+ dnode_t *dn;
+ blkptr_t bp;
+
+ if (dnode_hold(os, zb.zb_object, FTAG, &dn) != 0) {
+ dsl_dataset_rele(ds, FTAG);
+ return;
+ }
+
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
+ int error = dbuf_dnode_findbp(dn, zb.zb_level, zb.zb_blkid, &bp, NULL,
+ NULL);
+
+ if (error) {
+ rw_exit(&dn->dn_struct_rwlock);
+ dnode_rele(dn, FTAG);
+ dsl_dataset_rele(ds, FTAG);
+ return;
+ }
+
+ if (!error && BP_IS_HOLE(&bp)) {
+ rw_exit(&dn->dn_struct_rwlock);
+ dnode_rele(dn, FTAG);
+ dsl_dataset_rele(ds, FTAG);
+ return;
+ }
+
+ int zio_flags = ZIO_FLAG_SCAN_THREAD | ZIO_FLAG_RAW |
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB;
+
+ /* If it's an intent log block, failure is expected. */
+ if (zb.zb_level == ZB_ZIL_LEVEL)
+ zio_flags |= ZIO_FLAG_SPECULATIVE;
+
+ ASSERT(!BP_IS_EMBEDDED(&bp));
+ scan_exec_io(dp, &bp, zio_flags, &zb, NULL);
+ rw_exit(&dn->dn_struct_rwlock);
+ dnode_rele(dn, FTAG);
+ dsl_dataset_rele(ds, FTAG);
+}
+
+/*
+ * We keep track of the scrubbed error blocks in "count". This will be used
+ * when deciding whether we exceeded zfs_scrub_error_blocks_per_txg. This
+ * function is modelled after check_filesystem().
+ */
+static int
+scrub_filesystem(spa_t *spa, uint64_t fs, zbookmark_err_phys_t *zep,
+ int *count)
+{
+ dsl_dataset_t *ds;
+ dsl_pool_t *dp = spa->spa_dsl_pool;
+ dsl_scan_t *scn = dp->dp_scan;
+
+ int error = dsl_dataset_hold_obj(dp, fs, FTAG, &ds);
+ if (error != 0)
+ return (error);
+
+ uint64_t latest_txg;
+ uint64_t txg_to_consider = spa->spa_syncing_txg;
+ boolean_t check_snapshot = B_TRUE;
+
+ error = find_birth_txg(ds, zep, &latest_txg);
+
+ /*
+ * If find_birth_txg() errors out, then err on the side of caution and
+ * proceed. In worst case scenario scrub all objects. If zep->zb_birth
+ * is 0 (e.g. in case of encryption with unloaded keys) also proceed to
+ * scrub all objects.
+ */
+ if (error == 0 && zep->zb_birth == latest_txg) {
+ /* Block neither free nor re written. */
+ zbookmark_phys_t zb;
+ zep_to_zb(fs, zep, &zb);
+ scn->scn_zio_root = zio_root(spa, NULL, NULL,
+ ZIO_FLAG_CANFAIL);
+ /* We have already acquired the config lock for spa */
+ read_by_block_level(scn, zb);
+
+ (void) zio_wait(scn->scn_zio_root);
+ scn->scn_zio_root = NULL;
+
+ scn->errorscrub_phys.dep_examined++;
+ scn->errorscrub_phys.dep_to_examine--;
+ (*count)++;
+ if ((*count) == zfs_scrub_error_blocks_per_txg ||
+ dsl_error_scrub_check_suspend(scn, &zb)) {
+ dsl_dataset_rele(ds, FTAG);
+ return (SET_ERROR(EFAULT));
+ }
+
+ check_snapshot = B_FALSE;
+ } else if (error == 0) {
+ txg_to_consider = latest_txg;
+ }
+
+ /*
+ * Retrieve the number of snapshots if the dataset is not a snapshot.
+ */
+ uint64_t snap_count = 0;
+ if (dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0) {
+
+ error = zap_count(spa->spa_meta_objset,
+ dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
+
+ if (error != 0) {
+ dsl_dataset_rele(ds, FTAG);
+ return (error);
+ }
+ }
+
+ if (snap_count == 0) {
+ /* Filesystem without snapshots. */
+ dsl_dataset_rele(ds, FTAG);
+ return (0);
+ }
+
+ uint64_t snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ uint64_t snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+
+ dsl_dataset_rele(ds, FTAG);
+
+ /* Check only snapshots created from this file system. */
+ while (snap_obj != 0 && zep->zb_birth < snap_obj_txg &&
+ snap_obj_txg <= txg_to_consider) {
+
+ error = dsl_dataset_hold_obj(dp, snap_obj, FTAG, &ds);
+ if (error != 0)
+ return (error);
+
+ if (dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj != fs) {
+ snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+ dsl_dataset_rele(ds, FTAG);
+ continue;
+ }
+
+ boolean_t affected = B_TRUE;
+ if (check_snapshot) {
+ uint64_t blk_txg;
+ error = find_birth_txg(ds, zep, &blk_txg);
+
+ /*
+ * Scrub the snapshot also when zb_birth == 0 or when
+ * find_birth_txg() returns an error.
+ */
+ affected = (error == 0 && zep->zb_birth == blk_txg) ||
+ (error != 0) || (zep->zb_birth == 0);
+ }
+
+ /* Scrub snapshots. */
+ if (affected) {
+ zbookmark_phys_t zb;
+ zep_to_zb(snap_obj, zep, &zb);
+ scn->scn_zio_root = zio_root(spa, NULL, NULL,
+ ZIO_FLAG_CANFAIL);
+ /* We have already acquired the config lock for spa */
+ read_by_block_level(scn, zb);
+
+ (void) zio_wait(scn->scn_zio_root);
+ scn->scn_zio_root = NULL;
+
+ scn->errorscrub_phys.dep_examined++;
+ scn->errorscrub_phys.dep_to_examine--;
+ (*count)++;
+ if ((*count) == zfs_scrub_error_blocks_per_txg ||
+ dsl_error_scrub_check_suspend(scn, &zb)) {
+ dsl_dataset_rele(ds, FTAG);
+ return (EFAULT);
+ }
+ }
+ snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+ snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ dsl_dataset_rele(ds, FTAG);
+ }
+ return (0);
+}
+
+void
+dsl_errorscrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
+{
+ spa_t *spa = dp->dp_spa;
+ dsl_scan_t *scn = dp->dp_scan;
+
+ /*
+ * Only process scans in sync pass 1.
+ */
+
+ if (spa_sync_pass(spa) > 1)
+ return;
+
+ /*
+ * If the spa is shutting down, then stop scanning. This will
+ * ensure that the scan does not dirty any new data during the
+ * shutdown phase.
+ */
+ if (spa_shutting_down(spa))
+ return;
+
+ if (!dsl_errorscrub_active(scn) || dsl_errorscrub_is_paused(scn)) {
+ return;
+ }
+
+ if (dsl_scan_resilvering(scn->scn_dp)) {
+ /* cancel the error scrub if resilver started */
+ dsl_scan_cancel(scn->scn_dp);
+ return;
+ }
+
+ spa->spa_scrub_active = B_TRUE;
+ scn->scn_sync_start_time = gethrtime();
+
+ /*
+ * zfs_scan_suspend_progress can be set to disable scrub progress.
+ * See more detailed comment in dsl_scan_sync().
+ */
+ if (zfs_scan_suspend_progress) {
+ uint64_t scan_time_ns = gethrtime() - scn->scn_sync_start_time;
+ int mintime = zfs_scrub_min_time_ms;
+
+ while (zfs_scan_suspend_progress &&
+ !txg_sync_waiting(scn->scn_dp) &&
+ !spa_shutting_down(scn->scn_dp->dp_spa) &&
+ NSEC2MSEC(scan_time_ns) < mintime) {
+ delay(hz);
+ scan_time_ns = gethrtime() - scn->scn_sync_start_time;
+ }
+ return;
+ }
+
+ int i = 0;
+ zap_attribute_t *za;
+ zbookmark_phys_t *zb;
+ boolean_t limit_exceeded = B_FALSE;
+
+ za = kmem_zalloc(sizeof (zap_attribute_t), KM_SLEEP);
+ zb = kmem_zalloc(sizeof (zbookmark_phys_t), KM_SLEEP);
+
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
+ for (; zap_cursor_retrieve(&scn->errorscrub_cursor, za) == 0;
+ zap_cursor_advance(&scn->errorscrub_cursor)) {
+ name_to_bookmark(za->za_name, zb);
+
+ scn->scn_zio_root = zio_root(dp->dp_spa, NULL,
+ NULL, ZIO_FLAG_CANFAIL);
+ dsl_pool_config_enter(dp, FTAG);
+ read_by_block_level(scn, *zb);
+ dsl_pool_config_exit(dp, FTAG);
+
+ (void) zio_wait(scn->scn_zio_root);
+ scn->scn_zio_root = NULL;
+
+ scn->errorscrub_phys.dep_examined += 1;
+ scn->errorscrub_phys.dep_to_examine -= 1;
+ i++;
+ if (i == zfs_scrub_error_blocks_per_txg ||
+ dsl_error_scrub_check_suspend(scn, zb)) {
+ limit_exceeded = B_TRUE;
+ break;
+ }
+ }
+
+ if (!limit_exceeded)
+ dsl_errorscrub_done(scn, B_TRUE, tx);
+
+ dsl_errorscrub_sync_state(scn, tx);
+ kmem_free(za, sizeof (*za));
+ kmem_free(zb, sizeof (*zb));
+ return;
+ }
+
+ int error = 0;
+ for (; zap_cursor_retrieve(&scn->errorscrub_cursor, za) == 0;
+ zap_cursor_advance(&scn->errorscrub_cursor)) {
+
+ zap_cursor_t *head_ds_cursor;
+ zap_attribute_t *head_ds_attr;
+ zbookmark_err_phys_t head_ds_block;
+
+ head_ds_cursor = kmem_zalloc(sizeof (zap_cursor_t), KM_SLEEP);
+ head_ds_attr = kmem_zalloc(sizeof (zap_attribute_t), KM_SLEEP);
+
+ uint64_t head_ds_err_obj = za->za_first_integer;
+ uint64_t head_ds;
+ name_to_object(za->za_name, &head_ds);
+ boolean_t config_held = B_FALSE;
+ uint64_t top_affected_fs;
+
+ for (zap_cursor_init(head_ds_cursor, spa->spa_meta_objset,
+ head_ds_err_obj); zap_cursor_retrieve(head_ds_cursor,
+ head_ds_attr) == 0; zap_cursor_advance(head_ds_cursor)) {
+
+ name_to_errphys(head_ds_attr->za_name, &head_ds_block);
+
+ /*
+ * In case we are called from spa_sync the pool
+ * config is already held.
+ */
+ if (!dsl_pool_config_held(dp)) {
+ dsl_pool_config_enter(dp, FTAG);
+ config_held = B_TRUE;
+ }
+
+ error = find_top_affected_fs(spa,
+ head_ds, &head_ds_block, &top_affected_fs);
+ if (error)
+ break;
+
+ error = scrub_filesystem(spa, top_affected_fs,
+ &head_ds_block, &i);
+
+ if (error == SET_ERROR(EFAULT)) {
+ limit_exceeded = B_TRUE;
+ break;
+ }
+ }
+
+ zap_cursor_fini(head_ds_cursor);
+ kmem_free(head_ds_cursor, sizeof (*head_ds_cursor));
+ kmem_free(head_ds_attr, sizeof (*head_ds_attr));
+
+ if (config_held)
+ dsl_pool_config_exit(dp, FTAG);
+ }
+
+ kmem_free(za, sizeof (*za));
+ kmem_free(zb, sizeof (*zb));
+ if (!limit_exceeded)
+ dsl_errorscrub_done(scn, B_TRUE, tx);
+
+ dsl_errorscrub_sync_state(scn, tx);
+}
+
/*
* This is the primary entry point for scans that is called from syncing
* context. Scans must happen entirely during syncing context so that we
@@ -3639,8 +4351,9 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
*/
if (zfs_scan_suspend_progress) {
uint64_t scan_time_ns = gethrtime() - scn->scn_sync_start_time;
- int mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ?
- zfs_resilver_min_time_ms : zfs_scrub_min_time_ms;
+ uint_t mintime = (scn->scn_phys.scn_func ==
+ POOL_SCAN_RESILVER) ? zfs_resilver_min_time_ms :
+ zfs_scrub_min_time_ms;
while (zfs_scan_suspend_progress &&
!txg_sync_waiting(scn->scn_dp) &&
@@ -3653,6 +4366,16 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
}
/*
+ * Disabled by default, set zfs_scan_report_txgs to report
+ * average performance over the last zfs_scan_report_txgs TXGs.
+ */
+ if (zfs_scan_report_txgs != 0 &&
+ tx->tx_txg % zfs_scan_report_txgs == 0) {
+ scn->scn_issued_before_pass += spa->spa_scan_pass_issued;
+ spa_scan_stat_init(spa);
+ }
+
+ /*
* It is possible to switch from unsorted to sorted at any time,
* but afterwards the scan will remain sorted unless reloaded from
* a checkpoint after a reboot.
@@ -3711,12 +4434,13 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
taskqid_t prefetch_tqid;
/*
- * Recalculate the max number of in-flight bytes for pool-wide
- * scanning operations (minimum 1MB). Limits for the issuing
- * phase are done per top-level vdev and are handled separately.
+ * Calculate the max number of in-flight bytes for pool-wide
+ * scanning operations (minimum 1MB, maximum 1/4 of arc_c_max).
+ * Limits for the issuing phase are done per top-level vdev and
+ * are handled separately.
*/
- scn->scn_maxinflight_bytes = MAX(zfs_scan_vdev_limit *
- dsl_scan_count_data_disks(spa->spa_root_vdev), 1ULL << 20);
+ scn->scn_maxinflight_bytes = MIN(arc_c_max / 4, MAX(1ULL << 20,
+ zfs_scan_vdev_limit * dsl_scan_count_data_disks(spa)));
if (scnp->scn_ddt_bookmark.ddb_class <=
scnp->scn_ddt_class_max) {
@@ -3780,6 +4504,9 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
if (scn->scn_is_sorted) {
scn->scn_checkpointing = B_TRUE;
scn->scn_clearing = B_TRUE;
+ scn->scn_issued_before_pass +=
+ spa->spa_scan_pass_issued;
+ spa_scan_stat_init(spa);
}
zfs_dbgmsg("scan complete for %s txg %llu",
spa->spa_name,
@@ -3845,6 +4572,15 @@ count_block_issued(spa_t *spa, const blkptr_t *bp, boolean_t all)
}
static void
+count_block_skipped(dsl_scan_t *scn, const blkptr_t *bp, boolean_t all)
+{
+ if (BP_IS_EMBEDDED(bp))
+ return;
+ atomic_add_64(&scn->scn_phys.scn_skipped,
+ all ? BP_GET_ASIZE(bp) : DVA_GET_ASIZE(&bp->blk_dva[0]));
+}
+
+static void
count_block(zfs_all_blkstats_t *zab, const blkptr_t *bp)
{
/*
@@ -3981,7 +4717,7 @@ dsl_scan_scrub_cb(dsl_pool_t *dp,
{
dsl_scan_t *scn = dp->dp_scan;
spa_t *spa = dp->dp_spa;
- uint64_t phys_birth = BP_PHYSICAL_BIRTH(bp);
+ uint64_t phys_birth = BP_GET_BIRTH(bp);
size_t psize = BP_GET_PSIZE(bp);
boolean_t needs_io = B_FALSE;
int zio_flags = ZIO_FLAG_SCAN_THREAD | ZIO_FLAG_RAW | ZIO_FLAG_CANFAIL;
@@ -3989,7 +4725,7 @@ dsl_scan_scrub_cb(dsl_pool_t *dp,
count_block(dp->dp_blkstats, bp);
if (phys_birth <= scn->scn_phys.scn_min_txg ||
phys_birth >= scn->scn_phys.scn_max_txg) {
- count_block_issued(spa, bp, B_TRUE);
+ count_block_skipped(scn, bp, B_TRUE);
return (0);
}
@@ -4030,7 +4766,7 @@ dsl_scan_scrub_cb(dsl_pool_t *dp,
if (needs_io && !zfs_no_scrub_io) {
dsl_scan_enqueue(dp, bp, zio_flags, zb);
} else {
- count_block_issued(spa, bp, B_TRUE);
+ count_block_skipped(scn, bp, B_TRUE);
}
/* do not relocate this block */
@@ -4062,7 +4798,14 @@ dsl_scan_scrub_done(zio_t *zio)
if (zio->io_error && (zio->io_error != ECKSUM ||
!(zio->io_flags & ZIO_FLAG_SPECULATIVE))) {
- atomic_inc_64(&spa->spa_dsl_pool->dp_scan->scn_phys.scn_errors);
+ if (dsl_errorscrubbing(spa->spa_dsl_pool) &&
+ !dsl_errorscrub_is_paused(spa->spa_dsl_pool->dp_scan)) {
+ atomic_inc_64(&spa->spa_dsl_pool->dp_scan
+ ->errorscrub_phys.dep_errors);
+ } else {
+ atomic_inc_64(&spa->spa_dsl_pool->dp_scan->scn_phys
+ .scn_errors);
+ }
}
}
@@ -4148,6 +4891,7 @@ scan_exec_io(dsl_pool_t *dp, const blkptr_t *bp, int zio_flags,
* with single operation. Plus it makes scrubs more sequential and reduces
* chances that minor extent change move it within the B-tree.
*/
+__attribute__((always_inline)) inline
static int
ext_size_compare(const void *x, const void *y)
{
@@ -4156,13 +4900,17 @@ ext_size_compare(const void *x, const void *y)
return (TREE_CMP(*a, *b));
}
+ZFS_BTREE_FIND_IN_BUF_FUNC(ext_size_find_in_buf, uint64_t,
+ ext_size_compare)
+
static void
ext_size_create(range_tree_t *rt, void *arg)
{
(void) rt;
zfs_btree_t *size_tree = arg;
- zfs_btree_create(size_tree, ext_size_compare, sizeof (uint64_t));
+ zfs_btree_create(size_tree, ext_size_compare, ext_size_find_in_buf,
+ sizeof (uint64_t));
}
static void
@@ -4387,9 +5135,9 @@ dsl_scan_freed_dva(spa_t *spa, const blkptr_t *bp, int dva_i)
ASSERT(range_tree_contains(queue->q_exts_by_addr, start, size));
range_tree_remove_fill(queue->q_exts_by_addr, start, size);
- /* count the block as though we issued it */
+ /* count the block as though we skipped it */
sio2bp(sio, &tmpbp);
- count_block_issued(spa, &tmpbp, B_FALSE);
+ count_block_skipped(scn, &tmpbp, B_FALSE);
sio_free(sio);
}
@@ -4447,19 +5195,19 @@ dsl_scan_assess_vdev(dsl_pool_t *dp, vdev_t *vd)
spa_async_request(dp->dp_spa, SPA_ASYNC_RESILVER);
}
-ZFS_MODULE_PARAM(zfs, zfs_, scan_vdev_limit, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_vdev_limit, U64, ZMOD_RW,
"Max bytes in flight per leaf vdev for scrubs and resilvers");
-ZFS_MODULE_PARAM(zfs, zfs_, scrub_min_time_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scrub_min_time_ms, UINT, ZMOD_RW,
"Min millisecs to scrub per txg");
-ZFS_MODULE_PARAM(zfs, zfs_, obsolete_min_time_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, obsolete_min_time_ms, UINT, ZMOD_RW,
"Min millisecs to obsolete per txg");
-ZFS_MODULE_PARAM(zfs, zfs_, free_min_time_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, free_min_time_ms, UINT, ZMOD_RW,
"Min millisecs to free per txg");
-ZFS_MODULE_PARAM(zfs, zfs_, resilver_min_time_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, resilver_min_time_ms, UINT, ZMOD_RW,
"Min millisecs to resilver per txg");
ZFS_MODULE_PARAM(zfs, zfs_, scan_suspend_progress, INT, ZMOD_RW,
@@ -4471,10 +5219,10 @@ ZFS_MODULE_PARAM(zfs, zfs_, no_scrub_io, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, no_scrub_prefetch, INT, ZMOD_RW,
"Set to disable scrub prefetching");
-ZFS_MODULE_PARAM(zfs, zfs_, async_block_max_blocks, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, async_block_max_blocks, U64, ZMOD_RW,
"Max number of blocks freed in one txg");
-ZFS_MODULE_PARAM(zfs, zfs_, max_async_dedup_frees, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_async_dedup_frees, U64, ZMOD_RW,
"Max number of dedup blocks freed in one txg");
ZFS_MODULE_PARAM(zfs, zfs_, free_bpobj_enabled, INT, ZMOD_RW,
@@ -4483,29 +5231,36 @@ ZFS_MODULE_PARAM(zfs, zfs_, free_bpobj_enabled, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, scan_blkstats, INT, ZMOD_RW,
"Enable block statistics calculation during scrub");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_mem_lim_fact, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_mem_lim_fact, UINT, ZMOD_RW,
"Fraction of RAM for scan hard limit");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_issue_strategy, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_issue_strategy, UINT, ZMOD_RW,
"IO issuing strategy during scrubbing. 0 = default, 1 = LBA, 2 = size");
ZFS_MODULE_PARAM(zfs, zfs_, scan_legacy, INT, ZMOD_RW,
"Scrub using legacy non-sequential method");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_checkpoint_intval, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_checkpoint_intval, UINT, ZMOD_RW,
"Scan progress on-disk checkpointing interval");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_max_ext_gap, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_max_ext_gap, U64, ZMOD_RW,
"Max gap in bytes between sequential scrub / resilver I/Os");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_mem_lim_soft_fact, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_mem_lim_soft_fact, UINT, ZMOD_RW,
"Fraction of hard limit used as soft limit");
ZFS_MODULE_PARAM(zfs, zfs_, scan_strict_mem_lim, INT, ZMOD_RW,
"Tunable to attempt to reduce lock contention");
-ZFS_MODULE_PARAM(zfs, zfs_, scan_fill_weight, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, scan_fill_weight, UINT, ZMOD_RW,
"Tunable to adjust bias towards more filled segments during scans");
+ZFS_MODULE_PARAM(zfs, zfs_, scan_report_txgs, UINT, ZMOD_RW,
+ "Tunable to report resilver performance over the last N txgs");
+
ZFS_MODULE_PARAM(zfs, zfs_, resilver_disable_defer, INT, ZMOD_RW,
"Process all resilvers immediately");
+
+ZFS_MODULE_PARAM(zfs, zfs_, scrub_error_blocks_per_txg, UINT, ZMOD_RW,
+ "Error blocks to be scrubbed in one txg");
+/* END CSTYLED */
diff --git a/module/zfs/dsl_synctask.c b/module/zfs/dsl_synctask.c
index 9fc9d4011d11..409e12884d91 100644
--- a/module/zfs/dsl_synctask.c
+++ b/module/zfs/dsl_synctask.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/dsl_userhold.c b/module/zfs/dsl_userhold.c
index 499ab09ecf81..75953f70f926 100644
--- a/module/zfs/dsl_userhold.c
+++ b/module/zfs/dsl_userhold.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -115,7 +115,7 @@ dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
dsl_dataset_t *ds;
int error = 0;
- char *htag, *name;
+ const char *htag, *name;
/* must be a snapshot */
name = nvpair_name(pair);
@@ -572,7 +572,7 @@ dsl_dataset_user_release_impl(nvlist_t *holds, nvlist_t *errlist,
{
dsl_dataset_user_release_arg_t ddura;
nvpair_t *pair;
- char *pool;
+ const char *pool;
int error;
pair = nvlist_next_nvpair(holds, NULL);
diff --git a/module/zfs/edonr_zfs.c b/module/zfs/edonr_zfs.c
index e56b4054c67e..db21c9cf197c 100644
--- a/module/zfs/edonr_zfs.c
+++ b/module/zfs/edonr_zfs.c
@@ -90,17 +90,15 @@ abd_checksum_edonr_tmpl_init(const zio_cksum_salt_t *salt)
*/
_Static_assert(EDONR_BLOCK_SIZE == 2 * (EDONR_MODE / 8),
"Edon-R block size mismatch");
- EdonRHash(EDONR_MODE, salt->zcs_bytes, sizeof (salt->zcs_bytes) * 8,
- salt_block);
- EdonRHash(EDONR_MODE, salt_block, EDONR_MODE, salt_block +
- EDONR_MODE / 8);
+ EdonRHash(salt->zcs_bytes, sizeof (salt->zcs_bytes) * 8, salt_block);
+ EdonRHash(salt_block, EDONR_MODE, salt_block + EDONR_MODE / 8);
/*
* Feed the new salt block into the hash function - this will serve
* as our MAC key.
*/
ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
- EdonRInit(ctx, EDONR_MODE);
+ EdonRInit(ctx);
EdonRUpdate(ctx, salt_block, sizeof (salt_block) * 8);
return (ctx);
}
diff --git a/module/zfs/fm.c b/module/zfs/fm.c
index 5a52a881c687..77d87b694a43 100644
--- a/module/zfs/fm.c
+++ b/module/zfs/fm.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -68,9 +68,9 @@
#include <sys/condvar.h>
#include <sys/zfs_ioctl.h>
-static int zfs_zevent_len_max = 512;
+static uint_t zfs_zevent_len_max = 512;
-static int zevent_len_cur = 0;
+static uint_t zevent_len_cur = 0;
static int zevent_waiters = 0;
static int zevent_flags = 0;
@@ -148,8 +148,7 @@ zfs_zevent_drain(zevent_t *ev)
list_remove(&zevent_list, ev);
/* Remove references to this event in all private file data */
- while ((ze = list_head(&ev->ev_ze_list)) != NULL) {
- list_remove(&ev->ev_ze_list, ze);
+ while ((ze = list_remove_head(&ev->ev_ze_list)) != NULL) {
ze->ze_zevent = NULL;
ze->ze_dropped++;
}
@@ -158,7 +157,7 @@ zfs_zevent_drain(zevent_t *ev)
}
void
-zfs_zevent_drain_all(int *count)
+zfs_zevent_drain_all(uint_t *count)
{
zevent_t *ev;
@@ -380,8 +379,7 @@ zfs_zevent_wait(zfs_zevent_t *ze)
break;
}
- error = cv_wait_sig(&zevent_cv, &zevent_lock);
- if (signal_pending(current)) {
+ if (cv_wait_sig(&zevent_cv, &zevent_lock) == 0) {
error = SET_ERROR(EINTR);
break;
} else if (!list_is_empty(&zevent_list)) {
@@ -487,7 +485,7 @@ static void *
i_fm_alloc(nv_alloc_t *nva, size_t size)
{
(void) nva;
- return (kmem_zalloc(size, KM_SLEEP));
+ return (kmem_alloc(size, KM_SLEEP));
}
static void
@@ -893,7 +891,7 @@ fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth,
uint_t n;
int i, j;
va_list ap;
- char *hcname, *hcid;
+ const char *hcname, *hcid;
if (!fm_fmri_hc_set_common(fmri, version, auth))
return;
@@ -955,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;
}
}
@@ -1342,7 +1341,7 @@ fm_init(void)
void
fm_fini(void)
{
- int count;
+ uint_t count;
zfs_ereport_fini();
@@ -1354,7 +1353,7 @@ fm_fini(void)
zevent_flags |= ZEVENT_SHUTDOWN;
while (zevent_waiters > 0) {
mutex_exit(&zevent_lock);
- schedule();
+ kpreempt(KPREEMPT_SYNC);
mutex_enter(&zevent_lock);
}
mutex_exit(&zevent_lock);
@@ -1370,5 +1369,5 @@ fm_fini(void)
}
#endif /* _KERNEL */
-ZFS_MODULE_PARAM(zfs_zevent, zfs_zevent_, len_max, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_zevent, zfs_zevent_, len_max, UINT, ZMOD_RW,
"Max event queue length");
diff --git a/module/zfs/gzip.c b/module/zfs/gzip.c
index 6282229c8301..f3b19446352a 100644
--- a/module/zfs/gzip.c
+++ b/module/zfs/gzip.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/lzjb.c b/module/zfs/lzjb.c
index 1c536b110318..a24f17e0fe74 100644
--- a/module/zfs/lzjb.c
+++ b/module/zfs/lzjb.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c
index 444ab5222b3b..9e762357b727 100644
--- a/module/zfs/metaslab.c
+++ b/module/zfs/metaslab.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -40,8 +40,6 @@
#include <sys/zap.h>
#include <sys/btree.h>
-#define WITH_DF_BLOCK_ALLOCATOR
-
#define GANG_ALLOCATION(flags) \
((flags) & (METASLAB_GANG_CHILD | METASLAB_GANG_HEADER))
@@ -51,12 +49,17 @@
* operation, we will try to write this amount of data to each disk before
* moving on to the next top-level vdev.
*/
-static unsigned long metaslab_aliquot = 1024 * 1024;
+static uint64_t metaslab_aliquot = 1024 * 1024;
/*
* For testing, make some blocks above a certain size be gang blocks.
*/
-unsigned long metaslab_force_ganging = SPA_MAXBLOCKSIZE + 1;
+uint64_t metaslab_force_ganging = SPA_MAXBLOCKSIZE + 1;
+
+/*
+ * Of blocks of size >= metaslab_force_ganging, actually gang them this often.
+ */
+uint_t metaslab_force_ganging_pct = 3;
/*
* In pools where the log space map feature is not enabled we touch
@@ -81,7 +84,7 @@ int zfs_metaslab_sm_blksz_with_log = (1 << 17);
* space map representation must be before we compact it on-disk.
* Values should be greater than or equal to 100.
*/
-int zfs_condense_pct = 200;
+uint_t zfs_condense_pct = 200;
/*
* Condensing a metaslab is not guaranteed to actually reduce the amount of
@@ -111,7 +114,7 @@ static const int zfs_metaslab_condense_block_threshold = 4;
* eligible to allocate on any metaslab group. The default value of 0 means
* no metaslab group will be excluded based on this criterion.
*/
-static int zfs_mg_noalloc_threshold = 0;
+static uint_t zfs_mg_noalloc_threshold = 0;
/*
* Metaslab groups are considered eligible for allocations if their
@@ -135,7 +138,7 @@ static int zfs_mg_noalloc_threshold = 0;
* enough to avoid hitting the speed bump on pools that are being pushed
* to the edge.
*/
-static int zfs_mg_fragmentation_threshold = 95;
+static uint_t zfs_mg_fragmentation_threshold = 95;
/*
* Allow metaslabs to keep their active state as long as their fragmentation
@@ -143,7 +146,7 @@ static int zfs_mg_fragmentation_threshold = 95;
* active metaslab that exceeds this threshold will no longer keep its active
* status allowing better metaslabs to be selected.
*/
-static int zfs_metaslab_fragmentation_threshold = 70;
+static uint_t zfs_metaslab_fragmentation_threshold = 70;
/*
* When set will load all metaslabs when pool is first opened.
@@ -169,7 +172,7 @@ uint64_t metaslab_df_alloc_threshold = SPA_OLD_MAXBLOCKSIZE;
* Once the space map's free space drops below this level we dynamically
* switch to using best-fit allocations.
*/
-int metaslab_df_free_pct = 4;
+uint_t metaslab_df_free_pct = 4;
/*
* Maximum distance to search forward from the last offset. Without this
@@ -184,7 +187,7 @@ int metaslab_df_free_pct = 4;
* With the default setting of 16MB this is 16*1024 (with ashift=9) or
* 2048 (with ashift=12).
*/
-static int metaslab_df_max_search = 16 * 1024 * 1024;
+static uint_t metaslab_df_max_search = 16 * 1024 * 1024;
/*
* Forces the metaslab_block_picker function to search for at least this many
@@ -203,11 +206,6 @@ static const uint32_t metaslab_min_search_count = 100;
static int metaslab_df_use_largest_segment = B_FALSE;
/*
- * Percentage of all cpus that can be used by the metaslab taskq.
- */
-int metaslab_load_pct = 50;
-
-/*
* These tunables control how long a metaslab will remain loaded after the
* last allocation from it. A metaslab can't be unloaded until at least
* metaslab_unload_delay TXG's and metaslab_unload_delay_ms milliseconds
@@ -215,13 +213,13 @@ int metaslab_load_pct = 50;
* unloaded sooner. These settings are intended to be generous -- to keep
* metaslabs loaded for a long time, reducing the rate of metaslab loading.
*/
-static int metaslab_unload_delay = 32;
-static int metaslab_unload_delay_ms = 10 * 60 * 1000; /* ten minutes */
+static uint_t metaslab_unload_delay = 32;
+static uint_t metaslab_unload_delay_ms = 10 * 60 * 1000; /* ten minutes */
/*
* Max number of metaslabs per group to preload.
*/
-int metaslab_preload_limit = 10;
+uint_t metaslab_preload_limit = 10;
/*
* Enable/disable preloading of metaslab.
@@ -286,14 +284,14 @@ static const int max_disabled_ms = 3;
* Time (in seconds) to respect ms_max_size when the metaslab is not loaded.
* To avoid 64-bit overflow, don't set above UINT32_MAX.
*/
-static unsigned long zfs_metaslab_max_size_cache_sec = 1 * 60 * 60; /* 1 hour */
+static uint64_t zfs_metaslab_max_size_cache_sec = 1 * 60 * 60; /* 1 hour */
/*
* Maximum percentage of memory to use on storing loaded metaslabs. If loading
* a metaslab would take it over this percentage, the oldest selected metaslab
* is automatically unloaded.
*/
-static int zfs_metaslab_mem_limit = 25;
+static uint_t zfs_metaslab_mem_limit = 25;
/*
* Force the per-metaslab range trees to use 64-bit integers to store
@@ -337,7 +335,7 @@ static int zfs_metaslab_try_hard_before_gang = B_FALSE;
* subsequent metaslab has ms_max_size >60KB (but fewer segments in this
* bucket, and therefore a lower weight).
*/
-static int zfs_metaslab_find_max_tries = 100;
+static uint_t zfs_metaslab_find_max_tries = 100;
static uint64_t metaslab_weight(metaslab_t *, boolean_t);
static void metaslab_set_fragmentation(metaslab_t *, boolean_t);
@@ -641,7 +639,7 @@ metaslab_class_evict_old(metaslab_class_t *mc, uint64_t txg)
{
multilist_t *ml = &mc->mc_metaslab_txg_list;
for (int i = 0; i < multilist_get_num_sublists(ml); i++) {
- multilist_sublist_t *mls = multilist_sublist_lock(ml, i);
+ multilist_sublist_t *mls = multilist_sublist_lock_idx(ml, i);
metaslab_t *msp = multilist_sublist_head(mls);
multilist_sublist_unlock(mls);
while (msp != NULL) {
@@ -658,7 +656,7 @@ metaslab_class_evict_old(metaslab_class_t *mc, uint64_t txg)
i--;
break;
}
- mls = multilist_sublist_lock(ml, i);
+ mls = multilist_sublist_lock_idx(ml, i);
metaslab_t *next_msp = multilist_sublist_next(mls, msp);
multilist_sublist_unlock(mls);
if (txg >
@@ -851,9 +849,6 @@ metaslab_group_create(metaslab_class_t *mc, vdev_t *vd, int allocators)
zfs_refcount_create_tracked(&mga->mga_alloc_queue_depth);
}
- mg->mg_taskq = taskq_create("metaslab_group_taskq", metaslab_load_pct,
- maxclsyspri, 10, INT_MAX, TASKQ_THREADS_CPU_PCT | TASKQ_DYNAMIC);
-
return (mg);
}
@@ -869,7 +864,6 @@ metaslab_group_destroy(metaslab_group_t *mg)
*/
ASSERT(mg->mg_activation_count <= 0);
- taskq_destroy(mg->mg_taskq);
avl_destroy(&mg->mg_metaslab_tree);
mutex_destroy(&mg->mg_lock);
mutex_destroy(&mg->mg_ms_disabled_lock);
@@ -960,7 +954,7 @@ metaslab_group_passivate(metaslab_group_t *mg)
* allocations from taking place and any changes to the vdev tree.
*/
spa_config_exit(spa, locks & ~(SCL_ZIO - 1), spa);
- taskq_wait_outstanding(mg->mg_taskq, 0);
+ taskq_wait_outstanding(spa->spa_metaslab_taskq, 0);
spa_config_enter(spa, locks & ~(SCL_ZIO - 1), spa, RW_WRITER);
metaslab_group_alloc_update(mg);
for (int i = 0; i < mg->mg_allocators; i++) {
@@ -1223,7 +1217,7 @@ metaslab_group_fragmentation(metaslab_group_t *mg)
*/
static boolean_t
metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
- uint64_t psize, int allocator, int d)
+ int flags, uint64_t psize, int allocator, int d)
{
spa_t *spa = mg->mg_vd->vdev_spa;
metaslab_class_t *mc = mg->mg_class;
@@ -1268,6 +1262,15 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
return (B_FALSE);
/*
+ * Some allocations (e.g., those coming from device removal
+ * where the * allocations are not even counted in the
+ * metaslab * allocation queues) are allowed to bypass
+ * the throttle.
+ */
+ if (flags & METASLAB_DONT_THROTTLE)
+ return (B_TRUE);
+
+ /*
* Relax allocation throttling for ditto blocks. Due to
* random imbalances in allocation it tends to push copies
* to one vdev, that looks a bit better at the moment.
@@ -1278,7 +1281,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
/*
* If this metaslab group is below its qmax or it's
- * the only allocatable metasable group, then attempt
+ * the only allocatable metaslab group, then attempt
* to allocate from it.
*/
if (qdepth < qmax || mc->mc_alloc_groups == 1)
@@ -1333,6 +1336,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
* Comparison function for the private size-ordered tree using 32-bit
* ranges. Tree is sorted by size, larger sizes at the end of the tree.
*/
+__attribute__((always_inline)) inline
static int
metaslab_rangesize32_compare(const void *x1, const void *x2)
{
@@ -1343,16 +1347,15 @@ metaslab_rangesize32_compare(const void *x1, const void *x2)
uint64_t rs_size2 = r2->rs_end - r2->rs_start;
int cmp = TREE_CMP(rs_size1, rs_size2);
- if (likely(cmp))
- return (cmp);
- return (TREE_CMP(r1->rs_start, r2->rs_start));
+ return (cmp + !cmp * TREE_CMP(r1->rs_start, r2->rs_start));
}
/*
* Comparison function for the private size-ordered tree using 64-bit
* ranges. Tree is sorted by size, larger sizes at the end of the tree.
*/
+__attribute__((always_inline)) inline
static int
metaslab_rangesize64_compare(const void *x1, const void *x2)
{
@@ -1363,11 +1366,10 @@ metaslab_rangesize64_compare(const void *x1, const void *x2)
uint64_t rs_size2 = r2->rs_end - r2->rs_start;
int cmp = TREE_CMP(rs_size1, rs_size2);
- if (likely(cmp))
- return (cmp);
- return (TREE_CMP(r1->rs_start, r2->rs_start));
+ return (cmp + !cmp * TREE_CMP(r1->rs_start, r2->rs_start));
}
+
typedef struct metaslab_rt_arg {
zfs_btree_t *mra_bt;
uint32_t mra_floor_shift;
@@ -1403,6 +1405,13 @@ metaslab_size_tree_full_load(range_tree_t *rt)
range_tree_walk(rt, metaslab_size_sorted_add, &arg);
}
+
+ZFS_BTREE_FIND_IN_BUF_FUNC(metaslab_rt_find_rangesize32_in_buf,
+ range_seg32_t, metaslab_rangesize32_compare)
+
+ZFS_BTREE_FIND_IN_BUF_FUNC(metaslab_rt_find_rangesize64_in_buf,
+ range_seg64_t, metaslab_rangesize64_compare)
+
/*
* Create any block allocator specific components. The current allocators
* rely on using both a size-ordered range_tree_t and an array of uint64_t's.
@@ -1415,19 +1424,22 @@ metaslab_rt_create(range_tree_t *rt, void *arg)
size_t size;
int (*compare) (const void *, const void *);
+ bt_find_in_buf_f bt_find;
switch (rt->rt_type) {
case RANGE_SEG32:
size = sizeof (range_seg32_t);
compare = metaslab_rangesize32_compare;
+ bt_find = metaslab_rt_find_rangesize32_in_buf;
break;
case RANGE_SEG64:
size = sizeof (range_seg64_t);
compare = metaslab_rangesize64_compare;
+ bt_find = metaslab_rt_find_rangesize64_in_buf;
break;
default:
panic("Invalid range seg type %d", rt->rt_type);
}
- zfs_btree_create(size_tree, compare, size);
+ zfs_btree_create(size_tree, compare, bt_find, size);
mrap->mra_floor_shift = metaslab_by_size_min_shift;
}
@@ -1449,7 +1461,7 @@ metaslab_rt_add(range_tree_t *rt, range_seg_t *rs, void *arg)
zfs_btree_t *size_tree = mrap->mra_bt;
if (rs_get_end(rs, rt) - rs_get_start(rs, rt) <
- (1 << mrap->mra_floor_shift))
+ (1ULL << mrap->mra_floor_shift))
return;
zfs_btree_add(size_tree, rs);
@@ -1461,7 +1473,7 @@ metaslab_rt_remove(range_tree_t *rt, range_seg_t *rs, void *arg)
metaslab_rt_arg_t *mrap = arg;
zfs_btree_t *size_tree = mrap->mra_bt;
- if (rs_get_end(rs, rt) - rs_get_start(rs, rt) < (1 <<
+ if (rs_get_end(rs, rt) - rs_get_start(rs, rt) < (1ULL <<
mrap->mra_floor_shift))
return;
@@ -1599,9 +1611,6 @@ metaslab_block_find(zfs_btree_t *t, range_tree_t *rt, uint64_t start,
return (rs);
}
-#if defined(WITH_DF_BLOCK_ALLOCATOR) || \
- defined(WITH_CF_BLOCK_ALLOCATOR)
-
/*
* This is a helper function that can be used by the allocator to find a
* suitable block to allocate. This will search the specified B-tree looking
@@ -1636,9 +1645,74 @@ metaslab_block_picker(range_tree_t *rt, uint64_t *cursor, uint64_t size,
*cursor = 0;
return (-1ULL);
}
-#endif /* WITH_DF/CF_BLOCK_ALLOCATOR */
-#if defined(WITH_DF_BLOCK_ALLOCATOR)
+static uint64_t metaslab_df_alloc(metaslab_t *msp, uint64_t size);
+static uint64_t metaslab_cf_alloc(metaslab_t *msp, uint64_t size);
+static uint64_t metaslab_ndf_alloc(metaslab_t *msp, uint64_t size);
+metaslab_ops_t *metaslab_allocator(spa_t *spa);
+
+static metaslab_ops_t metaslab_allocators[] = {
+ { "dynamic", metaslab_df_alloc },
+ { "cursor", metaslab_cf_alloc },
+ { "new-dynamic", metaslab_ndf_alloc },
+};
+
+static int
+spa_find_allocator_byname(const char *val)
+{
+ int a = ARRAY_SIZE(metaslab_allocators) - 1;
+ if (strcmp("new-dynamic", val) == 0)
+ return (-1); /* remove when ndf is working */
+ for (; a >= 0; a--) {
+ if (strcmp(val, metaslab_allocators[a].msop_name) == 0)
+ return (a);
+ }
+ return (-1);
+}
+
+void
+spa_set_allocator(spa_t *spa, const char *allocator)
+{
+ int a = spa_find_allocator_byname(allocator);
+ if (a < 0) a = 0;
+ spa->spa_active_allocator = a;
+ zfs_dbgmsg("spa allocator: %s\n", metaslab_allocators[a].msop_name);
+}
+
+int
+spa_get_allocator(spa_t *spa)
+{
+ return (spa->spa_active_allocator);
+}
+
+#if defined(_KERNEL)
+int
+param_set_active_allocator_common(const char *val)
+{
+ char *p;
+
+ if (val == NULL)
+ return (SET_ERROR(EINVAL));
+
+ if ((p = strchr(val, '\n')) != NULL)
+ *p = '\0';
+
+ int a = spa_find_allocator_byname(val);
+ if (a < 0)
+ return (SET_ERROR(EINVAL));
+
+ zfs_active_allocator = metaslab_allocators[a].msop_name;
+ return (0);
+}
+#endif
+
+metaslab_ops_t *
+metaslab_allocator(spa_t *spa)
+{
+ int allocator = spa_get_allocator(spa);
+ return (&metaslab_allocators[allocator]);
+}
+
/*
* ==========================================================================
* Dynamic Fit (df) block allocator
@@ -1672,7 +1746,7 @@ metaslab_df_alloc(metaslab_t *msp, uint64_t size)
uint64_t align = size & -size;
uint64_t *cursor = &msp->ms_lbas[highbit64(align) - 1];
range_tree_t *rt = msp->ms_allocatable;
- int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
+ uint_t free_pct = range_tree_space(rt) * 100 / msp->ms_size;
uint64_t offset;
ASSERT(MUTEX_HELD(&msp->ms_lock));
@@ -1713,12 +1787,6 @@ metaslab_df_alloc(metaslab_t *msp, uint64_t size)
return (offset);
}
-const metaslab_ops_t zfs_metaslab_ops = {
- metaslab_df_alloc
-};
-#endif /* WITH_DF_BLOCK_ALLOCATOR */
-
-#if defined(WITH_CF_BLOCK_ALLOCATOR)
/*
* ==========================================================================
* Cursor fit block allocator -
@@ -1761,12 +1829,6 @@ metaslab_cf_alloc(metaslab_t *msp, uint64_t size)
return (offset);
}
-const metaslab_ops_t zfs_metaslab_ops = {
- metaslab_cf_alloc
-};
-#endif /* WITH_CF_BLOCK_ALLOCATOR */
-
-#if defined(WITH_NDF_BLOCK_ALLOCATOR)
/*
* ==========================================================================
* New dynamic fit allocator -
@@ -1823,12 +1885,6 @@ metaslab_ndf_alloc(metaslab_t *msp, uint64_t size)
return (-1ULL);
}
-const metaslab_ops_t zfs_metaslab_ops = {
- metaslab_ndf_alloc
-};
-#endif /* WITH_NDF_BLOCK_ALLOCATOR */
-
-
/*
* ==========================================================================
* Metaslabs
@@ -2169,19 +2225,19 @@ metaslab_potentially_evict(metaslab_class_t *mc)
uint64_t allmem = arc_all_memory();
uint64_t inuse = spl_kmem_cache_inuse(zfs_btree_leaf_cache);
uint64_t size = spl_kmem_cache_entry_size(zfs_btree_leaf_cache);
- int tries = 0;
+ uint_t tries = 0;
for (; allmem * zfs_metaslab_mem_limit / 100 < inuse * size &&
tries < multilist_get_num_sublists(&mc->mc_metaslab_txg_list) * 2;
tries++) {
unsigned int idx = multilist_get_random_index(
&mc->mc_metaslab_txg_list);
multilist_sublist_t *mls =
- multilist_sublist_lock(&mc->mc_metaslab_txg_list, idx);
+ multilist_sublist_lock_idx(&mc->mc_metaslab_txg_list, idx);
metaslab_t *msp = multilist_sublist_head(mls);
multilist_sublist_unlock(mls);
while (msp != NULL && allmem * zfs_metaslab_mem_limit / 100 <
inuse * size) {
- VERIFY3P(mls, ==, multilist_sublist_lock(
+ VERIFY3P(mls, ==, multilist_sublist_lock_idx(
&mc->mc_metaslab_txg_list, idx));
ASSERT3U(idx, ==,
metaslab_idx_func(&mc->mc_metaslab_txg_list, msp));
@@ -3186,6 +3242,15 @@ static boolean_t
metaslab_should_allocate(metaslab_t *msp, uint64_t asize, boolean_t try_hard)
{
/*
+ * This case will usually but not always get caught by the checks below;
+ * metaslabs can be loaded by various means, including the trim and
+ * initialize code. Once that happens, without this check they are
+ * allocatable even before they finish their first txg sync.
+ */
+ if (unlikely(msp->ms_new))
+ return (B_FALSE);
+
+ /*
* If the metaslab is loaded, ms_max_size is definitive and we can use
* the fast check. If it's not, the ms_max_size is a lower bound (once
* set), and we should use the fast check as long as we're not in
@@ -3497,10 +3562,8 @@ metaslab_group_preload(metaslab_group_t *mg)
avl_tree_t *t = &mg->mg_metaslab_tree;
int m = 0;
- if (spa_shutting_down(spa) || !metaslab_preload_enabled) {
- taskq_wait_outstanding(mg->mg_taskq, 0);
+ if (spa_shutting_down(spa) || !metaslab_preload_enabled)
return;
- }
mutex_enter(&mg->mg_lock);
@@ -3520,8 +3583,9 @@ metaslab_group_preload(metaslab_group_t *mg)
continue;
}
- VERIFY(taskq_dispatch(mg->mg_taskq, metaslab_preload,
- msp, TQ_SLEEP) != TASKQID_INVALID);
+ VERIFY(taskq_dispatch(spa->spa_metaslab_taskq, metaslab_preload,
+ msp, TQ_SLEEP | (m <= mg->mg_allocators ? TQ_FRONT : 0))
+ != TASKQID_INVALID);
}
mutex_exit(&mg->mg_lock);
}
@@ -3552,7 +3616,7 @@ metaslab_should_condense(metaslab_t *msp)
{
space_map_t *sm = msp->ms_sm;
vdev_t *vd = msp->ms_group->mg_vd;
- uint64_t vdev_blocksize = 1 << vd->vdev_ashift;
+ uint64_t vdev_blocksize = 1ULL << vd->vdev_ashift;
ASSERT(MUTEX_HELD(&msp->ms_lock));
ASSERT(msp->ms_loaded);
@@ -4278,7 +4342,8 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
uint64_t free_space = metaslab_class_get_space(spa_normal_class(spa)) -
metaslab_class_get_alloc(spa_normal_class(spa));
- if (free_space <= spa_get_slop_space(spa) || vd->vdev_removing) {
+ if (free_space <= spa_get_slop_space(spa) || vd->vdev_removing ||
+ vd->vdev_rz_expanding) {
defer_allowed = B_FALSE;
}
@@ -4586,6 +4651,7 @@ metaslab_block_alloc(metaslab_t *msp, uint64_t size, uint64_t txg)
ASSERT(MUTEX_HELD(&msp->ms_lock));
VERIFY(!msp->ms_condensing);
VERIFY0(msp->ms_disabled);
+ VERIFY0(msp->ms_new);
start = mc->mc_ops->msop_alloc(msp, size);
if (start != -1ULL) {
@@ -4640,7 +4706,7 @@ find_valid_metaslab(metaslab_group_t *mg, uint64_t activation_weight,
if (msp == NULL)
msp = avl_nearest(t, idx, AVL_AFTER);
- int tries = 0;
+ uint_t tries = 0;
for (; msp != NULL; msp = AVL_NEXT(t, msp)) {
int i;
@@ -4657,10 +4723,10 @@ find_valid_metaslab(metaslab_group_t *mg, uint64_t activation_weight,
}
/*
- * If the selected metaslab is condensing or disabled,
- * skip it.
+ * If the selected metaslab is condensing or disabled, or
+ * hasn't gone through a metaslab_sync_done(), then skip it.
*/
- if (msp->ms_condensing || msp->ms_disabled > 0)
+ if (msp->ms_condensing || msp->ms_disabled > 0 || msp->ms_new)
continue;
*was_active = msp->ms_allocator != -1;
@@ -5039,7 +5105,6 @@ metaslab_group_alloc(metaslab_group_t *mg, zio_alloc_list_t *zal,
int allocator, boolean_t try_hard)
{
uint64_t offset;
- ASSERT(mg->mg_initialized);
offset = metaslab_group_alloc_normal(mg, zal, asize, txg, want_unique,
dva, d, allocator, try_hard);
@@ -5078,7 +5143,7 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
zio_alloc_list_t *zal, int allocator)
{
metaslab_class_allocator_t *mca = &mc->mc_allocator[allocator];
- metaslab_group_t *mg, *fast_mg, *rotor;
+ metaslab_group_t *mg, *rotor;
vdev_t *vd;
boolean_t try_hard = B_FALSE;
@@ -5091,7 +5156,9 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
* damage can result in extremely long reconstruction times. This
* will also test spilling from special to normal.
*/
- if (psize >= metaslab_force_ganging && (random_in_range(100) < 3)) {
+ if (psize >= metaslab_force_ganging &&
+ metaslab_force_ganging_pct > 0 &&
+ (random_in_range(100) < MIN(metaslab_force_ganging_pct, 100))) {
metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG,
allocator);
return (SET_ERROR(ENOSPC));
@@ -5131,8 +5198,7 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
if (vd != NULL && vd->vdev_mg != NULL) {
mg = vdev_get_mg(vd, mc);
- if (flags & METASLAB_HINTBP_AVOID &&
- mg->mg_next != NULL)
+ if (flags & METASLAB_HINTBP_AVOID)
mg = mg->mg_next;
} else {
mg = mca->mca_rotor;
@@ -5140,15 +5206,6 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
} else if (d != 0) {
vd = vdev_lookup_top(spa, DVA_GET_VDEV(&dva[d - 1]));
mg = vd->vdev_mg->mg_next;
- } else if (flags & METASLAB_FASTWRITE) {
- mg = fast_mg = mca->mca_rotor;
-
- do {
- if (fast_mg->mg_vd->vdev_pending_fastwrite <
- mg->mg_vd->vdev_pending_fastwrite)
- mg = fast_mg;
- } while ((fast_mg = fast_mg->mg_next) != mca->mca_rotor);
-
} else {
ASSERT(mca->mca_rotor != NULL);
mg = mca->mca_rotor;
@@ -5189,7 +5246,7 @@ top:
*/
if (allocatable && !GANG_ALLOCATION(flags) && !try_hard) {
allocatable = metaslab_group_allocatable(mg, rotor,
- psize, allocator, d);
+ flags, psize, allocator, d);
}
if (!allocatable) {
@@ -5198,15 +5255,12 @@ top:
goto next;
}
- 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);
@@ -5215,7 +5269,7 @@ top:
ASSERT(mg->mg_class == mc);
- uint64_t asize = vdev_psize_to_asize(vd, psize);
+ uint64_t asize = vdev_psize_to_asize_txg(vd, psize, txg);
ASSERT(P2PHASE(asize, 1ULL << vd->vdev_ashift) == 0);
/*
@@ -5274,7 +5328,7 @@ top:
mg->mg_bias = 0;
}
- if ((flags & METASLAB_FASTWRITE) ||
+ if ((flags & METASLAB_ZIL) ||
atomic_add_64_nv(&mca->mca_aliquot, asize) >=
mg->mg_aliquot + mg->mg_bias) {
mca->mca_rotor = mg->mg_next;
@@ -5287,11 +5341,6 @@ top:
((flags & METASLAB_GANG_HEADER) ? 1 : 0));
DVA_SET_ASIZE(&dva[d], asize);
- if (flags & METASLAB_FASTWRITE) {
- atomic_add_64(&vd->vdev_pending_fastwrite,
- psize);
- }
-
return (0);
}
next:
@@ -5446,8 +5495,9 @@ remap_blkptr_cb(uint64_t inner_offset, vdev_t *vd, uint64_t offset,
vdev_t *oldvd = vdev_lookup_top(vd->vdev_spa,
DVA_GET_VDEV(&bp->blk_dva[0]));
vdev_indirect_births_t *vib = oldvd->vdev_indirect_births;
- bp->blk_phys_birth = vdev_indirect_births_physbirth(vib,
+ uint64_t physical_birth = vdev_indirect_births_physbirth(vib,
DVA_GET_OFFSET(&bp->blk_dva[0]), DVA_GET_ASIZE(&bp->blk_dva[0]));
+ BP_SET_PHYSICAL_BIRTH(bp, physical_birth);
DVA_SET_VDEV(&bp->blk_dva[0], vd->vdev_id);
DVA_SET_OFFSET(&bp->blk_dva[0], offset);
@@ -5634,8 +5684,7 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, int allocator,
* We reserve the slots individually so that we can unreserve
* them individually when an I/O completes.
*/
- for (int d = 0; d < slots; d++)
- zfs_refcount_add(&mca->mca_alloc_slots, zio);
+ zfs_refcount_add_few(&mca->mca_alloc_slots, slots, zio);
zio->io_flags |= ZIO_FLAG_IO_ALLOCATING;
return (B_TRUE);
}
@@ -5649,8 +5698,7 @@ metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots,
metaslab_class_allocator_t *mca = &mc->mc_allocator[allocator];
ASSERT(mc->mc_alloc_throttle_enabled);
- for (int d = 0; d < slots; d++)
- zfs_refcount_remove(&mca->mca_alloc_slots, zio);
+ zfs_refcount_remove_few(&mca->mca_alloc_slots, slots, zio);
}
static int
@@ -5798,8 +5846,8 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp,
dva_t *hintdva = (hintbp != NULL) ? hintbp->blk_dva : NULL;
int error = 0;
- ASSERT(bp->blk_birth == 0);
- ASSERT(BP_PHYSICAL_BIRTH(bp) == 0);
+ ASSERT0(BP_GET_LOGICAL_BIRTH(bp));
+ ASSERT0(BP_GET_PHYSICAL_BIRTH(bp));
spa_config_enter(spa, SCL_ALLOC, FTAG, RW_READER);
@@ -5853,7 +5901,7 @@ metaslab_free(spa_t *spa, const blkptr_t *bp, uint64_t txg, boolean_t now)
int ndvas = BP_GET_NDVAS(bp);
ASSERT(!BP_IS_HOLE(bp));
- ASSERT(!now || bp->blk_birth >= spa_syncing_txg(spa));
+ ASSERT(!now || BP_GET_LOGICAL_BIRTH(bp) >= spa_syncing_txg(spa));
/*
* If we have a checkpoint for the pool we need to make sure that
@@ -5871,7 +5919,7 @@ metaslab_free(spa_t *spa, const blkptr_t *bp, uint64_t txg, boolean_t now)
* normally as they will be referenced by the checkpointed uberblock.
*/
boolean_t checkpoint = B_FALSE;
- if (bp->blk_birth <= spa->spa_checkpoint_txg &&
+ if (BP_GET_LOGICAL_BIRTH(bp) <= spa->spa_checkpoint_txg &&
spa_syncing_txg(spa) > spa->spa_checkpoint_txg) {
/*
* At this point, if the block is part of the checkpoint
@@ -5929,55 +5977,6 @@ metaslab_claim(spa_t *spa, const blkptr_t *bp, uint64_t txg)
return (error);
}
-void
-metaslab_fastwrite_mark(spa_t *spa, const blkptr_t *bp)
-{
- const dva_t *dva = bp->blk_dva;
- int ndvas = BP_GET_NDVAS(bp);
- uint64_t psize = BP_GET_PSIZE(bp);
- int d;
- vdev_t *vd;
-
- ASSERT(!BP_IS_HOLE(bp));
- ASSERT(!BP_IS_EMBEDDED(bp));
- ASSERT(psize > 0);
-
- spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
-
- for (d = 0; d < ndvas; d++) {
- if ((vd = vdev_lookup_top(spa, DVA_GET_VDEV(&dva[d]))) == NULL)
- continue;
- atomic_add_64(&vd->vdev_pending_fastwrite, psize);
- }
-
- spa_config_exit(spa, SCL_VDEV, FTAG);
-}
-
-void
-metaslab_fastwrite_unmark(spa_t *spa, const blkptr_t *bp)
-{
- const dva_t *dva = bp->blk_dva;
- int ndvas = BP_GET_NDVAS(bp);
- uint64_t psize = BP_GET_PSIZE(bp);
- int d;
- vdev_t *vd;
-
- ASSERT(!BP_IS_HOLE(bp));
- ASSERT(!BP_IS_EMBEDDED(bp));
- ASSERT(psize > 0);
-
- spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
-
- for (d = 0; d < ndvas; d++) {
- if ((vd = vdev_lookup_top(spa, DVA_GET_VDEV(&dva[d]))) == NULL)
- continue;
- ASSERT3U(vd->vdev_pending_fastwrite, >=, psize);
- atomic_sub_64(&vd->vdev_pending_fastwrite, psize);
- }
-
- spa_config_exit(spa, SCL_VDEV, FTAG);
-}
-
static void
metaslab_check_free_impl_cb(uint64_t inner, vdev_t *vd, uint64_t offset,
uint64_t size, void *arg)
@@ -6203,7 +6202,7 @@ metaslab_unflushed_txg(metaslab_t *ms)
return (ms->ms_unflushed_txg);
}
-ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, aliquot, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, aliquot, U64, ZMOD_RW,
"Allocation granularity (a.k.a. stripe size)");
ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, debug_load, INT, ZMOD_RW,
@@ -6215,18 +6214,21 @@ ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, debug_unload, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, preload_enabled, INT, ZMOD_RW,
"Preload potential metaslabs during reassessment");
-ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, unload_delay, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, preload_limit, UINT, ZMOD_RW,
+ "Max number of metaslabs per group to preload");
+
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, unload_delay, UINT, ZMOD_RW,
"Delay in txgs after metaslab was last used before unloading");
-ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, unload_delay_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, unload_delay_ms, UINT, ZMOD_RW,
"Delay in milliseconds after metaslab was last used before unloading");
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs_mg, zfs_mg_, noalloc_threshold, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_mg, zfs_mg_, noalloc_threshold, UINT, ZMOD_RW,
"Percentage of metaslab group size that should be free to make it "
"eligible for allocation");
-ZFS_MODULE_PARAM(zfs_mg, zfs_mg_, fragmentation_threshold, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_mg, zfs_mg_, fragmentation_threshold, UINT, ZMOD_RW,
"Percentage of metaslab group size that should be considered eligible "
"for allocations unless all metaslab groups within the metaslab class "
"have also crossed this threshold");
@@ -6236,7 +6238,7 @@ ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, fragmentation_factor_enabled, INT,
"Use the fragmentation metric to prefer less fragmented metaslabs");
/* END CSTYLED */
-ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, fragmentation_threshold, INT,
+ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, fragmentation_threshold, UINT,
ZMOD_RW, "Fragmentation for metaslab to allow allocation");
ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, lba_weighting_enabled, INT, ZMOD_RW,
@@ -6251,23 +6253,32 @@ ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, segment_weight_enabled, INT,
ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, switch_threshold, INT, ZMOD_RW,
"Segment-based metaslab selection maximum buckets before switching");
-ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, force_ganging, ULONG, ZMOD_RW,
- "Blocks larger than this size are forced to be gang blocks");
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, force_ganging, U64, ZMOD_RW,
+ "Blocks larger than this size are sometimes forced to be gang blocks");
+
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, force_ganging_pct, UINT, ZMOD_RW,
+ "Percentage of large blocks that will be forced to be gang blocks");
-ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, df_max_search, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, df_max_search, UINT, ZMOD_RW,
"Max distance (bytes) to search forward before using size tree");
ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, df_use_largest_segment, INT, ZMOD_RW,
"When looking in size tree, use largest segment instead of exact fit");
-ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, max_size_cache_sec, ULONG,
+ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, max_size_cache_sec, U64,
ZMOD_RW, "How long to trust the cached max chunk size of a metaslab");
-ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, mem_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, mem_limit, UINT, ZMOD_RW,
"Percentage of memory that can be used to store metaslab range trees");
ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, try_hard_before_gang, INT,
ZMOD_RW, "Try hard to allocate before ganging");
-ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, find_max_tries, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_metaslab, zfs_metaslab_, find_max_tries, UINT, ZMOD_RW,
"Normally only consider this many of the best metaslabs in each vdev");
+
+/* BEGIN CSTYLED */
+ZFS_MODULE_PARAM_CALL(zfs, zfs_, active_allocator,
+ param_set_active_allocator, param_get_charp, ZMOD_RW,
+ "SPA active allocator");
+/* END CSTYLED */
diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c
index ab0f055ff8b1..71122542758d 100644
--- a/module/zfs/mmp.c
+++ b/module/zfs/mmp.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -156,7 +156,7 @@
* vary with the I/O load and this observed value is the ub_mmp_delay which is
* stored in the uberblock. The minimum allowed value is 100 ms.
*/
-ulong_t zfs_multihost_interval = MMP_DEFAULT_INTERVAL;
+uint64_t zfs_multihost_interval = MMP_DEFAULT_INTERVAL;
/*
* Used to control the duration of the activity test on import. Smaller values
@@ -303,8 +303,10 @@ mmp_next_leaf(spa_t *spa)
do {
leaf = list_next(&spa->spa_leaf_list, leaf);
- if (leaf == NULL)
+ if (leaf == NULL) {
leaf = list_head(&spa->spa_leaf_list);
+ ASSERT3P(leaf, !=, NULL);
+ }
/*
* We skip unwritable, offline, detached, and dRAID spare
@@ -443,7 +445,7 @@ mmp_write_uberblock(spa_t *spa)
uint64_t offset;
hrtime_t lock_acquire_time = gethrtime();
- spa_config_enter(spa, SCL_STATE, mmp_tag, RW_READER);
+ spa_config_enter_mmp(spa, SCL_STATE, mmp_tag, RW_READER);
lock_acquire_time = gethrtime() - lock_acquire_time;
if (lock_acquire_time > (MSEC2NSEC(MMP_MIN_INTERVAL) / 10))
zfs_dbgmsg("MMP SCL_STATE acquisition pool '%s' took %llu ns "
@@ -515,8 +517,9 @@ mmp_write_uberblock(spa_t *spa)
zio_t *zio = zio_null(mmp->mmp_zio_root, spa, NULL, NULL, NULL, flags);
abd_t *ub_abd = abd_alloc_for_io(VDEV_UBERBLOCK_SIZE(vd), B_TRUE);
- abd_zero(ub_abd, VDEV_UBERBLOCK_SIZE(vd));
abd_copy_from_buf(ub_abd, ub, sizeof (uberblock_t));
+ abd_zero_off(ub_abd, sizeof (uberblock_t),
+ VDEV_UBERBLOCK_SIZE(vd) - sizeof (uberblock_t));
mmp->mmp_seq++;
mmp->mmp_kstat_id++;
@@ -548,11 +551,11 @@ mmp_thread(void *arg)
uint32_t mmp_fail_intervals = MMP_FAIL_INTVS_OK(
zfs_multihost_fail_intervals);
hrtime_t mmp_fail_ns = mmp_fail_intervals * mmp_interval;
- boolean_t last_spa_suspended = suspended;
- boolean_t last_spa_multihost = multihost;
- uint64_t last_mmp_interval = mmp_interval;
- uint32_t last_mmp_fail_intervals = mmp_fail_intervals;
- hrtime_t last_mmp_fail_ns = mmp_fail_ns;
+ boolean_t last_spa_suspended;
+ boolean_t last_spa_multihost;
+ uint64_t last_mmp_interval;
+ uint32_t last_mmp_fail_intervals;
+ hrtime_t last_mmp_fail_ns;
callb_cpr_t cpr;
int skip_wait = 0;
@@ -661,12 +664,13 @@ mmp_thread(void *arg)
(gethrtime() - mmp->mmp_last_write) > mmp_fail_ns) {
zfs_dbgmsg("MMP suspending pool '%s': gethrtime %llu "
"mmp_last_write %llu mmp_interval %llu "
- "mmp_fail_intervals %llu mmp_fail_ns %llu",
+ "mmp_fail_intervals %llu mmp_fail_ns %llu txg %llu",
spa_name(spa), (u_longlong_t)gethrtime(),
(u_longlong_t)mmp->mmp_last_write,
(u_longlong_t)mmp_interval,
(u_longlong_t)mmp_fail_intervals,
- (u_longlong_t)mmp_fail_ns);
+ (u_longlong_t)mmp_fail_ns,
+ (u_longlong_t)spa->spa_uberblock.ub_txg);
cmn_err(CE_WARN, "MMP writes to pool '%s' have not "
"succeeded in over %llu ms; suspending pool. "
"Hrtime %llu",
@@ -734,7 +738,7 @@ mmp_signal_all_threads(void)
/* BEGIN CSTYLED */
ZFS_MODULE_PARAM_CALL(zfs_multihost, zfs_multihost_, interval,
- param_set_multihost_interval, param_get_ulong, ZMOD_RW,
+ param_set_multihost_interval, spl_param_get_u64, ZMOD_RW,
"Milliseconds between mmp writes to each leaf");
/* END CSTYLED */
diff --git a/module/zfs/multilist.c b/module/zfs/multilist.c
index fdc5f07c47ea..3d3ef86e6839 100644
--- a/module/zfs/multilist.c
+++ b/module/zfs/multilist.c
@@ -24,7 +24,7 @@
* This overrides the number of sublists in each multilist_t, which defaults
* to the number of CPUs in the system (see multilist_create()).
*/
-int zfs_multilist_num_sublists = 0;
+uint_t zfs_multilist_num_sublists = 0;
/*
* Given the object contained on the list, return a pointer to the
@@ -69,7 +69,7 @@ multilist_d2l(multilist_t *ml, void *obj)
*/
static void
multilist_create_impl(multilist_t *ml, size_t size, size_t offset,
- unsigned int num, multilist_sublist_index_func_t *index_func)
+ uint_t num, multilist_sublist_index_func_t *index_func)
{
ASSERT3U(size, >, 0);
ASSERT3U(size, >=, offset + sizeof (multilist_node_t));
@@ -104,7 +104,7 @@ void
multilist_create(multilist_t *ml, size_t size, size_t offset,
multilist_sublist_index_func_t *index_func)
{
- int num_sublists;
+ uint_t num_sublists;
if (zfs_multilist_num_sublists > 0) {
num_sublists = zfs_multilist_num_sublists;
@@ -277,9 +277,15 @@ multilist_get_random_index(multilist_t *ml)
return (random_in_range(ml->ml_num_sublists));
}
+void
+multilist_sublist_lock(multilist_sublist_t *mls)
+{
+ mutex_enter(&mls->mls_lock);
+}
+
/* Lock and return the sublist specified at the given index */
multilist_sublist_t *
-multilist_sublist_lock(multilist_t *ml, unsigned int sublist_idx)
+multilist_sublist_lock_idx(multilist_t *ml, unsigned int sublist_idx)
{
multilist_sublist_t *mls;
@@ -294,7 +300,7 @@ multilist_sublist_lock(multilist_t *ml, unsigned int sublist_idx)
multilist_sublist_t *
multilist_sublist_lock_obj(multilist_t *ml, void *obj)
{
- return (multilist_sublist_lock(ml, ml->ml_index_func(ml, obj)));
+ return (multilist_sublist_lock_idx(ml, ml->ml_index_func(ml, obj)));
}
void
@@ -327,6 +333,22 @@ multilist_sublist_insert_tail(multilist_sublist_t *mls, void *obj)
list_insert_tail(&mls->mls_list, obj);
}
+/* please see comment above multilist_sublist_insert_head */
+void
+multilist_sublist_insert_after(multilist_sublist_t *mls, void *prev, void *obj)
+{
+ ASSERT(MUTEX_HELD(&mls->mls_lock));
+ list_insert_after(&mls->mls_list, prev, obj);
+}
+
+/* please see comment above multilist_sublist_insert_head */
+void
+multilist_sublist_insert_before(multilist_sublist_t *mls, void *next, void *obj)
+{
+ ASSERT(MUTEX_HELD(&mls->mls_lock));
+ list_insert_before(&mls->mls_list, next, obj);
+}
+
/*
* Move the object one element forward in the list.
*
@@ -425,5 +447,5 @@ multilist_link_active(multilist_node_t *link)
return (list_link_active(link));
}
-ZFS_MODULE_PARAM(zfs, zfs_, multilist_num_sublists, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, multilist_num_sublists, UINT, ZMOD_RW,
"Number of sublists used in each multilist");
diff --git a/module/zfs/pathname.c b/module/zfs/pathname.c
index 84ab7b7e1111..51460d119106 100644
--- a/module/zfs/pathname.c
+++ b/module/zfs/pathname.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/range_tree.c b/module/zfs/range_tree.c
index 1ffb48cb5efa..5174e2c46633 100644
--- a/module/zfs/range_tree.c
+++ b/module/zfs/range_tree.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -151,6 +151,7 @@ range_tree_stat_decr(range_tree_t *rt, range_seg_t *rs)
rt->rt_histogram[idx]--;
}
+__attribute__((always_inline)) inline
static int
range_tree_seg32_compare(const void *x1, const void *x2)
{
@@ -163,6 +164,7 @@ range_tree_seg32_compare(const void *x1, const void *x2)
return ((r1->rs_start >= r2->rs_end) - (r1->rs_end <= r2->rs_start));
}
+__attribute__((always_inline)) inline
static int
range_tree_seg64_compare(const void *x1, const void *x2)
{
@@ -175,6 +177,7 @@ range_tree_seg64_compare(const void *x1, const void *x2)
return ((r1->rs_start >= r2->rs_end) - (r1->rs_end <= r2->rs_start));
}
+__attribute__((always_inline)) inline
static int
range_tree_seg_gap_compare(const void *x1, const void *x2)
{
@@ -187,6 +190,15 @@ range_tree_seg_gap_compare(const void *x1, const void *x2)
return ((r1->rs_start >= r2->rs_end) - (r1->rs_end <= r2->rs_start));
}
+ZFS_BTREE_FIND_IN_BUF_FUNC(range_tree_seg32_find_in_buf, range_seg32_t,
+ range_tree_seg32_compare)
+
+ZFS_BTREE_FIND_IN_BUF_FUNC(range_tree_seg64_find_in_buf, range_seg64_t,
+ range_tree_seg64_compare)
+
+ZFS_BTREE_FIND_IN_BUF_FUNC(range_tree_seg_gap_find_in_buf, range_seg_gap_t,
+ range_tree_seg_gap_compare)
+
range_tree_t *
range_tree_create_gap(const range_tree_ops_t *ops, range_seg_type_t type,
void *arg, uint64_t start, uint64_t shift, uint64_t gap)
@@ -197,23 +209,27 @@ range_tree_create_gap(const range_tree_ops_t *ops, range_seg_type_t type,
ASSERT3U(type, <=, RANGE_SEG_NUM_TYPES);
size_t size;
int (*compare) (const void *, const void *);
+ bt_find_in_buf_f bt_find;
switch (type) {
case RANGE_SEG32:
size = sizeof (range_seg32_t);
compare = range_tree_seg32_compare;
+ bt_find = range_tree_seg32_find_in_buf;
break;
case RANGE_SEG64:
size = sizeof (range_seg64_t);
compare = range_tree_seg64_compare;
+ bt_find = range_tree_seg64_find_in_buf;
break;
case RANGE_SEG_GAP:
size = sizeof (range_seg_gap_t);
compare = range_tree_seg_gap_compare;
+ bt_find = range_tree_seg_gap_find_in_buf;
break;
default:
panic("Invalid range seg type %d", type);
}
- zfs_btree_create(&rt->rt_root, compare, size);
+ zfs_btree_create(&rt->rt_root, compare, bt_find, size);
rt->rt_ops = ops;
rt->rt_gap = gap;
@@ -369,6 +385,7 @@ range_tree_add_impl(void *arg, uint64_t start, uint64_t size, uint64_t fill)
* invalid as soon as we do any mutating btree operations.
*/
rs_after = zfs_btree_find(&rt->rt_root, &tmp, &where_after);
+ ASSERT3P(rs_after, !=, NULL);
rs_set_start_raw(rs_after, rt, before_start);
rs_set_fill(rs_after, rt, after_fill + before_fill + fill);
rs = rs_after;
diff --git a/module/zfs/refcount.c b/module/zfs/refcount.c
index 390b2fdedc70..718bbb34a8d5 100644
--- a/module/zfs/refcount.c
+++ b/module/zfs/refcount.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,36 +33,43 @@
* cpu time. Until its performance is improved it should be manually enabled.
*/
int reference_tracking_enable = B_FALSE;
-static int reference_history = 3; /* tunable */
+static uint_t reference_history = 3; /* tunable */
static kmem_cache_t *reference_cache;
-static kmem_cache_t *reference_history_cache;
void
zfs_refcount_init(void)
{
reference_cache = kmem_cache_create("reference_cache",
sizeof (reference_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
-
- reference_history_cache = kmem_cache_create("reference_history_cache",
- sizeof (uint64_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
}
void
zfs_refcount_fini(void)
{
kmem_cache_destroy(reference_cache);
- kmem_cache_destroy(reference_history_cache);
+}
+
+static int
+zfs_refcount_compare(const void *x1, const void *x2)
+{
+ const reference_t *r1 = (const reference_t *)x1;
+ const reference_t *r2 = (const reference_t *)x2;
+
+ int cmp1 = TREE_CMP(r1->ref_holder, r2->ref_holder);
+ int cmp2 = TREE_CMP(r1->ref_number, r2->ref_number);
+ int cmp = cmp1 ? cmp1 : cmp2;
+ return ((cmp || r1->ref_search) ? cmp : TREE_PCMP(r1, r2));
}
void
zfs_refcount_create(zfs_refcount_t *rc)
{
mutex_init(&rc->rc_mtx, NULL, MUTEX_DEFAULT, NULL);
- list_create(&rc->rc_list, sizeof (reference_t),
- offsetof(reference_t, ref_link));
+ avl_create(&rc->rc_tree, zfs_refcount_compare, sizeof (reference_t),
+ offsetof(reference_t, ref_link.a));
list_create(&rc->rc_removed, sizeof (reference_t),
- offsetof(reference_t, ref_link));
+ offsetof(reference_t, ref_link.l));
rc->rc_count = 0;
rc->rc_removed_count = 0;
rc->rc_tracked = reference_tracking_enable;
@@ -86,19 +93,15 @@ void
zfs_refcount_destroy_many(zfs_refcount_t *rc, uint64_t number)
{
reference_t *ref;
+ void *cookie = NULL;
ASSERT3U(rc->rc_count, ==, number);
- while ((ref = list_head(&rc->rc_list))) {
- list_remove(&rc->rc_list, ref);
+ while ((ref = avl_destroy_nodes(&rc->rc_tree, &cookie)) != NULL)
kmem_cache_free(reference_cache, ref);
- }
- list_destroy(&rc->rc_list);
+ avl_destroy(&rc->rc_tree);
- while ((ref = list_head(&rc->rc_removed))) {
- list_remove(&rc->rc_removed, ref);
- kmem_cache_free(reference_history_cache, ref->ref_removed);
+ while ((ref = list_remove_head(&rc->rc_removed)))
kmem_cache_free(reference_cache, ref);
- }
list_destroy(&rc->rc_removed);
mutex_destroy(&rc->rc_mtx);
}
@@ -124,10 +127,10 @@ zfs_refcount_count(zfs_refcount_t *rc)
int64_t
zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, const void *holder)
{
- reference_t *ref = NULL;
+ reference_t *ref;
int64_t count;
- if (!rc->rc_tracked) {
+ if (likely(!rc->rc_tracked)) {
count = atomic_add_64_nv(&(rc)->rc_count, number);
ASSERT3U(count, >=, number);
return (count);
@@ -136,9 +139,9 @@ zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, const void *holder)
ref = kmem_cache_alloc(reference_cache, KM_SLEEP);
ref->ref_holder = holder;
ref->ref_number = number;
+ ref->ref_search = B_FALSE;
mutex_enter(&rc->rc_mtx);
- ASSERT3U(rc->rc_count, >=, 0);
- list_insert_head(&rc->rc_list, ref);
+ avl_add(&rc->rc_tree, ref);
rc->rc_count += number;
count = rc->rc_count;
mutex_exit(&rc->rc_mtx);
@@ -152,51 +155,55 @@ zfs_refcount_add(zfs_refcount_t *rc, const void *holder)
return (zfs_refcount_add_many(rc, 1, holder));
}
+void
+zfs_refcount_add_few(zfs_refcount_t *rc, uint64_t number, const void *holder)
+{
+ if (likely(!rc->rc_tracked))
+ (void) zfs_refcount_add_many(rc, number, holder);
+ else for (; number > 0; number--)
+ (void) zfs_refcount_add(rc, holder);
+}
+
int64_t
zfs_refcount_remove_many(zfs_refcount_t *rc, uint64_t number,
const void *holder)
{
- reference_t *ref;
+ reference_t *ref, s;
int64_t count;
- if (!rc->rc_tracked) {
+ if (likely(!rc->rc_tracked)) {
count = atomic_add_64_nv(&(rc)->rc_count, -number);
ASSERT3S(count, >=, 0);
return (count);
}
+ s.ref_holder = holder;
+ s.ref_number = number;
+ s.ref_search = B_TRUE;
mutex_enter(&rc->rc_mtx);
ASSERT3U(rc->rc_count, >=, number);
- for (ref = list_head(&rc->rc_list); ref;
- ref = list_next(&rc->rc_list, ref)) {
- if (ref->ref_holder == holder && ref->ref_number == number) {
- list_remove(&rc->rc_list, ref);
- if (reference_history > 0) {
- ref->ref_removed =
- kmem_cache_alloc(reference_history_cache,
- KM_SLEEP);
- list_insert_head(&rc->rc_removed, ref);
- rc->rc_removed_count++;
- if (rc->rc_removed_count > reference_history) {
- ref = list_tail(&rc->rc_removed);
- list_remove(&rc->rc_removed, ref);
- kmem_cache_free(reference_history_cache,
- ref->ref_removed);
- kmem_cache_free(reference_cache, ref);
- rc->rc_removed_count--;
- }
- } else {
- kmem_cache_free(reference_cache, ref);
- }
- rc->rc_count -= number;
- count = rc->rc_count;
- mutex_exit(&rc->rc_mtx);
- return (count);
+ ref = avl_find(&rc->rc_tree, &s, NULL);
+ if (unlikely(ref == NULL)) {
+ panic("No such hold %p on refcount %llx", holder,
+ (u_longlong_t)(uintptr_t)rc);
+ return (-1);
+ }
+ avl_remove(&rc->rc_tree, ref);
+ if (reference_history > 0) {
+ list_insert_head(&rc->rc_removed, ref);
+ if (rc->rc_removed_count >= reference_history) {
+ ref = list_remove_tail(&rc->rc_removed);
+ kmem_cache_free(reference_cache, ref);
+ } else {
+ rc->rc_removed_count++;
}
+ } else {
+ kmem_cache_free(reference_cache, ref);
}
- panic("No such hold %p on refcount %llx", holder,
- (u_longlong_t)(uintptr_t)rc);
- return (-1);
+ rc->rc_count -= number;
+ count = rc->rc_count;
+ mutex_exit(&rc->rc_mtx);
+ return (count);
}
int64_t
@@ -206,33 +213,49 @@ zfs_refcount_remove(zfs_refcount_t *rc, const void *holder)
}
void
+zfs_refcount_remove_few(zfs_refcount_t *rc, uint64_t number, const void *holder)
+{
+ if (likely(!rc->rc_tracked))
+ (void) zfs_refcount_remove_many(rc, number, holder);
+ else for (; number > 0; number--)
+ (void) zfs_refcount_remove(rc, holder);
+}
+
+void
zfs_refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src)
{
- int64_t count, removed_count;
- list_t list, removed;
+ avl_tree_t tree;
+ list_t removed;
+ reference_t *ref;
+ void *cookie = NULL;
+ uint64_t count;
+ uint_t removed_count;
- list_create(&list, sizeof (reference_t),
- offsetof(reference_t, ref_link));
+ avl_create(&tree, zfs_refcount_compare, sizeof (reference_t),
+ offsetof(reference_t, ref_link.a));
list_create(&removed, sizeof (reference_t),
- offsetof(reference_t, ref_link));
+ offsetof(reference_t, ref_link.l));
mutex_enter(&src->rc_mtx);
count = src->rc_count;
removed_count = src->rc_removed_count;
src->rc_count = 0;
src->rc_removed_count = 0;
- list_move_tail(&list, &src->rc_list);
+ avl_swap(&tree, &src->rc_tree);
list_move_tail(&removed, &src->rc_removed);
mutex_exit(&src->rc_mtx);
mutex_enter(&dst->rc_mtx);
dst->rc_count += count;
dst->rc_removed_count += removed_count;
- list_move_tail(&dst->rc_list, &list);
+ if (avl_is_empty(&dst->rc_tree))
+ avl_swap(&dst->rc_tree, &tree);
+ else while ((ref = avl_destroy_nodes(&tree, &cookie)) != NULL)
+ avl_add(&dst->rc_tree, ref);
list_move_tail(&dst->rc_removed, &removed);
mutex_exit(&dst->rc_mtx);
- list_destroy(&list);
+ avl_destroy(&tree);
list_destroy(&removed);
}
@@ -240,23 +263,19 @@ void
zfs_refcount_transfer_ownership_many(zfs_refcount_t *rc, uint64_t number,
const void *current_holder, const void *new_holder)
{
- reference_t *ref;
- boolean_t found = B_FALSE;
+ reference_t *ref, s;
- if (!rc->rc_tracked)
+ if (likely(!rc->rc_tracked))
return;
+ s.ref_holder = current_holder;
+ s.ref_number = number;
+ s.ref_search = B_TRUE;
mutex_enter(&rc->rc_mtx);
- for (ref = list_head(&rc->rc_list); ref;
- ref = list_next(&rc->rc_list, ref)) {
- if (ref->ref_holder == current_holder &&
- ref->ref_number == number) {
- ref->ref_holder = new_holder;
- found = B_TRUE;
- break;
- }
- }
- ASSERT(found);
+ ref = avl_find(&rc->rc_tree, &s, NULL);
+ ASSERT(ref);
+ ref->ref_holder = new_holder;
+ avl_update(&rc->rc_tree, ref);
mutex_exit(&rc->rc_mtx);
}
@@ -276,21 +295,23 @@ zfs_refcount_transfer_ownership(zfs_refcount_t *rc, const void *current_holder,
boolean_t
zfs_refcount_held(zfs_refcount_t *rc, const void *holder)
{
- reference_t *ref;
+ reference_t *ref, s;
+ avl_index_t idx;
+ boolean_t res;
- if (!rc->rc_tracked)
+ if (likely(!rc->rc_tracked))
return (zfs_refcount_count(rc) > 0);
+ s.ref_holder = holder;
+ s.ref_number = 0;
+ s.ref_search = B_TRUE;
mutex_enter(&rc->rc_mtx);
- for (ref = list_head(&rc->rc_list); ref;
- ref = list_next(&rc->rc_list, ref)) {
- if (ref->ref_holder == holder) {
- mutex_exit(&rc->rc_mtx);
- return (B_TRUE);
- }
- }
+ ref = avl_find(&rc->rc_tree, &s, &idx);
+ if (likely(ref == NULL))
+ ref = avl_nearest(&rc->rc_tree, idx, AVL_AFTER);
+ res = ref && ref->ref_holder == holder;
mutex_exit(&rc->rc_mtx);
- return (B_FALSE);
+ return (res);
}
/*
@@ -301,21 +322,23 @@ zfs_refcount_held(zfs_refcount_t *rc, const void *holder)
boolean_t
zfs_refcount_not_held(zfs_refcount_t *rc, const void *holder)
{
- reference_t *ref;
+ reference_t *ref, s;
+ avl_index_t idx;
+ boolean_t res;
- if (!rc->rc_tracked)
+ if (likely(!rc->rc_tracked))
return (B_TRUE);
mutex_enter(&rc->rc_mtx);
- for (ref = list_head(&rc->rc_list); ref;
- ref = list_next(&rc->rc_list, ref)) {
- if (ref->ref_holder == holder) {
- mutex_exit(&rc->rc_mtx);
- return (B_FALSE);
- }
- }
+ s.ref_holder = holder;
+ s.ref_number = 0;
+ s.ref_search = B_TRUE;
+ ref = avl_find(&rc->rc_tree, &s, &idx);
+ if (likely(ref == NULL))
+ ref = avl_nearest(&rc->rc_tree, idx, AVL_AFTER);
+ res = ref == NULL || ref->ref_holder != holder;
mutex_exit(&rc->rc_mtx);
- return (B_TRUE);
+ return (res);
}
EXPORT_SYMBOL(zfs_refcount_create);
@@ -330,7 +353,7 @@ EXPORT_SYMBOL(zfs_refcount_held);
ZFS_MODULE_PARAM(zfs, , reference_tracking_enable, INT, ZMOD_RW,
"Track reference holders to refcount_t objects");
-ZFS_MODULE_PARAM(zfs, , reference_history, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, , reference_history, UINT, ZMOD_RW,
"Maximum reference holders being tracked");
/* END CSTYLED */
#endif /* ZFS_DEBUG */
diff --git a/module/zfs/rrwlock.c b/module/zfs/rrwlock.c
index 8e3ee5ddfb6a..a8c438bb6ebd 100644
--- a/module/zfs/rrwlock.c
+++ b/module/zfs/rrwlock.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/sa.c b/module/zfs/sa.c
index 368a9e3d9080..0ae4c331dd36 100644
--- a/module/zfs/sa.c
+++ b/module/zfs/sa.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,6 +23,7 @@
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2017 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2023 RackTop Systems, Inc.
*/
#include <sys/zfs_context.h>
@@ -141,7 +142,7 @@ static int sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
sa_data_op_t action, sa_data_locator_t *locator, void *datastart,
uint16_t buflen, dmu_tx_t *tx);
-static const arc_byteswap_func_t sa_bswap_table[] = {
+static arc_byteswap_func_t sa_bswap_table[] = {
byteswap_uint64_array,
byteswap_uint32_array,
byteswap_uint16_array,
@@ -369,7 +370,7 @@ sa_attr_op(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count,
if (bulk[i].sa_data) {
SA_COPY_DATA(bulk[i].sa_data_func,
bulk[i].sa_addr, bulk[i].sa_data,
- bulk[i].sa_size);
+ MIN(bulk[i].sa_size, bulk[i].sa_length));
}
continue;
@@ -1201,6 +1202,7 @@ sa_attr_iter(objset_t *os, sa_hdr_phys_t *hdr, dmu_object_type_t type,
uint8_t idx_len;
reg_length = sa->sa_attr_table[tb->lot_attrs[i]].sa_length;
+ IMPLY(reg_length == 0, IS_SA_BONUSTYPE(type));
if (reg_length) {
attr_length = reg_length;
idx_len = 0;
@@ -1917,7 +1919,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
count = bonus_attr_count;
hdr = SA_GET_HDR(hdl, SA_BONUS);
idx_tab = SA_IDX_TAB_GET(hdl, SA_BONUS);
- for (; k != 2; k++) {
+ for (; ; k++) {
/*
* Iterate over each attribute in layout. Fetch the
* size of variable-length attributes needing rewrite
diff --git a/module/zfs/sha256.c b/module/zfs/sha2_zfs.c
index c5b033cf019d..872b1e53ee66 100644
--- a/module/zfs/sha256.c
+++ b/module/zfs/sha2_zfs.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -18,16 +18,14 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
* Copyright 2013 Saso Kiselkov. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
+
#include <sys/zfs_context.h>
-#include <sys/zio.h>
#include <sys/zio_checksum.h>
#include <sys/sha2.h>
#include <sys/abd.h>
@@ -42,7 +40,7 @@ sha_incremental(void *buf, size_t size, void *arg)
}
void
-abd_checksum_SHA256(abd_t *abd, uint64_t size,
+abd_checksum_sha256(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
(void) ctx_template;
@@ -79,7 +77,7 @@ bswap:
}
void
-abd_checksum_SHA512_native(abd_t *abd, uint64_t size,
+abd_checksum_sha512_native(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
(void) ctx_template;
@@ -91,12 +89,12 @@ abd_checksum_SHA512_native(abd_t *abd, uint64_t size,
}
void
-abd_checksum_SHA512_byteswap(abd_t *abd, uint64_t size,
+abd_checksum_sha512_byteswap(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
zio_cksum_t tmp;
- abd_checksum_SHA512_native(abd, size, ctx_template, &tmp);
+ abd_checksum_sha512_native(abd, size, ctx_template, &tmp);
zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]);
zcp->zc_word[1] = BSWAP_64(tmp.zc_word[1]);
zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]);
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index 55f3a4de603f..ec2b674fb7ee 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright (c) 2018, Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright 2013 Saso Kiselkov. All rights reserved.
@@ -33,6 +33,7 @@
* Copyright 2017 Joyent, Inc.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
+ * Copyright (c) 2023 Hewlett Packard Enterprise Development LP.
*/
/*
@@ -52,6 +53,7 @@
#include <sys/dmu_tx.h>
#include <sys/zap.h>
#include <sys/zil.h>
+#include <sys/brt.h>
#include <sys/ddt.h>
#include <sys/vdev_impl.h>
#include <sys/vdev_removal.h>
@@ -61,6 +63,7 @@
#include <sys/vdev_rebuild.h>
#include <sys/vdev_trim.h>
#include <sys/vdev_disk.h>
+#include <sys/vdev_raidz.h>
#include <sys/vdev_draid.h>
#include <sys/metaslab.h>
#include <sys/metaslab_impl.h>
@@ -81,7 +84,6 @@
#include <sys/arc.h>
#include <sys/callb.h>
#include <sys/systeminfo.h>
-#include <sys/spa_boot.h>
#include <sys/zfs_ioctl.h>
#include <sys/dsl_scan.h>
#include <sys/zfeature.h>
@@ -98,6 +100,27 @@
#include "zfs_prop.h"
#include "zfs_comutil.h"
+#include <cityhash.h>
+
+/*
+ * spa_thread() existed on Illumos as a parent thread for the various worker
+ * threads that actually run the pool, as a way to both reference the entire
+ * pool work as a single object, and to share properties like scheduling
+ * options. It has not yet been adapted to Linux or FreeBSD. This define is
+ * used to mark related parts of the code to make things easier for the reader,
+ * and to compile this code out. It can be removed when someone implements it,
+ * moves it to some Illumos-specific place, or removes it entirely.
+ */
+#undef HAVE_SPA_THREAD
+
+/*
+ * The "System Duty Cycle" scheduling class is an Illumos feature to help
+ * prevent CPU-intensive kernel threads from affecting latency on interactive
+ * threads. It doesn't exist on Linux or FreeBSD, so the supporting code is
+ * gated behind a define. On Illumos SDC depends on spa_thread(), but
+ * spa_thread() also has other uses, so this is a separate define.
+ */
+#undef HAVE_SYSDC
/*
* The interval, in seconds, at which failed configuration cache file writes
@@ -107,16 +130,16 @@ int zfs_ccw_retry_interval = 300;
typedef enum zti_modes {
ZTI_MODE_FIXED, /* value is # of threads (min 1) */
- ZTI_MODE_BATCH, /* cpu-intensive; value is ignored */
ZTI_MODE_SCALE, /* Taskqs scale with CPUs. */
+ ZTI_MODE_SYNC, /* sync thread assigned */
ZTI_MODE_NULL, /* don't create a taskq */
ZTI_NMODES
} zti_modes_t;
#define ZTI_P(n, q) { ZTI_MODE_FIXED, (n), (q) }
#define ZTI_PCT(n) { ZTI_MODE_ONLINE_PERCENT, (n), 1 }
-#define ZTI_BATCH { ZTI_MODE_BATCH, 0, 1 }
#define ZTI_SCALE { ZTI_MODE_SCALE, 0, 1 }
+#define ZTI_SYNC { ZTI_MODE_SYNC, 0, 1 }
#define ZTI_NULL { ZTI_MODE_NULL, 0, 0 }
#define ZTI_N(n) ZTI_P(n, 1)
@@ -137,27 +160,27 @@ static const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
* initializing a pool, we use this table to create an appropriately sized
* taskq. Some operations are low volume and therefore have a small, static
* number of threads assigned to their taskqs using the ZTI_N(#) or ZTI_ONE
- * macros. Other operations process a large amount of data; the ZTI_BATCH
+ * macros. Other operations process a large amount of data; the ZTI_SCALE
* macro causes us to create a taskq oriented for throughput. Some operations
* are so high frequency and short-lived that the taskq itself can become a
* point of lock contention. The ZTI_P(#, #) macro indicates that we need an
* additional degree of parallelism specified by the number of threads per-
* taskq and the number of taskqs; when dispatching an event in this case, the
- * particular taskq is chosen at random. ZTI_SCALE is similar to ZTI_BATCH,
- * but with number of taskqs also scaling with number of CPUs.
+ * particular taskq is chosen at random. ZTI_SCALE uses a number of taskqs
+ * that scales with the number of CPUs.
*
* The different taskq priorities are to handle the different contexts (issue
* and interrupt) and then to reserve threads for ZIO_PRIORITY_NOW I/Os that
* need to be handled with minimum delay.
*/
-static const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
+static zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
/* ISSUE ISSUE_HIGH INTR INTR_HIGH */
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* NULL */
{ ZTI_N(8), ZTI_NULL, ZTI_SCALE, ZTI_NULL }, /* READ */
- { ZTI_BATCH, ZTI_N(5), ZTI_SCALE, ZTI_N(5) }, /* WRITE */
+ { ZTI_SYNC, ZTI_N(5), ZTI_SCALE, ZTI_N(5) }, /* WRITE */
{ ZTI_SCALE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* FREE */
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* CLAIM */
- { ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* IOCTL */
+ { ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* FLUSH */
{ ZTI_N(4), ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* TRIM */
};
@@ -168,12 +191,24 @@ static int spa_load_impl(spa_t *spa, spa_import_type_t type,
const char **ereport);
static void spa_vdev_resilver_done(spa_t *spa);
+/*
+ * Percentage of all CPUs that can be used by the metaslab preload taskq.
+ */
+static uint_t metaslab_preload_pct = 50;
+
static uint_t zio_taskq_batch_pct = 80; /* 1 thread per cpu in pset */
static uint_t zio_taskq_batch_tpq; /* threads per taskq */
+
+#ifdef HAVE_SYSDC
static const boolean_t zio_taskq_sysdc = B_TRUE; /* use SDC scheduling class */
static const uint_t zio_taskq_basedc = 80; /* base duty cycle */
+#endif
+#ifdef HAVE_SPA_THREAD
static const boolean_t spa_create_process = B_TRUE; /* no process => no sysdc */
+#endif
+
+static uint_t zio_taskq_write_tpq = 16;
/*
* Report any spa_load_verify errors found, but do not fail spa_load.
@@ -219,7 +254,7 @@ static int spa_load_print_vdev_tree = B_FALSE;
* there are also risks of performing an inadvertent rewind as we might be
* missing all the vdevs with the latest uberblocks.
*/
-unsigned long zfs_max_missing_tvds = 0;
+uint64_t zfs_max_missing_tvds = 0;
/*
* The parameters below are similar to zfs_max_missing_tvds but are only
@@ -297,6 +332,22 @@ spa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, const char *strval,
}
/*
+ * Add a user property (source=src, propname=propval) to an nvlist.
+ */
+static void
+spa_prop_add_user(nvlist_t *nvl, const char *propname, char *strval,
+ zprop_source_t src)
+{
+ nvlist_t *propval;
+
+ VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ VERIFY(nvlist_add_uint64(propval, ZPROP_SOURCE, src) == 0);
+ VERIFY(nvlist_add_string(propval, ZPROP_VALUE, strval) == 0);
+ VERIFY(nvlist_add_nvlist(nvl, propname, propval) == 0);
+ nvlist_free(propval);
+}
+
+/*
* Get property values from the spa configuration.
*/
static void
@@ -342,6 +393,12 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp)
spa_prop_add_list(*nvp, ZPOOL_PROP_DEDUPRATIO, NULL,
ddt_get_pool_dedup_ratio(spa), src);
+ spa_prop_add_list(*nvp, ZPOOL_PROP_BCLONEUSED, NULL,
+ brt_get_used(spa), src);
+ spa_prop_add_list(*nvp, ZPOOL_PROP_BCLONESAVED, NULL,
+ brt_get_saved(spa), src);
+ spa_prop_add_list(*nvp, ZPOOL_PROP_BCLONERATIO, NULL,
+ brt_get_ratio(spa), src);
spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL,
rvd->vdev_state, src);
@@ -465,7 +522,8 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
zprop_source_t src = ZPROP_SRC_DEFAULT;
zpool_prop_t prop;
- if ((prop = zpool_name_to_prop(za.za_name)) == ZPOOL_PROP_INVAL)
+ if ((prop = zpool_name_to_prop(za.za_name)) ==
+ ZPOOL_PROP_INVAL && !zfs_prop_user(za.za_name))
continue;
switch (za.za_integer_length) {
@@ -508,7 +566,13 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
kmem_free(strval, za.za_num_integers);
break;
}
- spa_prop_add_list(*nvp, prop, strval, 0, src);
+ if (prop != ZPOOL_PROP_INVAL) {
+ spa_prop_add_list(*nvp, prop, strval, 0, src);
+ } else {
+ src = ZPROP_SRC_LOCAL;
+ spa_prop_add_user(*nvp, za.za_name, strval,
+ src);
+ }
kmem_free(strval, za.za_num_integers);
break;
@@ -544,42 +608,53 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
elem = NULL;
while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
uint64_t intval;
- char *strval, *slash, *check, *fname;
+ const char *strval, *slash, *check, *fname;
const char *propname = nvpair_name(elem);
zpool_prop_t prop = zpool_name_to_prop(propname);
switch (prop) {
case ZPOOL_PROP_INVAL:
- if (!zpool_prop_feature(propname)) {
- error = SET_ERROR(EINVAL);
- break;
- }
-
/*
* Sanitize the input.
*/
- if (nvpair_type(elem) != DATA_TYPE_UINT64) {
- error = SET_ERROR(EINVAL);
- break;
- }
+ if (zfs_prop_user(propname)) {
+ if (strlen(propname) >= ZAP_MAXNAMELEN) {
+ error = SET_ERROR(ENAMETOOLONG);
+ break;
+ }
- if (nvpair_value_uint64(elem, &intval) != 0) {
- error = SET_ERROR(EINVAL);
- break;
- }
+ if (strlen(fnvpair_value_string(elem)) >=
+ ZAP_MAXVALUELEN) {
+ error = SET_ERROR(E2BIG);
+ break;
+ }
+ } else if (zpool_prop_feature(propname)) {
+ if (nvpair_type(elem) != DATA_TYPE_UINT64) {
+ error = SET_ERROR(EINVAL);
+ break;
+ }
- if (intval != 0) {
- error = SET_ERROR(EINVAL);
- break;
- }
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = SET_ERROR(EINVAL);
+ break;
+ }
+
+ if (intval != 0) {
+ error = SET_ERROR(EINVAL);
+ break;
+ }
- fname = strchr(propname, '@') + 1;
- if (zfeature_lookup_name(fname, NULL) != 0) {
+ fname = strchr(propname, '@') + 1;
+ if (zfeature_lookup_name(fname, NULL) != 0) {
+ error = SET_ERROR(EINVAL);
+ break;
+ }
+
+ has_feature = B_TRUE;
+ } else {
error = SET_ERROR(EINVAL);
break;
}
-
- has_feature = B_TRUE;
break;
case ZPOOL_PROP_VERSION:
@@ -746,7 +821,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
void
spa_configfile_set(spa_t *spa, nvlist_t *nvp, boolean_t need_sync)
{
- char *cachefile;
+ const char *cachefile;
spa_config_dirent_t *dp;
if (nvlist_lookup_string(nvp, zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
@@ -786,6 +861,12 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
prop == ZPOOL_PROP_READONLY)
continue;
+ if (prop == ZPOOL_PROP_INVAL &&
+ zfs_prop_user(nvpair_name(elem))) {
+ need_sync = B_TRUE;
+ break;
+ }
+
if (prop == ZPOOL_PROP_VERSION || prop == ZPOOL_PROP_INVAL) {
uint64_t ver = 0;
@@ -910,7 +991,16 @@ spa_change_guid(spa_t *spa)
spa_change_guid_sync, &guid, 5, ZFS_SPACE_CHECK_RESERVED);
if (error == 0) {
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ /*
+ * Clear the kobj flag from all the vdevs to allow
+ * vdev_cache_process_kobj_evt() to post events to all the
+ * vdevs since GUID is updated.
+ */
+ vdev_clear_kobj_evt(spa->spa_root_vdev);
+ for (int i = 0; i < spa->spa_l2cache.sav_count; i++)
+ vdev_clear_kobj_evt(spa->spa_l2cache.sav_vdevs[i]);
+
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_TRUE);
spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_REGUID);
}
@@ -968,17 +1058,33 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
uint_t count = ztip->zti_count;
spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
uint_t cpus, flags = TASKQ_DYNAMIC;
- boolean_t batch = B_FALSE;
switch (mode) {
case ZTI_MODE_FIXED:
ASSERT3U(value, >, 0);
break;
- case ZTI_MODE_BATCH:
- batch = B_TRUE;
+ case ZTI_MODE_SYNC:
+
+ /*
+ * Create one wr_iss taskq for every 'zio_taskq_write_tpq' CPUs,
+ * not to exceed the number of spa allocators, and align to it.
+ */
+ cpus = MAX(1, boot_ncpus * zio_taskq_batch_pct / 100);
+ count = MAX(1, cpus / MAX(1, zio_taskq_write_tpq));
+ count = MAX(count, (zio_taskq_batch_pct + 99) / 100);
+ count = MIN(count, spa->spa_alloc_count);
+ while (spa->spa_alloc_count % count != 0 &&
+ spa->spa_alloc_count < count * 2)
+ count--;
+
+ /*
+ * zio_taskq_batch_pct is unbounded and may exceed 100%, but no
+ * single taskq may have more threads than 100% of online cpus.
+ */
+ value = (zio_taskq_batch_pct + count / 2) / count;
+ value = MIN(value, 100);
flags |= TASKQ_THREADS_CPU_PCT;
- value = MIN(zio_taskq_batch_pct, 100);
break;
case ZTI_MODE_SCALE:
@@ -1025,7 +1131,7 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
default:
panic("unrecognized mode for %s_%s taskq (%u:%u) in "
- "spa_activate()",
+ "spa_taskqs_init()",
zio_type_name[t], zio_taskq_types[q], mode, value);
break;
}
@@ -1045,14 +1151,13 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
(void) snprintf(name, sizeof (name), "%s_%s",
zio_type_name[t], zio_taskq_types[q]);
+#ifdef HAVE_SYSDC
if (zio_taskq_sysdc && spa->spa_proc != &p0) {
- if (batch)
- flags |= TASKQ_DC_BATCH;
-
(void) zio_taskq_basedc;
tq = taskq_create_sysdc(name, value, 50, INT_MAX,
spa->spa_proc, zio_taskq_basedc, flags);
} else {
+#endif
pri_t pri = maxclsyspri;
/*
* The write issue taskq can be extremely CPU
@@ -1078,7 +1183,9 @@ spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
}
tq = taskq_create_proc(name, value, pri, 50,
INT_MAX, spa->spa_proc, flags);
+#ifdef HAVE_SYSDC
}
+#endif
tqs->stqs_taskq[i] = tq;
}
@@ -1103,15 +1210,283 @@ spa_taskqs_fini(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
tqs->stqs_taskq = NULL;
}
+#ifdef _KERNEL
+/*
+ * The READ and WRITE rows of zio_taskqs are configurable at module load time
+ * by setting zio_taskq_read or zio_taskq_write.
+ *
+ * Example (the defaults for READ and WRITE)
+ * zio_taskq_read='fixed,1,8 null scale null'
+ * zio_taskq_write='sync fixed,1,5 scale fixed,1,5'
+ *
+ * Each sets the entire row at a time.
+ *
+ * 'fixed' is parameterised: fixed,Q,T where Q is number of taskqs, T is number
+ * of threads per taskq.
+ *
+ * 'null' can only be set on the high-priority queues (queue selection for
+ * high-priority queues will fall back to the regular queue if the high-pri
+ * is NULL.
+ */
+static const char *const modes[ZTI_NMODES] = {
+ "fixed", "scale", "sync", "null"
+};
+
+/* Parse the incoming config string. Modifies cfg */
+static int
+spa_taskq_param_set(zio_type_t t, char *cfg)
+{
+ int err = 0;
+
+ zio_taskq_info_t row[ZIO_TASKQ_TYPES] = {{0}};
+
+ char *next = cfg, *tok, *c;
+
+ /*
+ * Parse out each element from the string and fill `row`. The entire
+ * row has to be set at once, so any errors are flagged by just
+ * breaking out of this loop early.
+ */
+ uint_t q;
+ for (q = 0; q < ZIO_TASKQ_TYPES; q++) {
+ /* `next` is the start of the config */
+ if (next == NULL)
+ break;
+
+ /* Eat up leading space */
+ while (isspace(*next))
+ next++;
+ if (*next == '\0')
+ break;
+
+ /* Mode ends at space or end of string */
+ tok = next;
+ next = strchr(tok, ' ');
+ if (next != NULL) *next++ = '\0';
+
+ /* Parameters start after a comma */
+ c = strchr(tok, ',');
+ if (c != NULL) *c++ = '\0';
+
+ /* Match mode string */
+ uint_t mode;
+ for (mode = 0; mode < ZTI_NMODES; mode++)
+ if (strcmp(tok, modes[mode]) == 0)
+ break;
+ if (mode == ZTI_NMODES)
+ break;
+
+ /* Invalid canary */
+ row[q].zti_mode = ZTI_NMODES;
+
+ /* Per-mode setup */
+ switch (mode) {
+
+ /*
+ * FIXED is parameterised: number of queues, and number of
+ * threads per queue.
+ */
+ case ZTI_MODE_FIXED: {
+ /* No parameters? */
+ if (c == NULL || *c == '\0')
+ break;
+
+ /* Find next parameter */
+ tok = c;
+ c = strchr(tok, ',');
+ if (c == NULL)
+ break;
+
+ /* Take digits and convert */
+ unsigned long long nq;
+ if (!(isdigit(*tok)))
+ break;
+ err = ddi_strtoull(tok, &tok, 10, &nq);
+ /* Must succeed and also end at the next param sep */
+ if (err != 0 || tok != c)
+ break;
+
+ /* Move past the comma */
+ tok++;
+ /* Need another number */
+ if (!(isdigit(*tok)))
+ break;
+ /* Remember start to make sure we moved */
+ c = tok;
+
+ /* Take digits */
+ unsigned long long ntpq;
+ err = ddi_strtoull(tok, &tok, 10, &ntpq);
+ /* Must succeed, and moved forward */
+ if (err != 0 || tok == c || *tok != '\0')
+ break;
+
+ /*
+ * sanity; zero queues/threads make no sense, and
+ * 16K is almost certainly more than anyone will ever
+ * need and avoids silly numbers like UINT32_MAX
+ */
+ if (nq == 0 || nq >= 16384 ||
+ ntpq == 0 || ntpq >= 16384)
+ break;
+
+ const zio_taskq_info_t zti = ZTI_P(ntpq, nq);
+ row[q] = zti;
+ break;
+ }
+
+ case ZTI_MODE_SCALE: {
+ const zio_taskq_info_t zti = ZTI_SCALE;
+ row[q] = zti;
+ break;
+ }
+
+ case ZTI_MODE_SYNC: {
+ const zio_taskq_info_t zti = ZTI_SYNC;
+ row[q] = zti;
+ break;
+ }
+
+ case ZTI_MODE_NULL: {
+ /*
+ * Can only null the high-priority queues; the general-
+ * purpose ones have to exist.
+ */
+ if (q != ZIO_TASKQ_ISSUE_HIGH &&
+ q != ZIO_TASKQ_INTERRUPT_HIGH)
+ break;
+
+ const zio_taskq_info_t zti = ZTI_NULL;
+ row[q] = zti;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Ensure we set a mode */
+ if (row[q].zti_mode == ZTI_NMODES)
+ break;
+ }
+
+ /* Didn't get a full row, fail */
+ if (q < ZIO_TASKQ_TYPES)
+ return (SET_ERROR(EINVAL));
+
+ /* Eat trailing space */
+ if (next != NULL)
+ while (isspace(*next))
+ next++;
+
+ /* If there's anything left over then fail */
+ if (next != NULL && *next != '\0')
+ return (SET_ERROR(EINVAL));
+
+ /* Success! Copy it into the real config */
+ for (q = 0; q < ZIO_TASKQ_TYPES; q++)
+ zio_taskqs[t][q] = row[q];
+
+ return (0);
+}
+
+static int
+spa_taskq_param_get(zio_type_t t, char *buf, boolean_t add_newline)
+{
+ int pos = 0;
+
+ /* Build paramater string from live config */
+ const char *sep = "";
+ for (uint_t q = 0; q < ZIO_TASKQ_TYPES; q++) {
+ const zio_taskq_info_t *zti = &zio_taskqs[t][q];
+ if (zti->zti_mode == ZTI_MODE_FIXED)
+ pos += sprintf(&buf[pos], "%s%s,%u,%u", sep,
+ modes[zti->zti_mode], zti->zti_count,
+ zti->zti_value);
+ else
+ pos += sprintf(&buf[pos], "%s%s", sep,
+ modes[zti->zti_mode]);
+ sep = " ";
+ }
+
+ if (add_newline)
+ buf[pos++] = '\n';
+ buf[pos] = '\0';
+
+ return (pos);
+}
+
+#ifdef __linux__
+static int
+spa_taskq_read_param_set(const char *val, zfs_kernel_param_t *kp)
+{
+ char *cfg = kmem_strdup(val);
+ int err = spa_taskq_param_set(ZIO_TYPE_READ, cfg);
+ kmem_free(cfg, strlen(val)+1);
+ return (-err);
+}
+static int
+spa_taskq_read_param_get(char *buf, zfs_kernel_param_t *kp)
+{
+ return (spa_taskq_param_get(ZIO_TYPE_READ, buf, TRUE));
+}
+
+static int
+spa_taskq_write_param_set(const char *val, zfs_kernel_param_t *kp)
+{
+ char *cfg = kmem_strdup(val);
+ int err = spa_taskq_param_set(ZIO_TYPE_WRITE, cfg);
+ kmem_free(cfg, strlen(val)+1);
+ return (-err);
+}
+static int
+spa_taskq_write_param_get(char *buf, zfs_kernel_param_t *kp)
+{
+ return (spa_taskq_param_get(ZIO_TYPE_WRITE, buf, TRUE));
+}
+#else
+/*
+ * On FreeBSD load-time parameters can be set up before malloc() is available,
+ * so we have to do all the parsing work on the stack.
+ */
+#define SPA_TASKQ_PARAM_MAX (128)
+
+static int
+spa_taskq_read_param(ZFS_MODULE_PARAM_ARGS)
+{
+ char buf[SPA_TASKQ_PARAM_MAX];
+ int err;
+
+ (void) spa_taskq_param_get(ZIO_TYPE_READ, buf, FALSE);
+ err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (err || req->newptr == NULL)
+ return (err);
+ return (spa_taskq_param_set(ZIO_TYPE_READ, buf));
+}
+
+static int
+spa_taskq_write_param(ZFS_MODULE_PARAM_ARGS)
+{
+ char buf[SPA_TASKQ_PARAM_MAX];
+ int err;
+
+ (void) spa_taskq_param_get(ZIO_TYPE_WRITE, buf, FALSE);
+ err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
+ if (err || req->newptr == NULL)
+ return (err);
+ return (spa_taskq_param_set(ZIO_TYPE_WRITE, buf));
+}
+#endif
+#endif /* _KERNEL */
+
/*
* Dispatch a task to the appropriate taskq for the ZFS I/O type and priority.
* Note that a type may have multiple discrete taskqs to avoid lock contention
- * on the taskq itself. In that case we choose which taskq at random by using
- * the low bits of gethrtime().
+ * on the taskq itself.
*/
-void
-spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
- task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent)
+static taskq_t *
+spa_taskq_dispatch_select(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
+ zio_t *zio)
{
spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
taskq_t *tq;
@@ -1121,10 +1496,21 @@ spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
if (tqs->stqs_count == 1) {
tq = tqs->stqs_taskq[0];
+ } else if ((t == ZIO_TYPE_WRITE) && (q == ZIO_TASKQ_ISSUE) &&
+ (zio != NULL) && ZIO_HAS_ALLOCATOR(zio)) {
+ tq = tqs->stqs_taskq[zio->io_allocator % tqs->stqs_count];
} else {
tq = tqs->stqs_taskq[((uint64_t)gethrtime()) % tqs->stqs_count];
}
+ return (tq);
+}
+void
+spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
+ task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent,
+ zio_t *zio)
+{
+ taskq_t *tq = spa_taskq_dispatch_select(spa, t, q, zio);
taskq_dispatch_ent(tq, func, arg, flags, ent);
}
@@ -1135,20 +1521,8 @@ void
spa_taskq_dispatch_sync(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags)
{
- spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
- taskq_t *tq;
- taskqid_t id;
-
- ASSERT3P(tqs->stqs_taskq, !=, NULL);
- ASSERT3U(tqs->stqs_count, !=, 0);
-
- if (tqs->stqs_count == 1) {
- tq = tqs->stqs_taskq[0];
- } else {
- tq = tqs->stqs_taskq[((uint64_t)gethrtime()) % tqs->stqs_count];
- }
-
- id = taskq_dispatch(tq, func, arg, flags);
+ taskq_t *tq = spa_taskq_dispatch_select(spa, t, q, NULL);
+ taskqid_t id = taskq_dispatch(tq, func, arg, flags);
if (id)
taskq_wait_id(tq, id);
}
@@ -1163,11 +1537,6 @@ spa_create_zio_taskqs(spa_t *spa)
}
}
-/*
- * Disabled until spa_thread() can be adapted for Linux.
- */
-#undef HAVE_SPA_THREAD
-
#if defined(_KERNEL) && defined(HAVE_SPA_THREAD)
static void
spa_thread(void *arg)
@@ -1208,9 +1577,11 @@ spa_thread(void *arg)
pool_unlock();
}
+#ifdef HAVE_SYSDC
if (zio_taskq_sysdc) {
sysdc_thread_enter(curthread, 100, 0);
}
+#endif
spa->spa_proc = curproc;
spa->spa_did = curthread->t_did;
@@ -1239,24 +1610,26 @@ spa_thread(void *arg)
}
#endif
+extern metaslab_ops_t *metaslab_allocator(spa_t *spa);
+
/*
* Activate an uninitialized pool.
*/
static void
spa_activate(spa_t *spa, spa_mode_t mode)
{
+ metaslab_ops_t *msp = metaslab_allocator(spa);
ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
spa->spa_state = POOL_STATE_ACTIVE;
spa->spa_mode = mode;
spa->spa_read_spacemaps = spa_mode_readable_spacemaps;
- spa->spa_normal_class = metaslab_class_create(spa, &zfs_metaslab_ops);
- spa->spa_log_class = metaslab_class_create(spa, &zfs_metaslab_ops);
- spa->spa_embedded_log_class =
- metaslab_class_create(spa, &zfs_metaslab_ops);
- spa->spa_special_class = metaslab_class_create(spa, &zfs_metaslab_ops);
- spa->spa_dedup_class = metaslab_class_create(spa, &zfs_metaslab_ops);
+ spa->spa_normal_class = metaslab_class_create(spa, msp);
+ spa->spa_log_class = metaslab_class_create(spa, msp);
+ spa->spa_embedded_log_class = metaslab_class_create(spa, msp);
+ spa->spa_special_class = metaslab_class_create(spa, msp);
+ spa->spa_dedup_class = metaslab_class_create(spa, msp);
/* Try to create a covering process */
mutex_enter(&spa->spa_proc_lock);
@@ -1264,7 +1637,6 @@ spa_activate(spa_t *spa, spa_mode_t mode)
ASSERT(spa->spa_proc == &p0);
spa->spa_did = 0;
- (void) spa_create_process;
#ifdef HAVE_SPA_THREAD
/* Only create a process if we're going to be around a while. */
if (spa_create_process && strcmp(spa->spa_name, TRYIMPORT_NAME) != 0) {
@@ -1315,6 +1687,9 @@ spa_activate(spa_t *spa, spa_mode_t mode)
avl_create(&spa->spa_errlist_last,
spa_error_entry_compare, sizeof (spa_error_entry_t),
offsetof(spa_error_entry_t, se_avl));
+ avl_create(&spa->spa_errlist_healed,
+ spa_error_entry_compare, sizeof (spa_error_entry_t),
+ offsetof(spa_error_entry_t, se_avl));
spa_activate_os(spa);
@@ -1339,6 +1714,13 @@ spa_activate(spa_t *spa, spa_mode_t mode)
1, INT_MAX, 0);
/*
+ * The taskq to preload metaslabs.
+ */
+ spa->spa_metaslab_taskq = taskq_create("z_metaslab",
+ metaslab_preload_pct, maxclsyspri, 1, INT_MAX,
+ TASKQ_DYNAMIC | TASKQ_THREADS_CPU_PCT);
+
+ /*
* Taskq dedicated to prefetcher threads: this is used to prevent the
* pool traverse code from monopolizing the global (and limited)
* system_taskq by inappropriately scheduling long running tasks on it.
@@ -1373,6 +1755,11 @@ spa_deactivate(spa_t *spa)
spa->spa_zvol_taskq = NULL;
}
+ if (spa->spa_metaslab_taskq) {
+ taskq_destroy(spa->spa_metaslab_taskq);
+ spa->spa_metaslab_taskq = NULL;
+ }
+
if (spa->spa_prefetch_taskq) {
taskq_destroy(spa->spa_prefetch_taskq);
spa->spa_prefetch_taskq = NULL;
@@ -1425,6 +1812,7 @@ spa_deactivate(spa_t *spa)
spa_errlog_drain(spa);
avl_destroy(&spa->spa_errlist_scrub);
avl_destroy(&spa->spa_errlist_last);
+ avl_destroy(&spa->spa_errlist_healed);
spa_keystore_fini(&spa->spa_keystore);
@@ -1549,16 +1937,16 @@ spa_unload_log_sm_metadata(spa_t *spa)
{
void *cookie = NULL;
spa_log_sm_t *sls;
+ log_summary_entry_t *e;
+
while ((sls = avl_destroy_nodes(&spa->spa_sm_logs_by_txg,
&cookie)) != NULL) {
VERIFY0(sls->sls_mscount);
kmem_free(sls, sizeof (spa_log_sm_t));
}
- for (log_summary_entry_t *e = list_head(&spa->spa_log_summary);
- e != NULL; e = list_head(&spa->spa_log_summary)) {
+ while ((e = list_remove_head(&spa->spa_log_summary)) != NULL) {
VERIFY0(e->lse_mscount);
- list_remove(&spa->spa_log_summary, e);
kmem_free(e, sizeof (log_summary_entry_t));
}
@@ -1586,6 +1974,10 @@ spa_destroy_aux_threads(spa_t *spa)
zthr_destroy(spa->spa_livelist_condense_zthr);
spa->spa_livelist_condense_zthr = NULL;
}
+ if (spa->spa_raidz_expand_zthr != NULL) {
+ zthr_destroy(spa->spa_raidz_expand_zthr);
+ spa->spa_raidz_expand_zthr = NULL;
+ }
}
/*
@@ -1644,13 +2036,7 @@ spa_unload(spa_t *spa)
* This ensures that there is no async metaslab prefetching
* while we attempt to unload the spa.
*/
- if (spa->spa_root_vdev != NULL) {
- for (int c = 0; c < spa->spa_root_vdev->vdev_children; c++) {
- vdev_t *vc = spa->spa_root_vdev->vdev_child[c];
- if (vc->vdev_mg != NULL)
- taskq_wait(vc->vdev_mg->mg_taskq);
- }
- }
+ taskq_wait(spa->spa_metaslab_taskq);
if (spa->spa_mmp.mmp_thread)
mmp_thread_stop(spa);
@@ -1695,6 +2081,7 @@ spa_unload(spa_t *spa)
}
ddt_unload(spa);
+ brt_unload(spa);
spa_unload_log_sm_metadata(spa);
/*
@@ -1702,9 +2089,9 @@ spa_unload(spa_t *spa)
*/
spa_l2cache_drop(spa);
- for (int i = 0; i < spa->spa_spares.sav_count; i++)
- vdev_free(spa->spa_spares.sav_vdevs[i]);
if (spa->spa_spares.sav_vdevs) {
+ for (int i = 0; i < spa->spa_spares.sav_count; i++)
+ vdev_free(spa->spa_spares.sav_vdevs[i]);
kmem_free(spa->spa_spares.sav_vdevs,
spa->spa_spares.sav_count * sizeof (void *));
spa->spa_spares.sav_vdevs = NULL;
@@ -1715,11 +2102,11 @@ spa_unload(spa_t *spa)
}
spa->spa_spares.sav_count = 0;
- for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
- vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
- vdev_free(spa->spa_l2cache.sav_vdevs[i]);
- }
if (spa->spa_l2cache.sav_vdevs) {
+ for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
+ vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
+ vdev_free(spa->spa_l2cache.sav_vdevs[i]);
+ }
kmem_free(spa->spa_l2cache.sav_vdevs,
spa->spa_l2cache.sav_count * sizeof (void *));
spa->spa_l2cache.sav_vdevs = NULL;
@@ -1743,6 +2130,8 @@ spa_unload(spa_t *spa)
spa->spa_compatibility = NULL;
}
+ spa->spa_raidz_expand = NULL;
+
spa_config_exit(spa, SCL_ALL, spa);
}
@@ -1777,20 +2166,21 @@ spa_load_spares(spa_t *spa)
/*
* First, close and free any existing spare vdevs.
*/
- for (i = 0; i < spa->spa_spares.sav_count; i++) {
- vd = spa->spa_spares.sav_vdevs[i];
+ if (spa->spa_spares.sav_vdevs) {
+ for (i = 0; i < spa->spa_spares.sav_count; i++) {
+ vd = spa->spa_spares.sav_vdevs[i];
- /* Undo the call to spa_activate() below */
- if ((tvd = spa_lookup_by_guid(spa, vd->vdev_guid,
- B_FALSE)) != NULL && tvd->vdev_isspare)
- spa_spare_remove(tvd);
- vdev_close(vd);
- vdev_free(vd);
- }
+ /* Undo the call to spa_activate() below */
+ if ((tvd = spa_lookup_by_guid(spa, vd->vdev_guid,
+ B_FALSE)) != NULL && tvd->vdev_isspare)
+ spa_spare_remove(tvd);
+ vdev_close(vd);
+ vdev_free(vd);
+ }
- if (spa->spa_spares.sav_vdevs)
kmem_free(spa->spa_spares.sav_vdevs,
spa->spa_spares.sav_count * sizeof (void *));
+ }
if (spa->spa_spares.sav_config == NULL)
nspares = 0;
@@ -2001,23 +2391,24 @@ out:
/*
* Purge vdevs that were dropped
*/
- for (i = 0; i < oldnvdevs; i++) {
- uint64_t pool;
+ if (oldvdevs) {
+ for (i = 0; i < oldnvdevs; i++) {
+ uint64_t pool;
- vd = oldvdevs[i];
- if (vd != NULL) {
- ASSERT(vd->vdev_isl2cache);
+ vd = oldvdevs[i];
+ if (vd != NULL) {
+ ASSERT(vd->vdev_isl2cache);
- if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
- pool != 0ULL && l2arc_vdev_present(vd))
- l2arc_remove_vdev(vd);
- vdev_clear_stats(vd);
- vdev_free(vd);
+ if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
+ pool != 0ULL && l2arc_vdev_present(vd))
+ l2arc_remove_vdev(vd);
+ vdev_clear_stats(vd);
+ vdev_free(vd);
+ }
}
- }
- if (oldvdevs)
kmem_free(oldvdevs, oldnvdevs * sizeof (void *));
+ }
for (i = 0; i < sav->sav_count; i++)
nvlist_free(l2cache[i]);
@@ -2259,8 +2650,8 @@ spa_claim_notify(zio_t *zio)
return;
mutex_enter(&spa->spa_props_lock); /* any mutex will do */
- if (spa->spa_claim_max_txg < zio->io_bp->blk_birth)
- spa->spa_claim_max_txg = zio->io_bp->blk_birth;
+ if (spa->spa_claim_max_txg < BP_GET_LOGICAL_BIRTH(zio->io_bp))
+ spa->spa_claim_max_txg = BP_GET_LOGICAL_BIRTH(zio->io_bp);
mutex_exit(&spa->spa_props_lock);
}
@@ -2298,7 +2689,7 @@ spa_load_verify_done(zio_t *zio)
* Maximum number of inflight bytes is the log2 fraction of the arc size.
* By default, we set it to 1/16th of the arc.
*/
-static int spa_load_verify_shift = 4;
+static uint_t spa_load_verify_shift = 4;
static int spa_load_verify_metadata = B_TRUE;
static int spa_load_verify_data = B_TRUE;
@@ -2325,7 +2716,7 @@ spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
* When damaged consider it to be a metadata error since we cannot
* trust the BP_GET_TYPE and BP_GET_LEVEL values.
*/
- if (!zfs_blkptr_verify(spa, bp, B_FALSE, BLK_VERIFY_LOG)) {
+ if (!zfs_blkptr_verify(spa, bp, BLK_CONFIG_NEEDED, BLK_VERIFY_LOG)) {
atomic_inc_64(&sle->sle_meta_count);
return (0);
}
@@ -2877,8 +3268,7 @@ spa_spawn_aux_threads(spa_t *spa)
{
ASSERT(spa_writeable(spa));
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
-
+ spa_start_raidz_expansion_thread(spa);
spa_start_indirect_condensing_thread(spa);
spa_start_livelist_destroy_thread(spa);
spa_start_livelist_condensing_thread(spa);
@@ -2981,6 +3371,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type)
spa->spa_load_state = state;
(void) spa_import_progress_set_state(spa_guid(spa),
spa_load_state(spa));
+ spa_import_progress_set_notes(spa, "spa_load()");
gethrestime(&spa->spa_loaded_ts);
error = spa_load_impl(spa, type, &ereport);
@@ -3022,6 +3413,12 @@ vdev_count_verify_zaps(vdev_t *vd)
spa_t *spa = vd->vdev_spa;
uint64_t total = 0;
+ if (spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2) &&
+ vd->vdev_root_zap != 0) {
+ total++;
+ ASSERT0(zap_lookup_int(spa->spa_meta_objset,
+ spa->spa_all_vdev_zaps, vd->vdev_root_zap));
+ }
if (vd->vdev_top_zap != 0) {
total++;
ASSERT0(zap_lookup_int(spa->spa_meta_objset,
@@ -3192,18 +3589,23 @@ spa_activity_check_duration(spa_t *spa, uberblock_t *ub)
}
/*
- * Perform the import activity check. If the user canceled the import or
- * we detected activity then fail.
+ * Remote host activity check.
+ *
+ * error results:
+ * 0 - no activity detected
+ * EREMOTEIO - remote activity detected
+ * EINTR - user canceled the operation
*/
static int
-spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
+spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config,
+ boolean_t importing)
{
uint64_t txg = ub->ub_txg;
uint64_t timestamp = ub->ub_timestamp;
uint64_t mmp_config = ub->ub_mmp_config;
uint16_t mmp_seq = MMP_SEQ_VALID(ub) ? MMP_SEQ(ub) : 0;
uint64_t import_delay;
- hrtime_t import_expire;
+ hrtime_t import_expire, now;
nvlist_t *mmp_label = NULL;
vdev_t *rvd = spa->spa_root_vdev;
kcondvar_t cv;
@@ -3241,9 +3643,23 @@ spa_activity_check(spa_t *spa, uberblock_t *ub, nvlist_t *config)
import_expire = gethrtime() + import_delay;
- while (gethrtime() < import_expire) {
- (void) spa_import_progress_set_mmp_check(spa_guid(spa),
- NSEC2SEC(import_expire - gethrtime()));
+ if (importing) {
+ spa_import_progress_set_notes(spa, "Checking MMP activity, "
+ "waiting %llu ms", (u_longlong_t)NSEC2MSEC(import_delay));
+ }
+
+ int iterations = 0;
+ while ((now = gethrtime()) < import_expire) {
+ if (importing && iterations++ % 30 == 0) {
+ spa_import_progress_set_notes(spa, "Checking MMP "
+ "activity, %llu ms remaining",
+ (u_longlong_t)NSEC2MSEC(import_expire - now));
+ }
+
+ if (importing) {
+ (void) spa_import_progress_set_mmp_check(spa_guid(spa),
+ NSEC2SEC(import_expire - gethrtime()));
+ }
vdev_uberblock_load(rvd, ub, &mmp_label);
@@ -3325,11 +3741,66 @@ out:
return (error);
}
+/*
+ * Called from zfs_ioc_clear for a pool that was suspended
+ * after failing mmp write checks.
+ */
+boolean_t
+spa_mmp_remote_host_activity(spa_t *spa)
+{
+ ASSERT(spa_multihost(spa) && spa_suspended(spa));
+
+ nvlist_t *best_label;
+ uberblock_t best_ub;
+
+ /*
+ * Locate the best uberblock on disk
+ */
+ vdev_uberblock_load(spa->spa_root_vdev, &best_ub, &best_label);
+ if (best_label) {
+ /*
+ * confirm that the best hostid matches our hostid
+ */
+ if (nvlist_exists(best_label, ZPOOL_CONFIG_HOSTID) &&
+ spa_get_hostid(spa) !=
+ fnvlist_lookup_uint64(best_label, ZPOOL_CONFIG_HOSTID)) {
+ nvlist_free(best_label);
+ return (B_TRUE);
+ }
+ nvlist_free(best_label);
+ } else {
+ return (B_TRUE);
+ }
+
+ if (!MMP_VALID(&best_ub) ||
+ !MMP_FAIL_INT_VALID(&best_ub) ||
+ MMP_FAIL_INT(&best_ub) == 0) {
+ return (B_TRUE);
+ }
+
+ if (best_ub.ub_txg != spa->spa_uberblock.ub_txg ||
+ best_ub.ub_timestamp != spa->spa_uberblock.ub_timestamp) {
+ zfs_dbgmsg("txg mismatch detected during pool clear "
+ "txg %llu ub_txg %llu timestamp %llu ub_timestamp %llu",
+ (u_longlong_t)spa->spa_uberblock.ub_txg,
+ (u_longlong_t)best_ub.ub_txg,
+ (u_longlong_t)spa->spa_uberblock.ub_timestamp,
+ (u_longlong_t)best_ub.ub_timestamp);
+ return (B_TRUE);
+ }
+
+ /*
+ * Perform an activity check looking for any remote writer
+ */
+ return (spa_activity_check(spa, &spa->spa_uberblock, spa->spa_config,
+ B_FALSE) != 0);
+}
+
static int
spa_verify_host(spa_t *spa, nvlist_t *mos_config)
{
uint64_t hostid;
- char *hostname;
+ const char *hostname;
uint64_t myhostid = 0;
if (!spa_is_root(spa) && nvlist_lookup_uint64(mos_config,
@@ -3364,8 +3835,8 @@ spa_ld_parse_config(spa_t *spa, spa_import_type_t type)
int parse;
vdev_t *rvd;
uint64_t pool_guid;
- char *comment;
- char *compatibility;
+ const char *comment;
+ const char *compatibility;
/*
* Versioning wasn't explicitly added to the label until later, so if
@@ -3627,6 +4098,12 @@ spa_ld_select_uberblock(spa_t *spa, spa_import_type_t type)
}
spa_load_note(spa, "using uberblock with txg=%llu",
(u_longlong_t)ub->ub_txg);
+ if (ub->ub_raidz_reflow_info != 0) {
+ spa_load_note(spa, "uberblock raidz_reflow_info: "
+ "state=%u offset=%llu",
+ (int)RRSS_GET_STATE(ub),
+ (u_longlong_t)RRSS_GET_OFFSET(ub));
+ }
/*
@@ -3645,7 +4122,8 @@ spa_ld_select_uberblock(spa_t *spa, spa_import_type_t type)
return (spa_vdev_err(rvd, VDEV_AUX_ACTIVE, EREMOTEIO));
}
- int error = spa_activity_check(spa, ub, spa->spa_config);
+ int error =
+ spa_activity_check(spa, ub, spa->spa_config, B_TRUE);
if (error) {
nvlist_free(label);
return (error);
@@ -3852,6 +4330,24 @@ spa_ld_trusted_config(spa_t *spa, spa_import_type_t type,
spa_config_exit(spa, SCL_ALL, FTAG);
/*
+ * If 'zpool import' used a cached config, then the on-disk hostid and
+ * hostname may be different to the cached config in ways that should
+ * prevent import. Userspace can't discover this without a scan, but
+ * we know, so we add these values to LOAD_INFO so the caller can know
+ * the difference.
+ *
+ * Note that we have to do this before the config is regenerated,
+ * because the new config will have the hostid and hostname for this
+ * host, in readiness for import.
+ */
+ if (nvlist_exists(mos_config, ZPOOL_CONFIG_HOSTID))
+ fnvlist_add_uint64(spa->spa_load_info, ZPOOL_CONFIG_HOSTID,
+ fnvlist_lookup_uint64(mos_config, ZPOOL_CONFIG_HOSTID));
+ if (nvlist_exists(mos_config, ZPOOL_CONFIG_HOSTNAME))
+ fnvlist_add_string(spa->spa_load_info, ZPOOL_CONFIG_HOSTNAME,
+ fnvlist_lookup_string(mos_config, ZPOOL_CONFIG_HOSTNAME));
+
+ /*
* We will use spa_config if we decide to reload the spa or if spa_load
* fails and we rewind. We must thus regenerate the config using the
* MOS information with the updated paths. ZPOOL_LOAD_POLICY is used to
@@ -4209,6 +4705,7 @@ spa_ld_get_props(spa_t *spa)
spa->spa_avz_action = AVZ_ACTION_INITIALIZE;
ASSERT0(vdev_count_verify_zaps(spa->spa_root_vdev));
} else if (error != 0) {
+ nvlist_free(mos_config);
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
} else if (!nvlist_exists(mos_config, ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)) {
/*
@@ -4400,6 +4897,21 @@ spa_ld_load_dedup_tables(spa_t *spa)
}
static int
+spa_ld_load_brt(spa_t *spa)
+{
+ int error = 0;
+ vdev_t *rvd = spa->spa_root_vdev;
+
+ error = brt_load(spa);
+ if (error != 0) {
+ spa_load_failed(spa, "brt_load failed [error=%d]", error);
+ return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO));
+ }
+
+ return (0);
+}
+
+static int
spa_ld_verify_logs(spa_t *spa, spa_import_type_t type, const char **ereport)
{
vdev_t *rvd = spa->spa_root_vdev;
@@ -4527,7 +5039,8 @@ spa_ld_read_checkpoint_txg(spa_t *spa)
int error = 0;
ASSERT0(spa->spa_checkpoint_txg);
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
+ spa->spa_load_thread == curthread);
error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
DMU_POOL_ZPOOL_CHECKPOINT, sizeof (uint64_t),
@@ -4774,6 +5287,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
boolean_t checkpoint_rewind =
(spa->spa_import_flags & ZFS_IMPORT_CHECKPOINT);
boolean_t update_config_cache = B_FALSE;
+ hrtime_t load_start = gethrtime();
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(spa->spa_config_source != SPA_CONFIG_SRC_NONE);
@@ -4819,11 +5333,18 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
}
/*
+ * Drop the namespace lock for the rest of the function.
+ */
+ spa->spa_load_thread = curthread;
+ mutex_exit(&spa_namespace_lock);
+
+ /*
* Retrieve the checkpoint txg if the pool has a checkpoint.
*/
+ spa_import_progress_set_notes(spa, "Loading checkpoint txg");
error = spa_ld_read_checkpoint_txg(spa);
if (error != 0)
- return (error);
+ goto fail;
/*
* Retrieve the mapping of indirect vdevs. Those vdevs were removed
@@ -4833,60 +5354,73 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* initiated. Otherwise we could be reading from indirect vdevs before
* we have loaded their mappings.
*/
+ spa_import_progress_set_notes(spa, "Loading indirect vdev metadata");
error = spa_ld_open_indirect_vdev_metadata(spa);
if (error != 0)
- return (error);
+ goto fail;
/*
* Retrieve the full list of active features from the MOS and check if
* they are all supported.
*/
+ spa_import_progress_set_notes(spa, "Checking feature flags");
error = spa_ld_check_features(spa, &missing_feat_write);
if (error != 0)
- return (error);
+ goto fail;
/*
* Load several special directories from the MOS needed by the dsl_pool
* layer.
*/
+ spa_import_progress_set_notes(spa, "Loading special MOS directories");
error = spa_ld_load_special_directories(spa);
if (error != 0)
- return (error);
+ goto fail;
/*
* Retrieve pool properties from the MOS.
*/
+ spa_import_progress_set_notes(spa, "Loading properties");
error = spa_ld_get_props(spa);
if (error != 0)
- return (error);
+ goto fail;
/*
* Retrieve the list of auxiliary devices - cache devices and spares -
* and open them.
*/
+ spa_import_progress_set_notes(spa, "Loading AUX vdevs");
error = spa_ld_open_aux_vdevs(spa, type);
if (error != 0)
- return (error);
+ goto fail;
/*
* Load the metadata for all vdevs. Also check if unopenable devices
* should be autoreplaced.
*/
+ spa_import_progress_set_notes(spa, "Loading vdev metadata");
error = spa_ld_load_vdev_metadata(spa);
if (error != 0)
- return (error);
+ goto fail;
+ spa_import_progress_set_notes(spa, "Loading dedup tables");
error = spa_ld_load_dedup_tables(spa);
if (error != 0)
- return (error);
+ goto fail;
+
+ spa_import_progress_set_notes(spa, "Loading BRT");
+ error = spa_ld_load_brt(spa);
+ if (error != 0)
+ goto fail;
/*
* Verify the logs now to make sure we don't have any unexpected errors
* when we claim log blocks later.
*/
+ spa_import_progress_set_notes(spa, "Verifying Log Devices");
error = spa_ld_verify_logs(spa, type, ereport);
if (error != 0)
- return (error);
+ goto fail;
if (missing_feat_write) {
ASSERT(spa->spa_load_state == SPA_LOAD_TRYIMPORT);
@@ -4896,8 +5430,9 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* read-only mode but not read-write mode. We now have enough
* information and can return to userland.
*/
- return (spa_vdev_err(spa->spa_root_vdev, VDEV_AUX_UNSUP_FEAT,
- ENOTSUP));
+ error = spa_vdev_err(spa->spa_root_vdev, VDEV_AUX_UNSUP_FEAT,
+ ENOTSUP);
+ goto fail;
}
/*
@@ -4905,15 +5440,17 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* state. When performing an extreme rewind, we verify the whole pool,
* which can take a very long time.
*/
+ spa_import_progress_set_notes(spa, "Verifying pool data");
error = spa_ld_verify_pool_data(spa);
if (error != 0)
- return (error);
+ goto fail;
/*
* Calculate the deflated space for the pool. This must be done before
* we write anything to the pool because we'd need to update the space
* accounting using the deflated sizes.
*/
+ spa_import_progress_set_notes(spa, "Calculating deflated space");
spa_update_dspace(spa);
/*
@@ -4921,6 +5458,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* pool. If we are importing the pool in read-write mode, a few
* additional steps must be performed to finish the import.
*/
+ spa_import_progress_set_notes(spa, "Starting import");
if (spa_writeable(spa) && (spa->spa_load_state == SPA_LOAD_RECOVER ||
spa->spa_load_max_txg == UINT64_MAX)) {
uint64_t config_cache_txg = spa->spa_config_txg;
@@ -4928,6 +5466,13 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
ASSERT(spa->spa_load_state != SPA_LOAD_TRYIMPORT);
/*
+ * Before we do any zio_write's, complete the raidz expansion
+ * scratch space copying, if necessary.
+ */
+ if (RRSS_GET_STATE(&spa->spa_uberblock) == RRSS_SCRATCH_VALID)
+ vdev_raidz_reflow_copy_scratch(spa);
+
+ /*
* In case of a checkpoint rewind, log the original txg
* of the checkpointed uberblock.
*/
@@ -4937,6 +5482,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
(u_longlong_t)spa->spa_uberblock.ub_checkpoint_txg);
}
+ spa_import_progress_set_notes(spa, "Claiming ZIL blocks");
/*
* Traverse the ZIL and claim all blocks.
*/
@@ -4956,6 +5502,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* will have been set for us by ZIL traversal operations
* performed above.
*/
+ spa_import_progress_set_notes(spa, "Syncing ZIL claims");
txg_wait_synced(spa->spa_dsl_pool, spa->spa_claim_max_txg);
/*
@@ -4963,6 +5510,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* next sync, we would update the config stored in vdev labels
* and the cachefile (by default /etc/zfs/zpool.cache).
*/
+ spa_import_progress_set_notes(spa, "Updating configs");
spa_ld_check_for_config_update(spa, config_cache_txg,
update_config_cache);
@@ -4971,6 +5519,7 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* Then check all DTLs to see if anything needs resilvering.
* The resilver will be deferred if a rebuild was started.
*/
+ spa_import_progress_set_notes(spa, "Starting resilvers");
if (vdev_rebuild_active(spa->spa_root_vdev)) {
vdev_rebuild_restart(spa);
} else if (!dsl_scan_resilvering(spa->spa_dsl_pool) &&
@@ -4984,6 +5533,8 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
*/
spa_history_log_version(spa, "open", NULL);
+ spa_import_progress_set_notes(spa,
+ "Restarting device removals");
spa_restart_removal(spa);
spa_spawn_aux_threads(spa);
@@ -4996,27 +5547,40 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, const char **ereport)
* auxiliary threads above (from which the livelist
* deletion zthr is part of).
*/
+ spa_import_progress_set_notes(spa,
+ "Cleaning up inconsistent objsets");
(void) dmu_objset_find(spa_name(spa),
dsl_destroy_inconsistent, NULL, DS_FIND_CHILDREN);
/*
* Clean up any stale temporary dataset userrefs.
*/
+ spa_import_progress_set_notes(spa,
+ "Cleaning up temporary userrefs");
dsl_pool_clean_tmp_userrefs(spa->spa_dsl_pool);
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ spa_import_progress_set_notes(spa, "Restarting initialize");
vdev_initialize_restart(spa->spa_root_vdev);
+ spa_import_progress_set_notes(spa, "Restarting TRIM");
vdev_trim_restart(spa->spa_root_vdev);
vdev_autotrim_restart(spa);
spa_config_exit(spa, SCL_CONFIG, FTAG);
+ spa_import_progress_set_notes(spa, "Finished importing");
}
+ zio_handle_import_delay(spa, gethrtime() - load_start);
spa_import_progress_remove(spa_guid(spa));
spa_async_request(spa, SPA_ASYNC_L2CACHE_REBUILD);
spa_load_note(spa, "LOADED");
+fail:
+ mutex_enter(&spa_namespace_lock);
+ spa->spa_load_thread = NULL;
+ cv_broadcast(&spa_namespace_cv);
+
+ return (error);
- return (0);
}
static int
@@ -5216,7 +5780,7 @@ spa_open_common(const char *pool, spa_t **spapp, const void *tag,
*/
spa_unload(spa);
spa_deactivate(spa);
- spa_write_cachefile(spa, B_TRUE, B_TRUE);
+ spa_write_cachefile(spa, B_TRUE, B_TRUE, B_FALSE);
spa_remove(spa);
if (locked)
mutex_exit(&spa_namespace_lock);
@@ -5254,7 +5818,7 @@ spa_open_common(const char *pool, spa_t **spapp, const void *tag,
* 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);
}
@@ -5351,13 +5915,15 @@ spa_add_spares(spa_t *spa, nvlist_t *config)
for (i = 0; i < nspares; i++) {
guid = fnvlist_lookup_uint64(spares[i],
ZPOOL_CONFIG_GUID);
+ VERIFY0(nvlist_lookup_uint64_array(spares[i],
+ ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &vsc));
if (spa_spare_exists(guid, &pool, NULL) &&
pool != 0ULL) {
- VERIFY0(nvlist_lookup_uint64_array(spares[i],
- ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs,
- &vsc));
vs->vs_state = VDEV_STATE_CANT_OPEN;
vs->vs_aux = VDEV_AUX_SPARED;
+ } else {
+ vs->vs_state =
+ spa->spa_spares.sav_vdevs[i]->vdev_state;
}
}
}
@@ -5530,7 +6096,7 @@ spa_get_stats(const char *name, nvlist_t **config,
fnvlist_add_uint64(*config,
ZPOOL_CONFIG_ERRCOUNT,
- spa_get_errlog_size(spa));
+ spa_approx_errlog_size(spa));
if (spa_suspended(spa)) {
fnvlist_add_uint64(*config,
@@ -5755,7 +6321,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
nvlist_t *zplprops, dsl_crypto_params_t *dcp)
{
spa_t *spa;
- char *altroot = NULL;
+ const char *altroot = NULL;
vdev_t *rvd;
dsl_pool_t *dp;
dmu_tx_t *tx;
@@ -5768,12 +6334,13 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
boolean_t has_encryption;
boolean_t has_allocclass;
spa_feature_t feat;
- char *feat_name;
- char *poolname;
+ const char *feat_name;
+ const char *poolname;
nvlist_t *nvl;
if (props == NULL ||
- nvlist_lookup_string(props, "tname", &poolname) != 0)
+ nvlist_lookup_string(props,
+ zpool_prop_to_name(ZPOOL_PROP_TNAME), &poolname) != 0)
poolname = (char *)pool;
/*
@@ -5948,6 +6515,10 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
* Create DDTs (dedup tables).
*/
ddt_create(spa);
+ /*
+ * Create BRT table and BRT table object.
+ */
+ brt_create(spa);
spa_update_dspace(spa);
@@ -6040,7 +6611,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
spa_spawn_aux_threads(spa);
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_TRUE);
/*
* Don't count references from objsets that are already closed
@@ -6064,7 +6635,7 @@ int
spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
{
spa_t *spa;
- char *altroot = NULL;
+ const char *altroot = NULL;
spa_load_state_t state = SPA_LOAD_IMPORT;
zpool_load_policy_t policy;
spa_mode_t mode = spa_mode_global;
@@ -6103,7 +6674,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
if (props != NULL)
spa_configfile_set(spa, props, B_FALSE);
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE);
spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_IMPORT);
zfs_dbgmsg("spa_import: verbatim import of %s", pool);
mutex_exit(&spa_namespace_lock);
@@ -6244,7 +6815,7 @@ nvlist_t *
spa_tryimport(nvlist_t *tryconfig)
{
nvlist_t *config = NULL;
- char *poolname, *cachefile;
+ const char *poolname, *cachefile;
spa_t *spa;
uint64_t state;
int error;
@@ -6259,9 +6830,14 @@ spa_tryimport(nvlist_t *tryconfig)
/*
* Create and initialize the spa structure.
*/
+ char *name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+ (void) snprintf(name, MAXPATHLEN, "%s-%llx-%s",
+ TRYIMPORT_NAME, (u_longlong_t)curthread, poolname);
+
mutex_enter(&spa_namespace_lock);
- spa = spa_add(TRYIMPORT_NAME, tryconfig, NULL);
+ spa = spa_add(name, tryconfig, NULL);
spa_activate(spa, SPA_MODE_READ);
+ kmem_free(name, MAXPATHLEN);
/*
* Rewind pool if a max txg was provided.
@@ -6284,6 +6860,16 @@ spa_tryimport(nvlist_t *tryconfig)
spa->spa_config_source = SPA_CONFIG_SRC_SCAN;
}
+ /*
+ * spa_import() relies on a pool config fetched by spa_try_import()
+ * for spare/cache devices. Import flags are not passed to
+ * spa_tryimport(), which makes it return early due to a missing log
+ * device and missing retrieving the cache device and spare eventually.
+ * Passing ZFS_IMPORT_MISSING_LOG to spa_tryimport() makes it fetch
+ * the correct configuration regardless of the missing log device.
+ */
+ spa->spa_import_flags |= ZFS_IMPORT_MISSING_LOG;
+
error = spa_load(spa, SPA_LOAD_TRYIMPORT, SPA_IMPORT_EXISTING);
/*
@@ -6366,6 +6952,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
{
int error;
spa_t *spa;
+ hrtime_t export_start = gethrtime();
if (oldconfig)
*oldconfig = NULL;
@@ -6423,6 +7010,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
}
if (spa->spa_sync_on) {
+ vdev_t *rvd = spa->spa_root_vdev;
/*
* A pool cannot be exported if it has an active shared spare.
* This is to prevent other pools stealing the active spare
@@ -6442,13 +7030,10 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
* dirty data resulting from the initialization is
* committed to disk before we unload the pool.
*/
- if (spa->spa_root_vdev != NULL) {
- vdev_t *rvd = spa->spa_root_vdev;
- vdev_initialize_stop_all(rvd, VDEV_INITIALIZE_ACTIVE);
- vdev_trim_stop_all(rvd, VDEV_TRIM_ACTIVE);
- vdev_autotrim_stop_all(spa);
- vdev_rebuild_stop_all(spa);
- }
+ vdev_initialize_stop_all(rvd, VDEV_INITIALIZE_ACTIVE);
+ vdev_trim_stop_all(rvd, VDEV_TRIM_ACTIVE);
+ vdev_autotrim_stop_all(spa);
+ vdev_rebuild_stop_all(spa);
/*
* We want this to be reflected on every label,
@@ -6458,7 +7043,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
if (new_state != POOL_STATE_UNINITIALIZED && !hardforce) {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa->spa_state = new_state;
- vdev_config_dirty(spa->spa_root_vdev);
+ vdev_config_dirty(rvd);
spa_config_exit(spa, SCL_ALL, FTAG);
}
@@ -6501,7 +7086,7 @@ export_spa:
if (new_state != POOL_STATE_UNINITIALIZED) {
if (!hardforce)
- spa_write_cachefile(spa, B_TRUE, B_TRUE);
+ spa_write_cachefile(spa, B_TRUE, B_TRUE, B_FALSE);
spa_remove(spa);
} else {
/*
@@ -6512,6 +7097,9 @@ export_spa:
spa->spa_is_exporting = B_FALSE;
}
+ if (new_state == POOL_STATE_EXPORTED)
+ zio_handle_export_delay(spa, gethrtime() - export_start);
+
mutex_exit(&spa_namespace_lock);
return (0);
@@ -6577,7 +7165,7 @@ spa_draid_feature_incr(void *arg, dmu_tx_t *tx)
* Add a device to a storage pool.
*/
int
-spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
+spa_vdev_add(spa_t *spa, nvlist_t *nvroot, boolean_t check_ashift)
{
uint64_t txg, ndraid = 0;
int error;
@@ -6668,6 +7256,16 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
}
}
+ if (check_ashift && spa->spa_max_ashift == spa->spa_min_ashift) {
+ for (int c = 0; c < vd->vdev_children; c++) {
+ tvd = vd->vdev_child[c];
+ if (tvd->vdev_ashift != spa->spa_max_ashift) {
+ return (spa_vdev_exit(spa, vd, txg,
+ ZFS_ERR_ASHIFT_MISMATCH));
+ }
+ }
+ }
+
for (int c = 0; c < vd->vdev_children; c++) {
tvd = vd->vdev_child[c];
vdev_remove_child(vd, tvd);
@@ -6727,9 +7325,10 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
}
/*
- * Attach a device to a mirror. The arguments are the path to any device
- * in the mirror, and the nvroot for the new device. If the path specifies
- * a device that is not mirrored, we automatically insert the mirror vdev.
+ * Attach a device to a vdev specified by its guid. The vdev type can be
+ * a mirror, a raidz, or a leaf device that is also a top-level (e.g. a
+ * single device). When the vdev is a single device, a mirror vdev will be
+ * automatically inserted.
*
* If 'replacing' is specified, the new device is intended to replace the
* existing device; in this case the two devices are made into their own
@@ -6752,7 +7351,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
vdev_t *oldvd, *newvd, *newrootvd, *pvd, *tvd;
vdev_ops_t *pvops;
char *oldvdpath, *newvdpath;
- int newvd_isspare;
+ int newvd_isspare = B_FALSE;
int error;
ASSERT(spa_writeable(spa));
@@ -6772,28 +7371,49 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
if (!spa_feature_is_enabled(spa, SPA_FEATURE_DEVICE_REBUILD))
return (spa_vdev_exit(spa, NULL, txg, ENOTSUP));
- if (dsl_scan_resilvering(spa_get_dsl(spa)))
+ if (dsl_scan_resilvering(spa_get_dsl(spa)) ||
+ dsl_scan_resilver_scheduled(spa_get_dsl(spa))) {
return (spa_vdev_exit(spa, NULL, txg,
ZFS_ERR_RESILVER_IN_PROGRESS));
+ }
} else {
if (vdev_rebuild_active(rvd))
return (spa_vdev_exit(spa, NULL, txg,
ZFS_ERR_REBUILD_IN_PROGRESS));
}
- if (spa->spa_vdev_removal != NULL)
- return (spa_vdev_exit(spa, NULL, txg, EBUSY));
+ if (spa->spa_vdev_removal != NULL) {
+ return (spa_vdev_exit(spa, NULL, txg,
+ ZFS_ERR_DEVRM_IN_PROGRESS));
+ }
if (oldvd == NULL)
return (spa_vdev_exit(spa, NULL, txg, ENODEV));
- if (!oldvd->vdev_ops->vdev_op_leaf)
+ boolean_t raidz = oldvd->vdev_ops == &vdev_raidz_ops;
+
+ if (raidz) {
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_RAIDZ_EXPANSION))
+ return (spa_vdev_exit(spa, NULL, txg, ENOTSUP));
+
+ /*
+ * Can't expand a raidz while prior expand is in progress.
+ */
+ if (spa->spa_raidz_expand != NULL) {
+ return (spa_vdev_exit(spa, NULL, txg,
+ ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS));
+ }
+ } else if (!oldvd->vdev_ops->vdev_op_leaf) {
return (spa_vdev_exit(spa, NULL, txg, ENOTSUP));
+ }
- pvd = oldvd->vdev_parent;
+ if (raidz)
+ pvd = oldvd;
+ else
+ pvd = oldvd->vdev_parent;
- if ((error = spa_config_parse(spa, &newrootvd, nvroot, NULL, 0,
- VDEV_ALLOC_ATTACH)) != 0)
+ if (spa_config_parse(spa, &newrootvd, nvroot, NULL, 0,
+ VDEV_ALLOC_ATTACH) != 0)
return (spa_vdev_exit(spa, NULL, txg, EINVAL));
if (newrootvd->vdev_children != 1)
@@ -6808,10 +7428,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.
@@ -6840,11 +7462,13 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
if (!replacing) {
/*
- * For attach, the only allowable parent is a mirror or the root
- * vdev.
+ * For attach, the only allowable parent is a mirror or
+ * the root vdev. A raidz vdev can be attached to, but
+ * you cannot attach to a raidz child.
*/
if (pvd->vdev_ops != &vdev_mirror_ops &&
- pvd->vdev_ops != &vdev_root_ops)
+ pvd->vdev_ops != &vdev_root_ops &&
+ !raidz)
return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP));
pvops = &vdev_mirror_ops;
@@ -6883,7 +7507,8 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
/*
* Make sure the new device is big enough.
*/
- if (newvd->vdev_asize < vdev_get_min_asize(oldvd))
+ vdev_t *min_vdev = raidz ? oldvd->vdev_child[0] : oldvd;
+ if (newvd->vdev_asize < vdev_get_min_asize(min_vdev))
return (spa_vdev_exit(spa, newrootvd, txg, EOVERFLOW));
/*
@@ -6894,31 +7519,74 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP));
/*
+ * RAIDZ-expansion-specific checks.
+ */
+ if (raidz) {
+ if (vdev_raidz_attach_check(newvd) != 0)
+ return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP));
+
+ /*
+ * Fail early if a child is not healthy or being replaced
+ */
+ for (int i = 0; i < oldvd->vdev_children; i++) {
+ if (vdev_is_dead(oldvd->vdev_child[i]) ||
+ !oldvd->vdev_child[i]->vdev_ops->vdev_op_leaf) {
+ return (spa_vdev_exit(spa, newrootvd, txg,
+ ENXIO));
+ }
+ /* Also fail if reserved boot area is in-use */
+ if (vdev_check_boot_reserve(spa, oldvd->vdev_child[i])
+ != 0) {
+ return (spa_vdev_exit(spa, newrootvd, txg,
+ EADDRINUSE));
+ }
+ }
+ }
+
+ if (raidz) {
+ /*
+ * Note: oldvdpath is freed by spa_strfree(), but
+ * kmem_asprintf() is freed by kmem_strfree(), so we have to
+ * move it to a spa_strdup-ed string.
+ */
+ char *tmp = kmem_asprintf("raidz%u-%u",
+ (uint_t)vdev_get_nparity(oldvd), (uint_t)oldvd->vdev_id);
+ oldvdpath = spa_strdup(tmp);
+ kmem_strfree(tmp);
+ } else {
+ oldvdpath = spa_strdup(oldvd->vdev_path);
+ }
+ newvdpath = spa_strdup(newvd->vdev_path);
+
+ /*
* If this is an in-place replacement, update oldvd's path and devid
* to make it distinguishable from newvd, and unopenable from now on.
*/
- if (strcmp(oldvd->vdev_path, newvd->vdev_path) == 0) {
+ if (strcmp(oldvdpath, newvdpath) == 0) {
spa_strfree(oldvd->vdev_path);
- oldvd->vdev_path = kmem_alloc(strlen(newvd->vdev_path) + 5,
+ oldvd->vdev_path = kmem_alloc(strlen(newvdpath) + 5,
KM_SLEEP);
- (void) snprintf(oldvd->vdev_path, strlen(newvd->vdev_path) + 5,
- "%s/%s", newvd->vdev_path, "old");
+ (void) sprintf(oldvd->vdev_path, "%s/old",
+ newvdpath);
if (oldvd->vdev_devid != NULL) {
spa_strfree(oldvd->vdev_devid);
oldvd->vdev_devid = NULL;
}
+ spa_strfree(oldvdpath);
+ oldvdpath = spa_strdup(oldvd->vdev_path);
}
/*
* If the parent is not a mirror, or if we're replacing, insert the new
* mirror/replacing/spare vdev above oldvd.
*/
- if (pvd->vdev_ops != pvops)
+ if (!raidz && pvd->vdev_ops != pvops) {
pvd = vdev_add_parent(oldvd, pvops);
+ ASSERT(pvd->vdev_ops == pvops);
+ ASSERT(oldvd->vdev_parent == pvd);
+ }
ASSERT(pvd->vdev_top->vdev_parent == rvd);
- ASSERT(pvd->vdev_ops == pvops);
- ASSERT(oldvd->vdev_parent == pvd);
/*
* Extract the new device from its root and add it to pvd.
@@ -6946,41 +7614,66 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
*/
dtl_max_txg = txg + TXG_CONCURRENT_STATES;
- vdev_dtl_dirty(newvd, DTL_MISSING,
- TXG_INITIAL, dtl_max_txg - TXG_INITIAL);
+ if (raidz) {
+ /*
+ * Wait for the youngest allocations and frees to sync,
+ * and then wait for the deferral of those frees to finish.
+ */
+ spa_vdev_config_exit(spa, NULL,
+ txg + TXG_CONCURRENT_STATES + TXG_DEFER_SIZE, 0, FTAG);
- if (newvd->vdev_isspare) {
- spa_spare_activate(newvd);
- spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_SPARE);
- }
+ vdev_initialize_stop_all(tvd, VDEV_INITIALIZE_ACTIVE);
+ vdev_trim_stop_all(tvd, VDEV_TRIM_ACTIVE);
+ vdev_autotrim_stop_wait(tvd);
- oldvdpath = spa_strdup(oldvd->vdev_path);
- newvdpath = spa_strdup(newvd->vdev_path);
- newvd_isspare = newvd->vdev_isspare;
+ dtl_max_txg = spa_vdev_config_enter(spa);
- /*
- * Mark newvd's DTL dirty in this txg.
- */
- vdev_dirty(tvd, VDD_DTL, newvd, txg);
+ tvd->vdev_rz_expanding = B_TRUE;
- /*
- * Schedule the resilver or rebuild to restart in the future. We do
- * this to ensure that dmu_sync-ed blocks have been stitched into the
- * respective datasets.
- */
- if (rebuild) {
- newvd->vdev_rebuild_txg = txg;
+ vdev_dirty_leaves(tvd, VDD_DTL, dtl_max_txg);
+ vdev_config_dirty(tvd);
- vdev_rebuild(tvd);
+ dmu_tx_t *tx = dmu_tx_create_assigned(spa->spa_dsl_pool,
+ dtl_max_txg);
+ dsl_sync_task_nowait(spa->spa_dsl_pool, vdev_raidz_attach_sync,
+ newvd, tx);
+ dmu_tx_commit(tx);
} else {
- newvd->vdev_resilver_txg = txg;
+ vdev_dtl_dirty(newvd, DTL_MISSING, TXG_INITIAL,
+ dtl_max_txg - TXG_INITIAL);
- if (dsl_scan_resilvering(spa_get_dsl(spa)) &&
- spa_feature_is_enabled(spa, SPA_FEATURE_RESILVER_DEFER)) {
- vdev_defer_resilver(newvd);
+ if (newvd->vdev_isspare) {
+ spa_spare_activate(newvd);
+ spa_event_notify(spa, newvd, NULL, ESC_ZFS_VDEV_SPARE);
+ }
+
+ newvd_isspare = newvd->vdev_isspare;
+
+ /*
+ * Mark newvd's DTL dirty in this txg.
+ */
+ vdev_dirty(tvd, VDD_DTL, newvd, txg);
+
+ /*
+ * Schedule the resilver or rebuild to restart in the future.
+ * We do this to ensure that dmu_sync-ed blocks have been
+ * stitched into the respective datasets.
+ */
+ if (rebuild) {
+ newvd->vdev_rebuild_txg = txg;
+
+ vdev_rebuild(tvd);
} else {
- dsl_scan_restart_resilver(spa->spa_dsl_pool,
- dtl_max_txg);
+ newvd->vdev_resilver_txg = txg;
+
+ if (dsl_scan_resilvering(spa_get_dsl(spa)) &&
+ spa_feature_is_enabled(spa,
+ SPA_FEATURE_RESILVER_DEFER)) {
+ vdev_defer_resilver(newvd);
+ } else {
+ dsl_scan_restart_resilver(spa->spa_dsl_pool,
+ dtl_max_txg);
+ }
}
}
@@ -7010,7 +7703,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
* Detach a device from a mirror or replacing vdev.
*
* If 'replace_done' is specified, only detach if the parent
- * is a replacing vdev.
+ * is a replacing or a spare vdev.
*/
int
spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
@@ -7149,7 +7842,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
* it may be that the unwritability of the disk is the reason
* it's being detached!
*/
- error = vdev_label_init(vd, 0, VDEV_LABEL_REMOVE);
+ (void) vdev_label_init(vd, 0, VDEV_LABEL_REMOVE);
/*
* Remove vd from its parent and compact the parent's children.
@@ -7305,7 +7998,7 @@ spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
*/
if (cmd_type == POOL_INITIALIZE_START &&
(vd->vdev_initialize_thread != NULL ||
- vd->vdev_top->vdev_removing)) {
+ vd->vdev_top->vdev_removing || vd->vdev_top->vdev_rz_expanding)) {
mutex_exit(&vd->vdev_initialize_lock);
return (SET_ERROR(EBUSY));
} else if (cmd_type == POOL_INITIALIZE_CANCEL &&
@@ -7317,6 +8010,10 @@ spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
vd->vdev_initialize_state != VDEV_INITIALIZE_ACTIVE) {
mutex_exit(&vd->vdev_initialize_lock);
return (SET_ERROR(ESRCH));
+ } else if (cmd_type == POOL_INITIALIZE_UNINIT &&
+ vd->vdev_initialize_thread != NULL) {
+ mutex_exit(&vd->vdev_initialize_lock);
+ return (SET_ERROR(EBUSY));
}
switch (cmd_type) {
@@ -7329,6 +8026,9 @@ spa_vdev_initialize_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
case POOL_INITIALIZE_SUSPEND:
vdev_initialize_stop(vd, VDEV_INITIALIZE_SUSPENDED, vd_list);
break;
+ case POOL_INITIALIZE_UNINIT:
+ vdev_uninitialize(vd);
+ break;
default:
panic("invalid cmd_type %llu", (unsigned long long)cmd_type);
}
@@ -7420,7 +8120,8 @@ spa_vdev_trim_impl(spa_t *spa, uint64_t guid, uint64_t cmd_type,
* which has completed but the thread is not exited.
*/
if (cmd_type == POOL_TRIM_START &&
- (vd->vdev_trim_thread != NULL || vd->vdev_top->vdev_removing)) {
+ (vd->vdev_trim_thread != NULL || vd->vdev_top->vdev_removing ||
+ vd->vdev_top->vdev_rz_expanding)) {
mutex_exit(&vd->vdev_trim_lock);
return (SET_ERROR(EBUSY));
} else if (cmd_type == POOL_TRIM_CANCEL &&
@@ -7517,7 +8218,7 @@ spa_vdev_split_mirror(spa_t *spa, const char *newname, nvlist_t *config,
uint_t c, children, lastlog;
nvlist_t **child, *nvl, *tmp;
dmu_tx_t *tx;
- char *altroot = NULL;
+ const char *altroot = NULL;
vdev_t *rvd, **vml = NULL; /* vdev modify list */
boolean_t activate_slog;
@@ -8062,6 +8763,7 @@ spa_scan_stop(spa_t *spa)
ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == 0);
if (dsl_scan_resilvering(spa->spa_dsl_pool))
return (SET_ERROR(EBUSY));
+
return (dsl_scan_cancel(spa->spa_dsl_pool));
}
@@ -8087,6 +8789,10 @@ spa_scan(spa_t *spa, pool_scan_func_t func)
return (0);
}
+ if (func == POOL_SCAN_ERRORSCRUB &&
+ !spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG))
+ return (SET_ERROR(ENOTSUP));
+
return (dsl_scan(spa->spa_dsl_pool, func));
}
@@ -8125,15 +8831,16 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
}
static void
-spa_async_probe(spa_t *spa, vdev_t *vd)
+spa_async_fault_vdev(spa_t *spa, vdev_t *vd)
{
- if (vd->vdev_probe_wanted) {
- vd->vdev_probe_wanted = B_FALSE;
- vdev_reopen(vd); /* vdev_open() does the actual probe */
+ if (vd->vdev_fault_wanted) {
+ vd->vdev_fault_wanted = B_FALSE;
+ vdev_set_state(vd, B_TRUE, VDEV_STATE_FAULTED,
+ VDEV_AUX_ERR_EXCEEDED);
}
for (int c = 0; c < vd->vdev_children; c++)
- spa_async_probe(spa, vd->vdev_child[c]);
+ spa_async_fault_vdev(spa, vd->vdev_child[c]);
}
static void
@@ -8221,11 +8928,11 @@ spa_async_thread(void *arg)
}
/*
- * See if any devices need to be probed.
+ * See if any devices need to be marked faulted.
*/
- if (tasks & SPA_ASYNC_PROBE) {
+ if (tasks & SPA_ASYNC_FAULT_VDEV) {
spa_vdev_state_enter(spa, SCL_NONE);
- spa_async_probe(spa, spa->spa_root_vdev);
+ spa_async_fault_vdev(spa, spa->spa_root_vdev);
(void) spa_vdev_state_exit(spa, NULL, 0);
}
@@ -8233,7 +8940,8 @@ spa_async_thread(void *arg)
* If any devices are done replacing, detach them.
*/
if (tasks & SPA_ASYNC_RESILVER_DONE ||
- tasks & SPA_ASYNC_REBUILD_DONE) {
+ tasks & SPA_ASYNC_REBUILD_DONE ||
+ tasks & SPA_ASYNC_DETACH_SPARE) {
spa_vdev_resilver_done(spa);
}
@@ -8317,6 +9025,10 @@ spa_async_suspend(spa_t *spa)
if (condense_thread != NULL)
zthr_cancel(condense_thread);
+ zthr_t *raidz_expand_thread = spa->spa_raidz_expand_zthr;
+ if (raidz_expand_thread != NULL)
+ zthr_cancel(raidz_expand_thread);
+
zthr_t *discard_thread = spa->spa_checkpoint_discard_zthr;
if (discard_thread != NULL)
zthr_cancel(discard_thread);
@@ -8343,6 +9055,10 @@ spa_async_resume(spa_t *spa)
if (condense_thread != NULL)
zthr_resume(condense_thread);
+ zthr_t *raidz_expand_thread = spa->spa_raidz_expand_zthr;
+ if (raidz_expand_thread != NULL)
+ zthr_resume(raidz_expand_thread);
+
zthr_t *discard_thread = spa->spa_checkpoint_discard_zthr;
if (discard_thread != NULL)
zthr_resume(discard_thread);
@@ -8577,6 +9293,11 @@ spa_avz_build(vdev_t *vd, uint64_t avz, dmu_tx_t *tx)
{
spa_t *spa = vd->vdev_spa;
+ if (vd->vdev_root_zap != 0 &&
+ spa_feature_is_active(spa, SPA_FEATURE_AVZ_V2)) {
+ VERIFY0(zap_add_int(spa->spa_meta_objset, avz,
+ vd->vdev_root_zap, tx));
+ }
if (vd->vdev_top_zap != 0) {
VERIFY0(zap_add_int(spa->spa_meta_objset, avz,
vd->vdev_top_zap, tx));
@@ -8737,27 +9458,14 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
while ((elem = nvlist_next_nvpair(nvp, elem))) {
uint64_t intval;
- char *strval, *fname;
+ const char *strval, *fname;
zpool_prop_t prop;
const char *propname;
+ const char *elemname = nvpair_name(elem);
zprop_type_t proptype;
spa_feature_t fid;
- switch (prop = zpool_name_to_prop(nvpair_name(elem))) {
- case ZPOOL_PROP_INVAL:
- /*
- * We checked this earlier in spa_prop_validate().
- */
- ASSERT(zpool_prop_feature(nvpair_name(elem)));
-
- fname = strchr(nvpair_name(elem), '@') + 1;
- VERIFY0(zfeature_lookup_name(fname, &fid));
-
- spa_feature_enable(spa, fid, tx);
- spa_history_log_internal(spa, "set", tx,
- "%s=enabled", nvpair_name(elem));
- break;
-
+ switch (prop = zpool_name_to_prop(elemname)) {
case ZPOOL_PROP_VERSION:
intval = fnvpair_value_uint64(elem);
/*
@@ -8800,7 +9508,7 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
}
spa_history_log_internal(spa, "set", tx,
- "%s=%s", nvpair_name(elem), strval);
+ "%s=%s", elemname, strval);
break;
case ZPOOL_PROP_COMPATIBILITY:
strval = fnvpair_value_string(elem);
@@ -8819,6 +9527,20 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
"%s=%s", nvpair_name(elem), strval);
break;
+ case ZPOOL_PROP_INVAL:
+ if (zpool_prop_feature(elemname)) {
+ fname = strchr(elemname, '@') + 1;
+ VERIFY0(zfeature_lookup_name(fname, &fid));
+
+ spa_feature_enable(spa, fid, tx);
+ spa_history_log_internal(spa, "set", tx,
+ "%s=enabled", elemname);
+ break;
+ } else if (!zfs_prop_user(elemname)) {
+ ASSERT(zpool_prop_feature(elemname));
+ break;
+ }
+ zfs_fallthrough;
default:
/*
* Set pool property values in the poolprops mos object.
@@ -8831,8 +9553,13 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
}
/* normalize the property name */
- propname = zpool_prop_to_name(prop);
- proptype = zpool_prop_get_type(prop);
+ if (prop == ZPOOL_PROP_INVAL) {
+ propname = elemname;
+ proptype = PROP_TYPE_STRING;
+ } else {
+ propname = zpool_prop_to_name(prop);
+ proptype = zpool_prop_get_type(prop);
+ }
if (nvpair_type(elem) == DATA_TYPE_STRING) {
ASSERT(proptype == PROP_TYPE_STRING);
@@ -8841,7 +9568,7 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
spa->spa_pool_props_object, propname,
1, strlen(strval) + 1, strval, tx));
spa_history_log_internal(spa, "set", tx,
- "%s=%s", nvpair_name(elem), strval);
+ "%s=%s", elemname, strval);
} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
intval = fnvpair_value_uint64(elem);
@@ -8854,38 +9581,38 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
spa->spa_pool_props_object, propname,
8, 1, &intval, tx));
spa_history_log_internal(spa, "set", tx,
- "%s=%lld", nvpair_name(elem),
+ "%s=%lld", elemname,
(longlong_t)intval);
- } else {
- ASSERT(0); /* not allowed */
- }
- switch (prop) {
- case ZPOOL_PROP_DELEGATION:
- spa->spa_delegation = intval;
- break;
- case ZPOOL_PROP_BOOTFS:
- spa->spa_bootfs = intval;
- break;
- case ZPOOL_PROP_FAILUREMODE:
- spa->spa_failmode = intval;
- break;
- case ZPOOL_PROP_AUTOTRIM:
- spa->spa_autotrim = intval;
- spa_async_request(spa,
- SPA_ASYNC_AUTOTRIM_RESTART);
- break;
- case ZPOOL_PROP_AUTOEXPAND:
- spa->spa_autoexpand = intval;
- if (tx->tx_txg != TXG_INITIAL)
+ switch (prop) {
+ case ZPOOL_PROP_DELEGATION:
+ spa->spa_delegation = intval;
+ break;
+ case ZPOOL_PROP_BOOTFS:
+ spa->spa_bootfs = intval;
+ break;
+ case ZPOOL_PROP_FAILUREMODE:
+ spa->spa_failmode = intval;
+ break;
+ case ZPOOL_PROP_AUTOTRIM:
+ spa->spa_autotrim = intval;
spa_async_request(spa,
- SPA_ASYNC_AUTOEXPAND);
- break;
- case ZPOOL_PROP_MULTIHOST:
- spa->spa_multihost = intval;
- break;
- default:
- break;
+ SPA_ASYNC_AUTOTRIM_RESTART);
+ break;
+ case ZPOOL_PROP_AUTOEXPAND:
+ spa->spa_autoexpand = intval;
+ if (tx->tx_txg != TXG_INITIAL)
+ spa_async_request(spa,
+ SPA_ASYNC_AUTOEXPAND);
+ break;
+ case ZPOOL_PROP_MULTIHOST:
+ spa->spa_multihost = intval;
+ break;
+ default:
+ break;
+ }
+ } else {
+ ASSERT(0); /* not allowed */
}
}
@@ -9123,8 +9850,10 @@ spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx)
&spa->spa_deferred_bpobj, tx);
}
+ brt_sync(spa, txg);
ddt_sync(spa, txg);
dsl_scan_sync(dp, tx);
+ dsl_errorscrub_sync(dp, tx);
svr_sync(spa, tx);
spa_sync_upgrades(spa, tx);
@@ -9135,6 +9864,27 @@ spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx)
!= NULL)
vdev_sync(vd, txg);
+ if (pass == 1) {
+ /*
+ * dsl_pool_sync() -> dp_sync_tasks may have dirtied
+ * the config. If that happens, this txg should not
+ * be a no-op. So we must sync the config to the MOS
+ * before checking for no-op.
+ *
+ * Note that when the config is dirty, it will
+ * be written to the MOS (i.e. the MOS will be
+ * dirtied) every time we call spa_sync_config_object()
+ * in this txg. Therefore we can't call this after
+ * dsl_pool_sync() every pass, because it would
+ * prevent us from converging, since we'd dirty
+ * the MOS every pass.
+ *
+ * Sync tasks can only be processed in pass 1, so
+ * there's no need to do this in later passes.
+ */
+ spa_sync_config_object(spa, tx);
+ }
+
/*
* Note: We need to check if the MOS is dirty because we could
* have marked the MOS dirty without updating the uberblock
@@ -9145,7 +9895,7 @@ spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx)
* don't want to rely on that here).
*/
if (pass == 1 &&
- spa->spa_uberblock.ub_rootbp.blk_birth < txg &&
+ BP_GET_LOGICAL_BIRTH(&spa->spa_uberblock.ub_rootbp) < txg &&
!dmu_objset_is_dirty(mos, txg)) {
/*
* Nothing changed on the first pass, therefore this
@@ -9248,6 +9998,13 @@ spa_sync(spa_t *spa, uint64_t txg)
ZIO_FLAG_CANFAIL);
/*
+ * Now that there can be no more cloning in this transaction group,
+ * but we are still before issuing frees, we can process pending BRT
+ * updates.
+ */
+ brt_pending_apply(spa, txg);
+
+ /*
* Lock out configuration changes.
*/
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
@@ -9266,7 +10023,13 @@ spa_sync(spa_t *spa, uint64_t txg)
* into config changes that go out with this transaction group.
*/
spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
- while (list_head(&spa->spa_state_dirty_list) != NULL) {
+ while ((vd = list_head(&spa->spa_state_dirty_list)) != NULL) {
+ /* Avoid holding the write lock unless actually necessary */
+ if (vd->vdev_aux == NULL) {
+ vdev_state_clean(vd);
+ vdev_config_dirty(vd);
+ continue;
+ }
/*
* We need the write lock here because, for aux vdevs,
* calling vdev_config_dirty() modifies sav_config.
@@ -9387,6 +10150,9 @@ spa_sync(spa_t *spa, uint64_t txg)
spa_update_dspace(spa);
+ if (spa_get_autotrim(spa) == SPA_AUTOTRIM_ON)
+ vdev_autotrim_kick(spa);
+
/*
* It had better be the case that we didn't dirty anything
* since vdev_config_sync().
@@ -9440,6 +10206,132 @@ spa_sync_allpools(void)
mutex_exit(&spa_namespace_lock);
}
+taskq_t *
+spa_sync_tq_create(spa_t *spa, const char *name)
+{
+ kthread_t **kthreads;
+
+ ASSERT(spa->spa_sync_tq == NULL);
+ ASSERT3S(spa->spa_alloc_count, <=, boot_ncpus);
+
+ /*
+ * - do not allow more allocators than cpus.
+ * - there may be more cpus than allocators.
+ * - do not allow more sync taskq threads than allocators or cpus.
+ */
+ int nthreads = spa->spa_alloc_count;
+ spa->spa_syncthreads = kmem_zalloc(sizeof (spa_syncthread_info_t) *
+ nthreads, KM_SLEEP);
+
+ spa->spa_sync_tq = taskq_create_synced(name, nthreads, minclsyspri,
+ nthreads, INT_MAX, TASKQ_PREPOPULATE, &kthreads);
+ VERIFY(spa->spa_sync_tq != NULL);
+ VERIFY(kthreads != NULL);
+
+ spa_syncthread_info_t *ti = spa->spa_syncthreads;
+ for (int i = 0; i < nthreads; i++, ti++) {
+ ti->sti_thread = kthreads[i];
+ ti->sti_allocator = i;
+ }
+
+ kmem_free(kthreads, sizeof (*kthreads) * nthreads);
+ return (spa->spa_sync_tq);
+}
+
+void
+spa_sync_tq_destroy(spa_t *spa)
+{
+ ASSERT(spa->spa_sync_tq != NULL);
+
+ taskq_wait(spa->spa_sync_tq);
+ taskq_destroy(spa->spa_sync_tq);
+ kmem_free(spa->spa_syncthreads,
+ sizeof (spa_syncthread_info_t) * spa->spa_alloc_count);
+ spa->spa_sync_tq = NULL;
+}
+
+uint_t
+spa_acq_allocator(spa_t *spa)
+{
+ int i;
+
+ if (spa->spa_alloc_count == 1)
+ return (0);
+
+ mutex_enter(&spa->spa_allocs_use->sau_lock);
+ uint_t r = spa->spa_allocs_use->sau_rotor;
+ do {
+ if (++r == spa->spa_alloc_count)
+ r = 0;
+ } while (spa->spa_allocs_use->sau_inuse[r]);
+ spa->spa_allocs_use->sau_inuse[r] = B_TRUE;
+ spa->spa_allocs_use->sau_rotor = r;
+ mutex_exit(&spa->spa_allocs_use->sau_lock);
+
+ spa_syncthread_info_t *ti = spa->spa_syncthreads;
+ for (i = 0; i < spa->spa_alloc_count; i++, ti++) {
+ if (ti->sti_thread == curthread) {
+ ti->sti_allocator = r;
+ break;
+ }
+ }
+ ASSERT3S(i, <, spa->spa_alloc_count);
+ return (r);
+}
+
+void
+spa_rel_allocator(spa_t *spa, uint_t allocator)
+{
+ if (spa->spa_alloc_count > 1)
+ spa->spa_allocs_use->sau_inuse[allocator] = B_FALSE;
+}
+
+void
+spa_select_allocator(zio_t *zio)
+{
+ zbookmark_phys_t *bm = &zio->io_bookmark;
+ spa_t *spa = zio->io_spa;
+
+ ASSERT(zio->io_type == ZIO_TYPE_WRITE);
+
+ /*
+ * A gang block (for example) may have inherited its parent's
+ * allocator, in which case there is nothing further to do here.
+ */
+ if (ZIO_HAS_ALLOCATOR(zio))
+ return;
+
+ ASSERT(spa != NULL);
+ ASSERT(bm != NULL);
+
+ /*
+ * First try to use an allocator assigned to the syncthread, and set
+ * the corresponding write issue taskq for the allocator.
+ * Note, we must have an open pool to do this.
+ */
+ if (spa->spa_sync_tq != NULL) {
+ spa_syncthread_info_t *ti = spa->spa_syncthreads;
+ for (int i = 0; i < spa->spa_alloc_count; i++, ti++) {
+ if (ti->sti_thread == curthread) {
+ zio->io_allocator = ti->sti_allocator;
+ return;
+ }
+ }
+ }
+
+ /*
+ * We want to try to use as many allocators as possible to help improve
+ * performance, but we also want logically adjacent IOs to be physically
+ * adjacent to improve sequential read performance. We chunk each object
+ * into 2^20 block regions, and then hash based on the objset, object,
+ * level, and region to accomplish both of these goals.
+ */
+ uint64_t hv = cityhash4(bm->zb_objset, bm->zb_object, bm->zb_level,
+ bm->zb_blkid >> 20);
+
+ zio->io_allocator = (uint_t)hv % spa->spa_alloc_count;
+}
+
/*
* ==========================================================================
* Miscellaneous routines
@@ -9778,7 +10670,8 @@ spa_activity_in_progress(spa_t *spa, zpool_wait_activity_t activity,
DSS_SCANNING);
break;
case ZPOOL_WAIT_RESILVER:
- if ((*in_progress = vdev_rebuild_active(spa->spa_root_vdev)))
+ *in_progress = vdev_rebuild_active(spa->spa_root_vdev);
+ if (*in_progress)
break;
zfs_fallthrough;
case ZPOOL_WAIT_SCRUB:
@@ -9793,6 +10686,12 @@ spa_activity_in_progress(spa_t *spa, zpool_wait_activity_t activity,
is_scrub == (activity == ZPOOL_WAIT_SCRUB));
break;
}
+ case ZPOOL_WAIT_RAIDZ_EXPAND:
+ {
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+ *in_progress = (vre != NULL && vre->vre_state == DSS_SCANNING);
+ break;
+ }
default:
panic("unrecognized value for activity %d", activity);
}
@@ -9983,8 +10882,11 @@ EXPORT_SYMBOL(spa_prop_clear_bootfs);
/* asynchronous event notification */
EXPORT_SYMBOL(spa_event_notify);
+ZFS_MODULE_PARAM(zfs_metaslab, metaslab_, preload_pct, UINT, ZMOD_RW,
+ "Percentage of CPUs to run a metaslab preload taskq");
+
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs_spa, spa_, load_verify_shift, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_spa, spa_, load_verify_shift, UINT, ZMOD_RW,
"log2 fraction of arc that can be used by inflight I/Os when "
"verifying pool during import");
/* END CSTYLED */
@@ -9998,14 +10900,14 @@ ZFS_MODULE_PARAM(zfs_spa, spa_, load_verify_data, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_spa, spa_, load_print_vdev_tree, INT, ZMOD_RW,
"Print vdev tree to zfs_dbgmsg during pool import");
-ZFS_MODULE_PARAM(zfs_zio, zio_, taskq_batch_pct, UINT, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs_zio, zio_, taskq_batch_pct, UINT, ZMOD_RW,
"Percentage of CPUs to run an IO worker thread");
-ZFS_MODULE_PARAM(zfs_zio, zio_, taskq_batch_tpq, UINT, ZMOD_RD,
+ZFS_MODULE_PARAM(zfs_zio, zio_, taskq_batch_tpq, UINT, ZMOD_RW,
"Number of threads per IO worker taskqueue");
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs, zfs_, max_missing_tvds, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_missing_tvds, U64, ZMOD_RW,
"Allow importing pool with up to this number of missing top-level "
"vdevs (in read-only mode)");
/* END CSTYLED */
@@ -10029,4 +10931,16 @@ ZFS_MODULE_PARAM(zfs_livelist_condense, zfs_livelist_condense_, new_alloc, INT,
ZMOD_RW,
"Whether extra ALLOC blkptrs were added to a livelist entry while it "
"was being condensed");
+
+#ifdef _KERNEL
+ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs_zio, zio_, taskq_read,
+ spa_taskq_read_param_set, spa_taskq_read_param_get, ZMOD_RW,
+ "Configure IO queues for read IO");
+ZFS_MODULE_VIRTUAL_PARAM_CALL(zfs_zio, zio_, taskq_write,
+ spa_taskq_write_param_set, spa_taskq_write_param_get, ZMOD_RW,
+ "Configure IO queues for write IO");
+#endif
/* END CSTYLED */
+
+ZFS_MODULE_PARAM(zfs_zio, zio_, taskq_write_tpq, UINT, ZMOD_RW,
+ "Number of CPUs per write issue taskq");
diff --git a/module/zfs/spa_checkpoint.c b/module/zfs/spa_checkpoint.c
index 7c543caaa272..1efff47f87a0 100644
--- a/module/zfs/spa_checkpoint.c
+++ b/module/zfs/spa_checkpoint.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -158,7 +158,7 @@
* amount of checkpointed data that has been freed within them while
* the pool had a checkpoint.
*/
-static unsigned long zfs_spa_discard_memory_limit = 16 * 1024 * 1024;
+static uint64_t zfs_spa_discard_memory_limit = 16 * 1024 * 1024;
int
spa_checkpoint_get_stats(spa_t *spa, pool_checkpoint_stat_t *pcs)
@@ -347,7 +347,7 @@ spa_checkpoint_discard_thread_sync(void *arg, dmu_tx_t *tx)
if (error != 0) {
zfs_panic_recover("zfs: error %lld was returned "
"while incrementally destroying the checkpoint "
- "space map of vdev %u\n",
+ "space map of vdev %llu\n",
(longlong_t)error, vd->vdev_id);
}
ASSERT0(words_after);
@@ -465,6 +465,9 @@ spa_checkpoint_check(void *arg, dmu_tx_t *tx)
if (spa->spa_removing_phys.sr_state == DSS_SCANNING)
return (SET_ERROR(ZFS_ERR_DEVRM_IN_PROGRESS));
+ if (spa->spa_raidz_expand != NULL)
+ return (SET_ERROR(ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS));
+
if (spa->spa_checkpoint_txg != 0)
return (SET_ERROR(ZFS_ERR_CHECKPOINT_EXISTS));
@@ -631,7 +634,7 @@ EXPORT_SYMBOL(spa_checkpoint_discard_thread);
EXPORT_SYMBOL(spa_checkpoint_discard_thread_check);
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs_spa, zfs_spa_, discard_memory_limit, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_spa, zfs_spa_, discard_memory_limit, U64, ZMOD_RW,
"Limit for memory used in prefetching the checkpoint space map done "
"on each vdev while discarding the checkpoint");
/* END CSTYLED */
diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c
index 4dcb9f1532f8..a77874ea0dd3 100644
--- a/module/zfs/spa_config.c
+++ b/module/zfs/spa_config.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -240,11 +240,12 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
* would be required.
*/
void
-spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent)
+spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent,
+ boolean_t postblkidevent)
{
spa_config_dirent_t *dp, *tdp;
nvlist_t *nvl;
- char *pool_name;
+ const char *pool_name;
boolean_t ccw_failure;
int error = 0;
@@ -346,6 +347,18 @@ spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent)
if (postsysevent)
spa_event_notify(target, NULL, NULL, ESC_ZFS_CONFIG_SYNC);
+
+ /*
+ * Post udev event to sync blkid information if the pool is created
+ * or a new vdev is added to the pool.
+ */
+ if ((target->spa_root_vdev) && postblkidevent) {
+ vdev_post_kobj_evt(target->spa_root_vdev);
+ for (int i = 0; i < target->spa_l2cache.sav_count; i++)
+ vdev_post_kobj_evt(target->spa_l2cache.sav_vdevs[i]);
+ for (int i = 0; i < target->spa_spares.sav_count; i++)
+ vdev_post_kobj_evt(target->spa_spares.sav_vdevs[i]);
+ }
}
/*
@@ -354,23 +367,24 @@ spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent)
* So we have to invent the ZFS_IOC_CONFIG ioctl to grab the configuration
* information for all pool visible within the zone.
*/
-nvlist_t *
-spa_all_configs(uint64_t *generation)
+int
+spa_all_configs(uint64_t *generation, nvlist_t **pools)
{
- nvlist_t *pools;
spa_t *spa = NULL;
if (*generation == spa_config_generation)
- return (NULL);
+ return (SET_ERROR(EEXIST));
- pools = fnvlist_alloc();
+ int error = mutex_enter_interruptible(&spa_namespace_lock);
+ if (error)
+ return (SET_ERROR(EINTR));
- mutex_enter(&spa_namespace_lock);
+ *pools = fnvlist_alloc();
while ((spa = spa_next(spa)) != NULL) {
if (INGLOBALZONE(curproc) ||
zone_dataset_visible(spa_name(spa), NULL)) {
mutex_enter(&spa->spa_props_lock);
- fnvlist_add_nvlist(pools, spa_name(spa),
+ fnvlist_add_nvlist(*pools, spa_name(spa),
spa->spa_config);
mutex_exit(&spa->spa_props_lock);
}
@@ -378,7 +392,7 @@ spa_all_configs(uint64_t *generation)
*generation = spa_config_generation;
mutex_exit(&spa_namespace_lock);
- return (pools);
+ return (0);
}
void
@@ -405,7 +419,7 @@ spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
unsigned long hostid = 0;
boolean_t locked = B_FALSE;
uint64_t split_guid;
- char *pool_name;
+ const char *pool_name;
if (vd == NULL) {
vd = rvd;
@@ -600,6 +614,7 @@ spa_config_update(spa_t *spa, int what)
*/
if (!spa->spa_is_root) {
spa_write_cachefile(spa, B_FALSE,
+ what != SPA_CONFIG_UPDATE_POOL,
what != SPA_CONFIG_UPDATE_POOL);
}
diff --git a/module/zfs/spa_errlog.c b/module/zfs/spa_errlog.c
index 19a3cc814b87..62d7b4fa2df2 100644
--- a/module/zfs/spa_errlog.c
+++ b/module/zfs/spa_errlog.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,7 +21,8 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2014, Delphix. All rights reserved.
- * Copyright (c) 2021, George Amanakis. All rights reserved.
+ * Copyright (c) 2019 Datto Inc.
+ * Copyright (c) 2021, 2022, George Amanakis. All rights reserved.
*/
/*
@@ -67,14 +68,22 @@
#include <sys/dsl_dir.h>
#include <sys/dmu_objset.h>
#include <sys/dbuf.h>
+#include <sys/zfs_znode.h>
+
+#define NAME_MAX_LEN 64
+
+typedef struct clones {
+ uint64_t clone_ds;
+ list_node_t node;
+} clones_t;
/*
* spa_upgrade_errlog_limit : A zfs module parameter that controls the number
- * of on-disk error log entries that will be converted to the new
- * format when enabling head_errlog. Defaults to 0 which converts
- * all log entries.
+ * of on-disk error log entries that will be converted to the new
+ * format when enabling head_errlog. Defaults to 0 which converts
+ * all log entries.
*/
-static uint32_t spa_upgrade_errlog_limit = 0;
+static uint_t spa_upgrade_errlog_limit = 0;
/*
* Convert a bookmark to a string.
@@ -101,7 +110,7 @@ errphys_to_name(zbookmark_err_phys_t *zep, char *buf, size_t len)
/*
* Convert a string to a err_phys.
*/
-static void
+void
name_to_errphys(char *buf, zbookmark_err_phys_t *zep)
{
zep->zb_object = zfs_strtonum(buf, &buf);
@@ -130,8 +139,7 @@ name_to_bookmark(char *buf, zbookmark_phys_t *zb)
ASSERT(*buf == '\0');
}
-#ifdef _KERNEL
-static void
+void
zep_to_zb(uint64_t dataset, zbookmark_err_phys_t *zep, zbookmark_phys_t *zb)
{
zb->zb_objset = dataset;
@@ -139,7 +147,6 @@ zep_to_zb(uint64_t dataset, zbookmark_err_phys_t *zep, zbookmark_phys_t *zb)
zb->zb_level = zep->zb_level;
zb->zb_blkid = zep->zb_blkid;
}
-#endif
static void
name_to_object(char *buf, uint64_t *obj)
@@ -148,52 +155,22 @@ name_to_object(char *buf, uint64_t *obj)
ASSERT(*buf == '\0');
}
-static int
-get_head_and_birth_txg(spa_t *spa, zbookmark_err_phys_t *zep, uint64_t ds_obj,
- uint64_t *head_dataset_id)
+/*
+ * Retrieve the head filesystem.
+ */
+static int get_head_ds(spa_t *spa, uint64_t dsobj, uint64_t *head_ds)
{
- dsl_pool_t *dp = spa->spa_dsl_pool;
dsl_dataset_t *ds;
- objset_t *os;
-
- dsl_pool_config_enter(dp, FTAG);
- int error = dsl_dataset_hold_obj(dp, ds_obj, FTAG, &ds);
- if (error != 0) {
- dsl_pool_config_exit(dp, FTAG);
- return (error);
- }
- ASSERT(head_dataset_id);
- *head_dataset_id = dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
-
- error = dmu_objset_from_ds(ds, &os);
- if (error != 0) {
- dsl_dataset_rele(ds, FTAG);
- dsl_pool_config_exit(dp, FTAG);
- return (error);
- }
+ int error = dsl_dataset_hold_obj_flags(spa->spa_dsl_pool,
+ dsobj, DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
- dnode_t *dn;
- blkptr_t bp;
-
- error = dnode_hold(os, zep->zb_object, FTAG, &dn);
- if (error != 0) {
- dsl_dataset_rele(ds, FTAG);
- dsl_pool_config_exit(dp, FTAG);
+ if (error != 0)
return (error);
- }
-
- rw_enter(&dn->dn_struct_rwlock, RW_READER);
- error = dbuf_dnode_findbp(dn, zep->zb_level, zep->zb_blkid, &bp, NULL,
- NULL);
- if (error == 0 && BP_IS_HOLE(&bp))
- error = SET_ERROR(ENOENT);
+ ASSERT(head_ds);
+ *head_ds = dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
- zep->zb_birth = bp.blk_birth;
- rw_exit(&dn->dn_struct_rwlock);
- dnode_rele(dn, FTAG);
- dsl_dataset_rele(ds, FTAG);
- dsl_pool_config_exit(dp, FTAG);
return (error);
}
@@ -203,7 +180,7 @@ get_head_and_birth_txg(spa_t *spa, zbookmark_err_phys_t *zep, uint64_t ds_obj,
* during spa_errlog_sync().
*/
void
-spa_log_error(spa_t *spa, const zbookmark_phys_t *zb)
+spa_log_error(spa_t *spa, const zbookmark_phys_t *zb, const uint64_t birth)
{
spa_error_entry_t search;
spa_error_entry_t *new;
@@ -236,13 +213,24 @@ spa_log_error(spa_t *spa, const zbookmark_phys_t *zb)
new = kmem_zalloc(sizeof (spa_error_entry_t), KM_SLEEP);
new->se_bookmark = *zb;
- avl_insert(tree, new, where);
+ /*
+ * If the head_errlog feature is enabled, store the birth txg now. In
+ * case the file is deleted before spa_errlog_sync() runs, we will not
+ * be able to retrieve the birth txg.
+ */
+ if (spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
+ new->se_zep.zb_object = zb->zb_object;
+ new->se_zep.zb_level = zb->zb_level;
+ new->se_zep.zb_blkid = zb->zb_blkid;
+ new->se_zep.zb_birth = birth;
+ }
+
+ avl_insert(tree, new, where);
mutex_exit(&spa->spa_errlist_lock);
}
-#ifdef _KERNEL
-static int
+int
find_birth_txg(dsl_dataset_t *ds, zbookmark_err_phys_t *zep,
uint64_t *birth_txg)
{
@@ -261,33 +249,76 @@ find_birth_txg(dsl_dataset_t *ds, zbookmark_err_phys_t *zep,
rw_enter(&dn->dn_struct_rwlock, RW_READER);
error = dbuf_dnode_findbp(dn, zep->zb_level, zep->zb_blkid, &bp, NULL,
NULL);
-
if (error == 0 && BP_IS_HOLE(&bp))
error = SET_ERROR(ENOENT);
- *birth_txg = bp.blk_birth;
+ *birth_txg = BP_GET_LOGICAL_BIRTH(&bp);
rw_exit(&dn->dn_struct_rwlock);
dnode_rele(dn, FTAG);
return (error);
}
/*
- * This function serves a double role. If only_count is true, it returns
- * (in *count) how many times an error block belonging to this filesystem is
- * referenced by snapshots or clones. If only_count is false, each time the
- * error block is referenced by a snapshot or clone, it fills the userspace
- * array at uaddr with the bookmarks of the error blocks. The array is filled
- * from the back and *count is modified to be the number of unused entries at
- * the beginning of the array.
+ * This function finds the oldest affected filesystem containing an error
+ * block.
+ */
+int
+find_top_affected_fs(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
+ uint64_t *top_affected_fs)
+{
+ uint64_t oldest_dsobj;
+ int error = dsl_dataset_oldest_snapshot(spa, head_ds, zep->zb_birth,
+ &oldest_dsobj);
+ if (error != 0)
+ return (error);
+
+ dsl_dataset_t *ds;
+ error = dsl_dataset_hold_obj_flags(spa->spa_dsl_pool, oldest_dsobj,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
+ if (error != 0)
+ return (error);
+
+ *top_affected_fs =
+ dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ return (0);
+}
+
+
+#ifdef _KERNEL
+/*
+ * Copy the bookmark to the end of the user-space buffer which starts at
+ * uaddr and has *count unused entries, and decrement *count by 1.
+ */
+static int
+copyout_entry(const zbookmark_phys_t *zb, void *uaddr, uint64_t *count)
+{
+ if (*count == 0)
+ return (SET_ERROR(ENOMEM));
+
+ *count -= 1;
+ if (copyout(zb, (char *)uaddr + (*count) * sizeof (zbookmark_phys_t),
+ sizeof (zbookmark_phys_t)) != 0)
+ return (SET_ERROR(EFAULT));
+ return (0);
+}
+
+/*
+ * Each time the error block is referenced by a snapshot or clone, add a
+ * zbookmark_phys_t entry to the userspace array at uaddr. The array is
+ * filled from the back and the in-out parameter *count is modified to be the
+ * number of unused entries at the beginning of the array. The function
+ * scrub_filesystem() is modelled after this one.
*/
static int
check_filesystem(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
- uint64_t *count, void *uaddr, boolean_t only_count)
+ void *uaddr, uint64_t *count, list_t *clones_list)
{
dsl_dataset_t *ds;
dsl_pool_t *dp = spa->spa_dsl_pool;
- int error = dsl_dataset_hold_obj(dp, head_ds, FTAG, &ds);
+ int error = dsl_dataset_hold_obj_flags(dp, head_ds,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
if (error != 0)
return (error);
@@ -295,62 +326,72 @@ check_filesystem(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
uint64_t txg_to_consider = spa->spa_syncing_txg;
boolean_t check_snapshot = B_TRUE;
error = find_birth_txg(ds, zep, &latest_txg);
- if (error == 0) {
- if (zep->zb_birth == latest_txg) {
- /* Block neither free nor rewritten. */
- if (!only_count) {
- zbookmark_phys_t zb;
- zep_to_zb(head_ds, zep, &zb);
- if (copyout(&zb, (char *)uaddr + (*count - 1)
- * sizeof (zbookmark_phys_t),
- sizeof (zbookmark_phys_t)) != 0) {
- dsl_dataset_rele(ds, FTAG);
- return (SET_ERROR(EFAULT));
- }
- (*count)--;
- } else {
- (*count)++;
- }
- check_snapshot = B_FALSE;
- } else {
- ASSERT3U(zep->zb_birth, <, latest_txg);
- txg_to_consider = latest_txg;
+
+ /*
+ * If find_birth_txg() errors out otherwise, let txg_to_consider be
+ * equal to the spa's syncing txg: if check_filesystem() errors out
+ * then affected snapshots or clones will not be checked.
+ */
+ if (error == 0 && zep->zb_birth == latest_txg) {
+ /* Block neither free nor rewritten. */
+ zbookmark_phys_t zb;
+ zep_to_zb(head_ds, zep, &zb);
+ error = copyout_entry(&zb, uaddr, count);
+ if (error != 0) {
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ return (error);
}
+ check_snapshot = B_FALSE;
+ } else if (error == 0) {
+ txg_to_consider = latest_txg;
}
- /* How many snapshots reference this block. */
- uint64_t snap_count;
- error = zap_count(spa->spa_meta_objset,
- dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
- if (error != 0) {
- dsl_dataset_rele(ds, FTAG);
- return (error);
+ /*
+ * Retrieve the number of snapshots if the dataset is not a snapshot.
+ */
+ uint64_t snap_count = 0;
+ if (dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0) {
+
+ error = zap_count(spa->spa_meta_objset,
+ dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
+
+ if (error != 0) {
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ return (error);
+ }
}
if (snap_count == 0) {
- /* File system has no snapshot. */
- dsl_dataset_rele(ds, FTAG);
+ /* Filesystem without snapshots. */
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
return (0);
}
- uint64_t *snap_obj_array = kmem_alloc(snap_count * sizeof (uint64_t),
+ uint64_t *snap_obj_array = kmem_zalloc(snap_count * sizeof (uint64_t),
KM_SLEEP);
int aff_snap_count = 0;
uint64_t snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
uint64_t snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+ uint64_t zap_clone = dsl_dir_phys(ds->ds_dir)->dd_clones;
+
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
/* Check only snapshots created from this file system. */
while (snap_obj != 0 && zep->zb_birth < snap_obj_txg &&
snap_obj_txg <= txg_to_consider) {
- dsl_dataset_rele(ds, FTAG);
- error = dsl_dataset_hold_obj(dp, snap_obj, FTAG, &ds);
+ error = dsl_dataset_hold_obj_flags(dp, snap_obj,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
if (error != 0)
goto out;
- if (dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj != head_ds)
- break;
+ if (dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj != head_ds) {
+ snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ continue;
+ }
boolean_t affected = B_TRUE;
if (check_snapshot) {
@@ -359,50 +400,71 @@ check_filesystem(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
affected = (error == 0 && zep->zb_birth == blk_txg);
}
+ /* Report errors in snapshots. */
if (affected) {
snap_obj_array[aff_snap_count] = snap_obj;
aff_snap_count++;
- if (!only_count) {
- zbookmark_phys_t zb;
- zep_to_zb(snap_obj, zep, &zb);
- if (copyout(&zb, (char *)uaddr + (*count - 1) *
- sizeof (zbookmark_phys_t),
- sizeof (zbookmark_phys_t)) != 0) {
- dsl_dataset_rele(ds, FTAG);
- error = SET_ERROR(EFAULT);
- goto out;
- }
- (*count)--;
- } else {
- (*count)++;
+ zbookmark_phys_t zb;
+ zep_to_zb(snap_obj, zep, &zb);
+ error = copyout_entry(&zb, uaddr, count);
+ if (error != 0) {
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT,
+ FTAG);
+ goto out;
}
+ }
+ snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ }
- /*
- * Only clones whose origins were affected could also
- * have affected snapshots.
- */
- zap_cursor_t zc;
- zap_attribute_t za;
- for (zap_cursor_init(&zc, spa->spa_meta_objset,
- dsl_dataset_phys(ds)->ds_next_clones_obj);
- zap_cursor_retrieve(&zc, &za) == 0;
- zap_cursor_advance(&zc)) {
- error = check_filesystem(spa,
- za.za_first_integer, zep,
- count, uaddr, only_count);
+ if (zap_clone == 0 || aff_snap_count == 0) {
+ error = 0;
+ goto out;
+ }
- if (error != 0) {
- zap_cursor_fini(&zc);
- goto out;
- }
- }
- zap_cursor_fini(&zc);
+ /* Check clones. */
+ zap_cursor_t *zc;
+ zap_attribute_t *za;
+
+ zc = kmem_zalloc(sizeof (zap_cursor_t), KM_SLEEP);
+ za = kmem_zalloc(sizeof (zap_attribute_t), KM_SLEEP);
+
+ for (zap_cursor_init(zc, spa->spa_meta_objset, zap_clone);
+ zap_cursor_retrieve(zc, za) == 0;
+ zap_cursor_advance(zc)) {
+
+ dsl_dataset_t *clone;
+ error = dsl_dataset_hold_obj_flags(dp, za->za_first_integer,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &clone);
+
+ if (error != 0)
+ break;
+
+ /*
+ * Only clones whose origins were affected could also
+ * have affected snapshots.
+ */
+ boolean_t found = B_FALSE;
+ for (int i = 0; i < snap_count; i++) {
+ if (dsl_dir_phys(clone->ds_dir)->dd_origin_obj
+ == snap_obj_array[i])
+ found = B_TRUE;
}
- snap_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
- snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
+ dsl_dataset_rele_flags(clone, DS_HOLD_FLAG_DECRYPT, FTAG);
+
+ if (!found)
+ continue;
+
+ clones_t *ct = kmem_zalloc(sizeof (*ct), KM_SLEEP);
+ ct->clone_ds = za->za_first_integer;
+ list_insert_tail(clones_list, ct);
}
- dsl_dataset_rele(ds, FTAG);
+
+ zap_cursor_fini(zc);
+ kmem_free(za, sizeof (*za));
+ kmem_free(zc, sizeof (*zc));
out:
kmem_free(snap_obj_array, sizeof (*snap_obj_array));
@@ -410,114 +472,299 @@ out:
}
static int
-find_top_affected_fs(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
- uint64_t *top_affected_fs)
+process_error_block(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
+ void *uaddr, uint64_t *count)
{
- uint64_t oldest_dsobj;
- int error = dsl_dataset_oldest_snapshot(spa, head_ds, zep->zb_birth,
- &oldest_dsobj);
- if (error != 0)
- return (error);
+ /*
+ * If zb_birth == 0 or head_ds == 0 it means we failed to retrieve the
+ * birth txg or the head filesystem of the block pointer. This may
+ * happen e.g. when an encrypted filesystem is not mounted or when
+ * the key is not loaded. In this case do not proceed to
+ * check_filesystem(), instead do the accounting here.
+ */
+ if (zep->zb_birth == 0 || head_ds == 0) {
+ zbookmark_phys_t zb;
+ zep_to_zb(head_ds, zep, &zb);
+ int error = copyout_entry(&zb, uaddr, count);
+ if (error != 0) {
+ return (error);
+ }
+ return (0);
+ }
- dsl_dataset_t *ds;
- error = dsl_dataset_hold_obj(spa->spa_dsl_pool, oldest_dsobj,
- FTAG, &ds);
- if (error != 0)
- return (error);
+ uint64_t top_affected_fs;
+ uint64_t init_count = *count;
+ int error = find_top_affected_fs(spa, head_ds, zep, &top_affected_fs);
+ if (error == 0) {
+ clones_t *ct;
+ list_t clones_list;
- *top_affected_fs =
- dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
- dsl_dataset_rele(ds, FTAG);
- return (0);
-}
+ list_create(&clones_list, sizeof (clones_t),
+ offsetof(clones_t, node));
-static int
-process_error_block(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
- uint64_t *count, void *uaddr, boolean_t only_count)
-{
- dsl_pool_t *dp = spa->spa_dsl_pool;
- dsl_pool_config_enter(dp, FTAG);
- uint64_t top_affected_fs;
+ error = check_filesystem(spa, top_affected_fs, zep,
+ uaddr, count, &clones_list);
- int error = find_top_affected_fs(spa, head_ds, zep, &top_affected_fs);
- if (error == 0)
- error = check_filesystem(spa, top_affected_fs, zep, count,
- uaddr, only_count);
+ while ((ct = list_remove_head(&clones_list)) != NULL) {
+ error = check_filesystem(spa, ct->clone_ds, zep,
+ uaddr, count, &clones_list);
+ kmem_free(ct, sizeof (*ct));
+
+ if (error) {
+ while (!list_is_empty(&clones_list)) {
+ ct = list_remove_head(&clones_list);
+ kmem_free(ct, sizeof (*ct));
+ }
+ break;
+ }
+ }
+
+ list_destroy(&clones_list);
+ }
+ if (error == 0 && init_count == *count) {
+ /*
+ * If we reach this point, no errors have been detected
+ * in the checked filesystems/snapshots. Before returning mark
+ * the error block to be removed from the error lists and logs.
+ */
+ zbookmark_phys_t zb;
+ zep_to_zb(head_ds, zep, &zb);
+ spa_remove_error(spa, &zb, zep->zb_birth);
+ }
- dsl_pool_config_exit(dp, FTAG);
return (error);
}
+#endif
-static uint64_t
-get_errlog_size(spa_t *spa, uint64_t spa_err_obj)
+/* Return the number of errors in the error log */
+uint64_t
+spa_get_last_errlog_size(spa_t *spa)
{
- if (spa_err_obj == 0)
- return (0);
- uint64_t total = 0;
+ uint64_t total = 0, count;
+ mutex_enter(&spa->spa_errlog_lock);
+
+ if (spa->spa_errlog_last != 0 &&
+ zap_count(spa->spa_meta_objset, spa->spa_errlog_last,
+ &count) == 0)
+ total += count;
+ mutex_exit(&spa->spa_errlog_lock);
+ return (total);
+}
+
+/*
+ * If a healed bookmark matches an entry in the error log we stash it in a tree
+ * so that we can later remove the related log entries in sync context.
+ */
+static void
+spa_add_healed_error(spa_t *spa, uint64_t obj, zbookmark_phys_t *healed_zb,
+ const uint64_t birth)
+{
+ char name[NAME_MAX_LEN];
+
+ if (obj == 0)
+ return;
+
+ boolean_t held_list = B_FALSE;
+ boolean_t held_log = B_FALSE;
+
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
+ bookmark_to_name(healed_zb, name, sizeof (name));
+
+ if (zap_contains(spa->spa_meta_objset, healed_zb->zb_objset,
+ name) == 0) {
+ if (!MUTEX_HELD(&spa->spa_errlog_lock)) {
+ mutex_enter(&spa->spa_errlog_lock);
+ held_log = B_TRUE;
+ }
+
+ /*
+ * Found an error matching healed zb, add zb to our
+ * tree of healed errors
+ */
+ avl_tree_t *tree = &spa->spa_errlist_healed;
+ spa_error_entry_t search;
+ spa_error_entry_t *new;
+ avl_index_t where;
+ search.se_bookmark = *healed_zb;
+ if (!MUTEX_HELD(&spa->spa_errlist_lock)) {
+ mutex_enter(&spa->spa_errlist_lock);
+ held_list = B_TRUE;
+ }
+ if (avl_find(tree, &search, &where) != NULL) {
+ if (held_list)
+ mutex_exit(&spa->spa_errlist_lock);
+ if (held_log)
+ mutex_exit(&spa->spa_errlog_lock);
+ return;
+ }
+ new = kmem_zalloc(sizeof (spa_error_entry_t), KM_SLEEP);
+ new->se_bookmark = *healed_zb;
+ avl_insert(tree, new, where);
+ if (held_list)
+ mutex_exit(&spa->spa_errlist_lock);
+ if (held_log)
+ mutex_exit(&spa->spa_errlog_lock);
+ }
+ return;
+ }
+
+ zbookmark_err_phys_t healed_zep;
+ healed_zep.zb_object = healed_zb->zb_object;
+ healed_zep.zb_level = healed_zb->zb_level;
+ healed_zep.zb_blkid = healed_zb->zb_blkid;
+ healed_zep.zb_birth = birth;
+
+ errphys_to_name(&healed_zep, name, sizeof (name));
zap_cursor_t zc;
zap_attribute_t za;
- for (zap_cursor_init(&zc, spa->spa_meta_objset, spa_err_obj);
+ for (zap_cursor_init(&zc, spa->spa_meta_objset, spa->spa_errlog_last);
zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) {
+ if (zap_contains(spa->spa_meta_objset, za.za_first_integer,
+ name) == 0) {
+ if (!MUTEX_HELD(&spa->spa_errlog_lock)) {
+ mutex_enter(&spa->spa_errlog_lock);
+ held_log = B_TRUE;
+ }
- zap_cursor_t head_ds_cursor;
- zap_attribute_t head_ds_attr;
- zbookmark_err_phys_t head_ds_block;
-
- uint64_t head_ds;
- name_to_object(za.za_name, &head_ds);
+ avl_tree_t *tree = &spa->spa_errlist_healed;
+ spa_error_entry_t search;
+ spa_error_entry_t *new;
+ avl_index_t where;
+ search.se_bookmark = *healed_zb;
- for (zap_cursor_init(&head_ds_cursor, spa->spa_meta_objset,
- za.za_first_integer); zap_cursor_retrieve(&head_ds_cursor,
- &head_ds_attr) == 0; zap_cursor_advance(&head_ds_cursor)) {
+ if (!MUTEX_HELD(&spa->spa_errlist_lock)) {
+ mutex_enter(&spa->spa_errlist_lock);
+ held_list = B_TRUE;
+ }
- name_to_errphys(head_ds_attr.za_name, &head_ds_block);
- (void) process_error_block(spa, head_ds, &head_ds_block,
- &total, NULL, B_TRUE);
+ if (avl_find(tree, &search, &where) != NULL) {
+ if (held_list)
+ mutex_exit(&spa->spa_errlist_lock);
+ if (held_log)
+ mutex_exit(&spa->spa_errlog_lock);
+ continue;
+ }
+ new = kmem_zalloc(sizeof (spa_error_entry_t), KM_SLEEP);
+ new->se_bookmark = *healed_zb;
+ new->se_zep = healed_zep;
+ avl_insert(tree, new, where);
+
+ if (held_list)
+ mutex_exit(&spa->spa_errlist_lock);
+ if (held_log)
+ mutex_exit(&spa->spa_errlog_lock);
}
- zap_cursor_fini(&head_ds_cursor);
}
zap_cursor_fini(&zc);
- return (total);
+}
+
+/*
+ * If this error exists in the given tree remove it.
+ */
+static void
+remove_error_from_list(spa_t *spa, avl_tree_t *t, const zbookmark_phys_t *zb)
+{
+ spa_error_entry_t search, *found;
+ avl_index_t where;
+
+ mutex_enter(&spa->spa_errlist_lock);
+ search.se_bookmark = *zb;
+ if ((found = avl_find(t, &search, &where)) != NULL) {
+ avl_remove(t, found);
+ kmem_free(found, sizeof (spa_error_entry_t));
+ }
+ mutex_exit(&spa->spa_errlist_lock);
+}
+
+
+/*
+ * Removes all of the recv healed errors from both on-disk error logs
+ */
+static void
+spa_remove_healed_errors(spa_t *spa, avl_tree_t *s, avl_tree_t *l, dmu_tx_t *tx)
+{
+ char name[NAME_MAX_LEN];
+ spa_error_entry_t *se;
+ void *cookie = NULL;
+
+ ASSERT(MUTEX_HELD(&spa->spa_errlog_lock));
+
+ while ((se = avl_destroy_nodes(&spa->spa_errlist_healed,
+ &cookie)) != NULL) {
+ remove_error_from_list(spa, s, &se->se_bookmark);
+ remove_error_from_list(spa, l, &se->se_bookmark);
+
+ if (!spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
+ bookmark_to_name(&se->se_bookmark, name, sizeof (name));
+ (void) zap_remove(spa->spa_meta_objset,
+ spa->spa_errlog_last, name, tx);
+ (void) zap_remove(spa->spa_meta_objset,
+ spa->spa_errlog_scrub, name, tx);
+ } else {
+ errphys_to_name(&se->se_zep, name, sizeof (name));
+ zap_cursor_t zc;
+ zap_attribute_t za;
+ for (zap_cursor_init(&zc, spa->spa_meta_objset,
+ spa->spa_errlog_last);
+ zap_cursor_retrieve(&zc, &za) == 0;
+ zap_cursor_advance(&zc)) {
+ zap_remove(spa->spa_meta_objset,
+ za.za_first_integer, name, tx);
+ }
+ zap_cursor_fini(&zc);
+
+ for (zap_cursor_init(&zc, spa->spa_meta_objset,
+ spa->spa_errlog_scrub);
+ zap_cursor_retrieve(&zc, &za) == 0;
+ zap_cursor_advance(&zc)) {
+ zap_remove(spa->spa_meta_objset,
+ za.za_first_integer, name, tx);
+ }
+ zap_cursor_fini(&zc);
+ }
+ kmem_free(se, sizeof (spa_error_entry_t));
+ }
+}
+
+/*
+ * Stash away healed bookmarks to remove them from the on-disk error logs
+ * later in spa_remove_healed_errors().
+ */
+void
+spa_remove_error(spa_t *spa, zbookmark_phys_t *zb, uint64_t birth)
+{
+ spa_add_healed_error(spa, spa->spa_errlog_last, zb, birth);
+ spa_add_healed_error(spa, spa->spa_errlog_scrub, zb, birth);
}
static uint64_t
-get_errlist_size(spa_t *spa, avl_tree_t *tree)
+approx_errlog_size_impl(spa_t *spa, uint64_t spa_err_obj)
{
- if (avl_numnodes(tree) == 0)
+ if (spa_err_obj == 0)
return (0);
uint64_t total = 0;
- spa_error_entry_t *se;
- for (se = avl_first(tree); se != NULL; se = AVL_NEXT(tree, se)) {
- zbookmark_err_phys_t zep;
- zep.zb_object = se->se_bookmark.zb_object;
- zep.zb_level = se->se_bookmark.zb_level;
- zep.zb_blkid = se->se_bookmark.zb_blkid;
-
- /*
- * If we cannot find out the head dataset and birth txg of
- * the present error block, we opt not to error out. In the
- * next pool sync this information will be retrieved by
- * sync_error_list() and written to the on-disk error log.
- */
- uint64_t head_ds_obj;
- if (get_head_and_birth_txg(spa, &zep,
- se->se_bookmark.zb_objset, &head_ds_obj) == 0)
- (void) process_error_block(spa, head_ds_obj, &zep,
- &total, NULL, B_TRUE);
+ zap_cursor_t zc;
+ zap_attribute_t za;
+ for (zap_cursor_init(&zc, spa->spa_meta_objset, spa_err_obj);
+ zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) {
+ uint64_t count;
+ if (zap_count(spa->spa_meta_objset, za.za_first_integer,
+ &count) == 0)
+ total += count;
}
+ zap_cursor_fini(&zc);
return (total);
}
-#endif
/*
- * Return the number of errors currently in the error log. This is actually the
- * sum of both the last log and the current log, since we don't know the union
- * of these logs until we reach userland.
+ * Return the approximate number of errors currently in the error log. This
+ * will be nonzero if there are some errors, but otherwise it may be more
+ * or less than the number of entries returned by spa_get_errlog().
*/
uint64_t
-spa_get_errlog_size(spa_t *spa)
+spa_approx_errlog_size(spa_t *spa)
{
uint64_t total = 0;
@@ -535,23 +782,16 @@ spa_get_errlog_size(spa_t *spa)
total += count;
mutex_exit(&spa->spa_errlog_lock);
- mutex_enter(&spa->spa_errlist_lock);
- total += avl_numnodes(&spa->spa_errlist_last);
- total += avl_numnodes(&spa->spa_errlist_scrub);
- mutex_exit(&spa->spa_errlist_lock);
} else {
-#ifdef _KERNEL
mutex_enter(&spa->spa_errlog_lock);
- total += get_errlog_size(spa, spa->spa_errlog_last);
- total += get_errlog_size(spa, spa->spa_errlog_scrub);
+ total += approx_errlog_size_impl(spa, spa->spa_errlog_last);
+ total += approx_errlog_size_impl(spa, spa->spa_errlog_scrub);
mutex_exit(&spa->spa_errlog_lock);
-
- mutex_enter(&spa->spa_errlist_lock);
- total += get_errlist_size(spa, &spa->spa_errlist_last);
- total += get_errlist_size(spa, &spa->spa_errlist_scrub);
- mutex_exit(&spa->spa_errlist_lock);
-#endif
}
+ mutex_enter(&spa->spa_errlist_lock);
+ total += avl_numnodes(&spa->spa_errlist_last);
+ total += avl_numnodes(&spa->spa_errlist_scrub);
+ mutex_exit(&spa->spa_errlist_lock);
return (total);
}
@@ -595,23 +835,23 @@ sync_upgrade_errlog(spa_t *spa, uint64_t spa_err_obj, uint64_t *newobj,
zep.zb_object = zb.zb_object;
zep.zb_level = zb.zb_level;
zep.zb_blkid = zb.zb_blkid;
+ zep.zb_birth = 0;
/*
- * We cannot use get_head_and_birth_txg() because it will
- * acquire the pool config lock, which we already have. In case
- * of an error we simply continue.
+ * In case of an error we should simply continue instead of
+ * returning prematurely. See the next comment.
*/
- uint64_t head_dataset_obj;
+ uint64_t head_ds;
dsl_pool_t *dp = spa->spa_dsl_pool;
dsl_dataset_t *ds;
objset_t *os;
- int error = dsl_dataset_hold_obj(dp, zb.zb_objset, FTAG, &ds);
+ int error = dsl_dataset_hold_obj_flags(dp, zb.zb_objset,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
if (error != 0)
continue;
- head_dataset_obj =
- dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
+ head_ds = dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj;
/*
* The objset and the dnode are required for getting the block
@@ -622,7 +862,7 @@ sync_upgrade_errlog(spa_t *spa, uint64_t spa_err_obj, uint64_t *newobj,
* truly persistent, it should re-appear after a scan.
*/
if (dmu_objset_from_ds(ds, &os) != 0) {
- dsl_dataset_rele(ds, FTAG);
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
continue;
}
@@ -630,32 +870,35 @@ sync_upgrade_errlog(spa_t *spa, uint64_t spa_err_obj, uint64_t *newobj,
blkptr_t bp;
if (dnode_hold(os, zep.zb_object, FTAG, &dn) != 0) {
- dsl_dataset_rele(ds, FTAG);
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
continue;
}
rw_enter(&dn->dn_struct_rwlock, RW_READER);
error = dbuf_dnode_findbp(dn, zep.zb_level, zep.zb_blkid, &bp,
NULL, NULL);
+ if (error == EACCES)
+ error = 0;
+ else if (!error)
+ zep.zb_birth = BP_GET_LOGICAL_BIRTH(&bp);
- zep.zb_birth = bp.blk_birth;
rw_exit(&dn->dn_struct_rwlock);
dnode_rele(dn, FTAG);
- dsl_dataset_rele(ds, FTAG);
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
if (error != 0 || BP_IS_HOLE(&bp))
continue;
uint64_t err_obj;
error = zap_lookup_int_key(spa->spa_meta_objset, *newobj,
- head_dataset_obj, &err_obj);
+ head_ds, &err_obj);
if (error == ENOENT) {
err_obj = zap_create(spa->spa_meta_objset,
DMU_OT_ERROR_LOG, DMU_OT_NONE, 0, tx);
(void) zap_update_int_key(spa->spa_meta_objset,
- *newobj, head_dataset_obj, err_obj, tx);
+ *newobj, head_ds, err_obj, tx);
}
char buf[64];
@@ -679,82 +922,109 @@ spa_upgrade_errlog(spa_t *spa, dmu_tx_t *tx)
if (spa->spa_errlog_last != 0) {
sync_upgrade_errlog(spa, spa->spa_errlog_last, &newobj, tx);
spa->spa_errlog_last = newobj;
+
+ (void) zap_update(spa->spa_meta_objset,
+ DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_ERRLOG_LAST,
+ sizeof (uint64_t), 1, &spa->spa_errlog_last, tx);
}
if (spa->spa_errlog_scrub != 0) {
sync_upgrade_errlog(spa, spa->spa_errlog_scrub, &newobj, tx);
spa->spa_errlog_scrub = newobj;
+
+ (void) zap_update(spa->spa_meta_objset,
+ DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_ERRLOG_SCRUB,
+ sizeof (uint64_t), 1, &spa->spa_errlog_scrub, tx);
}
+
mutex_exit(&spa->spa_errlog_lock);
}
#ifdef _KERNEL
/*
- * If an error block is shared by two datasets it will be counted twice. For
- * detailed message see spa_get_errlog_size() above.
+ * If an error block is shared by two datasets it will be counted twice.
*/
static int
process_error_log(spa_t *spa, uint64_t obj, void *uaddr, uint64_t *count)
{
- zap_cursor_t zc;
- zap_attribute_t za;
-
if (obj == 0)
return (0);
+ zap_cursor_t *zc;
+ zap_attribute_t *za;
+
+ zc = kmem_zalloc(sizeof (zap_cursor_t), KM_SLEEP);
+ za = kmem_zalloc(sizeof (zap_attribute_t), KM_SLEEP);
+
if (!spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
- for (zap_cursor_init(&zc, spa->spa_meta_objset, obj);
- zap_cursor_retrieve(&zc, &za) == 0;
- zap_cursor_advance(&zc)) {
+ for (zap_cursor_init(zc, spa->spa_meta_objset, obj);
+ zap_cursor_retrieve(zc, za) == 0;
+ zap_cursor_advance(zc)) {
if (*count == 0) {
- zap_cursor_fini(&zc);
+ zap_cursor_fini(zc);
+ kmem_free(zc, sizeof (*zc));
+ kmem_free(za, sizeof (*za));
return (SET_ERROR(ENOMEM));
}
zbookmark_phys_t zb;
- name_to_bookmark(za.za_name, &zb);
+ name_to_bookmark(za->za_name, &zb);
- if (copyout(&zb, (char *)uaddr +
- (*count - 1) * sizeof (zbookmark_phys_t),
- sizeof (zbookmark_phys_t)) != 0) {
- zap_cursor_fini(&zc);
- return (SET_ERROR(EFAULT));
+ int error = copyout_entry(&zb, uaddr, count);
+ if (error != 0) {
+ zap_cursor_fini(zc);
+ kmem_free(zc, sizeof (*zc));
+ kmem_free(za, sizeof (*za));
+ return (error);
}
- *count -= 1;
-
}
- zap_cursor_fini(&zc);
+ zap_cursor_fini(zc);
+ kmem_free(zc, sizeof (*zc));
+ kmem_free(za, sizeof (*za));
return (0);
}
- for (zap_cursor_init(&zc, spa->spa_meta_objset, obj);
- zap_cursor_retrieve(&zc, &za) == 0;
- zap_cursor_advance(&zc)) {
+ for (zap_cursor_init(zc, spa->spa_meta_objset, obj);
+ zap_cursor_retrieve(zc, za) == 0;
+ zap_cursor_advance(zc)) {
+
+ zap_cursor_t *head_ds_cursor;
+ zap_attribute_t *head_ds_attr;
- zap_cursor_t head_ds_cursor;
- zap_attribute_t head_ds_attr;
+ head_ds_cursor = kmem_zalloc(sizeof (zap_cursor_t), KM_SLEEP);
+ head_ds_attr = kmem_zalloc(sizeof (zap_attribute_t), KM_SLEEP);
- uint64_t head_ds_err_obj = za.za_first_integer;
+ uint64_t head_ds_err_obj = za->za_first_integer;
uint64_t head_ds;
- name_to_object(za.za_name, &head_ds);
- for (zap_cursor_init(&head_ds_cursor, spa->spa_meta_objset,
- head_ds_err_obj); zap_cursor_retrieve(&head_ds_cursor,
- &head_ds_attr) == 0; zap_cursor_advance(&head_ds_cursor)) {
+ name_to_object(za->za_name, &head_ds);
+ for (zap_cursor_init(head_ds_cursor, spa->spa_meta_objset,
+ head_ds_err_obj); zap_cursor_retrieve(head_ds_cursor,
+ head_ds_attr) == 0; zap_cursor_advance(head_ds_cursor)) {
zbookmark_err_phys_t head_ds_block;
- name_to_errphys(head_ds_attr.za_name, &head_ds_block);
+ name_to_errphys(head_ds_attr->za_name, &head_ds_block);
int error = process_error_block(spa, head_ds,
- &head_ds_block, count, uaddr, B_FALSE);
+ &head_ds_block, uaddr, count);
if (error != 0) {
- zap_cursor_fini(&head_ds_cursor);
- zap_cursor_fini(&zc);
+ zap_cursor_fini(head_ds_cursor);
+ kmem_free(head_ds_cursor,
+ sizeof (*head_ds_cursor));
+ kmem_free(head_ds_attr, sizeof (*head_ds_attr));
+
+ zap_cursor_fini(zc);
+ kmem_free(za, sizeof (*za));
+ kmem_free(zc, sizeof (*zc));
return (error);
}
}
- zap_cursor_fini(&head_ds_cursor);
+ zap_cursor_fini(head_ds_cursor);
+ kmem_free(head_ds_cursor, sizeof (*head_ds_cursor));
+ kmem_free(head_ds_attr, sizeof (*head_ds_attr));
}
- zap_cursor_fini(&zc);
+ zap_cursor_fini(zc);
+ kmem_free(za, sizeof (*za));
+ kmem_free(zc, sizeof (*zc));
return (0);
}
@@ -766,34 +1036,30 @@ process_error_list(spa_t *spa, avl_tree_t *list, void *uaddr, uint64_t *count)
if (!spa_feature_is_enabled(spa, SPA_FEATURE_HEAD_ERRLOG)) {
for (se = avl_first(list); se != NULL;
se = AVL_NEXT(list, se)) {
-
- if (*count == 0)
- return (SET_ERROR(ENOMEM));
-
- if (copyout(&se->se_bookmark, (char *)uaddr +
- (*count - 1) * sizeof (zbookmark_phys_t),
- sizeof (zbookmark_phys_t)) != 0)
- return (SET_ERROR(EFAULT));
-
- *count -= 1;
+ int error =
+ copyout_entry(&se->se_bookmark, uaddr, count);
+ if (error != 0) {
+ return (error);
+ }
}
return (0);
}
for (se = avl_first(list); se != NULL; se = AVL_NEXT(list, se)) {
- zbookmark_err_phys_t zep;
- zep.zb_object = se->se_bookmark.zb_object;
- zep.zb_level = se->se_bookmark.zb_level;
- zep.zb_blkid = se->se_bookmark.zb_blkid;
+ uint64_t head_ds = 0;
+ int error = get_head_ds(spa, se->se_bookmark.zb_objset,
+ &head_ds);
- uint64_t head_ds_obj;
- int error = get_head_and_birth_txg(spa, &zep,
- se->se_bookmark.zb_objset, &head_ds_obj);
+ /*
+ * If get_head_ds() errors out, set the head filesystem
+ * to the filesystem stored in the bookmark of the
+ * error block.
+ */
if (error != 0)
- return (error);
+ head_ds = se->se_bookmark.zb_objset;
- error = process_error_block(spa, head_ds_obj, &zep, count,
- uaddr, B_FALSE);
+ error = process_error_block(spa, head_ds,
+ &se->se_zep, uaddr, count);
if (error != 0)
return (error);
}
@@ -818,6 +1084,13 @@ spa_get_errlog(spa_t *spa, void *uaddr, uint64_t *count)
int ret = 0;
#ifdef _KERNEL
+ /*
+ * The pool config lock is needed to hold a dataset_t via (among other
+ * places) process_error_list() -> process_error_block()->
+ * find_top_affected_fs(), and lock ordering requires that we get it
+ * before the spa_errlog_lock.
+ */
+ dsl_pool_config_enter(spa->spa_dsl_pool, FTAG);
mutex_enter(&spa->spa_errlog_lock);
ret = process_error_log(spa, spa->spa_errlog_scrub, uaddr, count);
@@ -836,6 +1109,7 @@ spa_get_errlog(spa_t *spa, void *uaddr, uint64_t *count)
mutex_exit(&spa->spa_errlist_lock);
mutex_exit(&spa->spa_errlog_lock);
+ dsl_pool_config_exit(spa->spa_dsl_pool, FTAG);
#else
(void) spa, (void) uaddr, (void) count;
#endif
@@ -887,7 +1161,7 @@ void
sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
{
spa_error_entry_t *se;
- char buf[64];
+ char buf[NAME_MAX_LEN];
void *cookie;
if (avl_numnodes(t) == 0)
@@ -910,33 +1184,33 @@ sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
} else {
for (se = avl_first(t); se != NULL; se = AVL_NEXT(t, se)) {
zbookmark_err_phys_t zep;
- zep.zb_object = se->se_bookmark.zb_object;
- zep.zb_level = se->se_bookmark.zb_level;
- zep.zb_blkid = se->se_bookmark.zb_blkid;
+ zep.zb_object = se->se_zep.zb_object;
+ zep.zb_level = se->se_zep.zb_level;
+ zep.zb_blkid = se->se_zep.zb_blkid;
+ zep.zb_birth = se->se_zep.zb_birth;
+
+ uint64_t head_ds = 0;
+ int error = get_head_ds(spa, se->se_bookmark.zb_objset,
+ &head_ds);
/*
- * If we cannot find out the head dataset and birth txg
- * of the present error block, we simply continue.
- * Reinserting that error block to the error lists,
- * even if we are not syncing the final txg, results
- * in duplicate posting of errors.
+ * If get_head_ds() errors out, set the head filesystem
+ * to the filesystem stored in the bookmark of the
+ * error block.
*/
- uint64_t head_dataset_obj;
- int error = get_head_and_birth_txg(spa, &zep,
- se->se_bookmark.zb_objset, &head_dataset_obj);
if (error != 0)
- continue;
+ head_ds = se->se_bookmark.zb_objset;
uint64_t err_obj;
error = zap_lookup_int_key(spa->spa_meta_objset,
- *obj, head_dataset_obj, &err_obj);
+ *obj, head_ds, &err_obj);
if (error == ENOENT) {
err_obj = zap_create(spa->spa_meta_objset,
DMU_OT_ERROR_LOG, DMU_OT_NONE, 0, tx);
(void) zap_update_int_key(spa->spa_meta_objset,
- *obj, head_dataset_obj, err_obj, tx);
+ *obj, head_ds, err_obj, tx);
}
errphys_to_name(&zep, buf, sizeof (buf));
@@ -992,6 +1266,7 @@ spa_errlog_sync(spa_t *spa, uint64_t txg)
*/
if (avl_numnodes(&spa->spa_errlist_scrub) == 0 &&
avl_numnodes(&spa->spa_errlist_last) == 0 &&
+ avl_numnodes(&spa->spa_errlist_healed) == 0 &&
!spa->spa_scrub_finished) {
mutex_exit(&spa->spa_errlist_lock);
return;
@@ -1002,11 +1277,23 @@ spa_errlog_sync(spa_t *spa, uint64_t txg)
spa->spa_scrub_finished = B_FALSE;
mutex_exit(&spa->spa_errlist_lock);
+
+ /*
+ * The pool config lock is needed to hold a dataset_t via
+ * sync_error_list() -> get_head_ds(), and lock ordering
+ * requires that we get it before the spa_errlog_lock.
+ */
+ dsl_pool_config_enter(spa->spa_dsl_pool, FTAG);
mutex_enter(&spa->spa_errlog_lock);
tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
/*
+ * Remove healed errors from errors.
+ */
+ spa_remove_healed_errors(spa, &last, &scrub, tx);
+
+ /*
* Sync out the current list of errors.
*/
sync_error_list(spa, &last, &spa->spa_errlog_last, tx);
@@ -1041,6 +1328,7 @@ spa_errlog_sync(spa_t *spa, uint64_t txg)
dmu_tx_commit(tx);
mutex_exit(&spa->spa_errlog_lock);
+ dsl_pool_config_exit(spa->spa_dsl_pool, FTAG);
}
static void
@@ -1083,7 +1371,8 @@ find_txg_ancestor_snapshot(spa_t *spa, uint64_t new_head, uint64_t old_head,
dsl_dataset_t *ds;
dsl_pool_t *dp = spa->spa_dsl_pool;
- int error = dsl_dataset_hold_obj(dp, old_head, FTAG, &ds);
+ int error = dsl_dataset_hold_obj_flags(dp, old_head,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds);
if (error != 0)
return (error);
@@ -1091,9 +1380,9 @@ find_txg_ancestor_snapshot(spa_t *spa, uint64_t new_head, uint64_t old_head,
uint64_t prev_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
while (prev_obj != 0) {
- dsl_dataset_rele(ds, FTAG);
- if ((error = dsl_dataset_hold_obj(dp, prev_obj,
- FTAG, &ds)) == 0 &&
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
+ if ((error = dsl_dataset_hold_obj_flags(dp, prev_obj,
+ DS_HOLD_FLAG_DECRYPT, FTAG, &ds)) == 0 &&
dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj == new_head)
break;
@@ -1103,7 +1392,7 @@ find_txg_ancestor_snapshot(spa_t *spa, uint64_t new_head, uint64_t old_head,
prev_obj_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg;
prev_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj;
}
- dsl_dataset_rele(ds, FTAG);
+ dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
ASSERT(prev_obj != 0);
*txg = prev_obj_txg;
return (0);
@@ -1177,7 +1466,8 @@ spa_swap_errlog(spa_t *spa, uint64_t new_head_ds, uint64_t old_head_ds,
#if defined(_KERNEL)
/* error handling */
EXPORT_SYMBOL(spa_log_error);
-EXPORT_SYMBOL(spa_get_errlog_size);
+EXPORT_SYMBOL(spa_approx_errlog_size);
+EXPORT_SYMBOL(spa_get_last_errlog_size);
EXPORT_SYMBOL(spa_get_errlog);
EXPORT_SYMBOL(spa_errlog_rotate);
EXPORT_SYMBOL(spa_errlog_drain);
@@ -1187,10 +1477,14 @@ EXPORT_SYMBOL(spa_delete_dataset_errlog);
EXPORT_SYMBOL(spa_swap_errlog);
EXPORT_SYMBOL(sync_error_list);
EXPORT_SYMBOL(spa_upgrade_errlog);
+EXPORT_SYMBOL(find_top_affected_fs);
+EXPORT_SYMBOL(find_birth_txg);
+EXPORT_SYMBOL(zep_to_zb);
+EXPORT_SYMBOL(name_to_errphys);
#endif
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs_spa, spa_, upgrade_errlog_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_spa, spa_, upgrade_errlog_limit, UINT, ZMOD_RW,
"Limit the number of errors which will be upgraded to the new "
"on-disk error log when enabling head_errlog");
/* END CSTYLED */
diff --git a/module/zfs/spa_history.c b/module/zfs/spa_history.c
index c0e0d8eeee68..de036d6c3718 100644
--- a/module/zfs/spa_history.c
+++ b/module/zfs/spa_history.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -199,7 +199,7 @@ spa_history_log_notify(spa_t *spa, nvlist_t *nvl)
{
nvlist_t *hist_nvl = fnvlist_alloc();
uint64_t uint64;
- char *string;
+ const char *string;
if (nvlist_lookup_string(nvl, ZPOOL_HIST_CMD, &string) == 0)
fnvlist_add_string(hist_nvl, ZFS_EV_HIST_CMD, string);
diff --git a/module/zfs/spa_log_spacemap.c b/module/zfs/spa_log_spacemap.c
index c5a1039bd838..32158e8c592c 100644
--- a/module/zfs/spa_log_spacemap.c
+++ b/module/zfs/spa_log_spacemap.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -188,13 +188,13 @@ static const unsigned long zfs_log_sm_blksz = 1ULL << 17;
* (thus the _ppm suffix; reads as "parts per million"). As an example,
* the default of 1000 allows 0.1% of memory to be used.
*/
-static unsigned long zfs_unflushed_max_mem_ppm = 1000;
+static uint64_t zfs_unflushed_max_mem_ppm = 1000;
/*
* Specific hard-limit in memory that ZFS allows to be used for
* unflushed changes.
*/
-static unsigned long zfs_unflushed_max_mem_amt = 1ULL << 30;
+static uint64_t zfs_unflushed_max_mem_amt = 1ULL << 30;
/*
* The following tunable determines the number of blocks that can be used for
@@ -243,33 +243,33 @@ static unsigned long zfs_unflushed_max_mem_amt = 1ULL << 30;
* provide upper and lower bounds for the log block limit.
* [see zfs_unflushed_log_block_{min,max}]
*/
-static unsigned long zfs_unflushed_log_block_pct = 400;
+static uint_t zfs_unflushed_log_block_pct = 400;
/*
* If the number of metaslabs is small and our incoming rate is high, we could
* get into a situation that we are flushing all our metaslabs every TXG. Thus
* we always allow at least this many log blocks.
*/
-static unsigned long zfs_unflushed_log_block_min = 1000;
+static uint64_t zfs_unflushed_log_block_min = 1000;
/*
* If the log becomes too big, the import time of the pool can take a hit in
* terms of performance. Thus we have a hard limit in the size of the log in
* terms of blocks.
*/
-static unsigned long zfs_unflushed_log_block_max = (1ULL << 17);
+static uint64_t zfs_unflushed_log_block_max = (1ULL << 17);
/*
* Also we have a hard limit in the size of the log in terms of dirty TXGs.
*/
-static unsigned long zfs_unflushed_log_txg_max = 1000;
+static uint64_t zfs_unflushed_log_txg_max = 1000;
/*
* Max # of rows allowed for the log_summary. The tradeoff here is accuracy and
* stability of the flushing algorithm (longer summary) vs its runtime overhead
* (smaller summary is faster to traverse).
*/
-static unsigned long zfs_max_logsm_summary_length = 10;
+static uint64_t zfs_max_logsm_summary_length = 10;
/*
* Tunable that sets the lower bound on the metaslabs to flush every TXG.
@@ -282,7 +282,7 @@ static unsigned long zfs_max_logsm_summary_length = 10;
* The point of this tunable is to be used in extreme cases where we really
* want to flush more metaslabs than our adaptable heuristic plans to flush.
*/
-static unsigned long zfs_min_metaslabs_to_flush = 1;
+static uint64_t zfs_min_metaslabs_to_flush = 1;
/*
* Tunable that specifies how far in the past do we want to look when trying to
@@ -293,7 +293,7 @@ static unsigned long zfs_min_metaslabs_to_flush = 1;
* average over all the blocks that we walk
* [see spa_estimate_incoming_log_blocks].
*/
-static unsigned long zfs_max_log_walking = 5;
+static uint64_t zfs_max_log_walking = 5;
/*
* This tunable exists solely for testing purposes. It ensures that the log
@@ -507,6 +507,7 @@ void
spa_log_summary_decrement_blkcount(spa_t *spa, uint64_t blocks_gone)
{
log_summary_entry_t *e = list_head(&spa->spa_log_summary);
+ ASSERT3P(e, !=, NULL);
if (e->lse_txgcount > 0)
e->lse_txgcount--;
for (; e != NULL; e = list_head(&spa->spa_log_summary)) {
@@ -690,7 +691,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;
@@ -781,7 +783,7 @@ spa_flush_metaslabs(spa_t *spa, dmu_tx_t *tx)
* request of flushing everything before we attempt to return
* immediately.
*/
- if (spa->spa_uberblock.ub_rootbp.blk_birth < txg &&
+ if (BP_GET_LOGICAL_BIRTH(&spa->spa_uberblock.ub_rootbp) < txg &&
!dmu_objset_is_dirty(spa_meta_objset(spa), txg) &&
!spa_flush_all_logs_requested(spa))
return;
@@ -1145,12 +1147,13 @@ spa_ld_log_sm_data(spa_t *spa)
/* Prefetch log spacemaps dnodes. */
for (sls = avl_first(&spa->spa_sm_logs_by_txg); sls;
sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls)) {
- dmu_prefetch(spa_meta_objset(spa), sls->sls_sm_obj,
- 0, 0, 0, ZIO_PRIORITY_SYNC_READ);
+ dmu_prefetch_dnode(spa_meta_objset(spa), sls->sls_sm_obj,
+ ZIO_PRIORITY_SYNC_READ);
}
uint_t pn = 0;
uint64_t ps = 0;
+ uint64_t nsm = 0;
psls = sls = avl_first(&spa->spa_sm_logs_by_txg);
while (sls != NULL) {
/* Prefetch log spacemaps up to 16 TXGs or MBs ahead. */
@@ -1176,13 +1179,17 @@ spa_ld_log_sm_data(spa_t *spa)
}
/* Load TXG log spacemap into ms_unflushed_allocs/frees. */
- cond_resched();
+ kpreempt(KPREEMPT_SYNC);
ASSERT0(sls->sls_nblocks);
sls->sls_nblocks = space_map_nblocks(sls->sls_sm);
spa->spa_unflushed_stats.sus_nblocks += sls->sls_nblocks;
summary_add_data(spa, sls->sls_txg,
sls->sls_mscount, 0, sls->sls_nblocks);
+ spa_import_progress_set_notes_nolog(spa,
+ "Read %llu of %lu log space maps", (u_longlong_t)nsm,
+ avl_numnodes(&spa->spa_sm_logs_by_txg));
+
struct spa_ld_log_sm_arg vla = {
.slls_spa = spa,
.slls_txg = sls->sls_txg
@@ -1198,6 +1205,7 @@ spa_ld_log_sm_data(spa_t *spa)
pn--;
ps -= space_map_length(sls->sls_sm);
+ nsm++;
space_map_close(sls->sls_sm);
sls->sls_sm = NULL;
sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls);
@@ -1208,11 +1216,11 @@ spa_ld_log_sm_data(spa_t *spa)
hrtime_t read_logs_endtime = gethrtime();
spa_load_note(spa,
- "read %llu log space maps (%llu total blocks - blksz = %llu bytes) "
- "in %lld ms", (u_longlong_t)avl_numnodes(&spa->spa_sm_logs_by_txg),
+ "Read %lu log space maps (%llu total blocks - blksz = %llu bytes) "
+ "in %lld ms", avl_numnodes(&spa->spa_sm_logs_by_txg),
(u_longlong_t)spa_log_sm_nblocks(spa),
(u_longlong_t)zfs_log_sm_blksz,
- (longlong_t)((read_logs_endtime - read_logs_starttime) / 1000000));
+ (longlong_t)NSEC2MSEC(read_logs_endtime - read_logs_starttime));
out:
if (error != 0) {
@@ -1356,34 +1364,34 @@ spa_ld_log_spacemaps(spa_t *spa)
}
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_max_mem_amt, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_max_mem_amt, U64, ZMOD_RW,
"Specific hard-limit in memory that ZFS allows to be used for "
"unflushed changes");
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_max_mem_ppm, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_max_mem_ppm, U64, ZMOD_RW,
"Percentage of the overall system memory that ZFS allows to be "
"used for unflushed changes (value is calculated over 1000000 for "
"finer granularity)");
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_max, U64, ZMOD_RW,
"Hard limit (upper-bound) in the size of the space map log "
"in terms of blocks.");
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_min, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_min, U64, ZMOD_RW,
"Lower-bound limit for the maximum amount of blocks allowed in "
"log spacemap (see zfs_unflushed_log_block_max)");
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_txg_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_txg_max, U64, ZMOD_RW,
"Hard limit (upper-bound) in the size of the space map log "
"in terms of dirty TXGs.");
-ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_pct, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, unflushed_log_block_pct, UINT, ZMOD_RW,
"Tunable used to determine the number of blocks that can be used for "
"the spacemap log, expressed as a percentage of the total number of "
"metaslabs in the pool (e.g. 400 means the number of log blocks is "
"capped at 4 times the number of metaslabs)");
-ZFS_MODULE_PARAM(zfs, zfs_, max_log_walking, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_log_walking, U64, ZMOD_RW,
"The number of past TXGs that the flushing algorithm of the log "
"spacemap feature uses to estimate incoming log blocks");
@@ -1392,8 +1400,8 @@ ZFS_MODULE_PARAM(zfs, zfs_, keep_log_spacemaps_at_export, INT, ZMOD_RW,
"during pool export/destroy");
/* END CSTYLED */
-ZFS_MODULE_PARAM(zfs, zfs_, max_logsm_summary_length, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_logsm_summary_length, U64, ZMOD_RW,
"Maximum number of rows allowed in the summary of the spacemap log");
-ZFS_MODULE_PARAM(zfs, zfs_, min_metaslabs_to_flush, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, min_metaslabs_to_flush, U64, ZMOD_RW,
"Minimum number of metaslabs to flush per dirty TXG");
diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c
index 2ae45e169ebe..e6d4a9bdb29c 100644
--- a/module/zfs/spa_misc.c
+++ b/module/zfs/spa_misc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,13 +20,14 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright 2013 Saso Kiselkov. All rights reserved.
* Copyright (c) 2017 Datto Inc.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+ * Copyright (c) 2023, Klara Inc.
*/
#include <sys/zfs_context.h>
@@ -57,6 +58,7 @@
#include <sys/fs/zfs.h>
#include <sys/metaslab_impl.h>
#include <sys/arc.h>
+#include <sys/brt.h>
#include <sys/ddt.h>
#include <sys/kstat.h>
#include "zfs_prop.h"
@@ -80,7 +82,8 @@
* - Check if spa_refcount is zero
* - Rename a spa_t
* - add/remove/attach/detach devices
- * - Held for the duration of create/destroy/import/export
+ * - Held for the duration of create/destroy/export
+ * - Held at the start and end of import
*
* It does not need to handle recursion. A create or destroy may
* reference objects (files or zvols) in other pools, but by
@@ -233,9 +236,9 @@
* locking is, always, based on spa_namespace_lock and spa_config_lock[].
*/
-static avl_tree_t spa_namespace_avl;
+avl_tree_t spa_namespace_avl;
kmutex_t spa_namespace_lock;
-static kcondvar_t spa_namespace_cv;
+kcondvar_t spa_namespace_cv;
static const int spa_max_replication_override = SPA_DVAS_PER_BP;
static kmutex_t spa_spare_lock;
@@ -304,20 +307,20 @@ int zfs_free_leak_on_eio = B_FALSE;
* has not completed in zfs_deadman_synctime_ms is considered "hung" resulting
* in one of three behaviors controlled by zfs_deadman_failmode.
*/
-unsigned long zfs_deadman_synctime_ms = 600000UL; /* 10 min. */
+uint64_t zfs_deadman_synctime_ms = 600000UL; /* 10 min. */
/*
* This value controls the maximum amount of time zio_wait() will block for an
* outstanding IO. By default this is 300 seconds at which point the "hung"
* behavior will be applied as described for zfs_deadman_synctime_ms.
*/
-unsigned long zfs_deadman_ziotime_ms = 300000UL; /* 5 min. */
+uint64_t zfs_deadman_ziotime_ms = 300000UL; /* 5 min. */
/*
* Check time in milliseconds. This defines the frequency at which we check
* for hung I/O.
*/
-unsigned long zfs_deadman_checktime_ms = 60000UL; /* 1 min. */
+uint64_t zfs_deadman_checktime_ms = 60000UL; /* 1 min. */
/*
* By default the deadman is enabled.
@@ -343,7 +346,7 @@ const char *zfs_deadman_failmode = "wait";
* the worst case is:
* (VDEV_RAIDZ_MAXPARITY + 1) * SPA_DVAS_PER_BP * 2 == 24
*/
-int spa_asize_inflation = 24;
+uint_t spa_asize_inflation = 24;
/*
* Normally, we don't allow the last 3.2% (1/(2^spa_slop_shift)) of space in
@@ -383,11 +386,21 @@ int spa_asize_inflation = 24;
*
* See also the comments in zfs_space_check_t.
*/
-int spa_slop_shift = 5;
+uint_t spa_slop_shift = 5;
static const uint64_t spa_min_slop = 128ULL * 1024 * 1024;
static const uint64_t spa_max_slop = 128ULL * 1024 * 1024 * 1024;
-static const int spa_allocators = 4;
+/*
+ * Number of allocators to use, per spa instance
+ */
+static int spa_num_allocators = 4;
+static int spa_cpus_per_allocator = 4;
+
+/*
+ * Spa active allocator.
+ * Valid values are zfs_active_allocator=<dynamic|cursor|new-dynamic>.
+ */
+const char *zfs_active_allocator = "dynamic";
void
spa_load_failed(spa_t *spa, const char *fmt, ...)
@@ -415,6 +428,8 @@ spa_load_note(spa_t *spa, const char *fmt, ...)
zfs_dbgmsg("spa_load(%s, config %s): %s", spa->spa_name,
spa->spa_trust_config ? "trusted" : "untrusted", buf);
+
+ spa_import_progress_set_notes_nolog(spa, "%s", buf);
}
/*
@@ -428,7 +443,7 @@ static int zfs_user_indirect_is_special = B_TRUE;
* Once we allocate 100 - zfs_special_class_metadata_reserve_pct we only
* let metadata into the class.
*/
-static int zfs_special_class_metadata_reserve_pct = 25;
+static uint_t zfs_special_class_metadata_reserve_pct = 25;
/*
* ==========================================================================
@@ -492,8 +507,9 @@ spa_config_tryenter(spa_t *spa, int locks, const void *tag, krw_t rw)
return (1);
}
-void
-spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
+static void
+spa_config_enter_impl(spa_t *spa, int locks, const void *tag, krw_t rw,
+ int mmp_flag)
{
(void) tag;
int wlocks_held = 0;
@@ -508,7 +524,8 @@ spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
continue;
mutex_enter(&scl->scl_lock);
if (rw == RW_READER) {
- while (scl->scl_writer || scl->scl_write_wanted) {
+ while (scl->scl_writer ||
+ (!mmp_flag && scl->scl_write_wanted)) {
cv_wait(&scl->scl_cv, &scl->scl_lock);
}
} else {
@@ -527,6 +544,27 @@ spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
}
void
+spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
+{
+ spa_config_enter_impl(spa, locks, tag, rw, 0);
+}
+
+/*
+ * The spa_config_enter_mmp() allows the mmp thread to cut in front of
+ * outstanding write lock requests. This is needed since the mmp updates are
+ * time sensitive and failure to service them promptly will result in a
+ * suspended pool. This pool suspension has been seen in practice when there is
+ * a single disk in a pool that is responding slowly and presumably about to
+ * fail.
+ */
+
+void
+spa_config_enter_mmp(spa_t *spa, int locks, const void *tag, krw_t rw)
+{
+ spa_config_enter_impl(spa, locks, tag, rw, 1);
+}
+
+void
spa_config_exit(spa_t *spa, int locks, const void *tag)
{
(void) tag;
@@ -583,6 +621,7 @@ spa_lookup(const char *name)
ASSERT(MUTEX_HELD(&spa_namespace_lock));
+retry:
(void) strlcpy(search.spa_name, name, sizeof (search.spa_name));
/*
@@ -594,6 +633,14 @@ spa_lookup(const char *name)
*cp = '\0';
spa = avl_find(&spa_namespace_avl, &search, &where);
+ if (spa == NULL)
+ return (NULL);
+
+ if (spa->spa_load_thread != NULL &&
+ spa->spa_load_thread != curthread) {
+ cv_wait(&spa_namespace_cv, &spa_namespace_lock);
+ goto retry;
+ }
return (spa);
}
@@ -686,11 +733,13 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
spa->spa_deadman_synctime = MSEC2NSEC(zfs_deadman_synctime_ms);
spa->spa_deadman_ziotime = MSEC2NSEC(zfs_deadman_ziotime_ms);
spa_set_deadman_failmode(spa, zfs_deadman_failmode);
+ spa_set_allocator(spa, zfs_active_allocator);
zfs_refcount_create(&spa->spa_refcount);
spa_config_lock_init(spa);
spa_stats_init(spa);
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
avl_add(&spa_namespace_avl, spa);
/*
@@ -699,15 +748,25 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
if (altroot)
spa->spa_root = spa_strdup(altroot);
- spa->spa_alloc_count = spa_allocators;
+ /* Do not allow more allocators than fraction of CPUs. */
+ spa->spa_alloc_count = MAX(MIN(spa_num_allocators,
+ boot_ncpus / MAX(spa_cpus_per_allocator, 1)), 1);
+
spa->spa_allocs = kmem_zalloc(spa->spa_alloc_count *
sizeof (spa_alloc_t), KM_SLEEP);
for (int i = 0; i < spa->spa_alloc_count; i++) {
mutex_init(&spa->spa_allocs[i].spaa_lock, NULL, MUTEX_DEFAULT,
NULL);
avl_create(&spa->spa_allocs[i].spaa_tree, zio_bookmark_compare,
- sizeof (zio_t), offsetof(zio_t, io_alloc_node));
+ sizeof (zio_t), offsetof(zio_t, io_queue_node.a));
}
+ if (spa->spa_alloc_count > 1) {
+ spa->spa_allocs_use = kmem_zalloc(offsetof(spa_allocs_use_t,
+ sau_inuse[spa->spa_alloc_count]), KM_SLEEP);
+ mutex_init(&spa->spa_allocs_use->sau_lock, NULL, MUTEX_DEFAULT,
+ NULL);
+ }
+
avl_create(&spa->spa_metaslabs_by_flushed, metaslab_sort_by_flushed,
sizeof (metaslab_t), offsetof(metaslab_t, ms_spa_txg_node));
avl_create(&spa->spa_sm_logs_by_txg, spa_log_sm_sort_by_txg,
@@ -748,6 +807,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
spa->spa_min_ashift = INT_MAX;
spa->spa_max_ashift = 0;
spa->spa_min_alloc = INT_MAX;
+ spa->spa_gcd_alloc = INT_MAX;
/* Reset cached value */
spa->spa_dedup_dspace = ~0ULL;
@@ -785,13 +845,11 @@ spa_remove(spa_t *spa)
nvlist_free(spa->spa_config_splitting);
avl_remove(&spa_namespace_avl, spa);
- cv_broadcast(&spa_namespace_cv);
if (spa->spa_root)
spa_strfree(spa->spa_root);
- while ((dp = list_head(&spa->spa_config_list)) != NULL) {
- list_remove(&spa->spa_config_list, dp);
+ while ((dp = list_remove_head(&spa->spa_config_list)) != NULL) {
if (dp->scd_path != NULL)
spa_strfree(dp->scd_path);
kmem_free(dp, sizeof (spa_config_dirent_t));
@@ -803,6 +861,11 @@ spa_remove(spa_t *spa)
}
kmem_free(spa->spa_allocs, spa->spa_alloc_count *
sizeof (spa_alloc_t));
+ if (spa->spa_alloc_count > 1) {
+ mutex_destroy(&spa->spa_allocs_use->sau_lock);
+ kmem_free(spa->spa_allocs_use, offsetof(spa_allocs_use_t,
+ sau_inuse[spa->spa_alloc_count]));
+ }
avl_destroy(&spa->spa_metaslabs_by_flushed);
avl_destroy(&spa->spa_sm_logs_by_txg);
@@ -880,7 +943,8 @@ void
spa_open_ref(spa_t *spa, const void *tag)
{
ASSERT(zfs_refcount_count(&spa->spa_refcount) >= spa->spa_minref ||
- MUTEX_HELD(&spa_namespace_lock));
+ MUTEX_HELD(&spa_namespace_lock) ||
+ spa->spa_load_thread == curthread);
(void) zfs_refcount_add(&spa->spa_refcount, tag);
}
@@ -892,7 +956,8 @@ void
spa_close(spa_t *spa, const void *tag)
{
ASSERT(zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref ||
- MUTEX_HELD(&spa_namespace_lock));
+ MUTEX_HELD(&spa_namespace_lock) ||
+ spa->spa_load_thread == curthread);
(void) zfs_refcount_remove(&spa->spa_refcount, tag);
}
@@ -1290,7 +1355,7 @@ spa_vdev_config_exit(spa_t *spa, vdev_t *vd, uint64_t txg, int error,
* If the config changed, update the config cache.
*/
if (config_changed)
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_TRUE);
}
/*
@@ -1385,7 +1450,7 @@ spa_vdev_state_exit(spa_t *spa, vdev_t *vd, int error)
*/
if (config_changed) {
mutex_enter(&spa_namespace_lock);
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE);
mutex_exit(&spa_namespace_lock);
}
@@ -1536,7 +1601,7 @@ snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp)
compress = zio_compress_table[BP_GET_COMPRESS(bp)].ci_name;
}
- SNPRINTF_BLKPTR(snprintf, ' ', buf, buflen, bp, type, checksum,
+ SNPRINTF_BLKPTR(kmem_scnprintf, ' ', buf, buflen, bp, type, checksum,
compress);
}
@@ -1654,10 +1719,10 @@ spa_altroot(spa_t *spa, char *buf, size_t buflen)
if (spa->spa_root == NULL)
buf[0] = '\0';
else
- (void) strncpy(buf, spa->spa_root, buflen);
+ (void) strlcpy(buf, spa->spa_root, buflen);
}
-int
+uint32_t
spa_sync_pass(spa_t *spa)
{
return (spa->spa_sync_pass);
@@ -1797,7 +1862,8 @@ spa_get_slop_space(spa_t *spa)
* deduplicated data, so since it's not useful to reserve more
* space with more deduplicated data, we subtract that out here.
*/
- space = spa_get_dspace(spa) - spa->spa_dedup_dspace;
+ space =
+ spa_get_dspace(spa) - spa->spa_dedup_dspace - brt_get_dspace(spa);
slop = MIN(space >> spa_slop_shift, spa_max_slop);
/*
@@ -1834,7 +1900,7 @@ void
spa_update_dspace(spa_t *spa)
{
spa->spa_dspace = metaslab_class_get_dspace(spa_normal_class(spa)) +
- ddt_get_dedup_dspace(spa);
+ ddt_get_dedup_dspace(spa) + brt_get_dspace(spa);
if (spa->spa_nonallocating_dspace > 0) {
/*
* Subtract the space provided by all non-allocating vdevs that
@@ -2146,6 +2212,7 @@ typedef struct spa_import_progress {
uint64_t pool_guid; /* unique id for updates */
char *pool_name;
spa_load_state_t spa_load_state;
+ char *spa_load_notes;
uint64_t mmp_sec_remaining; /* MMP activity check */
uint64_t spa_load_max_txg; /* rewind txg */
procfs_list_node_t smh_node;
@@ -2156,9 +2223,9 @@ spa_history_list_t *spa_import_progress_list = NULL;
static int
spa_import_progress_show_header(struct seq_file *f)
{
- seq_printf(f, "%-20s %-14s %-14s %-12s %s\n", "pool_guid",
+ seq_printf(f, "%-20s %-14s %-14s %-12s %-16s %s\n", "pool_guid",
"load_state", "multihost_secs", "max_txg",
- "pool_name");
+ "pool_name", "notes");
return (0);
}
@@ -2167,11 +2234,12 @@ spa_import_progress_show(struct seq_file *f, void *data)
{
spa_import_progress_t *sip = (spa_import_progress_t *)data;
- seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %s\n",
+ seq_printf(f, "%-20llu %-14llu %-14llu %-12llu %-16s %s\n",
(u_longlong_t)sip->pool_guid, (u_longlong_t)sip->spa_load_state,
(u_longlong_t)sip->mmp_sec_remaining,
(u_longlong_t)sip->spa_load_max_txg,
- (sip->pool_name ? sip->pool_name : "-"));
+ (sip->pool_name ? sip->pool_name : "-"),
+ (sip->spa_load_notes ? sip->spa_load_notes : "-"));
return (0);
}
@@ -2185,6 +2253,8 @@ spa_import_progress_truncate(spa_history_list_t *shl, unsigned int size)
sip = list_remove_head(&shl->procfs_list.pl_list);
if (sip->pool_name)
spa_strfree(sip->pool_name);
+ if (sip->spa_load_notes)
+ kmem_strfree(sip->spa_load_notes);
kmem_free(sip, sizeof (spa_import_progress_t));
shl->size--;
}
@@ -2240,6 +2310,10 @@ spa_import_progress_set_state(uint64_t pool_guid,
sip = list_prev(&shl->procfs_list.pl_list, sip)) {
if (sip->pool_guid == pool_guid) {
sip->spa_load_state = load_state;
+ if (sip->spa_load_notes != NULL) {
+ kmem_strfree(sip->spa_load_notes);
+ sip->spa_load_notes = NULL;
+ }
error = 0;
break;
}
@@ -2249,6 +2323,59 @@ spa_import_progress_set_state(uint64_t pool_guid,
return (error);
}
+static void
+spa_import_progress_set_notes_impl(spa_t *spa, boolean_t log_dbgmsg,
+ const char *fmt, va_list adx)
+{
+ spa_history_list_t *shl = spa_import_progress_list;
+ spa_import_progress_t *sip;
+ uint64_t pool_guid = spa_guid(spa);
+
+ if (shl->size == 0)
+ return;
+
+ char *notes = kmem_vasprintf(fmt, adx);
+
+ mutex_enter(&shl->procfs_list.pl_lock);
+ for (sip = list_tail(&shl->procfs_list.pl_list); sip != NULL;
+ sip = list_prev(&shl->procfs_list.pl_list, sip)) {
+ if (sip->pool_guid == pool_guid) {
+ if (sip->spa_load_notes != NULL) {
+ kmem_strfree(sip->spa_load_notes);
+ sip->spa_load_notes = NULL;
+ }
+ sip->spa_load_notes = notes;
+ if (log_dbgmsg)
+ zfs_dbgmsg("'%s' %s", sip->pool_name, notes);
+ notes = NULL;
+ break;
+ }
+ }
+ mutex_exit(&shl->procfs_list.pl_lock);
+ if (notes != NULL)
+ kmem_strfree(notes);
+}
+
+void
+spa_import_progress_set_notes(spa_t *spa, const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ spa_import_progress_set_notes_impl(spa, B_TRUE, fmt, adx);
+ va_end(adx);
+}
+
+void
+spa_import_progress_set_notes_nolog(spa_t *spa, const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ spa_import_progress_set_notes_impl(spa, B_FALSE, fmt, adx);
+ va_end(adx);
+}
+
int
spa_import_progress_set_max_txg(uint64_t pool_guid, uint64_t load_max_txg)
{
@@ -2306,7 +2433,7 @@ spa_import_progress_add(spa_t *spa)
{
spa_history_list_t *shl = spa_import_progress_list;
spa_import_progress_t *sip;
- char *poolname = NULL;
+ const char *poolname = NULL;
sip = kmem_zalloc(sizeof (spa_import_progress_t), KM_SLEEP);
sip->pool_guid = spa_guid(spa);
@@ -2317,6 +2444,7 @@ spa_import_progress_add(spa_t *spa)
poolname = spa_name(spa);
sip->pool_name = spa_strdup(poolname);
sip->spa_load_state = spa_load_state(spa);
+ sip->spa_load_notes = NULL;
mutex_enter(&shl->procfs_list.pl_lock);
procfs_list_add(&shl->procfs_list, sip);
@@ -2336,6 +2464,8 @@ spa_import_progress_remove(uint64_t pool_guid)
if (sip->pool_guid == pool_guid) {
if (sip->pool_name)
spa_strfree(sip->pool_name);
+ if (sip->spa_load_notes)
+ spa_strfree(sip->spa_load_notes);
list_remove(&shl->procfs_list.pl_list, sip);
shl->size--;
kmem_free(sip, sizeof (spa_import_progress_t));
@@ -2410,11 +2540,11 @@ spa_init(spa_mode_t mode)
unique_init();
zfs_btree_init();
metaslab_stat_init();
+ brt_init();
ddt_init();
zio_init();
dmu_init();
zil_init();
- vdev_cache_stat_init();
vdev_mirror_stat_init();
vdev_raidz_math_init();
vdev_file_init();
@@ -2438,7 +2568,6 @@ spa_fini(void)
spa_evict_all();
vdev_file_fini();
- vdev_cache_stat_fini();
vdev_mirror_stat_fini();
vdev_raidz_math_fini();
chksum_fini();
@@ -2446,6 +2575,7 @@ spa_fini(void)
dmu_fini();
zio_fini();
ddt_fini();
+ brt_fini();
metaslab_stat_fini();
zfs_btree_fini();
unique_fini();
@@ -2553,10 +2683,18 @@ spa_scan_stat_init(spa_t *spa)
spa->spa_scan_pass_scrub_pause = spa->spa_scan_pass_start;
else
spa->spa_scan_pass_scrub_pause = 0;
+
+ if (dsl_errorscrub_is_paused(spa->spa_dsl_pool->dp_scan))
+ spa->spa_scan_pass_errorscrub_pause = spa->spa_scan_pass_start;
+ else
+ spa->spa_scan_pass_errorscrub_pause = 0;
+
spa->spa_scan_pass_scrub_spent_paused = 0;
spa->spa_scan_pass_exam = 0;
spa->spa_scan_pass_issued = 0;
- vdev_scan_stat_init(spa->spa_root_vdev);
+
+ // error scrub stats
+ spa->spa_scan_pass_errorscrub_spent_paused = 0;
}
/*
@@ -2567,8 +2705,10 @@ spa_scan_get_stats(spa_t *spa, pool_scan_stat_t *ps)
{
dsl_scan_t *scn = spa->spa_dsl_pool ? spa->spa_dsl_pool->dp_scan : NULL;
- if (scn == NULL || scn->scn_phys.scn_func == POOL_SCAN_NONE)
+ if (scn == NULL || (scn->scn_phys.scn_func == POOL_SCAN_NONE &&
+ scn->errorscrub_phys.dep_func == POOL_SCAN_NONE))
return (SET_ERROR(ENOENT));
+
memset(ps, 0, sizeof (pool_scan_stat_t));
/* data stored on disk */
@@ -2578,7 +2718,7 @@ spa_scan_get_stats(spa_t *spa, pool_scan_stat_t *ps)
ps->pss_end_time = scn->scn_phys.scn_end_time;
ps->pss_to_examine = scn->scn_phys.scn_to_examine;
ps->pss_examined = scn->scn_phys.scn_examined;
- ps->pss_to_process = scn->scn_phys.scn_to_process;
+ ps->pss_skipped = scn->scn_phys.scn_skipped;
ps->pss_processed = scn->scn_phys.scn_processed;
ps->pss_errors = scn->scn_phys.scn_errors;
@@ -2591,6 +2731,18 @@ spa_scan_get_stats(spa_t *spa, pool_scan_stat_t *ps)
ps->pss_issued =
scn->scn_issued_before_pass + spa->spa_scan_pass_issued;
+ /* error scrub data stored on disk */
+ ps->pss_error_scrub_func = scn->errorscrub_phys.dep_func;
+ ps->pss_error_scrub_state = scn->errorscrub_phys.dep_state;
+ ps->pss_error_scrub_start = scn->errorscrub_phys.dep_start_time;
+ ps->pss_error_scrub_end = scn->errorscrub_phys.dep_end_time;
+ ps->pss_error_scrub_examined = scn->errorscrub_phys.dep_examined;
+ ps->pss_error_scrub_to_be_examined =
+ scn->errorscrub_phys.dep_to_examine;
+
+ /* error scrub data not stored on disk */
+ ps->pss_pass_error_scrub_pause = spa->spa_scan_pass_errorscrub_pause;
+
return (0);
}
@@ -2710,8 +2862,7 @@ spa_state_to_name(spa_t *spa)
vdev_state_t state = rvd->vdev_state;
vdev_aux_t aux = rvd->vdev_stat.vs_aux;
- if (spa_suspended(spa) &&
- (spa_get_failmode(spa) != ZIO_FAILURE_MODE_CONTINUE))
+ if (spa_suspended(spa))
return ("SUSPENDED");
switch (state) {
@@ -2922,13 +3073,13 @@ 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_deadman, zfs_deadman_, checktime_ms, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, checktime_ms, U64, ZMOD_RW,
"Dead I/O check interval in milliseconds");
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,
+ZFS_MODULE_PARAM(zfs_spa, spa_, asize_inflation, UINT, ZMOD_RW,
"SPA size estimate multiplication factor");
ZFS_MODULE_PARAM(zfs, zfs_, ddt_data_is_special, INT, ZMOD_RW,
@@ -2943,17 +3094,23 @@ ZFS_MODULE_PARAM_CALL(zfs_deadman, zfs_deadman_, failmode,
"Failmode for deadman timer");
ZFS_MODULE_PARAM_CALL(zfs_deadman, zfs_deadman_, synctime_ms,
- param_set_deadman_synctime, param_get_ulong, ZMOD_RW,
+ param_set_deadman_synctime, spl_param_get_u64, ZMOD_RW,
"Pool sync expiration time in milliseconds");
ZFS_MODULE_PARAM_CALL(zfs_deadman, zfs_deadman_, ziotime_ms,
- param_set_deadman_ziotime, param_get_ulong, ZMOD_RW,
+ param_set_deadman_ziotime, spl_param_get_u64, ZMOD_RW,
"IO expiration time in milliseconds");
-ZFS_MODULE_PARAM(zfs, zfs_, special_class_metadata_reserve_pct, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, special_class_metadata_reserve_pct, UINT, ZMOD_RW,
"Small file blocks in special vdevs depends on this much "
"free space available");
/* END CSTYLED */
ZFS_MODULE_PARAM_CALL(zfs_spa, spa_, slop_shift, param_set_slop_shift,
- param_get_int, ZMOD_RW, "Reserved free space in pool");
+ param_get_uint, ZMOD_RW, "Reserved free space in pool");
+
+ZFS_MODULE_PARAM(zfs, spa_, num_allocators, INT, ZMOD_RW,
+ "Number of allocators per spa");
+
+ZFS_MODULE_PARAM(zfs, spa_, cpus_per_allocator, INT, ZMOD_RW,
+ "Minimum number of CPUs per allocators");
diff --git a/module/zfs/spa_stats.c b/module/zfs/spa_stats.c
index f1d644bc68ca..17ed2a620b1e 100644
--- a/module/zfs/spa_stats.c
+++ b/module/zfs/spa_stats.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -28,7 +28,7 @@
/*
* Keeps stats on last N reads per spa_t, disabled by default.
*/
-static int zfs_read_history = B_FALSE;
+static uint_t zfs_read_history = B_FALSE;
/*
* Include cache hits in history, disabled by default.
@@ -38,12 +38,12 @@ static int zfs_read_history_hits = B_FALSE;
/*
* Keeps stats on the last 100 txgs by default.
*/
-static int zfs_txg_history = 100;
+static uint_t zfs_txg_history = 100;
/*
* Keeps stats on the last N MMP updates, disabled by default.
*/
-int zfs_multihost_history = B_FALSE;
+static uint_t zfs_multihost_history = B_FALSE;
/*
* ==========================================================================
@@ -1012,14 +1012,14 @@ spa_stats_destroy(spa_t *spa)
spa_guid_destroy(spa);
}
-ZFS_MODULE_PARAM(zfs, zfs_, read_history, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, read_history, UINT, ZMOD_RW,
"Historical statistics for the last N reads");
ZFS_MODULE_PARAM(zfs, zfs_, read_history_hits, INT, ZMOD_RW,
"Include cache hits in read history");
-ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, history, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, history, UINT, ZMOD_RW,
"Historical statistics for the last N txgs");
-ZFS_MODULE_PARAM(zfs_multihost, zfs_multihost_, history, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_multihost, zfs_multihost_, history, UINT, ZMOD_RW,
"Historical statistics for last N multihost writes");
diff --git a/module/zfs/space_map.c b/module/zfs/space_map.c
index 1aa20a96711e..a336ff41eadb 100644
--- a/module/zfs/space_map.c
+++ b/module/zfs/space_map.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/space_reftree.c b/module/zfs/space_reftree.c
index 080fc6646512..ee11e162dd5b 100644
--- a/module/zfs/space_reftree.c
+++ b/module/zfs/space_reftree.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/txg.c b/module/zfs/txg.c
index 6d5123076705..5ce6be69be14 100644
--- a/module/zfs/txg.c
+++ b/module/zfs/txg.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -111,7 +111,7 @@
static __attribute__((noreturn)) void txg_sync_thread(void *arg);
static __attribute__((noreturn)) void txg_quiesce_thread(void *arg);
-int zfs_txg_timeout = 5; /* max seconds worth of delta per txg */
+uint_t zfs_txg_timeout = 5; /* max seconds worth of delta per txg */
/*
* Prepare the txg subsystem.
@@ -429,7 +429,7 @@ txg_quiesce(dsl_pool_t *dp, uint64_t txg)
}
static void
-txg_do_callbacks(list_t *cb_list)
+txg_do_callbacks(void *cb_list)
{
dmu_tx_do_callbacks(cb_list, 0);
@@ -479,7 +479,7 @@ txg_dispatch_callbacks(dsl_pool_t *dp, uint64_t txg)
list_move_tail(cb_list, &tc->tc_callbacks[g]);
- (void) taskq_dispatch(tx->tx_commit_cb_taskq, (task_func_t *)
+ (void) taskq_dispatch(tx->tx_commit_cb_taskq,
txg_do_callbacks, cb_list, TQ_SLEEP);
}
}
@@ -551,6 +551,15 @@ txg_sync_thread(void *arg)
}
/*
+ * When we're suspended, nothing should be changing and for
+ * MMP we don't want to bump anything that would make it
+ * harder to detect if another host is changing it when
+ * resuming after a MMP suspend.
+ */
+ if (spa_suspended(spa))
+ continue;
+
+ /*
* Wait until the quiesce thread hands off a txg to us,
* prompting it to do so if necessary.
*/
@@ -895,15 +904,10 @@ txg_list_destroy(txg_list_t *tl)
boolean_t
txg_all_lists_empty(txg_list_t *tl)
{
- mutex_enter(&tl->tl_lock);
- for (int i = 0; i < TXG_SIZE; i++) {
- if (!txg_list_empty_impl(tl, i)) {
- mutex_exit(&tl->tl_lock);
- return (B_FALSE);
- }
- }
- mutex_exit(&tl->tl_lock);
- return (B_TRUE);
+ boolean_t res = B_TRUE;
+ for (int i = 0; i < TXG_SIZE; i++)
+ res &= (tl->tl_head[i] == NULL);
+ return (res);
}
/*
@@ -1069,5 +1073,5 @@ EXPORT_SYMBOL(txg_wait_callbacks);
EXPORT_SYMBOL(txg_stalled);
EXPORT_SYMBOL(txg_sync_waiting);
-ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, timeout, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, timeout, UINT, ZMOD_RW,
"Max seconds worth of delta per txg");
diff --git a/module/zfs/uberblock.c b/module/zfs/uberblock.c
index b8857d74d810..22ee8036c473 100644
--- a/module/zfs/uberblock.c
+++ b/module/zfs/uberblock.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -70,5 +70,5 @@ uberblock_update(uberblock_t *ub, vdev_t *rvd, uint64_t txg, uint64_t mmp_delay)
}
ub->ub_checkpoint_txg = 0;
- return (ub->ub_rootbp.blk_birth == txg);
+ return (BP_GET_LOGICAL_BIRTH(&ub->ub_rootbp) == txg);
}
diff --git a/module/zfs/unique.c b/module/zfs/unique.c
index 0e076797a002..799e4095db33 100644
--- a/module/zfs/unique.c
+++ b/module/zfs/unique.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c
index de29e6fd4c7c..c5551eb6cf6e 100644
--- a/module/zfs/vdev.c
+++ b/module/zfs/vdev.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -29,7 +29,7 @@
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, Datto Inc. All rights reserved.
* Copyright (c) 2021, Klara Inc.
- * Copyright [2021] Hewlett Packard Enterprise Development LP
+ * Copyright (c) 2021, 2023 Hewlett Packard Enterprise Development LP.
*/
#include <sys/zfs_context.h>
@@ -58,6 +58,7 @@
#include <sys/abd.h>
#include <sys/vdev_initialize.h>
#include <sys/vdev_trim.h>
+#include <sys/vdev_raidz.h>
#include <sys/zvol.h>
#include <sys/zfs_ratelimit.h>
#include "zfs_prop.h"
@@ -81,22 +82,22 @@
* 1 << (spa_slop_shift + 1), on small pools the usable space may be reduced
* (by more than 1<<spa_slop_shift) due to the embedded slog metaslab.
*/
-static int zfs_embedded_slog_min_ms = 64;
+static uint_t zfs_embedded_slog_min_ms = 64;
/* default target for number of metaslabs per top-level vdev */
-static int zfs_vdev_default_ms_count = 200;
+static uint_t zfs_vdev_default_ms_count = 200;
/* minimum number of metaslabs per top-level vdev */
-static int zfs_vdev_min_ms_count = 16;
+static uint_t zfs_vdev_min_ms_count = 16;
/* practical upper limit of total metaslabs per top-level vdev */
-static int zfs_vdev_ms_count_limit = 1ULL << 17;
+static uint_t zfs_vdev_ms_count_limit = 1ULL << 17;
/* lower limit for metaslab size (512M) */
-static int zfs_vdev_default_ms_shift = 29;
+static uint_t zfs_vdev_default_ms_shift = 29;
/* upper limit for metaslab size (16G) */
-static const int zfs_vdev_max_ms_shift = 34;
+static uint_t zfs_vdev_max_ms_shift = 34;
int vdev_validate_skip = B_FALSE;
@@ -136,8 +137,16 @@ int zfs_vdev_standard_sm_blksz = (1 << 17);
*/
int zfs_nocacheflush = 0;
-uint64_t zfs_vdev_max_auto_ashift = ASHIFT_MAX;
-uint64_t zfs_vdev_min_auto_ashift = ASHIFT_MIN;
+/*
+ * Maximum and minimum ashift values that can be automatically set based on
+ * vdev's physical ashift (disk's physical sector size). While ASHIFT_MAX
+ * is higher than the maximum value, it is intentionally limited here to not
+ * excessively impact pool space efficiency. Higher ashift values may still
+ * be forced by vdev logical ashift or by user via ashift property, but won't
+ * be set automatically as a performance optimization.
+ */
+uint_t zfs_vdev_max_auto_ashift = 14;
+uint_t zfs_vdev_min_auto_ashift = ASHIFT_MIN;
void
vdev_dbgmsg(vdev_t *vd, const char *fmt, ...)
@@ -216,7 +225,7 @@ vdev_dbgmsg_print_tree(vdev_t *vd, int indent)
* Virtual device management.
*/
-static const vdev_ops_t *const vdev_ops_table[] = {
+static vdev_ops_t *const vdev_ops_table[] = {
&vdev_root_ops,
&vdev_raidz_ops,
&vdev_draid_ops,
@@ -238,7 +247,7 @@ static const vdev_ops_t *const vdev_ops_table[] = {
static vdev_ops_t *
vdev_getops(const char *type)
{
- const vdev_ops_t *ops, *const *opspp;
+ vdev_ops_t *ops, *const *opspp;
for (opspp = vdev_ops_table; (ops = *opspp) != NULL; opspp++)
if (strcmp(ops->vdev_op_type, type) == 0)
@@ -297,13 +306,13 @@ vdev_derive_alloc_bias(const char *bias)
* all children. This is what's used by anything other than RAID-Z.
*/
uint64_t
-vdev_default_asize(vdev_t *vd, uint64_t psize)
+vdev_default_asize(vdev_t *vd, uint64_t psize, uint64_t txg)
{
uint64_t asize = P2ROUNDUP(psize, 1ULL << vd->vdev_top->vdev_ashift);
uint64_t csize;
for (int c = 0; c < vd->vdev_children; c++) {
- csize = vdev_psize_to_asize(vd->vdev_child[c], psize);
+ csize = vdev_psize_to_asize_txg(vd->vdev_child[c], psize, txg);
asize = MAX(asize, csize);
}
@@ -381,6 +390,33 @@ vdev_get_nparity(vdev_t *vd)
return (nparity);
}
+static int
+vdev_prop_get_int(vdev_t *vd, vdev_prop_t prop, uint64_t *value)
+{
+ spa_t *spa = vd->vdev_spa;
+ objset_t *mos = spa->spa_meta_objset;
+ uint64_t objid;
+ int err;
+
+ if (vd->vdev_root_zap != 0) {
+ objid = vd->vdev_root_zap;
+ } else if (vd->vdev_top_zap != 0) {
+ objid = vd->vdev_top_zap;
+ } else if (vd->vdev_leaf_zap != 0) {
+ objid = vd->vdev_leaf_zap;
+ } else {
+ return (EINVAL);
+ }
+
+ err = zap_lookup(mos, objid, vdev_prop_to_name(prop),
+ sizeof (uint64_t), 1, value);
+
+ if (err == ENOENT)
+ *value = vdev_prop_default_numeric(prop);
+
+ return (err);
+}
+
/*
* Get the number of data disks for a top-level vdev.
*/
@@ -634,6 +670,16 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
zfs_ratelimit_init(&vd->vdev_checksum_rl,
&zfs_checksum_events_per_second, 1);
+ /*
+ * Default Thresholds for tuning ZED
+ */
+ vd->vdev_checksum_n = vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_N);
+ vd->vdev_checksum_t = vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_T);
+ vd->vdev_io_n = vdev_prop_default_numeric(VDEV_PROP_IO_N);
+ vd->vdev_io_t = vdev_prop_default_numeric(VDEV_PROP_IO_T);
+ vd->vdev_slow_io_n = vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_N);
+ vd->vdev_slow_io_t = vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_T);
+
list_link_init(&vd->vdev_config_dirty_node);
list_link_init(&vd->vdev_state_dirty_node);
list_link_init(&vd->vdev_initialize_node);
@@ -655,6 +701,7 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
mutex_init(&vd->vdev_trim_io_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&vd->vdev_trim_cv, NULL, CV_DEFAULT, NULL);
cv_init(&vd->vdev_autotrim_cv, NULL, CV_DEFAULT, NULL);
+ cv_init(&vd->vdev_autotrim_kick_cv, NULL, CV_DEFAULT, NULL);
cv_init(&vd->vdev_trim_io_cv, NULL, CV_DEFAULT, NULL);
mutex_init(&vd->vdev_rebuild_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -671,7 +718,6 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
offsetof(struct vdev, vdev_dtl_node));
vd->vdev_stat.vs_timestamp = gethrtime();
vdev_queue_init(vd);
- vdev_cache_init(vd);
return (vd);
}
@@ -686,11 +732,11 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
int alloctype)
{
vdev_ops_t *ops;
- char *type;
+ const char *type;
uint64_t guid = 0, islog;
vdev_t *vd;
vdev_indirect_config_t *vic;
- char *tmp = NULL;
+ const char *tmp = NULL;
int rc;
vdev_alloc_bias_t alloc_bias = VDEV_BIAS_NONE;
boolean_t top_level = (parent && !parent->vdev_parent);
@@ -745,7 +791,7 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
return (SET_ERROR(ENOTSUP));
if (top_level && alloctype == VDEV_ALLOC_ADD) {
- char *bias;
+ const char *bias;
/*
* If creating a top-level vdev, check for allocation
@@ -791,8 +837,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
if (top_level && alloc_bias != VDEV_BIAS_NONE)
vd->vdev_alloc_bias = alloc_bias;
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &vd->vdev_path) == 0)
- vd->vdev_path = spa_strdup(vd->vdev_path);
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &tmp) == 0)
+ vd->vdev_path = spa_strdup(tmp);
/*
* ZPOOL_CONFIG_AUX_STATE = "external" means we previously forced a
@@ -806,18 +852,17 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
vd->vdev_label_aux = VDEV_AUX_EXTERNAL;
}
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &vd->vdev_devid) == 0)
- vd->vdev_devid = spa_strdup(vd->vdev_devid);
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PHYS_PATH,
- &vd->vdev_physpath) == 0)
- vd->vdev_physpath = spa_strdup(vd->vdev_physpath);
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &tmp) == 0)
+ vd->vdev_devid = spa_strdup(tmp);
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PHYS_PATH, &tmp) == 0)
+ vd->vdev_physpath = spa_strdup(tmp);
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
- &vd->vdev_enc_sysfs_path) == 0)
- vd->vdev_enc_sysfs_path = spa_strdup(vd->vdev_enc_sysfs_path);
+ &tmp) == 0)
+ vd->vdev_enc_sysfs_path = spa_strdup(tmp);
- if (nvlist_lookup_string(nv, ZPOOL_CONFIG_FRU, &vd->vdev_fru) == 0)
- vd->vdev_fru = spa_strdup(vd->vdev_fru);
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_FRU, &tmp) == 0)
+ vd->vdev_fru = spa_strdup(tmp);
/*
* Set the whole_disk property. If it's not specified, leave the value
@@ -847,9 +892,15 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
&vd->vdev_not_present);
/*
- * Get the alignment requirement.
+ * Get the alignment requirement. Ignore pool ashift for vdev
+ * attach case.
*/
- (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT, &vd->vdev_ashift);
+ if (alloctype != VDEV_ALLOC_ATTACH) {
+ (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT,
+ &vd->vdev_ashift);
+ } else {
+ vd->vdev_attaching = B_TRUE;
+ }
/*
* Retrieve the vdev creation time.
@@ -857,6 +908,14 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_CREATE_TXG,
&vd->vdev_crtxg);
+ if (vd->vdev_ops == &vdev_root_ops &&
+ (alloctype == VDEV_ALLOC_LOAD ||
+ alloctype == VDEV_ALLOC_SPLIT ||
+ alloctype == VDEV_ALLOC_ROOTPOOL)) {
+ (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_VDEV_ROOT_ZAP,
+ &vd->vdev_root_zap);
+ }
+
/*
* If we're a top-level vdev, try to load the allocation parameters.
*/
@@ -874,6 +933,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
&vd->vdev_removing);
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_VDEV_TOP_ZAP,
&vd->vdev_top_zap);
+ vd->vdev_rz_expanding = nvlist_exists(nv,
+ ZPOOL_CONFIG_RAIDZ_EXPANDING);
} else {
ASSERT0(vd->vdev_top_zap);
}
@@ -948,7 +1009,7 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
&vd->vdev_removed);
if (vd->vdev_faulted || vd->vdev_degraded) {
- char *aux;
+ const char *aux;
vd->vdev_label_aux =
VDEV_AUX_ERR_EXCEEDED;
@@ -1045,7 +1106,6 @@ vdev_free(vdev_t *vd)
* Clean up vdev structure.
*/
vdev_queue_fini(vd);
- vdev_cache_fini(vd);
if (vd->vdev_path)
spa_strfree(vd->vdev_path);
@@ -1108,6 +1168,7 @@ vdev_free(vdev_t *vd)
mutex_destroy(&vd->vdev_trim_io_lock);
cv_destroy(&vd->vdev_trim_cv);
cv_destroy(&vd->vdev_autotrim_cv);
+ cv_destroy(&vd->vdev_autotrim_kick_cv);
cv_destroy(&vd->vdev_trim_io_cv);
mutex_destroy(&vd->vdev_rebuild_lock);
@@ -1136,7 +1197,6 @@ vdev_top_transfer(vdev_t *svd, vdev_t *tvd)
ASSERT(tvd == tvd->vdev_top);
- tvd->vdev_pending_fastwrite = svd->vdev_pending_fastwrite;
tvd->vdev_ms_array = svd->vdev_ms_array;
tvd->vdev_ms_shift = svd->vdev_ms_shift;
tvd->vdev_ms_count = svd->vdev_ms_count;
@@ -1343,6 +1403,36 @@ vdev_remove_parent(vdev_t *cvd)
vdev_free(mvd);
}
+/*
+ * Choose GCD for spa_gcd_alloc.
+ */
+static uint64_t
+vdev_gcd(uint64_t a, uint64_t b)
+{
+ while (b != 0) {
+ uint64_t t = b;
+ b = a % b;
+ a = t;
+ }
+ return (a);
+}
+
+/*
+ * Set spa_min_alloc and spa_gcd_alloc.
+ */
+static void
+vdev_spa_set_alloc(spa_t *spa, uint64_t min_alloc)
+{
+ if (min_alloc < spa->spa_min_alloc)
+ spa->spa_min_alloc = min_alloc;
+ if (spa->spa_gcd_alloc == INT_MAX) {
+ spa->spa_gcd_alloc = min_alloc;
+ } else {
+ spa->spa_gcd_alloc = vdev_gcd(min_alloc,
+ spa->spa_gcd_alloc);
+ }
+}
+
void
vdev_metaslab_group_create(vdev_t *vd)
{
@@ -1395,8 +1485,7 @@ vdev_metaslab_group_create(vdev_t *vd)
spa->spa_min_ashift = vd->vdev_ashift;
uint64_t min_alloc = vdev_get_min_alloc(vd);
- if (min_alloc < spa->spa_min_alloc)
- spa->spa_min_alloc = min_alloc;
+ vdev_spa_set_alloc(spa, min_alloc);
}
}
}
@@ -1570,12 +1659,12 @@ vdev_metaslab_fini(vdev_t *vd)
}
}
ASSERT0(vd->vdev_ms_count);
- ASSERT3U(vd->vdev_pending_fastwrite, ==, 0);
}
typedef struct vdev_probe_stats {
boolean_t vps_readable;
boolean_t vps_writeable;
+ boolean_t vps_zio_done_probe;
int vps_flags;
} vdev_probe_stats_t;
@@ -1609,6 +1698,8 @@ vdev_probe_done(zio_t *zio)
vd->vdev_cant_read |= !vps->vps_readable;
vd->vdev_cant_write |= !vps->vps_writeable;
+ vdev_dbgmsg(vd, "probe done, cant_read=%u cant_write=%u",
+ vd->vdev_cant_read, vd->vdev_cant_write);
if (vdev_readable(vd) &&
(vdev_writeable(vd) || !spa_writeable(spa))) {
@@ -1619,6 +1710,17 @@ vdev_probe_done(zio_t *zio)
(void) zfs_ereport_post(FM_EREPORT_ZFS_PROBE_FAILURE,
spa, vd, NULL, NULL, 0);
zio->io_error = SET_ERROR(ENXIO);
+
+ /*
+ * If this probe was initiated from zio pipeline, then
+ * change the state in a spa_async_request. Probes that
+ * were initiated from a vdev_open can change the state
+ * as part of the open call.
+ */
+ if (vps->vps_zio_done_probe) {
+ vd->vdev_fault_wanted = B_TRUE;
+ spa_async_request(spa, SPA_ASYNC_FAULT_VDEV);
+ }
}
mutex_enter(&vd->vdev_probe_lock);
@@ -1668,8 +1770,8 @@ vdev_probe(vdev_t *vd, zio_t *zio)
vps = kmem_zalloc(sizeof (*vps), KM_SLEEP);
vps->vps_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_PROBE |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE |
- ZIO_FLAG_TRYHARD;
+ ZIO_FLAG_DONT_AGGREGATE | ZIO_FLAG_TRYHARD;
+ vps->vps_zio_done_probe = (zio != NULL);
if (spa_config_held(spa, SCL_ZIO, RW_WRITER)) {
/*
@@ -1696,15 +1798,6 @@ vdev_probe(vdev_t *vd, zio_t *zio)
vd->vdev_probe_zio = pio = zio_null(NULL, spa, vd,
vdev_probe_done, vps,
vps->vps_flags | ZIO_FLAG_DONT_PROPAGATE);
-
- /*
- * We can't change the vdev state in this context, so we
- * kick off an async task to do it on our behalf.
- */
- if (zio != NULL) {
- vd->vdev_probe_wanted = B_TRUE;
- spa_async_request(spa, SPA_ASYNC_PROBE);
- }
}
if (zio != NULL)
@@ -1831,21 +1924,42 @@ vdev_open_children_subset(vdev_t *vd, vdev_open_children_func_t *open_func)
}
/*
- * Compute the raidz-deflation ratio. Note, we hard-code
- * in 128k (1 << 17) because it is the "typical" blocksize.
- * Even though SPA_MAXBLOCKSIZE changed, this algorithm can not change,
- * otherwise it would inconsistently account for existing bp's.
+ * Compute the raidz-deflation ratio. Note, we hard-code 128k (1 << 17)
+ * because it is the "typical" blocksize. Even though SPA_MAXBLOCKSIZE
+ * changed, this algorithm can not change, otherwise it would inconsistently
+ * account for existing bp's. We also hard-code txg 0 for the same reason
+ * since expanded RAIDZ vdevs can use a different asize for different birth
+ * txg's.
*/
static void
vdev_set_deflate_ratio(vdev_t *vd)
{
if (vd == vd->vdev_top && !vd->vdev_ishole && vd->vdev_ashift != 0) {
vd->vdev_deflate_ratio = (1 << 17) /
- (vdev_psize_to_asize(vd, 1 << 17) >> SPA_MINBLOCKSHIFT);
+ (vdev_psize_to_asize_txg(vd, 1 << 17, 0) >>
+ SPA_MINBLOCKSHIFT);
}
}
/*
+ * Choose the best of two ashifts, preferring one between logical ashift
+ * (absolute minimum) and administrator defined maximum, otherwise take
+ * the biggest of the two.
+ */
+uint64_t
+vdev_best_ashift(uint64_t logical, uint64_t a, uint64_t b)
+{
+ if (a > logical && a <= zfs_vdev_max_auto_ashift) {
+ if (b <= logical || b > zfs_vdev_max_auto_ashift)
+ return (a);
+ else
+ return (MAX(a, b));
+ } else if (b <= logical || b > zfs_vdev_max_auto_ashift)
+ return (MAX(a, b));
+ return (b);
+}
+
+/*
* Maximize performance by inflating the configured ashift for top level
* vdevs to be as close to the physical ashift as possible while maintaining
* administrator defined limits and ensuring it doesn't go below the
@@ -1856,7 +1970,8 @@ vdev_ashift_optimize(vdev_t *vd)
{
ASSERT(vd == vd->vdev_top);
- if (vd->vdev_ashift < vd->vdev_physical_ashift) {
+ if (vd->vdev_ashift < vd->vdev_physical_ashift &&
+ vd->vdev_physical_ashift <= zfs_vdev_max_auto_ashift) {
vd->vdev_ashift = MIN(
MAX(zfs_vdev_max_auto_ashift, vd->vdev_ashift),
MAX(zfs_vdev_min_auto_ashift,
@@ -1921,6 +2036,14 @@ vdev_open(vdev_t *vd)
error = vd->vdev_ops->vdev_op_open(vd, &osize, &max_osize,
&logical_ashift, &physical_ashift);
+
+ /* Keep the device in removed state if unplugged */
+ if (error == ENOENT && vd->vdev_removed) {
+ vdev_set_state(vd, B_TRUE, VDEV_STATE_REMOVED,
+ VDEV_AUX_NONE);
+ return (error);
+ }
+
/*
* Physical volume size should never be larger than its max size, unless
* the disk has shrunk while we were reading it or the device is buggy
@@ -2068,9 +2191,9 @@ vdev_open(vdev_t *vd)
return (SET_ERROR(EDOM));
}
- if (vd->vdev_top == vd) {
+ if (vd->vdev_top == vd && vd->vdev_attaching == B_FALSE)
vdev_ashift_optimize(vd);
- }
+ vd->vdev_attaching = B_FALSE;
}
if (vd->vdev_ashift != 0 && (vd->vdev_ashift < ASHIFT_MIN ||
vd->vdev_ashift > ASHIFT_MAX)) {
@@ -2131,8 +2254,7 @@ vdev_open(vdev_t *vd)
if (vd->vdev_top == vd && vd->vdev_ashift != 0 &&
vd->vdev_islog == 0 && vd->vdev_aux == NULL) {
uint64_t min_alloc = vdev_get_min_alloc(vd);
- if (min_alloc < spa->spa_min_alloc)
- spa->spa_min_alloc = min_alloc;
+ vdev_spa_set_alloc(spa, min_alloc);
}
/*
@@ -2377,22 +2499,36 @@ vdev_validate(vdev_t *vd)
}
static void
-vdev_copy_path_impl(vdev_t *svd, vdev_t *dvd)
-{
- char *old, *new;
- if (svd->vdev_path != NULL && dvd->vdev_path != NULL) {
- if (strcmp(svd->vdev_path, dvd->vdev_path) != 0) {
- zfs_dbgmsg("vdev_copy_path: vdev %llu: path changed "
- "from '%s' to '%s'", (u_longlong_t)dvd->vdev_guid,
- dvd->vdev_path, svd->vdev_path);
- spa_strfree(dvd->vdev_path);
- dvd->vdev_path = spa_strdup(svd->vdev_path);
+vdev_update_path(const char *prefix, char *svd, char **dvd, uint64_t guid)
+{
+ if (svd != NULL && *dvd != NULL) {
+ if (strcmp(svd, *dvd) != 0) {
+ zfs_dbgmsg("vdev_copy_path: vdev %llu: %s changed "
+ "from '%s' to '%s'", (u_longlong_t)guid, prefix,
+ *dvd, svd);
+ spa_strfree(*dvd);
+ *dvd = spa_strdup(svd);
}
- } else if (svd->vdev_path != NULL) {
- dvd->vdev_path = spa_strdup(svd->vdev_path);
+ } else if (svd != NULL) {
+ *dvd = spa_strdup(svd);
zfs_dbgmsg("vdev_copy_path: vdev %llu: path set to '%s'",
- (u_longlong_t)dvd->vdev_guid, dvd->vdev_path);
+ (u_longlong_t)guid, *dvd);
}
+}
+
+static void
+vdev_copy_path_impl(vdev_t *svd, vdev_t *dvd)
+{
+ char *old, *new;
+
+ vdev_update_path("vdev_path", svd->vdev_path, &dvd->vdev_path,
+ dvd->vdev_guid);
+
+ vdev_update_path("vdev_devid", svd->vdev_devid, &dvd->vdev_devid,
+ dvd->vdev_guid);
+
+ vdev_update_path("vdev_physpath", svd->vdev_physpath,
+ &dvd->vdev_physpath, dvd->vdev_guid);
/*
* Our enclosure sysfs path may have changed between imports
@@ -2533,8 +2669,6 @@ vdev_close(vdev_t *vd)
vd->vdev_ops->vdev_op_close(vd);
- vdev_cache_purge(vd);
-
/*
* We record the previous state before we close it, so that if we are
* doing a reopen(), we don't generate FMA ereports if we notice that
@@ -2621,6 +2755,17 @@ vdev_reopen(vdev_t *vd)
}
/*
+ * Recheck if resilver is still needed and cancel any
+ * scheduled resilver if resilver is unneeded.
+ */
+ if (!vdev_resilver_needed(spa->spa_root_vdev, NULL, NULL) &&
+ spa->spa_async_tasks & SPA_ASYNC_RESILVER) {
+ mutex_enter(&spa->spa_async_lock);
+ spa->spa_async_tasks &= ~SPA_ASYNC_RESILVER;
+ mutex_exit(&spa->spa_async_lock);
+ }
+
+ /*
* Reassess parent vdev's health.
*/
vdev_propagate_state(vd);
@@ -3111,32 +3256,71 @@ vdev_dtl_reassess(vdev_t *vd, uint64_t txg, uint64_t scrub_txg,
if (txg != 0)
vdev_dirty(vd->vdev_top, VDD_DTL, vd, txg);
- return;
+ } else {
+ mutex_enter(&vd->vdev_dtl_lock);
+ for (int t = 0; t < DTL_TYPES; t++) {
+ /* account for child's outage in parent's missing map */
+ int s = (t == DTL_MISSING) ? DTL_OUTAGE: t;
+ if (t == DTL_SCRUB) {
+ /* leaf vdevs only */
+ continue;
+ }
+ if (t == DTL_PARTIAL) {
+ /* i.e. non-zero */
+ minref = 1;
+ } else if (vdev_get_nparity(vd) != 0) {
+ /* RAIDZ, DRAID */
+ minref = vdev_get_nparity(vd) + 1;
+ } else {
+ /* any kind of mirror */
+ minref = vd->vdev_children;
+ }
+ space_reftree_create(&reftree);
+ for (int c = 0; c < vd->vdev_children; c++) {
+ vdev_t *cvd = vd->vdev_child[c];
+ mutex_enter(&cvd->vdev_dtl_lock);
+ space_reftree_add_map(&reftree,
+ cvd->vdev_dtl[s], 1);
+ mutex_exit(&cvd->vdev_dtl_lock);
+ }
+ space_reftree_generate_map(&reftree,
+ vd->vdev_dtl[t], minref);
+ space_reftree_destroy(&reftree);
+ }
+ mutex_exit(&vd->vdev_dtl_lock);
}
- mutex_enter(&vd->vdev_dtl_lock);
- for (int t = 0; t < DTL_TYPES; t++) {
- /* account for child's outage in parent's missing map */
- int s = (t == DTL_MISSING) ? DTL_OUTAGE: t;
- if (t == DTL_SCRUB)
- continue; /* leaf vdevs only */
- if (t == DTL_PARTIAL)
- minref = 1; /* i.e. non-zero */
- else if (vdev_get_nparity(vd) != 0)
- minref = vdev_get_nparity(vd) + 1; /* RAID-Z, dRAID */
- else
- minref = vd->vdev_children; /* any kind of mirror */
- space_reftree_create(&reftree);
- for (int c = 0; c < vd->vdev_children; c++) {
- vdev_t *cvd = vd->vdev_child[c];
- mutex_enter(&cvd->vdev_dtl_lock);
- space_reftree_add_map(&reftree, cvd->vdev_dtl[s], 1);
- mutex_exit(&cvd->vdev_dtl_lock);
- }
- space_reftree_generate_map(&reftree, vd->vdev_dtl[t], minref);
- space_reftree_destroy(&reftree);
+ if (vd->vdev_top->vdev_ops == &vdev_raidz_ops) {
+ raidz_dtl_reassessed(vd);
}
- mutex_exit(&vd->vdev_dtl_lock);
+}
+
+/*
+ * Iterate over all the vdevs except spare, and post kobj events
+ */
+void
+vdev_post_kobj_evt(vdev_t *vd)
+{
+ if (vd->vdev_ops->vdev_op_kobj_evt_post &&
+ vd->vdev_kobj_flag == B_FALSE) {
+ vd->vdev_kobj_flag = B_TRUE;
+ vd->vdev_ops->vdev_op_kobj_evt_post(vd);
+ }
+
+ for (int c = 0; c < vd->vdev_children; c++)
+ vdev_post_kobj_evt(vd->vdev_child[c]);
+}
+
+/*
+ * Iterate over all the vdevs except spare, and clear kobj events
+ */
+void
+vdev_clear_kobj_evt(vdev_t *vd)
+{
+ vd->vdev_kobj_flag = B_FALSE;
+
+ for (int c = 0; c < vd->vdev_children; c++)
+ vdev_clear_kobj_evt(vd->vdev_child[c]);
}
int
@@ -3250,6 +3434,12 @@ vdev_construct_zaps(vdev_t *vd, dmu_tx_t *tx)
vdev_zap_allocation_data(vd, tx);
}
}
+ if (vd->vdev_ops == &vdev_root_ops && vd->vdev_root_zap == 0 &&
+ spa_feature_is_enabled(vd->vdev_spa, SPA_FEATURE_AVZ_V2)) {
+ if (!spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2))
+ spa_feature_incr(vd->vdev_spa, SPA_FEATURE_AVZ_V2, tx);
+ vd->vdev_root_zap = vdev_create_link_zap(vd, tx);
+ }
for (uint64_t i = 0; i < vd->vdev_children; i++) {
vdev_construct_zaps(vd->vdev_child[i], tx);
@@ -3477,6 +3667,12 @@ vdev_load(vdev_t *vd)
vdev_set_deflate_ratio(vd);
+ if (vd->vdev_ops == &vdev_raidz_ops) {
+ error = vdev_raidz_load(vd);
+ if (error != 0)
+ return (error);
+ }
+
/*
* On spa_load path, grab the allocation bias from our zap
*/
@@ -3500,6 +3696,26 @@ vdev_load(vdev_t *vd)
}
}
+ if (vd == vd->vdev_top && vd->vdev_top_zap != 0) {
+ spa_t *spa = vd->vdev_spa;
+ uint64_t failfast;
+
+ error = zap_lookup(spa->spa_meta_objset, vd->vdev_top_zap,
+ vdev_prop_to_name(VDEV_PROP_FAILFAST), sizeof (failfast),
+ 1, &failfast);
+ if (error == 0) {
+ vd->vdev_failfast = failfast & 1;
+ } else if (error == ENOENT) {
+ vd->vdev_failfast = vdev_prop_default_numeric(
+ VDEV_PROP_FAILFAST);
+ } else {
+ vdev_dbgmsg(vd,
+ "vdev_load: zap_lookup(top_zap=%llu) "
+ "failed [error=%d]",
+ (u_longlong_t)vd->vdev_top_zap, error);
+ }
+ }
+
/*
* Load any rebuild state from the top-level vdev zap.
*/
@@ -3514,6 +3730,51 @@ vdev_load(vdev_t *vd)
}
}
+ if (vd->vdev_top_zap != 0 || vd->vdev_leaf_zap != 0) {
+ uint64_t zapobj;
+
+ if (vd->vdev_top_zap != 0)
+ zapobj = vd->vdev_top_zap;
+ else
+ zapobj = vd->vdev_leaf_zap;
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_CHECKSUM_N,
+ &vd->vdev_checksum_n);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_CHECKSUM_T,
+ &vd->vdev_checksum_t);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_IO_N,
+ &vd->vdev_io_n);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_IO_T,
+ &vd->vdev_io_t);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_SLOW_IO_N,
+ &vd->vdev_slow_io_n);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+
+ error = vdev_prop_get_int(vd, VDEV_PROP_SLOW_IO_T,
+ &vd->vdev_slow_io_t);
+ if (error && error != ENOENT)
+ vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
+ "failed [error=%d]", (u_longlong_t)zapobj, error);
+ }
+
/*
* If this is a top-level vdev, initialize its metaslabs.
*/
@@ -3801,10 +4062,22 @@ vdev_sync(vdev_t *vd, uint64_t txg)
dmu_tx_commit(tx);
}
+/*
+ * Return the amount of space that should be (or was) allocated for the given
+ * psize (compressed block size) in the given TXG. Note that for expanded
+ * RAIDZ vdevs, the size allocated for older BP's may be larger. See
+ * vdev_raidz_asize().
+ */
+uint64_t
+vdev_psize_to_asize_txg(vdev_t *vd, uint64_t psize, uint64_t txg)
+{
+ return (vd->vdev_ops->vdev_op_asize(vd, psize, txg));
+}
+
uint64_t
vdev_psize_to_asize(vdev_t *vd, uint64_t psize)
{
- return (vd->vdev_ops->vdev_op_asize(vd, psize));
+ return (vdev_psize_to_asize_txg(vd, psize, 0));
}
/*
@@ -3920,6 +4193,36 @@ vdev_degrade(spa_t *spa, uint64_t guid, vdev_aux_t aux)
return (spa_vdev_state_exit(spa, vd, 0));
}
+int
+vdev_remove_wanted(spa_t *spa, uint64_t guid)
+{
+ vdev_t *vd;
+
+ spa_vdev_state_enter(spa, SCL_NONE);
+
+ if ((vd = spa_lookup_by_guid(spa, guid, B_TRUE)) == NULL)
+ return (spa_vdev_state_exit(spa, NULL, SET_ERROR(ENODEV)));
+
+ /*
+ * If the vdev is already removed, or expanding which can trigger
+ * repartition add/remove events, then don't do anything.
+ */
+ if (vd->vdev_removed || vd->vdev_expanding)
+ return (spa_vdev_state_exit(spa, NULL, 0));
+
+ /*
+ * Confirm the vdev has been removed, otherwise don't do anything.
+ */
+ if (vd->vdev_ops->vdev_op_leaf && !zio_wait(vdev_probe(vd, NULL)))
+ return (spa_vdev_state_exit(spa, NULL, SET_ERROR(EEXIST)));
+
+ vd->vdev_remove_wanted = B_TRUE;
+ spa_async_request(spa, SPA_ASYNC_REMOVE);
+
+ return (spa_vdev_state_exit(spa, vd, 0));
+}
+
+
/*
* Online the given vdev.
*
@@ -3940,9 +4243,6 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
if ((vd = spa_lookup_by_guid(spa, guid, B_TRUE)) == NULL)
return (spa_vdev_state_exit(spa, NULL, SET_ERROR(ENODEV)));
- if (!vd->vdev_ops->vdev_op_leaf)
- return (spa_vdev_state_exit(spa, NULL, SET_ERROR(ENOTSUP)));
-
wasoffline = (vd->vdev_offline || vd->vdev_tmpoffline);
oldstate = vd->vdev_state;
@@ -3981,6 +4281,7 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
/* XXX - L2ARC 1.0 does not support expansion */
if (vd->vdev_aux)
return (spa_vdev_state_exit(spa, vd, ENOTSUP));
+ spa->spa_ccw_fail_time = 0;
spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
}
@@ -4010,9 +4311,19 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
if (wasoffline ||
(oldstate < VDEV_STATE_DEGRADED &&
- vd->vdev_state >= VDEV_STATE_DEGRADED))
+ vd->vdev_state >= VDEV_STATE_DEGRADED)) {
spa_event_notify(spa, vd, NULL, ESC_ZFS_VDEV_ONLINE);
+ /*
+ * Asynchronously detach spare vdev if resilver or
+ * rebuild is not required
+ */
+ if (vd->vdev_unspare &&
+ !dsl_scan_resilvering(spa->spa_dsl_pool) &&
+ !dsl_scan_resilver_scheduled(spa->spa_dsl_pool) &&
+ !vdev_rebuild_active(tvd))
+ spa_async_request(spa, SPA_ASYNC_DETACH_SPARE);
+ }
return (spa_vdev_state_exit(spa, vd, 0));
}
@@ -4163,9 +4474,9 @@ vdev_clear(spa_t *spa, vdev_t *vd)
vdev_clear(spa, vd->vdev_child[c]);
/*
- * It makes no sense to "clear" an indirect vdev.
+ * It makes no sense to "clear" an indirect or removed vdev.
*/
- if (!vdev_is_concrete(vd))
+ if (!vdev_is_concrete(vd) || vd->vdev_removed)
return;
/*
@@ -4396,11 +4707,9 @@ vdev_get_stats_ex_impl(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx)
memcpy(vsx, &vd->vdev_stat_ex, sizeof (vd->vdev_stat_ex));
- for (t = 0; t < ARRAY_SIZE(vd->vdev_queue.vq_class); t++) {
- vsx->vsx_active_queue[t] =
- vd->vdev_queue.vq_class[t].vqc_active;
- vsx->vsx_pend_queue[t] = avl_numnodes(
- &vd->vdev_queue.vq_class[t].vqc_queued_tree);
+ for (t = 0; t < ZIO_PRIORITY_NUM_QUEUEABLE; t++) {
+ vsx->vsx_active_queue[t] = vd->vdev_queue.vq_cactive[t];
+ vsx->vsx_pend_queue[t] = vdev_queue_class_length(vd, t);
}
}
}
@@ -4463,7 +4772,10 @@ vdev_get_stats_ex(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx)
vs->vs_configured_ashift = vd->vdev_top != NULL
? vd->vdev_top->vdev_ashift : vd->vdev_ashift;
vs->vs_logical_ashift = vd->vdev_logical_ashift;
- vs->vs_physical_ashift = vd->vdev_physical_ashift;
+ if (vd->vdev_physical_ashift <= ASHIFT_MAX)
+ vs->vs_physical_ashift = vd->vdev_physical_ashift;
+ else
+ vs->vs_physical_ashift = 0;
/*
* Report fragmentation and rebuild progress for top-level,
@@ -4525,8 +4837,14 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
vdev_t *vd = zio->io_vd ? zio->io_vd : rvd;
vdev_t *pvd;
uint64_t txg = zio->io_txg;
+/* Suppress ASAN false positive */
+#ifdef __SANITIZE_ADDRESS__
vdev_stat_t *vs = vd ? &vd->vdev_stat : NULL;
vdev_stat_ex_t *vsx = vd ? &vd->vdev_stat_ex : NULL;
+#else
+ vdev_stat_t *vs = &vd->vdev_stat;
+ vdev_stat_ex_t *vsx = &vd->vdev_stat_ex;
+#endif
zio_type_t type = zio->io_type;
int flags = zio->io_flags;
@@ -4610,11 +4928,11 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
/*
* TRIM ops and bytes are reported to user space as
- * ZIO_TYPE_IOCTL. This is done to preserve the
+ * ZIO_TYPE_FLUSH. This is done to preserve the
* vdev_stat_t structure layout for user space.
*/
if (type == ZIO_TYPE_TRIM)
- vs_type = ZIO_TYPE_IOCTL;
+ vs_type = ZIO_TYPE_FLUSH;
/*
* Solely for the purposes of 'zpool iostat -lqrw'
@@ -5205,7 +5523,9 @@ vdev_expand(vdev_t *vd, uint64_t txg)
vdev_set_deflate_ratio(vd);
- if ((vd->vdev_asize >> vd->vdev_ms_shift) > vd->vdev_ms_count &&
+ if ((vd->vdev_spa->spa_raidz_expand == NULL ||
+ vd->vdev_spa->spa_raidz_expand->vre_vdev_id != vd->vdev_id) &&
+ (vd->vdev_asize >> vd->vdev_ms_shift) > vd->vdev_ms_count &&
vdev_is_concrete(vd)) {
vdev_metaslab_group_create(vd);
VERIFY(vdev_metaslab_init(vd, txg) == 0);
@@ -5221,9 +5541,13 @@ vdev_split(vdev_t *vd)
{
vdev_t *cvd, *pvd = vd->vdev_parent;
+ VERIFY3U(pvd->vdev_children, >, 1);
+
vdev_remove_child(pvd, vd);
vdev_compact_children(pvd);
+ ASSERT3P(pvd->vdev_child, !=, NULL);
+
cvd = pvd->vdev_child[0];
if (pvd->vdev_children == 1) {
vdev_remove_parent(cvd);
@@ -5245,20 +5569,20 @@ vdev_deadman(vdev_t *vd, const char *tag)
vdev_queue_t *vq = &vd->vdev_queue;
mutex_enter(&vq->vq_lock);
- if (avl_numnodes(&vq->vq_active_tree) > 0) {
+ if (vq->vq_active > 0) {
spa_t *spa = vd->vdev_spa;
zio_t *fio;
uint64_t delta;
- zfs_dbgmsg("slow vdev: %s has %lu active IOs",
- vd->vdev_path, avl_numnodes(&vq->vq_active_tree));
+ zfs_dbgmsg("slow vdev: %s has %u active IOs",
+ vd->vdev_path, vq->vq_active);
/*
* Look at the head of all the pending queues,
* if any I/O has been outstanding for longer than
* the spa_deadman_synctime invoke the deadman logic.
*/
- fio = avl_first(&vq->vq_active_tree);
+ fio = list_head(&vq->vq_active_list);
delta = gethrtime() - fio->io_timestamp;
if (delta > spa_deadman_synctime(spa))
zio_deadman(fio, tag);
@@ -5439,7 +5763,7 @@ vdev_replace_in_progress(vdev_t *vdev)
* Add a (source=src, propname=propval) list to an nvlist.
*/
static void
-vdev_prop_add_list(nvlist_t *nvl, const char *propname, char *strval,
+vdev_prop_add_list(nvlist_t *nvl, const char *propname, const char *strval,
uint64_t intval, zprop_source_t src)
{
nvlist_t *propval;
@@ -5465,6 +5789,7 @@ vdev_props_set_sync(void *arg, dmu_tx_t *tx)
objset_t *mos = spa->spa_meta_objset;
nvpair_t *elem = NULL;
uint64_t vdev_guid;
+ uint64_t objid;
nvlist_t *nvprops;
vdev_guid = fnvlist_lookup_uint64(nvp, ZPOOL_VDEV_PROPS_SET_VDEV);
@@ -5475,26 +5800,28 @@ vdev_props_set_sync(void *arg, dmu_tx_t *tx)
if (vd == NULL)
return;
+ /*
+ * Set vdev property values in the vdev props mos object.
+ */
+ if (vd->vdev_root_zap != 0) {
+ objid = vd->vdev_root_zap;
+ } else if (vd->vdev_top_zap != 0) {
+ objid = vd->vdev_top_zap;
+ } else if (vd->vdev_leaf_zap != 0) {
+ objid = vd->vdev_leaf_zap;
+ } else {
+ panic("unexpected vdev type");
+ }
+
mutex_enter(&spa->spa_props_lock);
while ((elem = nvlist_next_nvpair(nvprops, elem)) != NULL) {
- uint64_t intval, objid = 0;
- char *strval;
+ uint64_t intval;
+ const char *strval;
vdev_prop_t prop;
const char *propname = nvpair_name(elem);
zprop_type_t proptype;
- /*
- * Set vdev property values in the vdev props mos object.
- */
- if (vd->vdev_top_zap != 0) {
- objid = vd->vdev_top_zap;
- } else if (vd->vdev_leaf_zap != 0) {
- objid = vd->vdev_leaf_zap;
- } else {
- panic("vdev not top or leaf");
- }
-
switch (prop = vdev_name_to_prop(propname)) {
case VDEV_PROP_USERPROP:
if (vdev_prop_user(propname)) {
@@ -5559,10 +5886,16 @@ vdev_prop_set(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
nvpair_t *elem = NULL;
uint64_t vdev_guid;
nvlist_t *nvprops;
- int error;
+ int error = 0;
ASSERT(vd != NULL);
+ /* Check that vdev has a zap we can use */
+ if (vd->vdev_root_zap == 0 &&
+ vd->vdev_top_zap == 0 &&
+ vd->vdev_leaf_zap == 0)
+ return (SET_ERROR(EINVAL));
+
if (nvlist_lookup_uint64(innvl, ZPOOL_VDEV_PROPS_SET_VDEV,
&vdev_guid) != 0)
return (SET_ERROR(EINVAL));
@@ -5575,10 +5908,10 @@ vdev_prop_set(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
return (SET_ERROR(EINVAL));
while ((elem = nvlist_next_nvpair(nvprops, elem)) != NULL) {
- char *propname = nvpair_name(elem);
+ const char *propname = nvpair_name(elem);
vdev_prop_t prop = vdev_name_to_prop(propname);
uint64_t intval = 0;
- char *strval = NULL;
+ const char *strval = NULL;
if (prop == VDEV_PROP_USERPROP && !vdev_prop_user(propname)) {
error = EINVAL;
@@ -5620,6 +5953,55 @@ vdev_prop_set(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
else
error = spa_vdev_alloc(spa, vdev_guid);
break;
+ case VDEV_PROP_FAILFAST:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_failfast = intval & 1;
+ break;
+ case VDEV_PROP_CHECKSUM_N:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_checksum_n = intval;
+ break;
+ case VDEV_PROP_CHECKSUM_T:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_checksum_t = intval;
+ break;
+ case VDEV_PROP_IO_N:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_io_n = intval;
+ break;
+ case VDEV_PROP_IO_T:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_io_t = intval;
+ break;
+ case VDEV_PROP_SLOW_IO_N:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_slow_io_n = intval;
+ break;
+ case VDEV_PROP_SLOW_IO_T:
+ if (nvpair_value_uint64(elem, &intval) != 0) {
+ error = EINVAL;
+ break;
+ }
+ vd->vdev_slow_io_t = intval;
+ break;
default:
/* Most processing is done in vdev_props_set_sync */
break;
@@ -5660,7 +6042,9 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
nvlist_lookup_nvlist(innvl, ZPOOL_VDEV_PROPS_GET_PROPS, &nvprops);
- if (vd->vdev_top_zap != 0) {
+ if (vd->vdev_root_zap != 0) {
+ objid = vd->vdev_root_zap;
+ } else if (vd->vdev_top_zap != 0) {
objid = vd->vdev_top_zap;
} else if (vd->vdev_leaf_zap != 0) {
objid = vd->vdev_leaf_zap;
@@ -5859,12 +6243,12 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
case VDEV_PROP_OPS_TRIM:
/*
* TRIM ops and bytes are reported to user
- * space as ZIO_TYPE_IOCTL. This is done to
+ * space as ZIO_TYPE_FLUSH. This is done to
* preserve the vdev_stat_t structure layout
* for user space.
*/
vdev_prop_add_list(outnvl, propname, NULL,
- vd->vdev_stat.vs_ops[ZIO_TYPE_IOCTL],
+ vd->vdev_stat.vs_ops[ZIO_TYPE_FLUSH],
ZPROP_SRC_NONE);
continue;
case VDEV_PROP_BYTES_NULL:
@@ -5895,44 +6279,86 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
case VDEV_PROP_BYTES_TRIM:
/*
* TRIM ops and bytes are reported to user
- * space as ZIO_TYPE_IOCTL. This is done to
+ * space as ZIO_TYPE_FLUSH. This is done to
* preserve the vdev_stat_t structure layout
* for user space.
*/
vdev_prop_add_list(outnvl, propname, NULL,
- vd->vdev_stat.vs_bytes[ZIO_TYPE_IOCTL],
+ vd->vdev_stat.vs_bytes[ZIO_TYPE_FLUSH],
ZPROP_SRC_NONE);
continue;
case VDEV_PROP_REMOVING:
vdev_prop_add_list(outnvl, propname, NULL,
vd->vdev_removing, ZPROP_SRC_NONE);
continue;
+ case VDEV_PROP_RAIDZ_EXPANDING:
+ /* Only expose this for raidz */
+ if (vd->vdev_ops == &vdev_raidz_ops) {
+ vdev_prop_add_list(outnvl, propname,
+ NULL, vd->vdev_rz_expanding,
+ ZPROP_SRC_NONE);
+ }
+ continue;
/* Numeric Properites */
case VDEV_PROP_ALLOCATING:
+ /* Leaf vdevs cannot have this property */
+ if (vd->vdev_mg == NULL &&
+ vd->vdev_top != NULL) {
+ src = ZPROP_SRC_NONE;
+ intval = ZPROP_BOOLEAN_NA;
+ } else {
+ err = vdev_prop_get_int(vd, prop,
+ &intval);
+ if (err && err != ENOENT)
+ break;
+
+ if (intval ==
+ vdev_prop_default_numeric(prop))
+ src = ZPROP_SRC_DEFAULT;
+ else
+ src = ZPROP_SRC_LOCAL;
+ }
+
+ vdev_prop_add_list(outnvl, propname, NULL,
+ intval, src);
+ break;
+ case VDEV_PROP_FAILFAST:
src = ZPROP_SRC_LOCAL;
strval = NULL;
err = zap_lookup(mos, objid, nvpair_name(elem),
sizeof (uint64_t), 1, &intval);
if (err == ENOENT) {
- intval =
- vdev_prop_default_numeric(prop);
+ intval = vdev_prop_default_numeric(
+ prop);
err = 0;
- } else if (err)
+ } else if (err) {
break;
+ }
if (intval == vdev_prop_default_numeric(prop))
src = ZPROP_SRC_DEFAULT;
- /* Leaf vdevs cannot have this property */
- if (vd->vdev_mg == NULL &&
- vd->vdev_top != NULL) {
- src = ZPROP_SRC_NONE;
- intval = ZPROP_BOOLEAN_NA;
- }
-
vdev_prop_add_list(outnvl, propname, strval,
intval, src);
break;
+ case VDEV_PROP_CHECKSUM_N:
+ case VDEV_PROP_CHECKSUM_T:
+ case VDEV_PROP_IO_N:
+ case VDEV_PROP_IO_T:
+ case VDEV_PROP_SLOW_IO_N:
+ case VDEV_PROP_SLOW_IO_T:
+ err = vdev_prop_get_int(vd, prop, &intval);
+ if (err && err != ENOENT)
+ break;
+
+ if (intval == vdev_prop_default_numeric(prop))
+ src = ZPROP_SRC_DEFAULT;
+ else
+ src = ZPROP_SRC_LOCAL;
+
+ vdev_prop_add_list(outnvl, propname, NULL,
+ intval, src);
+ break;
/* Text Properties */
case VDEV_PROP_COMMENT:
/* Exists in the ZAP below */
@@ -5989,7 +6415,6 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
strval = NULL;
zprop_source_t src = ZPROP_SRC_DEFAULT;
propname = za.za_name;
- prop = vdev_name_to_prop(propname);
switch (za.za_integer_length) {
case 8:
@@ -6032,16 +6457,19 @@ EXPORT_SYMBOL(vdev_online);
EXPORT_SYMBOL(vdev_offline);
EXPORT_SYMBOL(vdev_clear);
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, default_ms_count, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, default_ms_count, UINT, ZMOD_RW,
"Target number of metaslabs per top-level vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, default_ms_shift, INT, ZMOD_RW,
- "Default limit for metaslab size");
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, default_ms_shift, UINT, ZMOD_RW,
+ "Default lower limit for metaslab size");
+
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, max_ms_shift, UINT, ZMOD_RW,
+ "Default upper limit for metaslab size");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, min_ms_count, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, min_ms_count, UINT, ZMOD_RW,
"Minimum number of metaslabs per top-level vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, ms_count_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, ms_count_limit, UINT, ZMOD_RW,
"Practical upper limit of total metaslabs per top-level vdev");
ZFS_MODULE_PARAM(zfs, zfs_, slow_io_events_per_second, UINT, ZMOD_RW,
@@ -6062,16 +6490,16 @@ ZFS_MODULE_PARAM(zfs_vdev, vdev_, validate_skip, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, nocacheflush, INT, ZMOD_RW,
"Disable cache flushes");
-ZFS_MODULE_PARAM(zfs, zfs_, embedded_slog_min_ms, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, embedded_slog_min_ms, UINT, ZMOD_RW,
"Minimum number of metaslabs required to dedicate one for log blocks");
/* BEGIN CSTYLED */
ZFS_MODULE_PARAM_CALL(zfs_vdev, zfs_vdev_, min_auto_ashift,
- param_set_min_auto_ashift, param_get_ulong, ZMOD_RW,
+ param_set_min_auto_ashift, param_get_uint, ZMOD_RW,
"Minimum ashift used when creating new top-level vdevs");
ZFS_MODULE_PARAM_CALL(zfs_vdev, zfs_vdev_, max_auto_ashift,
- param_set_max_auto_ashift, param_get_ulong, ZMOD_RW,
+ param_set_max_auto_ashift, param_get_uint, ZMOD_RW,
"Maximum ashift used when optimizing for logical -> physical sector "
"size on new top-level vdevs");
/* END CSTYLED */
diff --git a/module/zfs/vdev_cache.c b/module/zfs/vdev_cache.c
deleted file mode 100644
index a3433311b381..000000000000
--- a/module/zfs/vdev_cache.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/zfs_context.h>
-#include <sys/spa.h>
-#include <sys/vdev_impl.h>
-#include <sys/zio.h>
-#include <sys/kstat.h>
-#include <sys/abd.h>
-
-/*
- * Virtual device read-ahead caching.
- *
- * This file implements a simple LRU read-ahead cache. When the DMU reads
- * a given block, it will often want other, nearby blocks soon thereafter.
- * We take advantage of this by reading a larger disk region and caching
- * the result. In the best case, this can turn 128 back-to-back 512-byte
- * reads into a single 64k read followed by 127 cache hits; this reduces
- * latency dramatically. In the worst case, it can turn an isolated 512-byte
- * read into a 64k read, which doesn't affect latency all that much but is
- * terribly wasteful of bandwidth. A more intelligent version of the cache
- * could keep track of access patterns and not do read-ahead unless it sees
- * at least two temporally close I/Os to the same region. Currently, only
- * metadata I/O is inflated. A further enhancement could take advantage of
- * more semantic information about the I/O. And it could use something
- * faster than an AVL tree; that was chosen solely for convenience.
- *
- * There are five cache operations: allocate, fill, read, write, evict.
- *
- * (1) Allocate. This reserves a cache entry for the specified region.
- * We separate the allocate and fill operations so that multiple threads
- * don't generate I/O for the same cache miss.
- *
- * (2) Fill. When the I/O for a cache miss completes, the fill routine
- * places the data in the previously allocated cache entry.
- *
- * (3) Read. Read data from the cache.
- *
- * (4) Write. Update cache contents after write completion.
- *
- * (5) Evict. When allocating a new entry, we evict the oldest (LRU) entry
- * if the total cache size exceeds zfs_vdev_cache_size.
- */
-
-/*
- * These tunables are for performance analysis.
- */
-/*
- * All i/os smaller than zfs_vdev_cache_max will be turned into
- * 1<<zfs_vdev_cache_bshift byte reads by the vdev_cache (aka software
- * track buffer). At most zfs_vdev_cache_size bytes will be kept in each
- * vdev's vdev_cache.
- *
- * TODO: Note that with the current ZFS code, it turns out that the
- * vdev cache is not helpful, and in some cases actually harmful. It
- * is better if we disable this. Once some time has passed, we should
- * actually remove this to simplify the code. For now we just disable
- * it by setting the zfs_vdev_cache_size to zero. Note that Solaris 11
- * has made these same changes.
- */
-static int zfs_vdev_cache_max = 1 << 14; /* 16KB */
-static int zfs_vdev_cache_size = 0;
-static int zfs_vdev_cache_bshift = 16;
-
-#define VCBS (1 << zfs_vdev_cache_bshift) /* 64KB */
-
-static kstat_t *vdc_ksp = NULL;
-
-typedef struct vdc_stats {
- kstat_named_t vdc_stat_delegations;
- kstat_named_t vdc_stat_hits;
- kstat_named_t vdc_stat_misses;
-} vdc_stats_t;
-
-static vdc_stats_t vdc_stats = {
- { "delegations", KSTAT_DATA_UINT64 },
- { "hits", KSTAT_DATA_UINT64 },
- { "misses", KSTAT_DATA_UINT64 }
-};
-
-#define VDCSTAT_BUMP(stat) atomic_inc_64(&vdc_stats.stat.value.ui64);
-
-static inline int
-vdev_cache_offset_compare(const void *a1, const void *a2)
-{
- const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
- const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
-
- return (TREE_CMP(ve1->ve_offset, ve2->ve_offset));
-}
-
-static int
-vdev_cache_lastused_compare(const void *a1, const void *a2)
-{
- const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
- const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
-
- int cmp = TREE_CMP(ve1->ve_lastused, ve2->ve_lastused);
- if (likely(cmp))
- return (cmp);
-
- /*
- * Among equally old entries, sort by offset to ensure uniqueness.
- */
- return (vdev_cache_offset_compare(a1, a2));
-}
-
-/*
- * Evict the specified entry from the cache.
- */
-static void
-vdev_cache_evict(vdev_cache_t *vc, vdev_cache_entry_t *ve)
-{
- ASSERT(MUTEX_HELD(&vc->vc_lock));
- ASSERT3P(ve->ve_fill_io, ==, NULL);
- ASSERT3P(ve->ve_abd, !=, NULL);
-
- avl_remove(&vc->vc_lastused_tree, ve);
- avl_remove(&vc->vc_offset_tree, ve);
- abd_free(ve->ve_abd);
- kmem_free(ve, sizeof (vdev_cache_entry_t));
-}
-
-/*
- * Allocate an entry in the cache. At the point we don't have the data,
- * we're just creating a placeholder so that multiple threads don't all
- * go off and read the same blocks.
- */
-static vdev_cache_entry_t *
-vdev_cache_allocate(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- uint64_t offset = P2ALIGN(zio->io_offset, VCBS);
- vdev_cache_entry_t *ve;
-
- ASSERT(MUTEX_HELD(&vc->vc_lock));
-
- if (zfs_vdev_cache_size == 0)
- return (NULL);
-
- /*
- * If adding a new entry would exceed the cache size,
- * evict the oldest entry (LRU).
- */
- if ((avl_numnodes(&vc->vc_lastused_tree) << zfs_vdev_cache_bshift) >
- zfs_vdev_cache_size) {
- ve = avl_first(&vc->vc_lastused_tree);
- if (ve->ve_fill_io != NULL)
- return (NULL);
- ASSERT3U(ve->ve_hits, !=, 0);
- vdev_cache_evict(vc, ve);
- }
-
- ve = kmem_zalloc(sizeof (vdev_cache_entry_t), KM_SLEEP);
- ve->ve_offset = offset;
- ve->ve_lastused = ddi_get_lbolt();
- ve->ve_abd = abd_alloc_for_io(VCBS, B_TRUE);
-
- avl_add(&vc->vc_offset_tree, ve);
- avl_add(&vc->vc_lastused_tree, ve);
-
- return (ve);
-}
-
-static void
-vdev_cache_hit(vdev_cache_t *vc, vdev_cache_entry_t *ve, zio_t *zio)
-{
- uint64_t cache_phase = P2PHASE(zio->io_offset, VCBS);
-
- ASSERT(MUTEX_HELD(&vc->vc_lock));
- ASSERT3P(ve->ve_fill_io, ==, NULL);
-
- if (ve->ve_lastused != ddi_get_lbolt()) {
- avl_remove(&vc->vc_lastused_tree, ve);
- ve->ve_lastused = ddi_get_lbolt();
- avl_add(&vc->vc_lastused_tree, ve);
- }
-
- ve->ve_hits++;
- abd_copy_off(zio->io_abd, ve->ve_abd, 0, cache_phase, zio->io_size);
-}
-
-/*
- * Fill a previously allocated cache entry with data.
- */
-static void
-vdev_cache_fill(zio_t *fio)
-{
- vdev_t *vd = fio->io_vd;
- vdev_cache_t *vc = &vd->vdev_cache;
- vdev_cache_entry_t *ve = fio->io_private;
- zio_t *pio;
-
- ASSERT3U(fio->io_size, ==, VCBS);
-
- /*
- * Add data to the cache.
- */
- mutex_enter(&vc->vc_lock);
-
- ASSERT3P(ve->ve_fill_io, ==, fio);
- ASSERT3U(ve->ve_offset, ==, fio->io_offset);
- ASSERT3P(ve->ve_abd, ==, fio->io_abd);
-
- ve->ve_fill_io = NULL;
-
- /*
- * Even if this cache line was invalidated by a missed write update,
- * any reads that were queued up before the missed update are still
- * valid, so we can satisfy them from this line before we evict it.
- */
- zio_link_t *zl = NULL;
- while ((pio = zio_walk_parents(fio, &zl)) != NULL)
- vdev_cache_hit(vc, ve, pio);
-
- if (fio->io_error || ve->ve_missed_update)
- vdev_cache_evict(vc, ve);
-
- mutex_exit(&vc->vc_lock);
-}
-
-/*
- * Read data from the cache. Returns B_TRUE cache hit, B_FALSE on miss.
- */
-boolean_t
-vdev_cache_read(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- vdev_cache_entry_t *ve, ve_search;
- uint64_t cache_offset = P2ALIGN(zio->io_offset, VCBS);
- zio_t *fio;
- uint64_t cache_phase __maybe_unused = P2PHASE(zio->io_offset, VCBS);
-
- ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);
-
- if (zfs_vdev_cache_size == 0)
- return (B_FALSE);
-
- if (zio->io_flags & ZIO_FLAG_DONT_CACHE)
- return (B_FALSE);
-
- if (zio->io_size > zfs_vdev_cache_max)
- return (B_FALSE);
-
- /*
- * If the I/O straddles two or more cache blocks, don't cache it.
- */
- if (P2BOUNDARY(zio->io_offset, zio->io_size, VCBS))
- return (B_FALSE);
-
- ASSERT3U(cache_phase + zio->io_size, <=, VCBS);
-
- mutex_enter(&vc->vc_lock);
-
- ve_search.ve_offset = cache_offset;
- ve = avl_find(&vc->vc_offset_tree, &ve_search, NULL);
-
- if (ve != NULL) {
- if (ve->ve_missed_update) {
- mutex_exit(&vc->vc_lock);
- return (B_FALSE);
- }
-
- if ((fio = ve->ve_fill_io) != NULL) {
- zio_vdev_io_bypass(zio);
- zio_add_child(zio, fio);
- mutex_exit(&vc->vc_lock);
- VDCSTAT_BUMP(vdc_stat_delegations);
- return (B_TRUE);
- }
-
- vdev_cache_hit(vc, ve, zio);
- zio_vdev_io_bypass(zio);
-
- mutex_exit(&vc->vc_lock);
- VDCSTAT_BUMP(vdc_stat_hits);
- return (B_TRUE);
- }
-
- ve = vdev_cache_allocate(zio);
-
- if (ve == NULL) {
- mutex_exit(&vc->vc_lock);
- return (B_FALSE);
- }
-
- fio = zio_vdev_delegated_io(zio->io_vd, cache_offset,
- ve->ve_abd, VCBS, ZIO_TYPE_READ, ZIO_PRIORITY_NOW,
- ZIO_FLAG_DONT_CACHE, vdev_cache_fill, ve);
-
- ve->ve_fill_io = fio;
- zio_vdev_io_bypass(zio);
- zio_add_child(zio, fio);
-
- mutex_exit(&vc->vc_lock);
- zio_nowait(fio);
- VDCSTAT_BUMP(vdc_stat_misses);
-
- return (B_TRUE);
-}
-
-/*
- * Update cache contents upon write completion.
- */
-void
-vdev_cache_write(zio_t *zio)
-{
- vdev_cache_t *vc = &zio->io_vd->vdev_cache;
- vdev_cache_entry_t *ve, ve_search;
- uint64_t io_start = zio->io_offset;
- uint64_t io_end = io_start + zio->io_size;
- uint64_t min_offset = P2ALIGN(io_start, VCBS);
- uint64_t max_offset = P2ROUNDUP(io_end, VCBS);
- avl_index_t where;
-
- ASSERT3U(zio->io_type, ==, ZIO_TYPE_WRITE);
-
- mutex_enter(&vc->vc_lock);
-
- ve_search.ve_offset = min_offset;
- ve = avl_find(&vc->vc_offset_tree, &ve_search, &where);
-
- if (ve == NULL)
- ve = avl_nearest(&vc->vc_offset_tree, where, AVL_AFTER);
-
- while (ve != NULL && ve->ve_offset < max_offset) {
- uint64_t start = MAX(ve->ve_offset, io_start);
- uint64_t end = MIN(ve->ve_offset + VCBS, io_end);
-
- if (ve->ve_fill_io != NULL) {
- ve->ve_missed_update = 1;
- } else {
- abd_copy_off(ve->ve_abd, zio->io_abd,
- start - ve->ve_offset, start - io_start,
- end - start);
- }
- ve = AVL_NEXT(&vc->vc_offset_tree, ve);
- }
- mutex_exit(&vc->vc_lock);
-}
-
-void
-vdev_cache_purge(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
- vdev_cache_entry_t *ve;
-
- mutex_enter(&vc->vc_lock);
- while ((ve = avl_first(&vc->vc_offset_tree)) != NULL)
- vdev_cache_evict(vc, ve);
- mutex_exit(&vc->vc_lock);
-}
-
-void
-vdev_cache_init(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
-
- mutex_init(&vc->vc_lock, NULL, MUTEX_DEFAULT, NULL);
-
- avl_create(&vc->vc_offset_tree, vdev_cache_offset_compare,
- sizeof (vdev_cache_entry_t),
- offsetof(struct vdev_cache_entry, ve_offset_node));
-
- avl_create(&vc->vc_lastused_tree, vdev_cache_lastused_compare,
- sizeof (vdev_cache_entry_t),
- offsetof(struct vdev_cache_entry, ve_lastused_node));
-}
-
-void
-vdev_cache_fini(vdev_t *vd)
-{
- vdev_cache_t *vc = &vd->vdev_cache;
-
- vdev_cache_purge(vd);
-
- avl_destroy(&vc->vc_offset_tree);
- avl_destroy(&vc->vc_lastused_tree);
-
- mutex_destroy(&vc->vc_lock);
-}
-
-void
-vdev_cache_stat_init(void)
-{
- vdc_ksp = kstat_create("zfs", 0, "vdev_cache_stats", "misc",
- KSTAT_TYPE_NAMED, sizeof (vdc_stats) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL);
- if (vdc_ksp != NULL) {
- vdc_ksp->ks_data = &vdc_stats;
- kstat_install(vdc_ksp);
- }
-}
-
-void
-vdev_cache_stat_fini(void)
-{
- if (vdc_ksp != NULL) {
- kstat_delete(vdc_ksp);
- vdc_ksp = NULL;
- }
-}
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_max, INT, ZMOD_RW,
- "Inflate reads small than max");
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_size, INT, ZMOD_RD,
- "Total size of the per-disk cache");
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, cache_bshift, INT, ZMOD_RW,
- "Shift size to inflate reads too");
diff --git a/module/zfs/vdev_draid.c b/module/zfs/vdev_draid.c
index fa8daf57b2eb..13bb33cc6871 100644
--- a/module/zfs/vdev_draid.c
+++ b/module/zfs/vdev_draid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -541,7 +541,7 @@ vdev_draid_generate_perms(const draid_map_t *map, uint8_t **permsp)
int
vdev_draid_lookup_map(uint64_t children, const draid_map_t **mapp)
{
- for (int i = 0; i <= VDEV_DRAID_MAX_MAPS; i++) {
+ for (int i = 0; i < VDEV_DRAID_MAX_MAPS; i++) {
if (draid_maps[i].dm_children == children) {
*mapp = &draid_maps[i];
return (0);
@@ -577,8 +577,9 @@ vdev_draid_permute_id(vdev_draid_config_t *vdc,
* i.e. vdev_draid_psize_to_asize().
*/
static uint64_t
-vdev_draid_asize(vdev_t *vd, uint64_t psize)
+vdev_draid_asize(vdev_t *vd, uint64_t psize, uint64_t txg)
{
+ (void) txg;
vdev_draid_config_t *vdc = vd->vdev_tsd;
uint64_t ashift = vd->vdev_ashift;
@@ -960,7 +961,7 @@ vdev_draid_map_alloc_row(zio_t *zio, raidz_row_t **rrp, uint64_t io_offset,
vdev_draid_config_t *vdc = vd->vdev_tsd;
uint64_t ashift = vd->vdev_top->vdev_ashift;
uint64_t io_size = abd_size;
- uint64_t io_asize = vdev_draid_asize(vd, io_size);
+ uint64_t io_asize = vdev_draid_asize(vd, io_size, 0);
uint64_t group = vdev_draid_offset_to_group(vd, io_offset);
uint64_t start_offset = vdev_draid_group_to_offset(vd, group + 1);
@@ -1023,15 +1024,11 @@ vdev_draid_map_alloc_row(zio_t *zio, raidz_row_t **rrp, uint64_t io_offset,
/* The total number of data and parity sectors for this I/O. */
uint64_t tot = psize + (vdc->vdc_nparity * (q + (r == 0 ? 0 : 1)));
- raidz_row_t *rr;
- rr = kmem_alloc(offsetof(raidz_row_t, rr_col[groupwidth]), KM_SLEEP);
- rr->rr_cols = groupwidth;
- rr->rr_scols = groupwidth;
+ ASSERT3U(vdc->vdc_nparity, >, 0);
+
+ raidz_row_t *rr = vdev_raidz_row_alloc(groupwidth);
rr->rr_bigcols = bc;
- rr->rr_missingdata = 0;
- rr->rr_missingparity = 0;
rr->rr_firstdatacol = vdc->vdc_nparity;
- rr->rr_abd_empty = NULL;
#ifdef ZFS_DEBUG
rr->rr_offset = io_offset;
rr->rr_size = io_size;
@@ -1051,14 +1048,6 @@ vdev_draid_map_alloc_row(zio_t *zio, raidz_row_t **rrp, uint64_t io_offset,
rc->rc_devidx = vdev_draid_permute_id(vdc, base, iter, c);
rc->rc_offset = physical_offset;
- rc->rc_abd = NULL;
- rc->rc_orig_data = NULL;
- rc->rc_error = 0;
- rc->rc_tried = 0;
- rc->rc_skipped = 0;
- rc->rc_force_repair = 0;
- rc->rc_allow_repair = 1;
- rc->rc_need_orig_restore = B_FALSE;
if (q == 0 && i >= bc)
rc->rc_size = 0;
@@ -1127,7 +1116,7 @@ vdev_draid_map_alloc(zio_t *zio)
if (size < abd_size) {
vdev_t *vd = zio->io_vd;
- io_offset += vdev_draid_asize(vd, size);
+ io_offset += vdev_draid_asize(vd, size, 0);
abd_offset += size;
abd_size -= size;
nrows++;
@@ -1149,7 +1138,6 @@ vdev_draid_map_alloc(zio_t *zio)
rm->rm_row[0] = rr[0];
if (nrows == 2)
rm->rm_row[1] = rr[1];
-
return (rm);
}
@@ -1496,8 +1484,14 @@ vdev_draid_calculate_asize(vdev_t *vd, uint64_t *asizep, uint64_t *max_asizep,
asize = MIN(asize - 1, cvd->vdev_asize - 1) + 1;
max_asize = MIN(max_asize - 1, cvd->vdev_max_asize - 1) + 1;
logical_ashift = MAX(logical_ashift, cvd->vdev_ashift);
- physical_ashift = MAX(physical_ashift,
- cvd->vdev_physical_ashift);
+ }
+ for (int c = 0; c < vd->vdev_children; c++) {
+ vdev_t *cvd = vd->vdev_child[c];
+
+ if (cvd->vdev_ops == &vdev_draid_spare_ops)
+ continue;
+ physical_ashift = vdev_best_ashift(logical_ashift,
+ physical_ashift, cvd->vdev_physical_ashift);
}
*asizep = asize;
@@ -1775,7 +1769,7 @@ vdev_draid_need_resilver(vdev_t *vd, const dva_t *dva, size_t psize,
uint64_t phys_birth)
{
uint64_t offset = DVA_GET_OFFSET(dva);
- uint64_t asize = vdev_draid_asize(vd, psize);
+ uint64_t asize = vdev_draid_asize(vd, psize, 0);
if (phys_birth == TXG_UNKNOWN) {
/*
@@ -1832,7 +1826,7 @@ vdev_draid_io_verify(vdev_t *vd, raidz_row_t *rr, int col)
range_seg64_t logical_rs, physical_rs, remain_rs;
logical_rs.rs_start = rr->rr_offset;
logical_rs.rs_end = logical_rs.rs_start +
- vdev_draid_asize(vd, rr->rr_size);
+ vdev_draid_asize(vd, rr->rr_size, 0);
raidz_col_t *rc = &rr->rr_col[col];
vdev_t *cvd = vd->vdev_child[rc->rc_devidx];
@@ -2554,24 +2548,20 @@ vdev_draid_read_config_spare(vdev_t *vd)
}
/*
- * Handle any ioctl requested of the distributed spare. Only flushes
- * are supported in which case all children must be flushed.
+ * Handle any flush requested of the distributed spare. All children must be
+ * flushed.
*/
static int
-vdev_draid_spare_ioctl(zio_t *zio)
+vdev_draid_spare_flush(zio_t *zio)
{
vdev_t *vd = zio->io_vd;
int error = 0;
- if (zio->io_cmd == DKIOCFLUSHWRITECACHE) {
- for (int c = 0; c < vd->vdev_children; c++) {
- zio_nowait(zio_vdev_child_io(zio, NULL,
- vd->vdev_child[c], zio->io_offset, zio->io_abd,
- zio->io_size, zio->io_type, zio->io_priority, 0,
- vdev_draid_spare_child_done, zio));
- }
- } else {
- error = SET_ERROR(ENOTSUP);
+ for (int c = 0; c < vd->vdev_children; c++) {
+ zio_nowait(zio_vdev_child_io(zio, NULL,
+ vd->vdev_child[c], zio->io_offset, zio->io_abd,
+ zio->io_size, zio->io_type, zio->io_priority, 0,
+ vdev_draid_spare_child_done, zio));
}
return (error);
@@ -2602,8 +2592,8 @@ vdev_draid_spare_io_start(zio_t *zio)
}
switch (zio->io_type) {
- case ZIO_TYPE_IOCTL:
- zio->io_error = vdev_draid_spare_ioctl(zio);
+ case ZIO_TYPE_FLUSH:
+ zio->io_error = vdev_draid_spare_flush(zio);
break;
case ZIO_TYPE_WRITE:
@@ -2712,7 +2702,7 @@ vdev_draid_spare_lookup(spa_t *spa, nvlist_t *nv, uint64_t *top_guidp,
return (SET_ERROR(ENOENT));
}
- char *spare_name;
+ const char *spare_name;
error = nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &spare_name);
if (error != 0)
return (SET_ERROR(EINVAL));
@@ -2720,7 +2710,7 @@ vdev_draid_spare_lookup(spa_t *spa, nvlist_t *nv, uint64_t *top_guidp,
for (int i = 0; i < nspares; i++) {
nvlist_t *spare = spares[i];
uint64_t top_guid, spare_id;
- char *type, *path;
+ const char *type, *path;
/* Skip non-distributed spares */
error = nvlist_lookup_string(spare, ZPOOL_CONFIG_TYPE, &type);
diff --git a/module/zfs/vdev_indirect.c b/module/zfs/vdev_indirect.c
index 9189d3f31241..acb725696674 100644
--- a/module/zfs/vdev_indirect.c
+++ b/module/zfs/vdev_indirect.c
@@ -181,7 +181,7 @@ static int zfs_condense_indirect_vdevs_enable = B_TRUE;
* condenses. Higher values will condense less often (causing less
* i/o); lower values will reduce the mapping size more quickly.
*/
-static int zfs_condense_indirect_obsolete_pct = 25;
+static uint_t zfs_condense_indirect_obsolete_pct = 25;
/*
* Condense if the obsolete space map takes up more than this amount of
@@ -189,14 +189,14 @@ static int zfs_condense_indirect_obsolete_pct = 25;
* consumed by the obsolete space map; the default of 1GB is small enough
* that we typically don't mind "wasting" it.
*/
-static unsigned long zfs_condense_max_obsolete_bytes = 1024 * 1024 * 1024;
+static uint64_t zfs_condense_max_obsolete_bytes = 1024 * 1024 * 1024;
/*
* Don't bother condensing if the mapping uses less than this amount of
* memory. The default of 128KB is considered a "trivial" amount of
* memory and not worth reducing.
*/
-static unsigned long zfs_condense_min_mapping_bytes = 128 * 1024;
+static uint64_t zfs_condense_min_mapping_bytes = 128 * 1024;
/*
* This is used by the test suite so that it can ensure that certain
@@ -204,7 +204,7 @@ static unsigned long zfs_condense_min_mapping_bytes = 128 * 1024;
* complete too quickly). If used to reduce the performance impact of
* condensing in production, a maximum value of 1 should be sufficient.
*/
-static int zfs_condense_indirect_commit_entry_delay_ms = 0;
+static uint_t zfs_condense_indirect_commit_entry_delay_ms = 0;
/*
* If an indirect split block contains more than this many possible unique
@@ -214,7 +214,7 @@ static int zfs_condense_indirect_commit_entry_delay_ms = 0;
* copies to participate fairly in the reconstruction when all combinations
* cannot be checked and prevents repeated use of one bad copy.
*/
-int zfs_reconstruct_indirect_combinations_max = 4096;
+uint_t zfs_reconstruct_indirect_combinations_max = 4096;
/*
* Enable to simulate damaged segments and validate reconstruction. This
@@ -270,7 +270,7 @@ typedef struct indirect_split {
*/
indirect_child_t *is_good_child;
- indirect_child_t is_child[1]; /* variable-length */
+ indirect_child_t is_child[];
} indirect_split_t;
/*
@@ -293,17 +293,16 @@ vdev_indirect_map_free(zio_t *zio)
indirect_vsd_t *iv = zio->io_vsd;
indirect_split_t *is;
- while ((is = list_head(&iv->iv_splits)) != NULL) {
+ while ((is = list_remove_head(&iv->iv_splits)) != NULL) {
for (int c = 0; c < is->is_children; c++) {
indirect_child_t *ic = &is->is_child[c];
if (ic->ic_data != NULL)
abd_free(ic->ic_data);
}
- list_remove(&iv->iv_splits, is);
indirect_child_t *ic;
- while ((ic = list_head(&is->is_unique_child)) != NULL)
- list_remove(&is->is_unique_child, ic);
+ while ((ic = list_remove_head(&is->is_unique_child)) != NULL)
+ ;
list_destroy(&is->is_unique_child);
@@ -1319,6 +1318,7 @@ vdev_indirect_io_start(zio_t *zio)
vdev_indirect_gather_splits, zio);
indirect_split_t *first = list_head(&iv->iv_splits);
+ ASSERT3P(first, !=, NULL);
if (first->is_size == zio->io_size) {
/*
* This is not a split block; we are pointing to the entire
@@ -1369,9 +1369,10 @@ vdev_indirect_io_start(zio_t *zio)
is != NULL; is = list_next(&iv->iv_splits, is)) {
zio_nowait(zio_vdev_child_io(zio, NULL,
is->is_vdev, is->is_target_offset,
- abd_get_offset(zio->io_abd,
- is->is_split_offset), is->is_size,
- zio->io_type, zio->io_priority, 0,
+ abd_get_offset_size(zio->io_abd,
+ is->is_split_offset, is->is_size),
+ is->is_size, zio->io_type,
+ zio->io_priority, 0,
vdev_indirect_child_io_done, zio));
}
@@ -1397,7 +1398,7 @@ vdev_indirect_checksum_error(zio_t *zio,
vd->vdev_stat.vs_checksum_errors++;
mutex_exit(&vd->vdev_stat_lock);
- zio_bad_cksum_t zbc = {{{ 0 }}};
+ zio_bad_cksum_t zbc = { 0 };
abd_t *bad_abd = ic->ic_data;
abd_t *good_abd = is->is_good_child->ic_data;
(void) zfs_ereport_post_checksum(zio->io_spa, vd, NULL, zio,
@@ -1478,12 +1479,12 @@ vdev_indirect_all_checksum_errors(zio_t *zio)
vdev_t *vd = ic->ic_vdev;
- (void) zfs_ereport_post_checksum(zio->io_spa, vd,
- NULL, zio, is->is_target_offset, is->is_size,
- NULL, NULL, NULL);
mutex_enter(&vd->vdev_stat_lock);
vd->vdev_stat.vs_checksum_errors++;
mutex_exit(&vd->vdev_stat_lock);
+ (void) zfs_ereport_post_checksum(zio->io_spa, vd,
+ NULL, zio, is->is_target_offset, is->is_size,
+ NULL, NULL, NULL);
}
}
}
@@ -1657,8 +1658,8 @@ out:
for (indirect_split_t *is = list_head(&iv->iv_splits);
is != NULL; is = list_next(&iv->iv_splits, is)) {
indirect_child_t *ic;
- while ((ic = list_head(&is->is_unique_child)) != NULL)
- list_remove(&is->is_unique_child, ic);
+ while ((ic = list_remove_head(&is->is_unique_child)) != NULL)
+ ;
is->is_unique_children = 0;
}
@@ -1886,25 +1887,25 @@ EXPORT_SYMBOL(vdev_obsolete_sm_object);
ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, indirect_vdevs_enable, INT,
ZMOD_RW, "Whether to attempt condensing indirect vdev mappings");
-ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, indirect_obsolete_pct, INT,
+ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, indirect_obsolete_pct, UINT,
ZMOD_RW,
"Minimum obsolete percent of bytes in the mapping "
"to attempt condensing");
-ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, min_mapping_bytes, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, min_mapping_bytes, U64, ZMOD_RW,
"Don't bother condensing if the mapping uses less than this amount of "
"memory");
-ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, max_obsolete_bytes, ULONG,
+ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, max_obsolete_bytes, U64,
ZMOD_RW,
"Minimum size obsolete spacemap to attempt condensing");
ZFS_MODULE_PARAM(zfs_condense, zfs_condense_, indirect_commit_entry_delay_ms,
- INT, ZMOD_RW,
+ UINT, ZMOD_RW,
"Used by tests to ensure certain actions happen in the middle of a "
"condense. A maximum value of 1 should be sufficient.");
ZFS_MODULE_PARAM(zfs_reconstruct, zfs_reconstruct_, indirect_combinations_max,
- INT, ZMOD_RW,
+ UINT, ZMOD_RW,
"Maximum number of combinations when reconstructing split segments");
/* END CSTYLED */
diff --git a/module/zfs/vdev_initialize.c b/module/zfs/vdev_initialize.c
index 8945705a0a29..c5e16af16692 100644
--- a/module/zfs/vdev_initialize.c
+++ b/module/zfs/vdev_initialize.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2016, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2016, 2024 by Delphix. All rights reserved.
*/
#include <sys/spa.h>
@@ -36,23 +36,20 @@
/*
* Value that is written to disk during initialization.
*/
-#ifdef _ILP32
-static unsigned long zfs_initialize_value = 0xdeadbeefUL;
-#else
-static unsigned long zfs_initialize_value = 0xdeadbeefdeadbeeeULL;
-#endif
+static uint64_t zfs_initialize_value = 0xdeadbeefdeadbeeeULL;
/* maximum number of I/Os outstanding per leaf vdev */
static const int zfs_initialize_limit = 1;
/* size of initializing writes; default 1MiB, see zfs_remove_max_segment */
-static unsigned long zfs_initialize_chunk_size = 1024 * 1024;
+static uint64_t zfs_initialize_chunk_size = 1024 * 1024;
static boolean_t
vdev_initialize_should_stop(vdev_t *vd)
{
return (vd->vdev_initialize_exit_wanted || !vdev_writeable(vd) ||
- vd->vdev_detached || vd->vdev_top->vdev_removing);
+ vd->vdev_detached || vd->vdev_top->vdev_removing ||
+ vd->vdev_top->vdev_rz_expanding);
}
static void
@@ -71,7 +68,8 @@ vdev_initialize_zap_update_sync(void *arg, dmu_tx_t *tx)
kmem_free(arg, sizeof (uint64_t));
vdev_t *vd = spa_lookup_by_guid(tx->tx_pool->dp_spa, guid, B_FALSE);
- if (vd == NULL || vd->vdev_top->vdev_removing || !vdev_is_concrete(vd))
+ if (vd == NULL || vd->vdev_top->vdev_removing ||
+ !vdev_is_concrete(vd) || vd->vdev_top->vdev_rz_expanding)
return;
uint64_t last_offset = vd->vdev_initialize_offset[txg & TXG_MASK];
@@ -101,6 +99,39 @@ vdev_initialize_zap_update_sync(void *arg, dmu_tx_t *tx)
}
static void
+vdev_initialize_zap_remove_sync(void *arg, dmu_tx_t *tx)
+{
+ uint64_t guid = *(uint64_t *)arg;
+
+ kmem_free(arg, sizeof (uint64_t));
+
+ vdev_t *vd = spa_lookup_by_guid(tx->tx_pool->dp_spa, guid, B_FALSE);
+ if (vd == NULL || vd->vdev_top->vdev_removing || !vdev_is_concrete(vd))
+ return;
+
+ ASSERT3S(vd->vdev_initialize_state, ==, VDEV_INITIALIZE_NONE);
+ ASSERT3U(vd->vdev_leaf_zap, !=, 0);
+
+ vd->vdev_initialize_last_offset = 0;
+ vd->vdev_initialize_action_time = 0;
+
+ objset_t *mos = vd->vdev_spa->spa_meta_objset;
+ int error;
+
+ error = zap_remove(mos, vd->vdev_leaf_zap,
+ VDEV_LEAF_ZAP_INITIALIZE_LAST_OFFSET, tx);
+ VERIFY(error == 0 || error == ENOENT);
+
+ error = zap_remove(mos, vd->vdev_leaf_zap,
+ VDEV_LEAF_ZAP_INITIALIZE_STATE, tx);
+ VERIFY(error == 0 || error == ENOENT);
+
+ error = zap_remove(mos, vd->vdev_leaf_zap,
+ VDEV_LEAF_ZAP_INITIALIZE_ACTION_TIME, tx);
+ VERIFY(error == 0 || error == ENOENT);
+}
+
+static void
vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
{
ASSERT(MUTEX_HELD(&vd->vdev_initialize_lock));
@@ -127,8 +158,14 @@ vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
- dsl_sync_task_nowait(spa_get_dsl(spa), vdev_initialize_zap_update_sync,
- guid, tx);
+
+ if (new_state != VDEV_INITIALIZE_NONE) {
+ dsl_sync_task_nowait(spa_get_dsl(spa),
+ vdev_initialize_zap_update_sync, guid, tx);
+ } else {
+ dsl_sync_task_nowait(spa_get_dsl(spa),
+ vdev_initialize_zap_remove_sync, guid, tx);
+ }
switch (new_state) {
case VDEV_INITIALIZE_ACTIVE:
@@ -149,6 +186,10 @@ vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
spa_history_log_internal(spa, "initialize", tx,
"vdev=%s complete", vd->vdev_path);
break;
+ case VDEV_INITIALIZE_NONE:
+ spa_history_log_internal(spa, "uninitialize", tx,
+ "vdev=%s", vd->vdev_path);
+ break;
default:
panic("invalid state %llu", (unsigned long long)new_state);
}
@@ -261,15 +302,9 @@ vdev_initialize_block_fill(void *buf, size_t len, void *unused)
(void) unused;
ASSERT0(len % sizeof (uint64_t));
-#ifdef _ILP32
- for (uint64_t i = 0; i < len; i += sizeof (uint32_t)) {
- *(uint32_t *)((char *)(buf) + i) = zfs_initialize_value;
- }
-#else
for (uint64_t i = 0; i < len; i += sizeof (uint64_t)) {
*(uint64_t *)((char *)(buf) + i) = zfs_initialize_value;
}
-#endif
return (0);
}
@@ -598,6 +633,7 @@ vdev_initialize(vdev_t *vd)
ASSERT(!vd->vdev_detached);
ASSERT(!vd->vdev_initialize_exit_wanted);
ASSERT(!vd->vdev_top->vdev_removing);
+ ASSERT(!vd->vdev_top->vdev_rz_expanding);
vdev_initialize_change_state(vd, VDEV_INITIALIZE_ACTIVE);
vd->vdev_initialize_thread = thread_create(NULL, 0,
@@ -605,6 +641,24 @@ vdev_initialize(vdev_t *vd)
}
/*
+ * Uninitializes a device. Caller must hold vdev_initialize_lock.
+ * Device must be a leaf and not already be initializing.
+ */
+void
+vdev_uninitialize(vdev_t *vd)
+{
+ ASSERT(MUTEX_HELD(&vd->vdev_initialize_lock));
+ ASSERT(vd->vdev_ops->vdev_op_leaf);
+ ASSERT(vdev_is_concrete(vd));
+ ASSERT3P(vd->vdev_initialize_thread, ==, NULL);
+ ASSERT(!vd->vdev_detached);
+ ASSERT(!vd->vdev_initialize_exit_wanted);
+ ASSERT(!vd->vdev_top->vdev_removing);
+
+ vdev_initialize_change_state(vd, VDEV_INITIALIZE_NONE);
+}
+
+/*
* Wait for the initialize thread to be terminated (cancelled or stopped).
*/
static void
@@ -721,7 +775,8 @@ vdev_initialize_stop_all(vdev_t *vd, vdev_initializing_state_t tgt_state)
void
vdev_initialize_restart(vdev_t *vd)
{
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
+ vd->vdev_spa->spa_load_thread == curthread);
ASSERT(!spa_config_held(vd->vdev_spa, SCL_ALL, RW_WRITER));
if (vd->vdev_leaf_zap != 0) {
@@ -740,13 +795,14 @@ vdev_initialize_restart(vdev_t *vd)
ASSERT(err == 0 || err == ENOENT);
vd->vdev_initialize_action_time = timestamp;
- if (vd->vdev_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
- vd->vdev_offline) {
+ if ((vd->vdev_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
+ vd->vdev_offline) && !vd->vdev_top->vdev_rz_expanding) {
/* load progress for reporting, but don't resume */
VERIFY0(vdev_initialize_load(vd));
} else if (vd->vdev_initialize_state ==
VDEV_INITIALIZE_ACTIVE && vdev_writeable(vd) &&
!vd->vdev_top->vdev_removing &&
+ !vd->vdev_top->vdev_rz_expanding &&
vd->vdev_initialize_thread == NULL) {
vdev_initialize(vd);
}
@@ -760,13 +816,14 @@ vdev_initialize_restart(vdev_t *vd)
}
EXPORT_SYMBOL(vdev_initialize);
+EXPORT_SYMBOL(vdev_uninitialize);
EXPORT_SYMBOL(vdev_initialize_stop);
EXPORT_SYMBOL(vdev_initialize_stop_all);
EXPORT_SYMBOL(vdev_initialize_stop_wait);
EXPORT_SYMBOL(vdev_initialize_restart);
-ZFS_MODULE_PARAM(zfs, zfs_, initialize_value, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, initialize_value, U64, ZMOD_RW,
"Value written during zpool initialize");
-ZFS_MODULE_PARAM(zfs, zfs_, initialize_chunk_size, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, initialize_chunk_size, U64, ZMOD_RW,
"Size in bytes of writes by zpool initialize");
diff --git a/module/zfs/vdev_label.c b/module/zfs/vdev_label.c
index 865710337e63..ed592514fded 100644
--- a/module/zfs/vdev_label.c
+++ b/module/zfs/vdev_label.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -142,6 +142,7 @@
#include <sys/zap.h>
#include <sys/vdev.h>
#include <sys/vdev_impl.h>
+#include <sys/vdev_raidz.h>
#include <sys/vdev_draid.h>
#include <sys/uberblock_impl.h>
#include <sys/metaslab.h>
@@ -423,6 +424,13 @@ root_vdev_actions_getprogress(vdev_t *vd, nvlist_t *nvl)
ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t *)&pcs,
sizeof (pcs) / sizeof (uint64_t));
}
+
+ pool_raidz_expand_stat_t pres;
+ if (spa_raidz_expand_get_stats(spa, &pres) == 0) {
+ fnvlist_add_uint64_array(nvl,
+ ZPOOL_CONFIG_RAIDZ_EXPAND_STATS, (uint64_t *)&pres,
+ sizeof (pres) / sizeof (uint64_t));
+ }
}
static void
@@ -486,6 +494,9 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
if (vd->vdev_isspare)
fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1);
+ if (flags & VDEV_CONFIG_L2CACHE)
+ fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT, vd->vdev_ashift);
+
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
vd == vd->vdev_top) {
fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
@@ -500,7 +511,12 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
fnvlist_add_uint64(nv, ZPOOL_CONFIG_NONALLOCATING,
vd->vdev_noalloc);
}
- if (vd->vdev_removing) {
+
+ /*
+ * Slog devices are removed synchronously so don't
+ * persist the vdev_removing flag to the label.
+ */
+ if (vd->vdev_removing && !vd->vdev_islog) {
fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
vd->vdev_removing);
}
@@ -568,6 +584,12 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
vd->vdev_top_zap);
}
+ if (vd->vdev_ops == &vdev_root_ops && vd->vdev_root_zap != 0 &&
+ spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2)) {
+ fnvlist_add_uint64(nv, ZPOOL_CONFIG_VDEV_ROOT_ZAP,
+ vd->vdev_root_zap);
+ }
+
if (vd->vdev_resilver_deferred) {
ASSERT(vd->vdev_ops->vdev_op_leaf);
ASSERT(spa->spa_resilver_deferred);
@@ -644,35 +666,22 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
if (!vd->vdev_ops->vdev_op_leaf) {
nvlist_t **child;
- int c, idx;
+ uint64_t c;
ASSERT(!vd->vdev_ishole);
child = kmem_alloc(vd->vdev_children * sizeof (nvlist_t *),
KM_SLEEP);
- for (c = 0, idx = 0; c < vd->vdev_children; c++) {
- vdev_t *cvd = vd->vdev_child[c];
-
- /*
- * If we're generating an nvlist of removing
- * vdevs then skip over any device which is
- * not being removed.
- */
- if ((flags & VDEV_CONFIG_REMOVING) &&
- !cvd->vdev_removing)
- continue;
-
- child[idx++] = vdev_config_generate(spa, cvd,
+ for (c = 0; c < vd->vdev_children; c++) {
+ child[c] = vdev_config_generate(spa, vd->vdev_child[c],
getstats, flags);
}
- if (idx) {
- fnvlist_add_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
- (const nvlist_t * const *)child, idx);
- }
+ fnvlist_add_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
+ (const nvlist_t * const *)child, vd->vdev_children);
- for (c = 0; c < idx; c++)
+ for (c = 0; c < vd->vdev_children; c++)
nvlist_free(child[c]);
kmem_free(child, vd->vdev_children * sizeof (nvlist_t *));
@@ -1022,6 +1031,10 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
int error;
uint64_t spare_guid = 0, l2cache_guid = 0;
int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL;
+ boolean_t reason_spare = (reason == VDEV_LABEL_SPARE || (reason ==
+ VDEV_LABEL_REMOVE && vd->vdev_isspare));
+ boolean_t reason_l2cache = (reason == VDEV_LABEL_L2CACHE || (reason ==
+ VDEV_LABEL_REMOVE && vd->vdev_isl2cache));
ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
@@ -1107,36 +1120,58 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
* really part of an active pool just yet. The labels will
* be written again with a meaningful txg by spa_sync().
*/
- if (reason == VDEV_LABEL_SPARE ||
- (reason == VDEV_LABEL_REMOVE && vd->vdev_isspare)) {
+ if (reason_spare || reason_l2cache) {
/*
- * For inactive hot spares, we generate a special label that
- * identifies as a mutually shared hot spare. We write the
- * label if we are adding a hot spare, or if we are removing an
- * active hot spare (in which case we want to revert the
- * labels).
+ * For inactive hot spares and level 2 ARC devices, we generate
+ * a special label that identifies as a mutually shared hot
+ * spare or l2cache device. We write the label in case of
+ * addition or removal of hot spare or l2cache vdev (in which
+ * case we want to revert the labels).
*/
VERIFY(nvlist_alloc(&label, NV_UNIQUE_NAME, KM_SLEEP) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_VERSION,
spa_version(spa)) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_POOL_STATE,
- POOL_STATE_SPARE) == 0);
+ reason_spare ? POOL_STATE_SPARE : POOL_STATE_L2CACHE) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_GUID,
vd->vdev_guid) == 0);
- } else if (reason == VDEV_LABEL_L2CACHE ||
- (reason == VDEV_LABEL_REMOVE && vd->vdev_isl2cache)) {
+
/*
- * For level 2 ARC devices, add a special label.
+ * This is merely to facilitate reporting the ashift of the
+ * cache device through zdb. The actual retrieval of the
+ * ashift (in vdev_alloc()) uses the nvlist
+ * spa->spa_l2cache->sav_config (populated in
+ * spa_ld_open_aux_vdevs()).
*/
- VERIFY(nvlist_alloc(&label, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ if (reason_l2cache) {
+ VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_ASHIFT,
+ vd->vdev_ashift) == 0);
+ }
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_VERSION,
- spa_version(spa)) == 0);
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_POOL_STATE,
- POOL_STATE_L2CACHE) == 0);
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_GUID,
- vd->vdev_guid) == 0);
+ /*
+ * Add path information to help find it during pool import
+ */
+ if (vd->vdev_path != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_PATH,
+ vd->vdev_path) == 0);
+ }
+ if (vd->vdev_devid != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_DEVID,
+ vd->vdev_devid) == 0);
+ }
+ if (vd->vdev_physpath != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_PHYS_PATH,
+ vd->vdev_physpath) == 0);
+ }
+
+ /*
+ * When spare or l2cache (aux) vdev is added during pool
+ * creation, spa->spa_uberblock is not written until this
+ * point. Write it on next config sync.
+ */
+ if (uberblock_verify(&spa->spa_uberblock))
+ spa->spa_aux_sync_uber = B_TRUE;
} else {
uint64_t txg = 0ULL;
@@ -1168,8 +1203,9 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
* Initialize uberblock template.
*/
ub_abd = abd_alloc_linear(VDEV_UBERBLOCK_RING, B_TRUE);
- abd_zero(ub_abd, VDEV_UBERBLOCK_RING);
abd_copy_from_buf(ub_abd, &spa->spa_uberblock, sizeof (uberblock_t));
+ abd_zero_off(ub_abd, sizeof (uberblock_t),
+ VDEV_UBERBLOCK_RING - sizeof (uberblock_t));
ub = abd_to_buf(ub_abd);
ub->ub_txg = 0;
@@ -1359,6 +1395,7 @@ vdev_label_write_bootenv(vdev_t *vd, nvlist_t *env)
int error;
size_t nvsize;
char *nvbuf;
+ const char *tmp;
error = nvlist_size(env, &nvsize, NV_ENCODE_XDR);
if (error != 0)
@@ -1398,8 +1435,8 @@ vdev_label_write_bootenv(vdev_t *vd, nvlist_t *env)
bootenv->vbe_version = fnvlist_lookup_uint64(env, BOOTENV_VERSION);
switch (bootenv->vbe_version) {
case VB_RAW:
- if (nvlist_lookup_string(env, GRUB_ENVMAP, &nvbuf) == 0) {
- (void) strlcpy(bootenv->vbe_bootenv, nvbuf, nvsize);
+ if (nvlist_lookup_string(env, GRUB_ENVMAP, &tmp) == 0) {
+ (void) strlcpy(bootenv->vbe_bootenv, tmp, nvsize);
}
error = 0;
break;
@@ -1492,7 +1529,8 @@ vdev_uberblock_compare(const uberblock_t *ub1, const uberblock_t *ub2)
}
struct ubl_cbdata {
- uberblock_t *ubl_ubbest; /* Best uberblock */
+ uberblock_t ubl_latest; /* Most recent uberblock */
+ uberblock_t *ubl_ubbest; /* Best uberblock (w/r/t max_txg) */
vdev_t *ubl_vd; /* vdev associated with the above */
};
@@ -1509,6 +1547,9 @@ vdev_uberblock_load_done(zio_t *zio)
if (zio->io_error == 0 && uberblock_verify(ub) == 0) {
mutex_enter(&rio->io_lock);
+ if (vdev_uberblock_compare(ub, &cbp->ubl_latest) > 0) {
+ cbp->ubl_latest = *ub;
+ }
if (ub->ub_txg <= spa->spa_load_max_txg &&
vdev_uberblock_compare(ub, cbp->ubl_ubbest) > 0) {
/*
@@ -1566,10 +1607,10 @@ vdev_uberblock_load(vdev_t *rvd, uberblock_t *ub, nvlist_t **config)
ASSERT(config);
memset(ub, 0, sizeof (uberblock_t));
+ memset(&cb, 0, sizeof (cb));
*config = NULL;
cb.ubl_ubbest = ub;
- cb.ubl_vd = NULL;
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
zio = zio_root(spa, NULL, &cb, flags);
@@ -1586,6 +1627,22 @@ vdev_uberblock_load(vdev_t *rvd, uberblock_t *ub, nvlist_t **config)
vdev_dbgmsg(cb.ubl_vd, "best uberblock found for spa %s. "
"txg %llu", spa->spa_name, (u_longlong_t)ub->ub_txg);
+ if (ub->ub_raidz_reflow_info !=
+ cb.ubl_latest.ub_raidz_reflow_info) {
+ vdev_dbgmsg(cb.ubl_vd,
+ "spa=%s best uberblock (txg=%llu info=0x%llx) "
+ "has different raidz_reflow_info than latest "
+ "uberblock (txg=%llu info=0x%llx)",
+ spa->spa_name,
+ (u_longlong_t)ub->ub_txg,
+ (u_longlong_t)ub->ub_raidz_reflow_info,
+ (u_longlong_t)cb.ubl_latest.ub_txg,
+ (u_longlong_t)cb.ubl_latest.ub_raidz_reflow_info);
+ memset(ub, 0, sizeof (uberblock_t));
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ return;
+ }
+
*config = vdev_label_read_config(cb.ubl_vd, ub->ub_txg);
if (*config == NULL && spa->spa_extreme_rewind) {
vdev_dbgmsg(cb.ubl_vd, "failed to read label config. "
@@ -1707,13 +1764,29 @@ vdev_uberblock_sync(zio_t *zio, uint64_t *good_writes,
vd->vdev_copy_uberblocks = B_FALSE;
}
+ /*
+ * We chose a slot based on the txg. If this uberblock has a special
+ * RAIDZ expansion state, then it is essentially an update of the
+ * current uberblock (it has the same txg). However, the current
+ * state is committed, so we want to write it to a different slot. If
+ * we overwrote the same slot, and we lose power during the uberblock
+ * write, and the disk does not do single-sector overwrites
+ * atomically (even though it is required to - i.e. we should see
+ * either the old or the new uberblock), then we could lose this
+ * txg's uberblock. Rewinding to the previous txg's uberblock may not
+ * be possible because RAIDZ expansion may have already overwritten
+ * some of the data, so we need the progress indicator in the
+ * uberblock.
+ */
int m = spa_multihost(vd->vdev_spa) ? MMP_BLOCKS_PER_LABEL : 0;
- int n = ub->ub_txg % (VDEV_UBERBLOCK_COUNT(vd) - m);
+ int n = (ub->ub_txg - (RRSS_GET_STATE(ub) == RRSS_SCRATCH_VALID)) %
+ (VDEV_UBERBLOCK_COUNT(vd) - m);
/* Copy the uberblock_t into the ABD */
abd_t *ub_abd = abd_alloc_for_io(VDEV_UBERBLOCK_SIZE(vd), B_TRUE);
- abd_zero(ub_abd, VDEV_UBERBLOCK_SIZE(vd));
abd_copy_from_buf(ub_abd, ub, sizeof (uberblock_t));
+ abd_zero_off(ub_abd, sizeof (uberblock_t),
+ VDEV_UBERBLOCK_SIZE(vd) - sizeof (uberblock_t));
for (int l = 0; l < VDEV_LABELS; l++)
vdev_label_write(zio, vd, l, ub_abd,
@@ -1725,7 +1798,7 @@ vdev_uberblock_sync(zio_t *zio, uint64_t *good_writes,
}
/* Sync the uberblocks to all vdevs in svd[] */
-static int
+int
vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
{
spa_t *spa = svd[0]->vdev_spa;
@@ -1737,6 +1810,16 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
for (int v = 0; v < svdcount; v++)
vdev_uberblock_sync(zio, &good_writes, ub, svd[v], flags);
+ if (spa->spa_aux_sync_uber) {
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_spares.sav_vdevs[v], flags);
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_l2cache.sav_vdevs[v], flags);
+ }
+ }
(void) zio_wait(zio);
/*
@@ -1751,6 +1834,19 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
zio_flush(zio, svd[v]);
}
}
+ if (spa->spa_aux_sync_uber) {
+ spa->spa_aux_sync_uber = B_FALSE;
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ if (vdev_writeable(spa->spa_spares.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_spares.sav_vdevs[v]);
+ }
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ if (vdev_writeable(spa->spa_l2cache.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_l2cache.sav_vdevs[v]);
+ }
+ }
+ }
(void) zio_wait(zio);
@@ -1931,6 +2027,7 @@ retry:
/*
* If this isn't a resync due to I/O errors,
* and nothing changed in this transaction group,
+ * and multihost protection isn't enabled,
* and the vdev configuration hasn't changed,
* then there's nothing to do.
*/
@@ -1938,7 +2035,8 @@ retry:
boolean_t changed = uberblock_update(ub, spa->spa_root_vdev,
txg, spa->spa_mmp.mmp_delay);
- if (!changed && list_is_empty(&spa->spa_config_dirty_list))
+ if (!changed && list_is_empty(&spa->spa_config_dirty_list) &&
+ !spa_multihost(spa))
return (0);
}
diff --git a/module/zfs/vdev_mirror.c b/module/zfs/vdev_mirror.c
index b869718677e0..102eacb03349 100644
--- a/module/zfs/vdev_mirror.c
+++ b/module/zfs/vdev_mirror.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -409,8 +409,14 @@ vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize,
*asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1;
*max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1;
*logical_ashift = MAX(*logical_ashift, cvd->vdev_ashift);
- *physical_ashift = MAX(*physical_ashift,
- cvd->vdev_physical_ashift);
+ }
+ for (int c = 0; c < vd->vdev_children; c++) {
+ vdev_t *cvd = vd->vdev_child[c];
+
+ if (cvd->vdev_open_error)
+ continue;
+ *physical_ashift = vdev_best_ashift(*logical_ashift,
+ *physical_ashift, cvd->vdev_physical_ashift);
}
if (numerrors == vd->vdev_children) {
@@ -525,7 +531,7 @@ vdev_mirror_child_select(zio_t *zio)
uint64_t txg = zio->io_txg;
int c, lowest_load;
- ASSERT(zio->io_bp == NULL || BP_PHYSICAL_BIRTH(zio->io_bp) == txg);
+ ASSERT(zio->io_bp == NULL || BP_GET_BIRTH(zio->io_bp) == txg);
lowest_load = INT_MAX;
mm->mm_preferred_cnt = 0;
diff --git a/module/zfs/vdev_missing.c b/module/zfs/vdev_missing.c
index 505df23c1fb2..d3580882c3e0 100644
--- a/module/zfs/vdev_missing.c
+++ b/module/zfs/vdev_missing.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c
index 0cad5839bb34..092b3f375be0 100644
--- a/module/zfs/vdev_queue.c
+++ b/module/zfs/vdev_queue.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -121,7 +121,7 @@
* The maximum number of i/os active to each device. Ideally, this will be >=
* the sum of each queue's max_active.
*/
-uint32_t zfs_vdev_max_active = 1000;
+uint_t zfs_vdev_max_active = 1000;
/*
* Per-queue limits on the number of i/os active to each device. If the
@@ -141,24 +141,24 @@ uint32_t zfs_vdev_max_active = 1000;
* more quickly, but reads and writes to have higher latency and lower
* throughput.
*/
-static uint32_t zfs_vdev_sync_read_min_active = 10;
-static uint32_t zfs_vdev_sync_read_max_active = 10;
-static uint32_t zfs_vdev_sync_write_min_active = 10;
-static uint32_t zfs_vdev_sync_write_max_active = 10;
-static uint32_t zfs_vdev_async_read_min_active = 1;
-/* */ uint32_t zfs_vdev_async_read_max_active = 3;
-static uint32_t zfs_vdev_async_write_min_active = 2;
-/* */ uint32_t zfs_vdev_async_write_max_active = 10;
-static uint32_t zfs_vdev_scrub_min_active = 1;
-static uint32_t zfs_vdev_scrub_max_active = 3;
-static uint32_t zfs_vdev_removal_min_active = 1;
-static uint32_t zfs_vdev_removal_max_active = 2;
-static uint32_t zfs_vdev_initializing_min_active = 1;
-static uint32_t zfs_vdev_initializing_max_active = 1;
-static uint32_t zfs_vdev_trim_min_active = 1;
-static uint32_t zfs_vdev_trim_max_active = 2;
-static uint32_t zfs_vdev_rebuild_min_active = 1;
-static uint32_t zfs_vdev_rebuild_max_active = 3;
+static uint_t zfs_vdev_sync_read_min_active = 10;
+static uint_t zfs_vdev_sync_read_max_active = 10;
+static uint_t zfs_vdev_sync_write_min_active = 10;
+static uint_t zfs_vdev_sync_write_max_active = 10;
+static uint_t zfs_vdev_async_read_min_active = 1;
+/* */ uint_t zfs_vdev_async_read_max_active = 3;
+static uint_t zfs_vdev_async_write_min_active = 2;
+/* */ uint_t zfs_vdev_async_write_max_active = 10;
+static uint_t zfs_vdev_scrub_min_active = 1;
+static uint_t zfs_vdev_scrub_max_active = 3;
+static uint_t zfs_vdev_removal_min_active = 1;
+static uint_t zfs_vdev_removal_max_active = 2;
+static uint_t zfs_vdev_initializing_min_active = 1;
+static uint_t zfs_vdev_initializing_max_active = 1;
+static uint_t zfs_vdev_trim_min_active = 1;
+static uint_t zfs_vdev_trim_max_active = 2;
+static uint_t zfs_vdev_rebuild_min_active = 1;
+static uint_t zfs_vdev_rebuild_max_active = 3;
/*
* When the pool has less than zfs_vdev_async_write_active_min_dirty_percent
@@ -167,8 +167,8 @@ static uint32_t zfs_vdev_rebuild_max_active = 3;
* zfs_vdev_async_write_max_active. The value is linearly interpolated
* between min and max.
*/
-int zfs_vdev_async_write_active_min_dirty_percent = 30;
-int zfs_vdev_async_write_active_max_dirty_percent = 60;
+uint_t zfs_vdev_async_write_active_min_dirty_percent = 30;
+uint_t zfs_vdev_async_write_active_max_dirty_percent = 60;
/*
* For non-interactive I/O (scrub, resilver, removal, initialize and rebuild),
@@ -198,10 +198,10 @@ static uint_t zfs_vdev_nia_credit = 5;
* we include spans of optional I/Os to aid aggregation at the disk even when
* they aren't able to help us aggregate at this level.
*/
-static int zfs_vdev_aggregation_limit = 1 << 20;
-static int zfs_vdev_aggregation_limit_non_rotating = SPA_OLD_MAXBLOCKSIZE;
-static int zfs_vdev_read_gap_limit = 32 << 10;
-static int zfs_vdev_write_gap_limit = 4 << 10;
+static uint_t zfs_vdev_aggregation_limit = 1 << 20;
+static uint_t zfs_vdev_aggregation_limit_non_rotating = SPA_OLD_MAXBLOCKSIZE;
+static uint_t zfs_vdev_read_gap_limit = 32 << 10;
+static uint_t zfs_vdev_write_gap_limit = 4 << 10;
/*
* Define the queue depth percentage for each top-level. This percentage is
@@ -214,9 +214,9 @@ static int zfs_vdev_write_gap_limit = 4 << 10;
* to 30 allocations per device.
*/
#ifdef _KERNEL
-int zfs_vdev_queue_depth_pct = 1000;
+uint_t zfs_vdev_queue_depth_pct = 1000;
#else
-int zfs_vdev_queue_depth_pct = 300;
+uint_t zfs_vdev_queue_depth_pct = 300;
#endif
/*
@@ -226,14 +226,7 @@ int zfs_vdev_queue_depth_pct = 300;
* we assume that the average allocation size is 4k, so we need the queue depth
* to be 32 per allocator to get good aggregation of sequential writes.
*/
-int zfs_vdev_def_queue_depth = 32;
-
-/*
- * Allow TRIM I/Os to be aggregated. This should normally not be needed since
- * TRIM I/O for extents up to zfs_trim_extent_bytes_max (128M) can be submitted
- * by the TRIM code in zfs_trim.c.
- */
-static int zfs_vdev_aggregate_trim = 0;
+uint_t zfs_vdev_def_queue_depth = 32;
static int
vdev_queue_offset_compare(const void *x1, const void *x2)
@@ -249,39 +242,64 @@ vdev_queue_offset_compare(const void *x1, const void *x2)
return (TREE_PCMP(z1, z2));
}
-static inline avl_tree_t *
-vdev_queue_class_tree(vdev_queue_t *vq, zio_priority_t p)
-{
- return (&vq->vq_class[p].vqc_queued_tree);
-}
-
-static inline avl_tree_t *
-vdev_queue_type_tree(vdev_queue_t *vq, zio_type_t t)
-{
- ASSERT(t == ZIO_TYPE_READ || t == ZIO_TYPE_WRITE || t == ZIO_TYPE_TRIM);
- if (t == ZIO_TYPE_READ)
- return (&vq->vq_read_offset_tree);
- else if (t == ZIO_TYPE_WRITE)
- return (&vq->vq_write_offset_tree);
- else
- return (&vq->vq_trim_offset_tree);
-}
+#define VDQ_T_SHIFT 29
static int
-vdev_queue_timestamp_compare(const void *x1, const void *x2)
+vdev_queue_to_compare(const void *x1, const void *x2)
{
const zio_t *z1 = (const zio_t *)x1;
const zio_t *z2 = (const zio_t *)x2;
- int cmp = TREE_CMP(z1->io_timestamp, z2->io_timestamp);
+ int tcmp = TREE_CMP(z1->io_timestamp >> VDQ_T_SHIFT,
+ z2->io_timestamp >> VDQ_T_SHIFT);
+ int ocmp = TREE_CMP(z1->io_offset, z2->io_offset);
+ int cmp = tcmp ? tcmp : ocmp;
- if (likely(cmp))
+ if (likely(cmp | (z1->io_queue_state == ZIO_QS_NONE)))
return (cmp);
return (TREE_PCMP(z1, z2));
}
-static int
+static inline boolean_t
+vdev_queue_class_fifo(zio_priority_t p)
+{
+ return (p == ZIO_PRIORITY_SYNC_READ || p == ZIO_PRIORITY_SYNC_WRITE ||
+ p == ZIO_PRIORITY_TRIM);
+}
+
+static void
+vdev_queue_class_add(vdev_queue_t *vq, zio_t *zio)
+{
+ zio_priority_t p = zio->io_priority;
+ vq->vq_cqueued |= 1U << p;
+ if (vdev_queue_class_fifo(p)) {
+ list_insert_tail(&vq->vq_class[p].vqc_list, zio);
+ vq->vq_class[p].vqc_list_numnodes++;
+ }
+ else
+ avl_add(&vq->vq_class[p].vqc_tree, zio);
+}
+
+static void
+vdev_queue_class_remove(vdev_queue_t *vq, zio_t *zio)
+{
+ zio_priority_t p = zio->io_priority;
+ uint32_t empty;
+ if (vdev_queue_class_fifo(p)) {
+ list_t *list = &vq->vq_class[p].vqc_list;
+ list_remove(list, zio);
+ empty = list_is_empty(list);
+ vq->vq_class[p].vqc_list_numnodes--;
+ } else {
+ avl_tree_t *tree = &vq->vq_class[p].vqc_tree;
+ avl_remove(tree, zio);
+ empty = avl_is_empty(tree);
+ }
+ vq->vq_cqueued &= ~(empty << p);
+}
+
+static uint_t
vdev_queue_class_min_active(vdev_queue_t *vq, zio_priority_t p)
{
switch (p) {
@@ -313,10 +331,10 @@ vdev_queue_class_min_active(vdev_queue_t *vq, zio_priority_t p)
}
}
-static int
+static uint_t
vdev_queue_max_async_writes(spa_t *spa)
{
- int writes;
+ uint_t writes;
uint64_t dirty = 0;
dsl_pool_t *dp = spa_get_dsl(spa);
uint64_t min_bytes = zfs_dirty_data_max *
@@ -359,8 +377,8 @@ vdev_queue_max_async_writes(spa_t *spa)
return (writes);
}
-static int
-vdev_queue_class_max_active(spa_t *spa, vdev_queue_t *vq, zio_priority_t p)
+static uint_t
+vdev_queue_class_max_active(vdev_queue_t *vq, zio_priority_t p)
{
switch (p) {
case ZIO_PRIORITY_SYNC_READ:
@@ -370,7 +388,7 @@ vdev_queue_class_max_active(spa_t *spa, vdev_queue_t *vq, zio_priority_t p)
case ZIO_PRIORITY_ASYNC_READ:
return (zfs_vdev_async_read_max_active);
case ZIO_PRIORITY_ASYNC_WRITE:
- return (vdev_queue_max_async_writes(spa));
+ return (vdev_queue_max_async_writes(vq->vq_vdev->vdev_spa));
case ZIO_PRIORITY_SCRUB:
if (vq->vq_ia_active > 0) {
return (MIN(vq->vq_nia_credit,
@@ -414,10 +432,10 @@ vdev_queue_class_max_active(spa_t *spa, vdev_queue_t *vq, zio_priority_t p)
static zio_priority_t
vdev_queue_class_to_issue(vdev_queue_t *vq)
{
- spa_t *spa = vq->vq_vdev->vdev_spa;
- zio_priority_t p, n;
+ uint32_t cq = vq->vq_cqueued;
+ zio_priority_t p, p1;
- if (avl_numnodes(&vq->vq_active_tree) >= zfs_vdev_max_active)
+ if (cq == 0 || vq->vq_active >= zfs_vdev_max_active)
return (ZIO_PRIORITY_NUM_QUEUEABLE);
/*
@@ -425,14 +443,18 @@ vdev_queue_class_to_issue(vdev_queue_t *vq)
* Do round-robin to reduce starvation due to zfs_vdev_max_active
* and vq_nia_credit limits.
*/
- for (n = 0; n < ZIO_PRIORITY_NUM_QUEUEABLE; n++) {
- p = (vq->vq_last_prio + n + 1) % ZIO_PRIORITY_NUM_QUEUEABLE;
- if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 &&
- vq->vq_class[p].vqc_active <
- vdev_queue_class_min_active(vq, p)) {
- vq->vq_last_prio = p;
- return (p);
- }
+ p1 = vq->vq_last_prio + 1;
+ if (p1 >= ZIO_PRIORITY_NUM_QUEUEABLE)
+ p1 = 0;
+ for (p = p1; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) {
+ if ((cq & (1U << p)) != 0 && vq->vq_cactive[p] <
+ vdev_queue_class_min_active(vq, p))
+ goto found;
+ }
+ for (p = 0; p < p1; p++) {
+ if ((cq & (1U << p)) != 0 && vq->vq_cactive[p] <
+ vdev_queue_class_min_active(vq, p))
+ goto found;
}
/*
@@ -440,16 +462,14 @@ vdev_queue_class_to_issue(vdev_queue_t *vq)
* maximum # outstanding i/os.
*/
for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) {
- if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 &&
- vq->vq_class[p].vqc_active <
- vdev_queue_class_max_active(spa, vq, p)) {
- vq->vq_last_prio = p;
- return (p);
- }
+ if ((cq & (1U << p)) != 0 && vq->vq_cactive[p] <
+ vdev_queue_class_max_active(vq, p))
+ break;
}
- /* No eligible queued i/os */
- return (ZIO_PRIORITY_NUM_QUEUEABLE);
+found:
+ vq->vq_last_prio = p;
+ return (p);
}
void
@@ -458,42 +478,30 @@ vdev_queue_init(vdev_t *vd)
vdev_queue_t *vq = &vd->vdev_queue;
zio_priority_t p;
- mutex_init(&vq->vq_lock, NULL, MUTEX_DEFAULT, NULL);
vq->vq_vdev = vd;
- taskq_init_ent(&vd->vdev_queue.vq_io_search.io_tqent);
-
- avl_create(&vq->vq_active_tree, vdev_queue_offset_compare,
- sizeof (zio_t), offsetof(struct zio, io_queue_node));
- avl_create(vdev_queue_type_tree(vq, ZIO_TYPE_READ),
- vdev_queue_offset_compare, sizeof (zio_t),
- offsetof(struct zio, io_offset_node));
- avl_create(vdev_queue_type_tree(vq, ZIO_TYPE_WRITE),
- vdev_queue_offset_compare, sizeof (zio_t),
- offsetof(struct zio, io_offset_node));
- avl_create(vdev_queue_type_tree(vq, ZIO_TYPE_TRIM),
- vdev_queue_offset_compare, sizeof (zio_t),
- offsetof(struct zio, io_offset_node));
for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) {
- int (*compfn) (const void *, const void *);
-
- /*
- * The synchronous/trim i/o queues are dispatched in FIFO rather
- * than LBA order. This provides more consistent latency for
- * these i/os.
- */
- if (p == ZIO_PRIORITY_SYNC_READ ||
- p == ZIO_PRIORITY_SYNC_WRITE ||
- p == ZIO_PRIORITY_TRIM) {
- compfn = vdev_queue_timestamp_compare;
+ if (vdev_queue_class_fifo(p)) {
+ list_create(&vq->vq_class[p].vqc_list,
+ sizeof (zio_t),
+ offsetof(struct zio, io_queue_node.l));
} else {
- compfn = vdev_queue_offset_compare;
+ avl_create(&vq->vq_class[p].vqc_tree,
+ vdev_queue_to_compare, sizeof (zio_t),
+ offsetof(struct zio, io_queue_node.a));
}
- avl_create(vdev_queue_class_tree(vq, p), compfn,
- sizeof (zio_t), offsetof(struct zio, io_queue_node));
}
+ avl_create(&vq->vq_read_offset_tree,
+ vdev_queue_offset_compare, sizeof (zio_t),
+ offsetof(struct zio, io_offset_node));
+ avl_create(&vq->vq_write_offset_tree,
+ vdev_queue_offset_compare, sizeof (zio_t),
+ offsetof(struct zio, io_offset_node));
vq->vq_last_offset = 0;
+ list_create(&vq->vq_active_list, sizeof (struct zio),
+ offsetof(struct zio, io_queue_node.l));
+ mutex_init(&vq->vq_lock, NULL, MUTEX_DEFAULT, NULL);
}
void
@@ -501,30 +509,39 @@ vdev_queue_fini(vdev_t *vd)
{
vdev_queue_t *vq = &vd->vdev_queue;
- for (zio_priority_t p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++)
- avl_destroy(vdev_queue_class_tree(vq, p));
- avl_destroy(&vq->vq_active_tree);
- avl_destroy(vdev_queue_type_tree(vq, ZIO_TYPE_READ));
- avl_destroy(vdev_queue_type_tree(vq, ZIO_TYPE_WRITE));
- avl_destroy(vdev_queue_type_tree(vq, ZIO_TYPE_TRIM));
+ for (zio_priority_t p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) {
+ if (vdev_queue_class_fifo(p))
+ list_destroy(&vq->vq_class[p].vqc_list);
+ else
+ avl_destroy(&vq->vq_class[p].vqc_tree);
+ }
+ avl_destroy(&vq->vq_read_offset_tree);
+ avl_destroy(&vq->vq_write_offset_tree);
+ list_destroy(&vq->vq_active_list);
mutex_destroy(&vq->vq_lock);
}
static void
vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio)
{
- ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE);
- avl_add(vdev_queue_class_tree(vq, zio->io_priority), zio);
- avl_add(vdev_queue_type_tree(vq, zio->io_type), zio);
+ zio->io_queue_state = ZIO_QS_QUEUED;
+ vdev_queue_class_add(vq, zio);
+ if (zio->io_type == ZIO_TYPE_READ)
+ avl_add(&vq->vq_read_offset_tree, zio);
+ else if (zio->io_type == ZIO_TYPE_WRITE)
+ avl_add(&vq->vq_write_offset_tree, zio);
}
static void
vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio)
{
- ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE);
- avl_remove(vdev_queue_class_tree(vq, zio->io_priority), zio);
- avl_remove(vdev_queue_type_tree(vq, zio->io_type), zio);
+ vdev_queue_class_remove(vq, zio);
+ if (zio->io_type == ZIO_TYPE_READ)
+ avl_remove(&vq->vq_read_offset_tree, zio);
+ else if (zio->io_type == ZIO_TYPE_WRITE)
+ avl_remove(&vq->vq_write_offset_tree, zio);
+ zio->io_queue_state = ZIO_QS_NONE;
}
static boolean_t
@@ -546,14 +563,16 @@ vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio)
{
ASSERT(MUTEX_HELD(&vq->vq_lock));
ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE);
- vq->vq_class[zio->io_priority].vqc_active++;
+ vq->vq_cactive[zio->io_priority]++;
+ vq->vq_active++;
if (vdev_queue_is_interactive(zio->io_priority)) {
if (++vq->vq_ia_active == 1)
vq->vq_nia_credit = 1;
} else if (vq->vq_ia_active > 0) {
vq->vq_nia_credit--;
}
- avl_add(&vq->vq_active_tree, zio);
+ zio->io_queue_state = ZIO_QS_ACTIVE;
+ list_insert_tail(&vq->vq_active_list, zio);
}
static void
@@ -561,7 +580,8 @@ vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio)
{
ASSERT(MUTEX_HELD(&vq->vq_lock));
ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE);
- vq->vq_class[zio->io_priority].vqc_active--;
+ vq->vq_cactive[zio->io_priority]--;
+ vq->vq_active--;
if (vdev_queue_is_interactive(zio->io_priority)) {
if (--vq->vq_ia_active == 0)
vq->vq_nia_credit = 0;
@@ -569,7 +589,8 @@ vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio)
vq->vq_nia_credit = zfs_vdev_nia_credit;
} else if (vq->vq_ia_active == 0)
vq->vq_nia_credit++;
- avl_remove(&vq->vq_active_tree, zio);
+ list_remove(&vq->vq_active_list, zio);
+ zio->io_queue_state = ZIO_QS_NONE;
}
static void
@@ -602,29 +623,28 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
uint64_t maxgap = 0;
uint64_t size;
uint64_t limit;
- int maxblocksize;
boolean_t stretch = B_FALSE;
- avl_tree_t *t = vdev_queue_type_tree(vq, zio->io_type);
- enum zio_flag flags = zio->io_flags & ZIO_FLAG_AGG_INHERIT;
uint64_t next_offset;
abd_t *abd;
+ avl_tree_t *t;
+
+ /*
+ * TRIM aggregation should not be needed since code in zfs_trim.c can
+ * submit TRIM I/O for extents up to zfs_trim_extent_bytes_max (128M).
+ */
+ if (zio->io_type == ZIO_TYPE_TRIM)
+ return (NULL);
+
+ if (zio->io_flags & ZIO_FLAG_DONT_AGGREGATE)
+ return (NULL);
- maxblocksize = spa_maxblocksize(vq->vq_vdev->vdev_spa);
if (vq->vq_vdev->vdev_nonrot)
limit = zfs_vdev_aggregation_limit_non_rotating;
else
limit = zfs_vdev_aggregation_limit;
- limit = MAX(MIN(limit, maxblocksize), 0);
-
- if (zio->io_flags & ZIO_FLAG_DONT_AGGREGATE || limit == 0)
- return (NULL);
-
- /*
- * While TRIM commands could be aggregated based on offset this
- * behavior is disabled until it's determined to be beneficial.
- */
- if (zio->io_type == ZIO_TYPE_TRIM && !zfs_vdev_aggregate_trim)
+ if (limit == 0)
return (NULL);
+ limit = MIN(limit, SPA_MAXBLOCKSIZE);
/*
* I/Os to distributed spares are directly dispatched to the dRAID
@@ -635,8 +655,13 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
first = last = zio;
- if (zio->io_type == ZIO_TYPE_READ)
+ if (zio->io_type == ZIO_TYPE_READ) {
maxgap = zfs_vdev_read_gap_limit;
+ t = &vq->vq_read_offset_tree;
+ } else {
+ ASSERT3U(zio->io_type, ==, ZIO_TYPE_WRITE);
+ t = &vq->vq_write_offset_tree;
+ }
/*
* We can aggregate I/Os that are sufficiently adjacent and of
@@ -657,6 +682,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
* Walk backwards through sufficiently contiguous I/Os
* recording the last non-optional I/O.
*/
+ zio_flag_t flags = zio->io_flags & ZIO_FLAG_AGG_INHERIT;
while ((dio = AVL_PREV(t, first)) != NULL &&
(dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags &&
IO_SPAN(dio, last) <= limit &&
@@ -686,7 +712,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
(dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags &&
(IO_SPAN(first, dio) <= limit ||
(dio->io_flags & ZIO_FLAG_OPTIONAL)) &&
- IO_SPAN(first, dio) <= maxblocksize &&
+ IO_SPAN(first, dio) <= SPA_MAXBLOCKSIZE &&
IO_GAP(last, dio) <= maxgap &&
dio->io_type == zio->io_type) {
last = dio;
@@ -725,6 +751,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
* after our span is mandatory.
*/
dio = AVL_NEXT(t, last);
+ ASSERT3P(dio, !=, NULL);
dio->io_flags &= ~ZIO_FLAG_OPTIONAL;
} else {
/* do not include the optional i/o */
@@ -739,7 +766,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
return (NULL);
size = IO_SPAN(first, last);
- ASSERT3U(size, <=, maxblocksize);
+ ASSERT3U(size, <=, SPA_MAXBLOCKSIZE);
abd = abd_alloc_gang();
if (abd == NULL)
@@ -747,8 +774,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
aio = zio_vdev_delegated_io(first->io_vd, first->io_offset,
abd, size, first->io_type, zio->io_priority,
- flags | ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE,
- vdev_queue_agg_io_done, NULL);
+ flags | ZIO_FLAG_DONT_QUEUE, vdev_queue_agg_io_done, NULL);
aio->io_timestamp = first->io_timestamp;
nio = first;
@@ -756,6 +782,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
do {
dio = nio;
nio = AVL_NEXT(t, dio);
+ ASSERT3P(dio, !=, NULL);
zio_add_child(dio, aio);
vdev_queue_io_remove(vq, dio);
@@ -823,19 +850,30 @@ again:
return (NULL);
}
- /*
- * For LBA-ordered queues (async / scrub / initializing), issue the
- * i/o which follows the most recently issued i/o in LBA (offset) order.
- *
- * For FIFO queues (sync/trim), issue the i/o with the lowest timestamp.
- */
- tree = vdev_queue_class_tree(vq, p);
- vq->vq_io_search.io_timestamp = 0;
- vq->vq_io_search.io_offset = vq->vq_last_offset - 1;
- VERIFY3P(avl_find(tree, &vq->vq_io_search, &idx), ==, NULL);
- zio = avl_nearest(tree, idx, AVL_AFTER);
- if (zio == NULL)
- zio = avl_first(tree);
+ if (vdev_queue_class_fifo(p)) {
+ zio = list_head(&vq->vq_class[p].vqc_list);
+ } else {
+ /*
+ * For LBA-ordered queues (async / scrub / initializing),
+ * issue the I/O which follows the most recently issued I/O
+ * in LBA (offset) order, but to avoid starvation only within
+ * the same 0.5 second interval as the first I/O.
+ */
+ tree = &vq->vq_class[p].vqc_tree;
+ zio = aio = avl_first(tree);
+ if (zio->io_offset < vq->vq_last_offset) {
+ vq->vq_io_search.io_timestamp = zio->io_timestamp;
+ vq->vq_io_search.io_offset = vq->vq_last_offset;
+ zio = avl_find(tree, &vq->vq_io_search, &idx);
+ if (zio == NULL) {
+ zio = avl_nearest(tree, idx, AVL_AFTER);
+ if (zio == NULL ||
+ (zio->io_timestamp >> VDQ_T_SHIFT) !=
+ (aio->io_timestamp >> VDQ_T_SHIFT))
+ zio = aio;
+ }
+ }
+ }
ASSERT3U(zio->io_priority, ==, p);
aio = vdev_queue_aggregate(vq, zio);
@@ -905,7 +943,7 @@ vdev_queue_io(zio_t *zio)
ASSERT(zio->io_priority == ZIO_PRIORITY_TRIM);
}
- zio->io_flags |= ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE;
+ zio->io_flags |= ZIO_FLAG_DONT_QUEUE;
zio->io_timestamp = gethrtime();
mutex_enter(&vq->vq_lock);
@@ -966,7 +1004,6 @@ void
vdev_queue_change_io_priority(zio_t *zio, zio_priority_t priority)
{
vdev_queue_t *vq = &zio->io_vd->vdev_queue;
- avl_tree_t *tree;
/*
* ZIO_PRIORITY_NOW is used by the vdev cache code and the aggregate zio
@@ -1001,12 +1038,11 @@ vdev_queue_change_io_priority(zio_t *zio, zio_priority_t priority)
* Otherwise, the zio is currently active and we cannot change its
* priority.
*/
- tree = vdev_queue_class_tree(vq, zio->io_priority);
- if (avl_find(tree, zio, NULL) == zio) {
- avl_remove(vdev_queue_class_tree(vq, zio->io_priority), zio);
+ if (zio->io_queue_state == ZIO_QS_QUEUED) {
+ vdev_queue_class_remove(vq, zio);
zio->io_priority = priority;
- avl_add(vdev_queue_class_tree(vq, zio->io_priority), zio);
- } else if (avl_find(&vq->vq_active_tree, zio, NULL) != zio) {
+ vdev_queue_class_add(vq, zio);
+ } else if (zio->io_queue_state == ZIO_QS_NONE) {
zio->io_priority = priority;
}
@@ -1019,10 +1055,10 @@ vdev_queue_change_io_priority(zio_t *zio, zio_priority_t priority)
* vq_lock mutex use here, instead we prefer to keep it lock free for
* performance.
*/
-int
+uint32_t
vdev_queue_length(vdev_t *vd)
{
- return (avl_numnodes(&vd->vdev_queue.vq_active_tree));
+ return (vd->vdev_queue.vq_active);
}
uint64_t
@@ -1031,89 +1067,99 @@ vdev_queue_last_offset(vdev_t *vd)
return (vd->vdev_queue.vq_last_offset);
}
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, aggregation_limit, INT, ZMOD_RW,
+uint64_t
+vdev_queue_class_length(vdev_t *vd, zio_priority_t p)
+{
+ vdev_queue_t *vq = &vd->vdev_queue;
+ if (vdev_queue_class_fifo(p))
+ return (vq->vq_class[p].vqc_list_numnodes);
+ else
+ return (avl_numnodes(&vq->vq_class[p].vqc_tree));
+}
+
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, aggregation_limit, UINT, ZMOD_RW,
"Max vdev I/O aggregation size");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, aggregation_limit_non_rotating, INT,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, aggregation_limit_non_rotating, UINT,
ZMOD_RW, "Max vdev I/O aggregation size for non-rotating media");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, aggregate_trim, INT, ZMOD_RW,
- "Allow TRIM I/O to be aggregated");
-
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, read_gap_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, read_gap_limit, UINT, ZMOD_RW,
"Aggregate read I/O over gap");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, write_gap_limit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, write_gap_limit, UINT, ZMOD_RW,
"Aggregate write I/O over gap");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, max_active, UINT, ZMOD_RW,
"Maximum number of active I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_active_max_dirty_percent, INT,
- ZMOD_RW, "Async write concurrency max threshold");
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_active_max_dirty_percent,
+ UINT, ZMOD_RW, "Async write concurrency max threshold");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_active_min_dirty_percent, INT,
- ZMOD_RW, "Async write concurrency min threshold");
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_active_min_dirty_percent,
+ UINT, ZMOD_RW, "Async write concurrency min threshold");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_read_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_read_max_active, UINT, ZMOD_RW,
"Max active async read I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_read_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_read_min_active, UINT, ZMOD_RW,
"Min active async read I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_max_active, UINT, ZMOD_RW,
"Max active async write I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, async_write_min_active, UINT, ZMOD_RW,
"Min active async write I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, initializing_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, initializing_max_active, UINT, ZMOD_RW,
"Max active initializing I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, initializing_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, initializing_min_active, UINT, ZMOD_RW,
"Min active initializing I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, removal_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, removal_max_active, UINT, ZMOD_RW,
"Max active removal I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, removal_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, removal_min_active, UINT, ZMOD_RW,
"Min active removal I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, scrub_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, scrub_max_active, UINT, ZMOD_RW,
"Max active scrub I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, scrub_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, scrub_min_active, UINT, ZMOD_RW,
"Min active scrub I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_read_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_read_max_active, UINT, ZMOD_RW,
"Max active sync read I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_read_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_read_min_active, UINT, ZMOD_RW,
"Min active sync read I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_write_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_write_max_active, UINT, ZMOD_RW,
"Max active sync write I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_write_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, sync_write_min_active, UINT, ZMOD_RW,
"Min active sync write I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, trim_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, trim_max_active, UINT, ZMOD_RW,
"Max active trim/discard I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, trim_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, trim_min_active, UINT, ZMOD_RW,
"Min active trim/discard I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, rebuild_max_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, rebuild_max_active, UINT, ZMOD_RW,
"Max active rebuild I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, rebuild_min_active, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, rebuild_min_active, UINT, ZMOD_RW,
"Min active rebuild I/Os per vdev");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, nia_credit, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, nia_credit, UINT, ZMOD_RW,
"Number of non-interactive I/Os to allow in sequence");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, nia_delay, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, nia_delay, UINT, ZMOD_RW,
"Number of non-interactive I/Os before _max_active");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, queue_depth_pct, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, queue_depth_pct, UINT, ZMOD_RW,
"Queue depth percentage for each top-level vdev");
+
+ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, def_queue_depth, UINT, ZMOD_RW,
+ "Default queue depth for each allocator");
diff --git a/module/zfs/vdev_raidz.c b/module/zfs/vdev_raidz.c
index 3633937f462b..de7d0fa79478 100644
--- a/module/zfs/vdev_raidz.c
+++ b/module/zfs/vdev_raidz.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -27,15 +27,22 @@
#include <sys/zfs_context.h>
#include <sys/spa.h>
+#include <sys/spa_impl.h>
+#include <sys/zap.h>
#include <sys/vdev_impl.h>
+#include <sys/metaslab_impl.h>
#include <sys/zio.h>
#include <sys/zio_checksum.h>
+#include <sys/dmu_tx.h>
#include <sys/abd.h>
+#include <sys/zfs_rlock.h>
#include <sys/fs/zfs.h>
#include <sys/fm/fs/zfs.h>
#include <sys/vdev_raidz.h>
#include <sys/vdev_raidz_impl.h>
#include <sys/vdev_draid.h>
+#include <sys/uberblock_impl.h>
+#include <sys/dsl_scan.h>
#ifdef ZFS_DEBUG
#include <sys/vdev.h> /* For vdev_xlate() in vdev_raidz_io_verify() */
@@ -135,6 +142,237 @@
VDEV_RAIDZ_64MUL_2((x), mask); \
}
+
+/*
+ * Big Theory Statement for how a RAIDZ VDEV is expanded
+ *
+ * An existing RAIDZ VDEV can be expanded by attaching a new disk. Expansion
+ * works with all three RAIDZ parity choices, including RAIDZ1, 2, or 3. VDEVs
+ * that have been previously expanded can be expanded again.
+ *
+ * The RAIDZ VDEV must be healthy (must be able to write to all the drives in
+ * the VDEV) when an expansion starts. And the expansion will pause if any
+ * disk in the VDEV fails, and resume once the VDEV is healthy again. All other
+ * operations on the pool can continue while an expansion is in progress (e.g.
+ * read/write, snapshot, zpool add, etc). Except zpool checkpoint, zpool trim,
+ * and zpool initialize which can't be run during an expansion. Following a
+ * reboot or export/import, the expansion resumes where it left off.
+ *
+ * == Reflowing the Data ==
+ *
+ * The expansion involves reflowing (copying) the data from the current set
+ * of disks to spread it across the new set which now has one more disk. This
+ * reflow operation is similar to reflowing text when the column width of a
+ * text editor window is expanded. The text doesn’t change but the location of
+ * the text changes to accommodate the new width. An example reflow result for
+ * a 4-wide RAIDZ1 to a 5-wide is shown below.
+ *
+ * Reflow End State
+ * Each letter indicates a parity group (logical stripe)
+ *
+ * Before expansion After Expansion
+ * D1 D2 D3 D4 D1 D2 D3 D4 D5
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | A | A | A | A | | A | A | A | A | B |
+ * | 1| 2| 3| 4| | 1| 2| 3| 4| 5|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | B | B | C | C | | B | C | C | C | C |
+ * | 5| 6| 7| 8| | 6| 7| 8| 9| 10|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | C | C | D | D | | D | D | E | E | E |
+ * | 9| 10| 11| 12| | 11| 12| 13| 14| 15|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | E | E | E | E | --> | E | F | F | G | G |
+ * | 13| 14| 15| 16| | 16| 17| 18|p 19| 20|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | F | F | G | G | | G | G | H | H | H |
+ * | 17| 18| 19| 20| | 21| 22| 23| 24| 25|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | G | G | H | H | | H | I | I | J | J |
+ * | 21| 22| 23| 24| | 26| 27| 28| 29| 30|
+ * +------+------+------+------+ +------+------+------+------+------+
+ * | | | | | | | | | | |
+ * | H | H | I | I | | J | J | | | K |
+ * | 25| 26| 27| 28| | 31| 32| 33| 34| 35|
+ * +------+------+------+------+ +------+------+------+------+------+
+ *
+ * This reflow approach has several advantages. There is no need to read or
+ * modify the block pointers or recompute any block checksums. The reflow
+ * doesn’t need to know where the parity sectors reside. We can read and write
+ * data sequentially and the copy can occur in a background thread in open
+ * context. The design also allows for fast discovery of what data to copy.
+ *
+ * The VDEV metaslabs are processed, one at a time, to copy the block data to
+ * have it flow across all the disks. The metaslab is disabled for allocations
+ * during the copy. As an optimization, we only copy the allocated data which
+ * can be determined by looking at the metaslab range tree. During the copy we
+ * must maintain the redundancy guarantees of the RAIDZ VDEV (i.e., we still
+ * need to be able to survive losing parity count disks). This means we
+ * cannot overwrite data during the reflow that would be needed if a disk is
+ * lost.
+ *
+ * After the reflow completes, all newly-written blocks will have the new
+ * layout, i.e., they will have the parity to data ratio implied by the new
+ * number of disks in the RAIDZ group. Even though the reflow copies all of
+ * the allocated space (data and parity), it is only rearranged, not changed.
+ *
+ * This act of reflowing the data has a few implications about blocks
+ * that were written before the reflow completes:
+ *
+ * - Old blocks will still use the same amount of space (i.e., they will have
+ * the parity to data ratio implied by the old number of disks in the RAIDZ
+ * group).
+ * - Reading old blocks will be slightly slower than before the reflow, for
+ * two reasons. First, we will have to read from all disks in the RAIDZ
+ * VDEV, rather than being able to skip the children that contain only
+ * parity of this block (because the data of a single block is now spread
+ * out across all the disks). Second, in most cases there will be an extra
+ * bcopy, needed to rearrange the data back to its original layout in memory.
+ *
+ * == Scratch Area ==
+ *
+ * As we copy the block data, we can only progress to the point that writes
+ * will not overlap with blocks whose progress has not yet been recorded on
+ * disk. Since partially-copied rows are always read from the old location,
+ * we need to stop one row before the sector-wise overlap, to prevent any
+ * row-wise overlap. For example, in the diagram above, when we reflow sector
+ * B6 it will overwite the original location for B5.
+ *
+ * To get around this, a scratch space is used so that we can start copying
+ * without risking data loss by overlapping the row. As an added benefit, it
+ * improves performance at the beginning of the reflow, but that small perf
+ * boost wouldn't be worth the complexity on its own.
+ *
+ * Ideally we want to copy at least 2 * (new_width)^2 so that we have a
+ * separation of 2*(new_width+1) and a chunk size of new_width+2. With the max
+ * RAIDZ width of 255 and 4K sectors this would be 2MB per disk. In practice
+ * the widths will likely be single digits so we can get a substantial chuck
+ * size using only a few MB of scratch per disk.
+ *
+ * The scratch area is persisted to disk which holds a large amount of reflowed
+ * state. We can always read the partially written stripes when a disk fails or
+ * the copy is interrupted (crash) during the initial copying phase and also
+ * get past a small chunk size restriction. At a minimum, the scratch space
+ * must be large enough to get us to the point that one row does not overlap
+ * itself when moved (i.e new_width^2). But going larger is even better. We
+ * use the 3.5 MiB reserved "boot" space that resides after the ZFS disk labels
+ * as our scratch space to handle overwriting the initial part of the VDEV.
+ *
+ * 0 256K 512K 4M
+ * +------+------+-----------------------+-----------------------------
+ * | VDEV | VDEV | Boot Block (3.5M) | Allocatable space ...
+ * | L0 | L1 | Reserved | (Metaslabs)
+ * +------+------+-----------------------+-------------------------------
+ * Scratch Area
+ *
+ * == Reflow Progress Updates ==
+ * After the initial scratch-based reflow, the expansion process works
+ * similarly to device removal. We create a new open context thread which
+ * reflows the data, and periodically kicks off sync tasks to update logical
+ * state. In this case, state is the committed progress (offset of next data
+ * to copy). We need to persist the completed offset on disk, so that if we
+ * crash we know which format each VDEV offset is in.
+ *
+ * == Time Dependent Geometry ==
+ *
+ * In non-expanded RAIDZ, blocks are read from disk in a column by column
+ * fashion. For a multi-row block, the second sector is in the first column
+ * not in the second column. This allows us to issue full reads for each
+ * column directly into the request buffer. The block data is thus laid out
+ * sequentially in a column-by-column fashion.
+ *
+ * For example, in the before expansion diagram above, one logical block might
+ * be sectors G19-H26. The parity is in G19,H23; and the data is in
+ * G20,H24,G21,H25,G22,H26.
+ *
+ * After a block is reflowed, the sectors that were all in the original column
+ * data can now reside in different columns. When reading from an expanded
+ * VDEV, we need to know the logical stripe width for each block so we can
+ * reconstitute the block’s data after the reads are completed. Likewise,
+ * when we perform the combinatorial reconstruction we need to know the
+ * original width so we can retry combinations from the past layouts.
+ *
+ * Time dependent geometry is what we call having blocks with different layouts
+ * (stripe widths) in the same VDEV. This time-dependent geometry uses the
+ * block’s birth time (+ the time expansion ended) to establish the correct
+ * width for a given block. After an expansion completes, we record the time
+ * for blocks written with a particular width (geometry).
+ *
+ * == On Disk Format Changes ==
+ *
+ * New pool feature flag, 'raidz_expansion' whose reference count is the number
+ * of RAIDZ VDEVs that have been expanded.
+ *
+ * The blocks on expanded RAIDZ VDEV can have different logical stripe widths.
+ *
+ * Since the uberblock can point to arbitrary blocks, which might be on the
+ * expanding RAIDZ, and might or might not have been expanded. We need to know
+ * which way a block is laid out before reading it. This info is the next
+ * offset that needs to be reflowed and we persist that in the uberblock, in
+ * the new ub_raidz_reflow_info field, as opposed to the MOS or the vdev label.
+ * After the expansion is complete, we then use the raidz_expand_txgs array
+ * (see below) to determine how to read a block and the ub_raidz_reflow_info
+ * field no longer required.
+ *
+ * The uberblock's ub_raidz_reflow_info field also holds the scratch space
+ * state (i.e., active or not) which is also required before reading a block
+ * during the initial phase of reflowing the data.
+ *
+ * The top-level RAIDZ VDEV has two new entries in the nvlist:
+ *
+ * 'raidz_expand_txgs' array: logical stripe widths by txg are recorded here
+ * and used after the expansion is complete to
+ * determine how to read a raidz block
+ * 'raidz_expanding' boolean: present during reflow and removed after completion
+ * used during a spa import to resume an unfinished
+ * expansion
+ *
+ * And finally the VDEVs top zap adds the following informational entries:
+ * VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE
+ * VDEV_TOP_ZAP_RAIDZ_EXPAND_START_TIME
+ * VDEV_TOP_ZAP_RAIDZ_EXPAND_END_TIME
+ * VDEV_TOP_ZAP_RAIDZ_EXPAND_BYTES_COPIED
+ */
+
+/*
+ * For testing only: pause the raidz expansion after reflowing this amount.
+ * (accessed by ZTS and ztest)
+ */
+#ifdef _KERNEL
+static
+#endif /* _KERNEL */
+unsigned long raidz_expand_max_reflow_bytes = 0;
+
+/*
+ * For testing only: pause the raidz expansion at a certain point.
+ */
+uint_t raidz_expand_pause_point = 0;
+
+/*
+ * Maximum amount of copy io's outstanding at once.
+ */
+static unsigned long raidz_expand_max_copy_bytes = 10 * SPA_MAXBLOCKSIZE;
+
+/*
+ * Apply raidz map abds aggregation if the number of rows in the map is equal
+ * or greater than the value below.
+ */
+static unsigned long raidz_io_aggregate_rows = 4;
+
+/*
+ * Automatically start a pool scrub when a RAIDZ expansion completes in
+ * order to verify the checksums of all blocks which have been copied
+ * during the expansion. Automatic scrubbing is enabled by default and
+ * is strongly recommended.
+ */
+static int zfs_scrub_after_expand = 1;
+
static void
vdev_raidz_row_free(raidz_row_t *rr)
{
@@ -159,6 +397,17 @@ vdev_raidz_map_free(raidz_map_t *rm)
for (int i = 0; i < rm->rm_nrows; i++)
vdev_raidz_row_free(rm->rm_row[i]);
+ if (rm->rm_nphys_cols) {
+ for (int i = 0; i < rm->rm_nphys_cols; i++) {
+ if (rm->rm_phys_col[i].rc_abd != NULL)
+ abd_free(rm->rm_phys_col[i].rc_abd);
+ }
+
+ kmem_free(rm->rm_phys_col, sizeof (raidz_col_t) *
+ rm->rm_nphys_cols);
+ }
+
+ ASSERT3P(rm->rm_lr, ==, NULL);
kmem_free(rm, offsetof(raidz_map_t, rm_row[rm->rm_nrows]));
}
@@ -170,10 +419,37 @@ vdev_raidz_map_free_vsd(zio_t *zio)
vdev_raidz_map_free(rm);
}
+static int
+vdev_raidz_reflow_compare(const void *x1, const void *x2)
+{
+ const reflow_node_t *l = x1;
+ const reflow_node_t *r = x2;
+
+ return (TREE_CMP(l->re_txg, r->re_txg));
+}
+
const zio_vsd_ops_t vdev_raidz_vsd_ops = {
.vsd_free = vdev_raidz_map_free_vsd,
};
+raidz_row_t *
+vdev_raidz_row_alloc(int cols)
+{
+ raidz_row_t *rr =
+ kmem_zalloc(offsetof(raidz_row_t, rr_col[cols]), KM_SLEEP);
+
+ rr->rr_cols = cols;
+ rr->rr_scols = cols;
+
+ for (int c = 0; c < cols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ rc->rc_shadow_devidx = INT_MAX;
+ rc->rc_shadow_offset = UINT64_MAX;
+ rc->rc_allow_repair = 1;
+ }
+ return (rr);
+}
+
static void
vdev_raidz_map_alloc_write(zio_t *zio, raidz_map_t *rm, uint64_t ashift)
{
@@ -302,7 +578,7 @@ vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols,
uint64_t f = b % dcols;
/* The starting byte offset on each child vdev. */
uint64_t o = (b / dcols) << ashift;
- uint64_t q, r, c, bc, col, acols, scols, coff, devidx, asize, tot;
+ uint64_t acols, scols;
raidz_map_t *rm =
kmem_zalloc(offsetof(raidz_map_t, rm_row[1]), KM_SLEEP);
@@ -312,22 +588,22 @@ vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols,
* "Quotient": The number of data sectors for this stripe on all but
* the "big column" child vdevs that also contain "remainder" data.
*/
- q = s / (dcols - nparity);
+ uint64_t q = s / (dcols - nparity);
/*
* "Remainder": The number of partial stripe data sectors in this I/O.
* This will add a sector to some, but not all, child vdevs.
*/
- r = s - q * (dcols - nparity);
+ uint64_t r = s - q * (dcols - nparity);
/* The number of "big columns" - those which contain remainder data. */
- bc = (r == 0 ? 0 : r + nparity);
+ uint64_t bc = (r == 0 ? 0 : r + nparity);
/*
* The total number of data and parity sectors associated with
* this I/O.
*/
- tot = s + nparity * (q + (r == 0 ? 0 : 1));
+ uint64_t tot = s + nparity * (q + (r == 0 ? 0 : 1));
/*
* acols: The columns that will be accessed.
@@ -343,43 +619,28 @@ vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols,
}
ASSERT3U(acols, <=, scols);
-
- rr = kmem_alloc(offsetof(raidz_row_t, rr_col[scols]), KM_SLEEP);
+ rr = vdev_raidz_row_alloc(scols);
rm->rm_row[0] = rr;
-
rr->rr_cols = acols;
- rr->rr_scols = scols;
rr->rr_bigcols = bc;
- rr->rr_missingdata = 0;
- rr->rr_missingparity = 0;
rr->rr_firstdatacol = nparity;
- rr->rr_abd_empty = NULL;
- rr->rr_nempty = 0;
#ifdef ZFS_DEBUG
rr->rr_offset = zio->io_offset;
rr->rr_size = zio->io_size;
#endif
- asize = 0;
+ uint64_t asize = 0;
- for (c = 0; c < scols; c++) {
+ for (uint64_t c = 0; c < scols; c++) {
raidz_col_t *rc = &rr->rr_col[c];
- col = f + c;
- coff = o;
+ uint64_t col = f + c;
+ uint64_t coff = o;
if (col >= dcols) {
col -= dcols;
coff += 1ULL << ashift;
}
rc->rc_devidx = col;
rc->rc_offset = coff;
- rc->rc_abd = NULL;
- rc->rc_orig_data = NULL;
- rc->rc_error = 0;
- rc->rc_tried = 0;
- rc->rc_skipped = 0;
- rc->rc_force_repair = 0;
- rc->rc_allow_repair = 1;
- rc->rc_need_orig_restore = B_FALSE;
if (c >= acols)
rc->rc_size = 0;
@@ -419,13 +680,12 @@ vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols,
ASSERT(rr->rr_col[0].rc_size == rr->rr_col[1].rc_size);
if (rr->rr_firstdatacol == 1 && (zio->io_offset & (1ULL << 20))) {
- devidx = rr->rr_col[0].rc_devidx;
+ uint64_t devidx = rr->rr_col[0].rc_devidx;
o = rr->rr_col[0].rc_offset;
rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx;
rr->rr_col[0].rc_offset = rr->rr_col[1].rc_offset;
rr->rr_col[1].rc_devidx = devidx;
rr->rr_col[1].rc_offset = o;
-
if (rm->rm_skipstart == 0)
rm->rm_skipstart = 1;
}
@@ -435,7 +695,338 @@ vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols,
} else {
vdev_raidz_map_alloc_read(zio, rm);
}
+ /* init RAIDZ parity ops */
+ rm->rm_ops = vdev_raidz_math_get_ops();
+ return (rm);
+}
+
+/*
+ * Everything before reflow_offset_synced should have been moved to the new
+ * location (read and write completed). However, this may not yet be reflected
+ * in the on-disk format (e.g. raidz_reflow_sync() has been called but the
+ * uberblock has not yet been written). If reflow is not in progress,
+ * reflow_offset_synced should be UINT64_MAX. For each row, if the row is
+ * entirely before reflow_offset_synced, it will come from the new location.
+ * Otherwise this row will come from the old location. Therefore, rows that
+ * straddle the reflow_offset_synced will come from the old location.
+ *
+ * For writes, reflow_offset_next is the next offset to copy. If a sector has
+ * been copied, but not yet reflected in the on-disk progress
+ * (reflow_offset_synced), it will also be written to the new (already copied)
+ * offset.
+ */
+noinline raidz_map_t *
+vdev_raidz_map_alloc_expanded(zio_t *zio,
+ uint64_t ashift, uint64_t physical_cols, uint64_t logical_cols,
+ uint64_t nparity, uint64_t reflow_offset_synced,
+ uint64_t reflow_offset_next, boolean_t use_scratch)
+{
+ abd_t *abd = zio->io_abd;
+ uint64_t offset = zio->io_offset;
+ uint64_t size = zio->io_size;
+
+ /* The zio's size in units of the vdev's minimum sector size. */
+ uint64_t s = size >> ashift;
+
+ /*
+ * "Quotient": The number of data sectors for this stripe on all but
+ * the "big column" child vdevs that also contain "remainder" data.
+ * AKA "full rows"
+ */
+ uint64_t q = s / (logical_cols - nparity);
+
+ /*
+ * "Remainder": The number of partial stripe data sectors in this I/O.
+ * This will add a sector to some, but not all, child vdevs.
+ */
+ uint64_t r = s - q * (logical_cols - nparity);
+
+ /* The number of "big columns" - those which contain remainder data. */
+ uint64_t bc = (r == 0 ? 0 : r + nparity);
+
+ /*
+ * The total number of data and parity sectors associated with
+ * this I/O.
+ */
+ uint64_t tot = s + nparity * (q + (r == 0 ? 0 : 1));
+
+ /* How many rows contain data (not skip) */
+ uint64_t rows = howmany(tot, logical_cols);
+ int cols = MIN(tot, logical_cols);
+
+ raidz_map_t *rm =
+ kmem_zalloc(offsetof(raidz_map_t, rm_row[rows]),
+ KM_SLEEP);
+ rm->rm_nrows = rows;
+ rm->rm_nskip = roundup(tot, nparity + 1) - tot;
+ rm->rm_skipstart = bc;
+ uint64_t asize = 0;
+
+ for (uint64_t row = 0; row < rows; row++) {
+ boolean_t row_use_scratch = B_FALSE;
+ raidz_row_t *rr = vdev_raidz_row_alloc(cols);
+ rm->rm_row[row] = rr;
+
+ /* The starting RAIDZ (parent) vdev sector of the row. */
+ uint64_t b = (offset >> ashift) + row * logical_cols;
+
+ /*
+ * If we are in the middle of a reflow, and the copying has
+ * not yet completed for any part of this row, then use the
+ * old location of this row. Note that reflow_offset_synced
+ * reflects the i/o that's been completed, because it's
+ * updated by a synctask, after zio_wait(spa_txg_zio[]).
+ * This is sufficient for our check, even if that progress
+ * has not yet been recorded to disk (reflected in
+ * spa_ubsync). Also note that we consider the last row to
+ * be "full width" (`cols`-wide rather than `bc`-wide) for
+ * this calculation. This causes a tiny bit of unnecessary
+ * double-writes but is safe and simpler to calculate.
+ */
+ int row_phys_cols = physical_cols;
+ if (b + cols > reflow_offset_synced >> ashift)
+ row_phys_cols--;
+ else if (use_scratch)
+ row_use_scratch = B_TRUE;
+
+ /* starting child of this row */
+ uint64_t child_id = b % row_phys_cols;
+ /* The starting byte offset on each child vdev. */
+ uint64_t child_offset = (b / row_phys_cols) << ashift;
+
+ /*
+ * Note, rr_cols is the entire width of the block, even
+ * if this row is shorter. This is needed because parity
+ * generation (for Q and R) needs to know the entire width,
+ * because it treats the short row as though it was
+ * full-width (and the "phantom" sectors were zero-filled).
+ *
+ * Another approach to this would be to set cols shorter
+ * (to just the number of columns that we might do i/o to)
+ * and have another mechanism to tell the parity generation
+ * about the "entire width". Reconstruction (at least
+ * vdev_raidz_reconstruct_general()) would also need to
+ * know about the "entire width".
+ */
+ rr->rr_firstdatacol = nparity;
+#ifdef ZFS_DEBUG
+ /*
+ * note: rr_size is PSIZE, not ASIZE
+ */
+ rr->rr_offset = b << ashift;
+ rr->rr_size = (rr->rr_cols - rr->rr_firstdatacol) << ashift;
+#endif
+
+ for (int c = 0; c < rr->rr_cols; c++, child_id++) {
+ if (child_id >= row_phys_cols) {
+ child_id -= row_phys_cols;
+ child_offset += 1ULL << ashift;
+ }
+ raidz_col_t *rc = &rr->rr_col[c];
+ rc->rc_devidx = child_id;
+ rc->rc_offset = child_offset;
+
+ /*
+ * Get this from the scratch space if appropriate.
+ * This only happens if we crashed in the middle of
+ * raidz_reflow_scratch_sync() (while it's running,
+ * the rangelock prevents us from doing concurrent
+ * io), and even then only during zpool import or
+ * when the pool is imported readonly.
+ */
+ if (row_use_scratch)
+ rc->rc_offset -= VDEV_BOOT_SIZE;
+
+ uint64_t dc = c - rr->rr_firstdatacol;
+ if (c < rr->rr_firstdatacol) {
+ rc->rc_size = 1ULL << ashift;
+
+ /*
+ * Parity sectors' rc_abd's are set below
+ * after determining if this is an aggregation.
+ */
+ } else if (row == rows - 1 && bc != 0 && c >= bc) {
+ /*
+ * Past the end of the block (even including
+ * skip sectors). This sector is part of the
+ * map so that we have full rows for p/q parity
+ * generation.
+ */
+ rc->rc_size = 0;
+ rc->rc_abd = NULL;
+ } else {
+ /* "data column" (col excluding parity) */
+ uint64_t off;
+
+ if (c < bc || r == 0) {
+ off = dc * rows + row;
+ } else {
+ off = r * rows +
+ (dc - r) * (rows - 1) + row;
+ }
+ rc->rc_size = 1ULL << ashift;
+ rc->rc_abd = abd_get_offset_struct(
+ &rc->rc_abdstruct, abd, off << ashift,
+ rc->rc_size);
+ }
+
+ if (rc->rc_size == 0)
+ continue;
+
+ /*
+ * If any part of this row is in both old and new
+ * locations, the primary location is the old
+ * location. If this sector was already copied to the
+ * new location, we need to also write to the new,
+ * "shadow" location.
+ *
+ * Note, `row_phys_cols != physical_cols` indicates
+ * that the primary location is the old location.
+ * `b+c < reflow_offset_next` indicates that the copy
+ * to the new location has been initiated. We know
+ * that the copy has completed because we have the
+ * rangelock, which is held exclusively while the
+ * copy is in progress.
+ */
+ if (row_use_scratch ||
+ (row_phys_cols != physical_cols &&
+ b + c < reflow_offset_next >> ashift)) {
+ rc->rc_shadow_devidx = (b + c) % physical_cols;
+ rc->rc_shadow_offset =
+ ((b + c) / physical_cols) << ashift;
+ if (row_use_scratch)
+ rc->rc_shadow_offset -= VDEV_BOOT_SIZE;
+ }
+
+ asize += rc->rc_size;
+ }
+
+ /*
+ * See comment in vdev_raidz_map_alloc()
+ */
+ if (rr->rr_firstdatacol == 1 && rr->rr_cols > 1 &&
+ (offset & (1ULL << 20))) {
+ ASSERT(rr->rr_cols >= 2);
+ ASSERT(rr->rr_col[0].rc_size == rr->rr_col[1].rc_size);
+
+ int devidx0 = rr->rr_col[0].rc_devidx;
+ uint64_t offset0 = rr->rr_col[0].rc_offset;
+ int shadow_devidx0 = rr->rr_col[0].rc_shadow_devidx;
+ uint64_t shadow_offset0 =
+ rr->rr_col[0].rc_shadow_offset;
+
+ rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx;
+ rr->rr_col[0].rc_offset = rr->rr_col[1].rc_offset;
+ rr->rr_col[0].rc_shadow_devidx =
+ rr->rr_col[1].rc_shadow_devidx;
+ rr->rr_col[0].rc_shadow_offset =
+ rr->rr_col[1].rc_shadow_offset;
+
+ rr->rr_col[1].rc_devidx = devidx0;
+ rr->rr_col[1].rc_offset = offset0;
+ rr->rr_col[1].rc_shadow_devidx = shadow_devidx0;
+ rr->rr_col[1].rc_shadow_offset = shadow_offset0;
+ }
+ }
+ ASSERT3U(asize, ==, tot << ashift);
+
+ /*
+ * Determine if the block is contiguous, in which case we can use
+ * an aggregation.
+ */
+ if (rows >= raidz_io_aggregate_rows) {
+ rm->rm_nphys_cols = physical_cols;
+ rm->rm_phys_col =
+ kmem_zalloc(sizeof (raidz_col_t) * rm->rm_nphys_cols,
+ KM_SLEEP);
+
+ /*
+ * Determine the aggregate io's offset and size, and check
+ * that the io is contiguous.
+ */
+ for (int i = 0;
+ i < rm->rm_nrows && rm->rm_phys_col != NULL; i++) {
+ raidz_row_t *rr = rm->rm_row[i];
+ for (int c = 0; c < rr->rr_cols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ raidz_col_t *prc =
+ &rm->rm_phys_col[rc->rc_devidx];
+
+ if (rc->rc_size == 0)
+ continue;
+
+ if (prc->rc_size == 0) {
+ ASSERT0(prc->rc_offset);
+ prc->rc_offset = rc->rc_offset;
+ } else if (prc->rc_offset + prc->rc_size !=
+ rc->rc_offset) {
+ /*
+ * This block is not contiguous and
+ * therefore can't be aggregated.
+ * This is expected to be rare, so
+ * the cost of allocating and then
+ * freeing rm_phys_col is not
+ * significant.
+ */
+ kmem_free(rm->rm_phys_col,
+ sizeof (raidz_col_t) *
+ rm->rm_nphys_cols);
+ rm->rm_phys_col = NULL;
+ rm->rm_nphys_cols = 0;
+ break;
+ }
+ prc->rc_size += rc->rc_size;
+ }
+ }
+ }
+ if (rm->rm_phys_col != NULL) {
+ /*
+ * Allocate aggregate ABD's.
+ */
+ for (int i = 0; i < rm->rm_nphys_cols; i++) {
+ raidz_col_t *prc = &rm->rm_phys_col[i];
+
+ prc->rc_devidx = i;
+
+ if (prc->rc_size == 0)
+ continue;
+
+ prc->rc_abd =
+ abd_alloc_linear(rm->rm_phys_col[i].rc_size,
+ B_FALSE);
+ }
+
+ /*
+ * Point the parity abd's into the aggregate abd's.
+ */
+ for (int i = 0; i < rm->rm_nrows; i++) {
+ raidz_row_t *rr = rm->rm_row[i];
+ for (int c = 0; c < rr->rr_firstdatacol; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ raidz_col_t *prc =
+ &rm->rm_phys_col[rc->rc_devidx];
+ rc->rc_abd =
+ abd_get_offset_struct(&rc->rc_abdstruct,
+ prc->rc_abd,
+ rc->rc_offset - prc->rc_offset,
+ rc->rc_size);
+ }
+ }
+ } else {
+ /*
+ * Allocate new abd's for the parity sectors.
+ */
+ for (int i = 0; i < rm->rm_nrows; i++) {
+ raidz_row_t *rr = rm->rm_row[i];
+ for (int c = 0; c < rr->rr_firstdatacol; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ rc->rc_abd =
+ abd_alloc_linear(rc->rc_size,
+ B_TRUE);
+ }
+ }
+ }
/* init RAIDZ parity ops */
rm->rm_ops = vdev_raidz_math_get_ops();
@@ -453,11 +1044,11 @@ vdev_raidz_p_func(void *buf, size_t size, void *private)
{
struct pqr_struct *pqr = private;
const uint64_t *src = buf;
- int i, cnt = size / sizeof (src[0]);
+ int cnt = size / sizeof (src[0]);
ASSERT(pqr->p && !pqr->q && !pqr->r);
- for (i = 0; i < cnt; i++, src++, pqr->p++)
+ for (int i = 0; i < cnt; i++, src++, pqr->p++)
*pqr->p ^= *src;
return (0);
@@ -469,11 +1060,11 @@ vdev_raidz_pq_func(void *buf, size_t size, void *private)
struct pqr_struct *pqr = private;
const uint64_t *src = buf;
uint64_t mask;
- int i, cnt = size / sizeof (src[0]);
+ int cnt = size / sizeof (src[0]);
ASSERT(pqr->p && pqr->q && !pqr->r);
- for (i = 0; i < cnt; i++, src++, pqr->p++, pqr->q++) {
+ for (int i = 0; i < cnt; i++, src++, pqr->p++, pqr->q++) {
*pqr->p ^= *src;
VDEV_RAIDZ_64MUL_2(*pqr->q, mask);
*pqr->q ^= *src;
@@ -488,11 +1079,11 @@ vdev_raidz_pqr_func(void *buf, size_t size, void *private)
struct pqr_struct *pqr = private;
const uint64_t *src = buf;
uint64_t mask;
- int i, cnt = size / sizeof (src[0]);
+ int cnt = size / sizeof (src[0]);
ASSERT(pqr->p && pqr->q && pqr->r);
- for (i = 0; i < cnt; i++, src++, pqr->p++, pqr->q++, pqr->r++) {
+ for (int i = 0; i < cnt; i++, src++, pqr->p++, pqr->q++, pqr->r++) {
*pqr->p ^= *src;
VDEV_RAIDZ_64MUL_2(*pqr->q, mask);
*pqr->q ^= *src;
@@ -618,7 +1209,15 @@ vdev_raidz_generate_parity_pqr(raidz_row_t *rr)
void
vdev_raidz_generate_parity_row(raidz_map_t *rm, raidz_row_t *rr)
{
- ASSERT3U(rr->rr_cols, !=, 0);
+ if (rr->rr_cols == 0) {
+ /*
+ * We are handling this block one row at a time (because
+ * this block has a different logical vs physical width,
+ * due to RAIDZ expansion), and this is a pad-only row,
+ * which has no parity.
+ */
+ return;
+ }
/* Generate using the new math implementation */
if (vdev_raidz_math_generate(rm, rr) != RAIDZ_ORIGINAL_IMPL)
@@ -770,6 +1369,9 @@ vdev_raidz_reconstruct_p(raidz_row_t *rr, int *tgts, int ntgts)
int x = tgts[0];
abd_t *dst, *src;
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT)
+ zfs_dbgmsg("reconstruct_p(rm=%px x=%u)", rr, x);
+
ASSERT3U(ntgts, ==, 1);
ASSERT3U(x, >=, rr->rr_firstdatacol);
ASSERT3U(x, <, rr->rr_cols);
@@ -802,6 +1404,9 @@ vdev_raidz_reconstruct_q(raidz_row_t *rr, int *tgts, int ntgts)
int c, exp;
abd_t *dst, *src;
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT)
+ zfs_dbgmsg("reconstruct_q(rm=%px x=%u)", rr, x);
+
ASSERT(ntgts == 1);
ASSERT(rr->rr_col[x].rc_size <= rr->rr_col[VDEV_RAIDZ_Q].rc_size);
@@ -848,6 +1453,9 @@ vdev_raidz_reconstruct_pq(raidz_row_t *rr, int *tgts, int ntgts)
int y = tgts[1];
abd_t *xd, *yd;
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT)
+ zfs_dbgmsg("reconstruct_pq(rm=%px x=%u y=%u)", rr, x, y);
+
ASSERT(ntgts == 2);
ASSERT(x < y);
ASSERT(x >= rr->rr_firstdatacol);
@@ -1283,8 +1891,9 @@ vdev_raidz_matrix_reconstruct(raidz_row_t *rr, int n, int nmissing,
static void
vdev_raidz_reconstruct_general(raidz_row_t *rr, int *tgts, int ntgts)
{
- int n, i, c, t, tt;
- int nmissing_rows;
+ int i, c, t, tt;
+ unsigned int n;
+ unsigned int nmissing_rows;
int missing_rows[VDEV_RAIDZ_MAXPARITY];
int parity_map[VDEV_RAIDZ_MAXPARITY];
uint8_t *p, *pp;
@@ -1295,11 +1904,14 @@ vdev_raidz_reconstruct_general(raidz_row_t *rr, int *tgts, int ntgts)
abd_t **bufs = NULL;
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT)
+ zfs_dbgmsg("reconstruct_general(rm=%px ntgts=%u)", rr, ntgts);
/*
* Matrix reconstruction can't use scatter ABDs yet, so we allocate
* temporary linear ABDs if any non-linear ABDs are found.
*/
for (i = rr->rr_firstdatacol; i < rr->rr_cols; i++) {
+ ASSERT(rr->rr_col[i].rc_abd != NULL);
if (!abd_is_linear(rr->rr_col[i].rc_abd)) {
bufs = kmem_alloc(rr->rr_cols * sizeof (abd_t *),
KM_PUSHPAGE);
@@ -1427,10 +2039,23 @@ vdev_raidz_reconstruct_row(raidz_map_t *rm, raidz_row_t *rr,
int nbadparity, nbaddata;
int parity_valid[VDEV_RAIDZ_MAXPARITY];
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT) {
+ zfs_dbgmsg("reconstruct(rm=%px nt=%u cols=%u md=%u mp=%u)",
+ rr, nt, (int)rr->rr_cols, (int)rr->rr_missingdata,
+ (int)rr->rr_missingparity);
+ }
+
nbadparity = rr->rr_firstdatacol;
nbaddata = rr->rr_cols - nbadparity;
ntgts = 0;
for (i = 0, c = 0; c < rr->rr_cols; c++) {
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT) {
+ zfs_dbgmsg("reconstruct(rm=%px col=%u devid=%u "
+ "offset=%llx error=%u)",
+ rr, c, (int)rr->rr_col[c].rc_devidx,
+ (long long)rr->rr_col[c].rc_offset,
+ (int)rr->rr_col[c].rc_error);
+ }
if (c < rr->rr_firstdatacol)
parity_valid[c] = B_FALSE;
@@ -1527,12 +2152,25 @@ vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize,
*asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1;
*max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1;
*logical_ashift = MAX(*logical_ashift, cvd->vdev_ashift);
- *physical_ashift = MAX(*physical_ashift,
- cvd->vdev_physical_ashift);
}
+ for (c = 0; c < vd->vdev_children; c++) {
+ vdev_t *cvd = vd->vdev_child[c];
+
+ if (cvd->vdev_open_error != 0)
+ continue;
+ *physical_ashift = vdev_best_ashift(*logical_ashift,
+ *physical_ashift, cvd->vdev_physical_ashift);
+ }
+
+ if (vd->vdev_rz_expanding) {
+ *asize *= vd->vdev_children - 1;
+ *max_asize *= vd->vdev_children - 1;
- *asize *= vd->vdev_children;
- *max_asize *= vd->vdev_children;
+ vd->vdev_min_asize = *asize;
+ } else {
+ *asize *= vd->vdev_children;
+ *max_asize *= vd->vdev_children;
+ }
if (numerrors > nparity) {
vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS;
@@ -1551,19 +2189,70 @@ vdev_raidz_close(vdev_t *vd)
}
}
+/*
+ * Return the logical width to use, given the txg in which the allocation
+ * happened. Note that BP_GET_BIRTH() is usually the txg in which the
+ * BP was allocated. Remapped BP's (that were relocated due to device
+ * removal, see remap_blkptr_cb()), will have a more recent physical birth
+ * which reflects when the BP was relocated, but we can ignore these because
+ * they can't be on RAIDZ (device removal doesn't support RAIDZ).
+ */
+static uint64_t
+vdev_raidz_get_logical_width(vdev_raidz_t *vdrz, uint64_t txg)
+{
+ reflow_node_t lookup = {
+ .re_txg = txg,
+ };
+ avl_index_t where;
+
+ uint64_t width;
+ mutex_enter(&vdrz->vd_expand_lock);
+ reflow_node_t *re = avl_find(&vdrz->vd_expand_txgs, &lookup, &where);
+ if (re != NULL) {
+ width = re->re_logical_width;
+ } else {
+ re = avl_nearest(&vdrz->vd_expand_txgs, where, AVL_BEFORE);
+ if (re != NULL)
+ width = re->re_logical_width;
+ else
+ width = vdrz->vd_original_width;
+ }
+ mutex_exit(&vdrz->vd_expand_lock);
+ return (width);
+}
+
+/*
+ * Note: If the RAIDZ vdev has been expanded, older BP's may have allocated
+ * more space due to the lower data-to-parity ratio. In this case it's
+ * important to pass in the correct txg. Note that vdev_gang_header_asize()
+ * relies on a constant asize for psize=SPA_GANGBLOCKSIZE=SPA_MINBLOCKSIZE,
+ * regardless of txg. This is assured because for a single data sector, we
+ * allocate P+1 sectors regardless of width ("cols", which is at least P+1).
+ */
static uint64_t
-vdev_raidz_asize(vdev_t *vd, uint64_t psize)
+vdev_raidz_asize(vdev_t *vd, uint64_t psize, uint64_t txg)
{
vdev_raidz_t *vdrz = vd->vdev_tsd;
uint64_t asize;
uint64_t ashift = vd->vdev_top->vdev_ashift;
- uint64_t cols = vdrz->vd_logical_width;
+ uint64_t cols = vdrz->vd_original_width;
uint64_t nparity = vdrz->vd_nparity;
+ cols = vdev_raidz_get_logical_width(vdrz, txg);
+
asize = ((psize - 1) >> ashift) + 1;
asize += nparity * ((asize + cols - nparity - 1) / (cols - nparity));
asize = roundup(asize, nparity + 1) << ashift;
+#ifdef ZFS_DEBUG
+ uint64_t asize_new = ((psize - 1) >> ashift) + 1;
+ uint64_t ncols_new = vdrz->vd_physical_width;
+ asize_new += nparity * ((asize_new + ncols_new - nparity - 1) /
+ (ncols_new - nparity));
+ asize_new = roundup(asize_new, nparity + 1) << ashift;
+ VERIFY3U(asize_new, <=, asize);
+#endif
+
return (asize);
}
@@ -1590,21 +2279,37 @@ vdev_raidz_child_done(zio_t *zio)
}
static void
-vdev_raidz_io_verify(vdev_t *vd, raidz_row_t *rr, int col)
+vdev_raidz_shadow_child_done(zio_t *zio)
{
-#ifdef ZFS_DEBUG
- vdev_t *tvd = vd->vdev_top;
+ raidz_col_t *rc = zio->io_private;
+ rc->rc_shadow_error = zio->io_error;
+}
+
+static void
+vdev_raidz_io_verify(zio_t *zio, raidz_map_t *rm, raidz_row_t *rr, int col)
+{
+ (void) rm;
+#ifdef ZFS_DEBUG
range_seg64_t logical_rs, physical_rs, remain_rs;
logical_rs.rs_start = rr->rr_offset;
logical_rs.rs_end = logical_rs.rs_start +
- vdev_raidz_asize(vd, rr->rr_size);
+ vdev_raidz_asize(zio->io_vd, rr->rr_size,
+ BP_GET_BIRTH(zio->io_bp));
raidz_col_t *rc = &rr->rr_col[col];
- vdev_t *cvd = vd->vdev_child[rc->rc_devidx];
+ vdev_t *cvd = zio->io_vd->vdev_child[rc->rc_devidx];
vdev_xlate(cvd, &logical_rs, &physical_rs, &remain_rs);
ASSERT(vdev_xlate_is_empty(&remain_rs));
+ if (vdev_xlate_is_empty(&physical_rs)) {
+ /*
+ * If we are in the middle of expansion, the
+ * physical->logical mapping is changing so vdev_xlate()
+ * can't give us a reliable answer.
+ */
+ return;
+ }
ASSERT3U(rc->rc_offset, ==, physical_rs.rs_start);
ASSERT3U(rc->rc_offset, <, physical_rs.rs_end);
/*
@@ -1615,7 +2320,7 @@ vdev_raidz_io_verify(vdev_t *vd, raidz_row_t *rr, int col)
*/
if (physical_rs.rs_end > rc->rc_offset + rc->rc_size) {
ASSERT3U(physical_rs.rs_end, ==, rc->rc_offset +
- rc->rc_size + (1 << tvd->vdev_ashift));
+ rc->rc_size + (1 << zio->io_vd->vdev_top->vdev_ashift));
} else {
ASSERT3U(physical_rs.rs_end, ==, rc->rc_offset + rc->rc_size);
}
@@ -1623,7 +2328,7 @@ vdev_raidz_io_verify(vdev_t *vd, raidz_row_t *rr, int col)
}
static void
-vdev_raidz_io_start_write(zio_t *zio, raidz_row_t *rr, uint64_t ashift)
+vdev_raidz_io_start_write(zio_t *zio, raidz_row_t *rr)
{
vdev_t *vd = zio->io_vd;
raidz_map_t *rm = zio->io_vsd;
@@ -1635,31 +2340,66 @@ vdev_raidz_io_start_write(zio_t *zio, raidz_row_t *rr, uint64_t ashift)
vdev_t *cvd = vd->vdev_child[rc->rc_devidx];
/* Verify physical to logical translation */
- vdev_raidz_io_verify(vd, rr, c);
+ vdev_raidz_io_verify(zio, rm, rr, c);
- if (rc->rc_size > 0) {
- ASSERT3P(rc->rc_abd, !=, NULL);
- zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
- rc->rc_offset, rc->rc_abd,
- abd_get_size(rc->rc_abd), zio->io_type,
- zio->io_priority, 0, vdev_raidz_child_done, rc));
- } else {
- /*
- * Generate optional write for skip sector to improve
- * aggregation contiguity.
- */
- ASSERT3P(rc->rc_abd, ==, NULL);
- zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
- rc->rc_offset, NULL, 1ULL << ashift,
- zio->io_type, zio->io_priority,
- ZIO_FLAG_NODATA | ZIO_FLAG_OPTIONAL, NULL,
- NULL));
+ if (rc->rc_size == 0)
+ continue;
+
+ ASSERT3U(rc->rc_offset + rc->rc_size, <,
+ cvd->vdev_psize - VDEV_LABEL_END_SIZE);
+
+ ASSERT3P(rc->rc_abd, !=, NULL);
+ zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
+ rc->rc_offset, rc->rc_abd,
+ abd_get_size(rc->rc_abd), zio->io_type,
+ zio->io_priority, 0, vdev_raidz_child_done, rc));
+
+ if (rc->rc_shadow_devidx != INT_MAX) {
+ vdev_t *cvd2 = vd->vdev_child[rc->rc_shadow_devidx];
+
+ ASSERT3U(
+ rc->rc_shadow_offset + abd_get_size(rc->rc_abd), <,
+ cvd2->vdev_psize - VDEV_LABEL_END_SIZE);
+
+ zio_nowait(zio_vdev_child_io(zio, NULL, cvd2,
+ rc->rc_shadow_offset, rc->rc_abd,
+ abd_get_size(rc->rc_abd),
+ zio->io_type, zio->io_priority, 0,
+ vdev_raidz_shadow_child_done, rc));
}
}
}
+/*
+ * Generate optional I/Os for skip sectors to improve aggregation contiguity.
+ * This only works for vdev_raidz_map_alloc() (not _expanded()).
+ */
static void
-vdev_raidz_io_start_read(zio_t *zio, raidz_row_t *rr)
+raidz_start_skip_writes(zio_t *zio)
+{
+ vdev_t *vd = zio->io_vd;
+ uint64_t ashift = vd->vdev_top->vdev_ashift;
+ raidz_map_t *rm = zio->io_vsd;
+ ASSERT3U(rm->rm_nrows, ==, 1);
+ raidz_row_t *rr = rm->rm_row[0];
+ for (int c = 0; c < rr->rr_scols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ vdev_t *cvd = vd->vdev_child[rc->rc_devidx];
+ if (rc->rc_size != 0)
+ continue;
+ ASSERT3P(rc->rc_abd, ==, NULL);
+
+ ASSERT3U(rc->rc_offset, <,
+ cvd->vdev_psize - VDEV_LABEL_END_SIZE);
+
+ zio_nowait(zio_vdev_child_io(zio, NULL, cvd, rc->rc_offset,
+ NULL, 1ULL << ashift, zio->io_type, zio->io_priority,
+ ZIO_FLAG_NODATA | ZIO_FLAG_OPTIONAL, NULL, NULL));
+ }
+}
+
+static void
+vdev_raidz_io_start_read_row(zio_t *zio, raidz_row_t *rr, boolean_t forceparity)
{
vdev_t *vd = zio->io_vd;
@@ -1691,7 +2431,8 @@ vdev_raidz_io_start_read(zio_t *zio, raidz_row_t *rr)
rc->rc_skipped = 1;
continue;
}
- if (c >= rr->rr_firstdatacol || rr->rr_missingdata > 0 ||
+ if (forceparity ||
+ c >= rr->rr_firstdatacol || rr->rr_missingdata > 0 ||
(zio->io_flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER))) {
zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
rc->rc_offset, rc->rc_abd, rc->rc_size,
@@ -1701,6 +2442,56 @@ vdev_raidz_io_start_read(zio_t *zio, raidz_row_t *rr)
}
}
+static void
+vdev_raidz_io_start_read_phys_cols(zio_t *zio, raidz_map_t *rm)
+{
+ vdev_t *vd = zio->io_vd;
+
+ for (int i = 0; i < rm->rm_nphys_cols; i++) {
+ raidz_col_t *prc = &rm->rm_phys_col[i];
+ if (prc->rc_size == 0)
+ continue;
+
+ ASSERT3U(prc->rc_devidx, ==, i);
+ vdev_t *cvd = vd->vdev_child[i];
+ if (!vdev_readable(cvd)) {
+ prc->rc_error = SET_ERROR(ENXIO);
+ prc->rc_tried = 1; /* don't even try */
+ prc->rc_skipped = 1;
+ continue;
+ }
+ if (vdev_dtl_contains(cvd, DTL_MISSING, zio->io_txg, 1)) {
+ prc->rc_error = SET_ERROR(ESTALE);
+ prc->rc_skipped = 1;
+ continue;
+ }
+ zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
+ prc->rc_offset, prc->rc_abd, prc->rc_size,
+ zio->io_type, zio->io_priority, 0,
+ vdev_raidz_child_done, prc));
+ }
+}
+
+static void
+vdev_raidz_io_start_read(zio_t *zio, raidz_map_t *rm)
+{
+ /*
+ * If there are multiple rows, we will be hitting
+ * all disks, so go ahead and read the parity so
+ * that we are reading in decent size chunks.
+ */
+ boolean_t forceparity = rm->rm_nrows > 1;
+
+ if (rm->rm_phys_col) {
+ vdev_raidz_io_start_read_phys_cols(zio, rm);
+ } else {
+ for (int i = 0; i < rm->rm_nrows; i++) {
+ raidz_row_t *rr = rm->rm_row[i];
+ vdev_raidz_io_start_read_row(zio, rr, forceparity);
+ }
+ }
+}
+
/*
* Start an IO operation on a RAIDZ VDev
*
@@ -1724,24 +2515,83 @@ vdev_raidz_io_start(zio_t *zio)
vdev_t *vd = zio->io_vd;
vdev_t *tvd = vd->vdev_top;
vdev_raidz_t *vdrz = vd->vdev_tsd;
+ raidz_map_t *rm;
+
+ uint64_t logical_width = vdev_raidz_get_logical_width(vdrz,
+ BP_GET_BIRTH(zio->io_bp));
+ if (logical_width != vdrz->vd_physical_width) {
+ zfs_locked_range_t *lr = NULL;
+ uint64_t synced_offset = UINT64_MAX;
+ uint64_t next_offset = UINT64_MAX;
+ boolean_t use_scratch = B_FALSE;
+ /*
+ * Note: when the expansion is completing, we set
+ * vre_state=DSS_FINISHED (in raidz_reflow_complete_sync())
+ * in a later txg than when we last update spa_ubsync's state
+ * (see the end of spa_raidz_expand_thread()). Therefore we
+ * may see vre_state!=SCANNING before
+ * VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE=DSS_FINISHED is reflected
+ * on disk, but the copying progress has been synced to disk
+ * (and reflected in spa_ubsync). In this case it's fine to
+ * treat the expansion as completed, since if we crash there's
+ * no additional copying to do.
+ */
+ if (vdrz->vn_vre.vre_state == DSS_SCANNING) {
+ ASSERT3P(vd->vdev_spa->spa_raidz_expand, ==,
+ &vdrz->vn_vre);
+ lr = zfs_rangelock_enter(&vdrz->vn_vre.vre_rangelock,
+ zio->io_offset, zio->io_size, RL_READER);
+ use_scratch =
+ (RRSS_GET_STATE(&vd->vdev_spa->spa_ubsync) ==
+ RRSS_SCRATCH_VALID);
+ synced_offset =
+ RRSS_GET_OFFSET(&vd->vdev_spa->spa_ubsync);
+ next_offset = vdrz->vn_vre.vre_offset;
+ /*
+ * If we haven't resumed expanding since importing the
+ * pool, vre_offset won't have been set yet. In
+ * this case the next offset to be copied is the same
+ * as what was synced.
+ */
+ if (next_offset == UINT64_MAX) {
+ next_offset = synced_offset;
+ }
+ }
+ if (use_scratch) {
+ zfs_dbgmsg("zio=%px %s io_offset=%llu offset_synced="
+ "%lld next_offset=%lld use_scratch=%u",
+ zio,
+ zio->io_type == ZIO_TYPE_WRITE ? "WRITE" : "READ",
+ (long long)zio->io_offset,
+ (long long)synced_offset,
+ (long long)next_offset,
+ use_scratch);
+ }
+
+ rm = vdev_raidz_map_alloc_expanded(zio,
+ tvd->vdev_ashift, vdrz->vd_physical_width,
+ logical_width, vdrz->vd_nparity,
+ synced_offset, next_offset, use_scratch);
+ rm->rm_lr = lr;
+ } else {
+ rm = vdev_raidz_map_alloc(zio,
+ tvd->vdev_ashift, logical_width, vdrz->vd_nparity);
+ }
+ rm->rm_original_width = vdrz->vd_original_width;
- raidz_map_t *rm = vdev_raidz_map_alloc(zio, tvd->vdev_ashift,
- vdrz->vd_logical_width, vdrz->vd_nparity);
zio->io_vsd = rm;
zio->io_vsd_ops = &vdev_raidz_vsd_ops;
-
- /*
- * Until raidz expansion is implemented all maps for a raidz vdev
- * contain a single row.
- */
- ASSERT3U(rm->rm_nrows, ==, 1);
- raidz_row_t *rr = rm->rm_row[0];
-
if (zio->io_type == ZIO_TYPE_WRITE) {
- vdev_raidz_io_start_write(zio, rr, tvd->vdev_ashift);
+ for (int i = 0; i < rm->rm_nrows; i++) {
+ vdev_raidz_io_start_write(zio, rm->rm_row[i]);
+ }
+
+ if (logical_width == vdrz->vd_physical_width) {
+ raidz_start_skip_writes(zio);
+ }
} else {
ASSERT(zio->io_type == ZIO_TYPE_READ);
- vdev_raidz_io_start_read(zio, rr);
+ vdev_raidz_io_start_read(zio, rm);
}
zio_execute(zio);
@@ -1763,12 +2613,12 @@ vdev_raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data)
zbc.zbc_has_cksum = 0;
zbc.zbc_injected = rm->rm_ecksuminjected;
- (void) zfs_ereport_post_checksum(zio->io_spa, vd,
- &zio->io_bookmark, zio, rc->rc_offset, rc->rc_size,
- rc->rc_abd, bad_data, &zbc);
mutex_enter(&vd->vdev_stat_lock);
vd->vdev_stat.vs_checksum_errors++;
mutex_exit(&vd->vdev_stat_lock);
+ (void) zfs_ereport_post_checksum(zio->io_spa, vd,
+ &zio->io_bookmark, zio, rc->rc_offset, rc->rc_size,
+ rc->rc_abd, bad_data, &zbc);
}
}
@@ -1779,7 +2629,7 @@ vdev_raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data)
static int
raidz_checksum_verify(zio_t *zio)
{
- zio_bad_cksum_t zbc = {{{0}}};
+ zio_bad_cksum_t zbc = {0};
raidz_map_t *rm = zio->io_vsd;
int ret = zio_checksum_error(zio, &zbc);
@@ -1841,6 +2691,8 @@ raidz_parity_verify(zio_t *zio, raidz_row_t *rr)
continue;
if (abd_cmp(orig[c], rc->rc_abd) != 0) {
+ zfs_dbgmsg("found error on col=%u devidx=%u off %llx",
+ c, (int)rc->rc_devidx, (u_longlong_t)rc->rc_offset);
vdev_raidz_checksum_error(zio, rc, orig[c]);
rc->rc_error = SET_ERROR(ECKSUM);
ret++;
@@ -1856,8 +2708,10 @@ vdev_raidz_worst_error(raidz_row_t *rr)
{
int error = 0;
- for (int c = 0; c < rr->rr_cols; c++)
+ for (int c = 0; c < rr->rr_cols; c++) {
error = zio_worst_error(error, rr->rr_col[c].rc_error);
+ error = zio_worst_error(error, rr->rr_col[c].rc_shadow_error);
+ }
return (error);
}
@@ -1923,6 +2777,10 @@ vdev_raidz_io_done_verified(zio_t *zio, raidz_row_t *rr)
continue;
}
+ zfs_dbgmsg("zio=%px repairing c=%u devidx=%u "
+ "offset=%llx",
+ zio, c, rc->rc_devidx, (long long)rc->rc_offset);
+
zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
rc->rc_offset, rc->rc_abd, rc->rc_size,
ZIO_TYPE_WRITE,
@@ -1932,6 +2790,42 @@ vdev_raidz_io_done_verified(zio_t *zio, raidz_row_t *rr)
ZIO_FLAG_SELF_HEAL : 0), NULL, NULL));
}
}
+
+ /*
+ * Scrub or resilver i/o's: overwrite any shadow locations with the
+ * good data. This ensures that if we've already copied this sector,
+ * it will be corrected if it was damaged. This writes more than is
+ * necessary, but since expansion is paused during scrub/resilver, at
+ * most a single row will have a shadow location.
+ */
+ if (zio->io_error == 0 && spa_writeable(zio->io_spa) &&
+ (zio->io_flags & (ZIO_FLAG_RESILVER | ZIO_FLAG_SCRUB))) {
+ for (int c = 0; c < rr->rr_cols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ vdev_t *vd = zio->io_vd;
+
+ if (rc->rc_shadow_devidx == INT_MAX || rc->rc_size == 0)
+ continue;
+ vdev_t *cvd = vd->vdev_child[rc->rc_shadow_devidx];
+
+ /*
+ * Note: We don't want to update the repair stats
+ * because that would incorrectly indicate that there
+ * was bad data to repair, which we aren't sure about.
+ * By clearing the SCAN_THREAD flag, we prevent this
+ * from happening, despite having the REPAIR flag set.
+ * We need to set SELF_HEAL so that this i/o can't be
+ * bypassed by zio_vdev_io_start().
+ */
+ zio_t *cio = zio_vdev_child_io(zio, NULL, cvd,
+ rc->rc_shadow_offset, rc->rc_abd, rc->rc_size,
+ ZIO_TYPE_WRITE, ZIO_PRIORITY_ASYNC_WRITE,
+ ZIO_FLAG_IO_REPAIR | ZIO_FLAG_SELF_HEAL,
+ NULL, NULL);
+ cio->io_flags &= ~ZIO_FLAG_SCAN_THREAD;
+ zio_nowait(cio);
+ }
+ }
}
static void
@@ -1951,6 +2845,43 @@ raidz_restore_orig_data(raidz_map_t *rm)
}
/*
+ * During raidz_reconstruct() for expanded VDEV, we need special consideration
+ * failure simulations. See note in raidz_reconstruct() on simulating failure
+ * of a pre-expansion device.
+ *
+ * Treating logical child i as failed, return TRUE if the given column should
+ * be treated as failed. The idea of logical children allows us to imagine
+ * that a disk silently failed before a RAIDZ expansion (reads from this disk
+ * succeed but return the wrong data). Since the expansion doesn't verify
+ * checksums, the incorrect data will be moved to new locations spread among
+ * the children (going diagonally across them).
+ *
+ * Higher "logical child failures" (values of `i`) indicate these
+ * "pre-expansion failures". The first physical_width values imagine that a
+ * current child failed; the next physical_width-1 values imagine that a
+ * child failed before the most recent expansion; the next physical_width-2
+ * values imagine a child failed in the expansion before that, etc.
+ */
+static boolean_t
+raidz_simulate_failure(int physical_width, int original_width, int ashift,
+ int i, raidz_col_t *rc)
+{
+ uint64_t sector_id =
+ physical_width * (rc->rc_offset >> ashift) +
+ rc->rc_devidx;
+
+ for (int w = physical_width; w >= original_width; w--) {
+ if (i < w) {
+ return (sector_id % w == i);
+ } else {
+ i -= w;
+ }
+ }
+ ASSERT(!"invalid logical child id");
+ return (B_FALSE);
+}
+
+/*
* returns EINVAL if reconstruction of the block will not be possible
* returns ECKSUM if this specific reconstruction failed
* returns 0 on successful reconstruction
@@ -1959,6 +2890,15 @@ static int
raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
{
raidz_map_t *rm = zio->io_vsd;
+ int physical_width = zio->io_vd->vdev_children;
+ int original_width = (rm->rm_original_width != 0) ?
+ rm->rm_original_width : physical_width;
+ int dbgmsg = zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT;
+
+ if (dbgmsg) {
+ zfs_dbgmsg("raidz_reconstruct_expanded(zio=%px ltgts=%u,%u,%u "
+ "ntgts=%u", zio, ltgts[0], ltgts[1], ltgts[2], ntgts);
+ }
/* Reconstruct each row */
for (int r = 0; r < rm->rm_nrows; r++) {
@@ -1968,6 +2908,9 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
int dead = 0;
int dead_data = 0;
+ if (dbgmsg)
+ zfs_dbgmsg("raidz_reconstruct_expanded(row=%u)", r);
+
for (int c = 0; c < rr->rr_cols; c++) {
raidz_col_t *rc = &rr->rr_col[c];
ASSERT0(rc->rc_need_orig_restore);
@@ -1980,7 +2923,10 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
if (rc->rc_size == 0)
continue;
for (int lt = 0; lt < ntgts; lt++) {
- if (rc->rc_devidx == ltgts[lt]) {
+ if (raidz_simulate_failure(physical_width,
+ original_width,
+ zio->io_vd->vdev_top->vdev_ashift,
+ ltgts[lt], rc)) {
if (rc->rc_orig_data == NULL) {
rc->rc_orig_data =
abd_alloc_linear(
@@ -1993,13 +2939,37 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
dead++;
if (c >= nparity)
dead_data++;
- my_tgts[t++] = c;
+ /*
+ * Note: simulating failure of a
+ * pre-expansion device can hit more
+ * than one column, in which case we
+ * might try to simulate more failures
+ * than can be reconstructed, which is
+ * also more than the size of my_tgts.
+ * This check prevents accessing past
+ * the end of my_tgts. The "dead >
+ * nparity" check below will fail this
+ * reconstruction attempt.
+ */
+ if (t < VDEV_RAIDZ_MAXPARITY) {
+ my_tgts[t++] = c;
+ if (dbgmsg) {
+ zfs_dbgmsg("simulating "
+ "failure of col %u "
+ "devidx %u", c,
+ (int)rc->rc_devidx);
+ }
+ }
break;
}
}
}
if (dead > nparity) {
/* reconstruction not possible */
+ if (dbgmsg) {
+ zfs_dbgmsg("reconstruction not possible; "
+ "too many failures");
+ }
raidz_restore_orig_data(rm);
return (EINVAL);
}
@@ -2043,11 +3013,19 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
zio_checksum_verified(zio);
+ if (dbgmsg) {
+ zfs_dbgmsg("reconstruction successful "
+ "(checksum verified)");
+ }
return (0);
}
/* Reconstruction failed - restore original data */
raidz_restore_orig_data(rm);
+ if (dbgmsg) {
+ zfs_dbgmsg("raidz_reconstruct_expanded(zio=%px) checksum "
+ "failed", zio);
+ }
return (ECKSUM);
}
@@ -2062,7 +3040,7 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
* The order that we find the various possible combinations of failed
* disks is dictated by these rules:
* - Examine each "slot" (the "i" in tgts[i])
- * - Try to increment this slot (tgts[i] = tgts[i] + 1)
+ * - Try to increment this slot (tgts[i] += 1)
* - if we can't increment because it runs into the next slot,
* reset our slot to the minimum, and examine the next slot
*
@@ -2093,18 +3071,22 @@ raidz_reconstruct(zio_t *zio, int *ltgts, int ntgts, int nparity)
*
* This strategy works for dRAID but is less efficient when there are a large
* number of child vdevs and therefore permutations to check. Furthermore,
- * since the raidz_map_t rows likely do not overlap reconstruction would be
+ * since the raidz_map_t rows likely do not overlap, reconstruction would be
* possible as long as there are no more than nparity data errors per row.
* These additional permutations are not currently checked but could be as
* a future improvement.
+ *
+ * Returns 0 on success, ECKSUM on failure.
*/
static int
vdev_raidz_combrec(zio_t *zio)
{
int nparity = vdev_get_nparity(zio->io_vd);
raidz_map_t *rm = zio->io_vsd;
+ int physical_width = zio->io_vd->vdev_children;
+ int original_width = (rm->rm_original_width != 0) ?
+ rm->rm_original_width : physical_width;
- /* Check if there's enough data to attempt reconstrution. */
for (int i = 0; i < rm->rm_nrows; i++) {
raidz_row_t *rr = rm->rm_row[i];
int total_errors = 0;
@@ -2122,8 +3104,16 @@ vdev_raidz_combrec(zio_t *zio)
int tstore[VDEV_RAIDZ_MAXPARITY + 2];
int *ltgts = &tstore[1]; /* value is logical child ID */
- /* Determine number of logical children, n */
- int n = zio->io_vd->vdev_children;
+
+ /*
+ * Determine number of logical children, n. See comment
+ * above raidz_simulate_failure().
+ */
+ int n = 0;
+ for (int w = physical_width;
+ w >= original_width; w--) {
+ n += w;
+ }
ASSERT3U(num_failures, <=, nparity);
ASSERT3U(num_failures, <=, VDEV_RAIDZ_MAXPARITY);
@@ -2154,6 +3144,14 @@ vdev_raidz_combrec(zio_t *zio)
if (ltgts[t] == n) {
/* try more failures */
ASSERT3U(t, ==, num_failures - 1);
+ if (zfs_flags &
+ ZFS_DEBUG_RAIDZ_RECONSTRUCT) {
+ zfs_dbgmsg("reconstruction "
+ "failed for num_failures="
+ "%u; tried all "
+ "combinations",
+ num_failures);
+ }
break;
}
@@ -2165,7 +3163,7 @@ vdev_raidz_combrec(zio_t *zio)
* Try the next combination.
*/
if (ltgts[t] != ltgts[t + 1])
- break;
+ break; // found next combination
/*
* Otherwise, reset this tgt to the minimum,
@@ -2180,7 +3178,8 @@ vdev_raidz_combrec(zio_t *zio)
break;
}
}
-
+ if (zfs_flags & ZFS_DEBUG_RAIDZ_RECONSTRUCT)
+ zfs_dbgmsg("reconstruction failed for all num_failures");
return (ECKSUM);
}
@@ -2205,7 +3204,8 @@ vdev_raidz_reconstruct(raidz_map_t *rm, const int *t, int nt)
static void
vdev_raidz_io_done_write_impl(zio_t *zio, raidz_row_t *rr)
{
- int total_errors = 0;
+ int normal_errors = 0;
+ int shadow_errors = 0;
ASSERT3U(rr->rr_missingparity, <=, rr->rr_firstdatacol);
ASSERT3U(rr->rr_missingdata, <=, rr->rr_cols - rr->rr_firstdatacol);
@@ -2214,24 +3214,31 @@ vdev_raidz_io_done_write_impl(zio_t *zio, raidz_row_t *rr)
for (int c = 0; c < rr->rr_cols; c++) {
raidz_col_t *rc = &rr->rr_col[c];
- if (rc->rc_error) {
+ if (rc->rc_error != 0) {
ASSERT(rc->rc_error != ECKSUM); /* child has no bp */
-
- total_errors++;
+ normal_errors++;
+ }
+ if (rc->rc_shadow_error != 0) {
+ ASSERT(rc->rc_shadow_error != ECKSUM);
+ shadow_errors++;
}
}
/*
* Treat partial writes as a success. If we couldn't write enough
- * columns to reconstruct the data, the I/O failed. Otherwise,
- * good enough.
+ * columns to reconstruct the data, the I/O failed. Otherwise, good
+ * enough. Note that in the case of a shadow write (during raidz
+ * expansion), depending on if we crash, either the normal (old) or
+ * shadow (new) location may become the "real" version of the block,
+ * so both locations must have sufficient redundancy.
*
* Now that we support write reallocation, it would be better
* to treat partial failure as real failure unless there are
* no non-degraded top-level vdevs left, and not update DTLs
* if we intend to reallocate.
*/
- if (total_errors > rr->rr_firstdatacol) {
+ if (normal_errors > rr->rr_firstdatacol ||
+ shadow_errors > rr->rr_firstdatacol) {
zio->io_error = zio_worst_error(zio->io_error,
vdev_raidz_worst_error(rr));
}
@@ -2248,7 +3255,6 @@ vdev_raidz_io_done_reconstruct_known_missing(zio_t *zio, raidz_map_t *rm,
ASSERT3U(rr->rr_missingparity, <=, rr->rr_firstdatacol);
ASSERT3U(rr->rr_missingdata, <=, rr->rr_cols - rr->rr_firstdatacol);
- ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);
for (int c = 0; c < rr->rr_cols; c++) {
raidz_col_t *rc = &rr->rr_col[c];
@@ -2331,7 +3337,7 @@ vdev_raidz_read_all(zio_t *zio, raidz_row_t *rr)
* for a normal read then allocate an ABD for them now so they
* may be read, verified, and any needed repairs performed.
*/
- if (rr->rr_nempty && rr->rr_abd_empty == NULL)
+ if (rr->rr_nempty != 0 && rr->rr_abd_empty == NULL)
vdev_draid_map_alloc_empty(zio, rr);
for (int c = 0; c < rr->rr_cols; c++) {
@@ -2374,12 +3380,12 @@ vdev_raidz_io_done_unrecoverable(zio_t *zio)
zbc.zbc_has_cksum = 0;
zbc.zbc_injected = rm->rm_ecksuminjected;
- (void) zfs_ereport_start_checksum(zio->io_spa,
- cvd, &zio->io_bookmark, zio, rc->rc_offset,
- rc->rc_size, &zbc);
mutex_enter(&cvd->vdev_stat_lock);
cvd->vdev_stat.vs_checksum_errors++;
mutex_exit(&cvd->vdev_stat_lock);
+ (void) zfs_ereport_start_checksum(zio->io_spa,
+ cvd, &zio->io_bookmark, zio, rc->rc_offset,
+ rc->rc_size, &zbc);
}
}
}
@@ -2389,11 +3395,48 @@ vdev_raidz_io_done(zio_t *zio)
{
raidz_map_t *rm = zio->io_vsd;
+ ASSERT(zio->io_bp != NULL);
if (zio->io_type == ZIO_TYPE_WRITE) {
for (int i = 0; i < rm->rm_nrows; i++) {
vdev_raidz_io_done_write_impl(zio, rm->rm_row[i]);
}
} else {
+ if (rm->rm_phys_col) {
+ /*
+ * This is an aggregated read. Copy the data and status
+ * from the aggregate abd's to the individual rows.
+ */
+ for (int i = 0; i < rm->rm_nrows; i++) {
+ raidz_row_t *rr = rm->rm_row[i];
+
+ for (int c = 0; c < rr->rr_cols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+ if (rc->rc_tried || rc->rc_size == 0)
+ continue;
+
+ raidz_col_t *prc =
+ &rm->rm_phys_col[rc->rc_devidx];
+ rc->rc_error = prc->rc_error;
+ rc->rc_tried = prc->rc_tried;
+ rc->rc_skipped = prc->rc_skipped;
+ if (c >= rr->rr_firstdatacol) {
+ /*
+ * Note: this is slightly faster
+ * than using abd_copy_off().
+ */
+ char *physbuf = abd_to_buf(
+ prc->rc_abd);
+ void *physloc = physbuf +
+ rc->rc_offset -
+ prc->rc_offset;
+
+ abd_copy_from_buf(rc->rc_abd,
+ physloc, rc->rc_size);
+ }
+ }
+ }
+ }
+
for (int i = 0; i < rm->rm_nrows; i++) {
raidz_row_t *rr = rm->rm_row[i];
vdev_raidz_io_done_reconstruct_known_missing(zio,
@@ -2440,7 +3483,54 @@ vdev_raidz_io_done(zio_t *zio)
zio_vdev_io_redone(zio);
return;
}
-
+ /*
+ * It would be too expensive to try every possible
+ * combination of failed sectors in every row, so
+ * instead we try every combination of failed current or
+ * past physical disk. This means that if the incorrect
+ * sectors were all on Nparity disks at any point in the
+ * past, we will find the correct data. The only known
+ * case where this is less durable than a non-expanded
+ * RAIDZ, is if we have a silent failure during
+ * expansion. In that case, one block could be
+ * partially in the old format and partially in the
+ * new format, so we'd lost some sectors from the old
+ * format and some from the new format.
+ *
+ * e.g. logical_width=4 physical_width=6
+ * the 15 (6+5+4) possible failed disks are:
+ * width=6 child=0
+ * width=6 child=1
+ * width=6 child=2
+ * width=6 child=3
+ * width=6 child=4
+ * width=6 child=5
+ * width=5 child=0
+ * width=5 child=1
+ * width=5 child=2
+ * width=5 child=3
+ * width=5 child=4
+ * width=4 child=0
+ * width=4 child=1
+ * width=4 child=2
+ * width=4 child=3
+ * And we will try every combination of Nparity of these
+ * failing.
+ *
+ * As a first pass, we can generate every combo,
+ * and try reconstructing, ignoring any known
+ * failures. If any row has too many known + simulated
+ * failures, then we bail on reconstructing with this
+ * number of simulated failures. As an improvement,
+ * we could detect the number of whole known failures
+ * (i.e. we have known failures on these disks for
+ * every row; the disks never succeeded), and
+ * subtract that from the max # failures to simulate.
+ * We could go even further like the current
+ * combrec code, but that doesn't seem like it
+ * gains us very much. If we simulate a failure
+ * that is also a known failure, that's fine.
+ */
zio->io_error = vdev_raidz_combrec(zio);
if (zio->io_error == ECKSUM &&
!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
@@ -2448,6 +3538,10 @@ vdev_raidz_io_done(zio_t *zio)
}
}
}
+ if (rm->rm_lr != NULL) {
+ zfs_rangelock_exit(rm->rm_lr);
+ rm->rm_lr = NULL;
+ }
}
static void
@@ -2474,6 +3568,14 @@ vdev_raidz_need_resilver(vdev_t *vd, const dva_t *dva, size_t psize,
uint64_t phys_birth)
{
vdev_raidz_t *vdrz = vd->vdev_tsd;
+
+ /*
+ * If we're in the middle of a RAIDZ expansion, this block may be in
+ * the old and/or new location. For simplicity, always resilver it.
+ */
+ if (vdrz->vn_vre.vre_state == DSS_SCANNING)
+ return (B_TRUE);
+
uint64_t dcols = vd->vdev_children;
uint64_t nparity = vdrz->vd_nparity;
uint64_t ashift = vd->vdev_top->vdev_ashift;
@@ -2518,7 +3620,24 @@ vdev_raidz_xlate(vdev_t *cvd, const range_seg64_t *logical_rs,
vdev_t *raidvd = cvd->vdev_parent;
ASSERT(raidvd->vdev_ops == &vdev_raidz_ops);
- uint64_t width = raidvd->vdev_children;
+ vdev_raidz_t *vdrz = raidvd->vdev_tsd;
+
+ if (vdrz->vn_vre.vre_state == DSS_SCANNING) {
+ /*
+ * We're in the middle of expansion, in which case the
+ * translation is in flux. Any answer we give may be wrong
+ * by the time we return, so it isn't safe for the caller to
+ * act on it. Therefore we say that this range isn't present
+ * on any children. The only consumers of this are "zpool
+ * initialize" and trimming, both of which are "best effort"
+ * anyway.
+ */
+ physical_rs->rs_start = physical_rs->rs_end = 0;
+ remain_rs->rs_start = remain_rs->rs_end = 0;
+ return;
+ }
+
+ uint64_t width = vdrz->vd_physical_width;
uint64_t tgt_col = cvd->vdev_id;
uint64_t ashift = raidvd->vdev_top->vdev_ashift;
@@ -2544,15 +3663,1155 @@ vdev_raidz_xlate(vdev_t *cvd, const range_seg64_t *logical_rs,
logical_rs->rs_end - logical_rs->rs_start);
}
+static void
+raidz_reflow_sync(void *arg, dmu_tx_t *tx)
+{
+ spa_t *spa = arg;
+ int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+
+ /*
+ * Ensure there are no i/os to the range that is being committed.
+ */
+ uint64_t old_offset = RRSS_GET_OFFSET(&spa->spa_uberblock);
+ ASSERT3U(vre->vre_offset_pertxg[txgoff], >=, old_offset);
+
+ mutex_enter(&vre->vre_lock);
+ uint64_t new_offset =
+ MIN(vre->vre_offset_pertxg[txgoff], vre->vre_failed_offset);
+ /*
+ * We should not have committed anything that failed.
+ */
+ VERIFY3U(vre->vre_failed_offset, >=, old_offset);
+ mutex_exit(&vre->vre_lock);
+
+ zfs_locked_range_t *lr = zfs_rangelock_enter(&vre->vre_rangelock,
+ old_offset, new_offset - old_offset,
+ RL_WRITER);
+
+ /*
+ * Update the uberblock that will be written when this txg completes.
+ */
+ RAIDZ_REFLOW_SET(&spa->spa_uberblock,
+ RRSS_SCRATCH_INVALID_SYNCED_REFLOW, new_offset);
+ vre->vre_offset_pertxg[txgoff] = 0;
+ zfs_rangelock_exit(lr);
+
+ mutex_enter(&vre->vre_lock);
+ vre->vre_bytes_copied += vre->vre_bytes_copied_pertxg[txgoff];
+ vre->vre_bytes_copied_pertxg[txgoff] = 0;
+ mutex_exit(&vre->vre_lock);
+
+ vdev_t *vd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ VERIFY0(zap_update(spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_BYTES_COPIED,
+ sizeof (vre->vre_bytes_copied), 1, &vre->vre_bytes_copied, tx));
+}
+
+static void
+raidz_reflow_complete_sync(void *arg, dmu_tx_t *tx)
+{
+ spa_t *spa = arg;
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+ vdev_t *raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ vdev_raidz_t *vdrz = raidvd->vdev_tsd;
+
+ for (int i = 0; i < TXG_SIZE; i++)
+ VERIFY0(vre->vre_offset_pertxg[i]);
+
+ reflow_node_t *re = kmem_zalloc(sizeof (*re), KM_SLEEP);
+ re->re_txg = tx->tx_txg + TXG_CONCURRENT_STATES;
+ re->re_logical_width = vdrz->vd_physical_width;
+ mutex_enter(&vdrz->vd_expand_lock);
+ avl_add(&vdrz->vd_expand_txgs, re);
+ mutex_exit(&vdrz->vd_expand_lock);
+
+ vdev_t *vd = vdev_lookup_top(spa, vre->vre_vdev_id);
+
+ /*
+ * Dirty the config so that the updated ZPOOL_CONFIG_RAIDZ_EXPAND_TXGS
+ * will get written (based on vd_expand_txgs).
+ */
+ vdev_config_dirty(vd);
+
+ /*
+ * Before we change vre_state, the on-disk state must reflect that we
+ * have completed all copying, so that vdev_raidz_io_start() can use
+ * vre_state to determine if the reflow is in progress. See also the
+ * end of spa_raidz_expand_thread().
+ */
+ VERIFY3U(RRSS_GET_OFFSET(&spa->spa_ubsync), ==,
+ raidvd->vdev_ms_count << raidvd->vdev_ms_shift);
+
+ vre->vre_end_time = gethrestime_sec();
+ vre->vre_state = DSS_FINISHED;
+
+ uint64_t state = vre->vre_state;
+ VERIFY0(zap_update(spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE,
+ sizeof (state), 1, &state, tx));
+
+ uint64_t end_time = vre->vre_end_time;
+ VERIFY0(zap_update(spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_END_TIME,
+ sizeof (end_time), 1, &end_time, tx));
+
+ spa->spa_uberblock.ub_raidz_reflow_info = 0;
+
+ spa_history_log_internal(spa, "raidz vdev expansion completed", tx,
+ "%s vdev %llu new width %llu", spa_name(spa),
+ (unsigned long long)vd->vdev_id,
+ (unsigned long long)vd->vdev_children);
+
+ spa->spa_raidz_expand = NULL;
+ raidvd->vdev_rz_expanding = B_FALSE;
+
+ spa_async_request(spa, SPA_ASYNC_INITIALIZE_RESTART);
+ spa_async_request(spa, SPA_ASYNC_TRIM_RESTART);
+ spa_async_request(spa, SPA_ASYNC_AUTOTRIM_RESTART);
+
+ spa_notify_waiters(spa);
+
+ /*
+ * While we're in syncing context take the opportunity to
+ * setup a scrub. All the data has been sucessfully copied
+ * but we have not validated any checksums.
+ */
+ pool_scan_func_t func = POOL_SCAN_SCRUB;
+ if (zfs_scrub_after_expand && dsl_scan_setup_check(&func, tx) == 0)
+ dsl_scan_setup_sync(&func, tx);
+}
+
+/*
+ * Struct for one copy zio.
+ */
+typedef struct raidz_reflow_arg {
+ vdev_raidz_expand_t *rra_vre;
+ zfs_locked_range_t *rra_lr;
+ uint64_t rra_txg;
+} raidz_reflow_arg_t;
+
+/*
+ * The write of the new location is done.
+ */
+static void
+raidz_reflow_write_done(zio_t *zio)
+{
+ raidz_reflow_arg_t *rra = zio->io_private;
+ vdev_raidz_expand_t *vre = rra->rra_vre;
+
+ abd_free(zio->io_abd);
+
+ mutex_enter(&vre->vre_lock);
+ if (zio->io_error != 0) {
+ /* Force a reflow pause on errors */
+ vre->vre_failed_offset =
+ MIN(vre->vre_failed_offset, rra->rra_lr->lr_offset);
+ }
+ ASSERT3U(vre->vre_outstanding_bytes, >=, zio->io_size);
+ vre->vre_outstanding_bytes -= zio->io_size;
+ if (rra->rra_lr->lr_offset + rra->rra_lr->lr_length <
+ vre->vre_failed_offset) {
+ vre->vre_bytes_copied_pertxg[rra->rra_txg & TXG_MASK] +=
+ zio->io_size;
+ }
+ cv_signal(&vre->vre_cv);
+ mutex_exit(&vre->vre_lock);
+
+ zfs_rangelock_exit(rra->rra_lr);
+
+ kmem_free(rra, sizeof (*rra));
+ spa_config_exit(zio->io_spa, SCL_STATE, zio->io_spa);
+}
+
+/*
+ * The read of the old location is done. The parent zio is the write to
+ * the new location. Allow it to start.
+ */
+static void
+raidz_reflow_read_done(zio_t *zio)
+{
+ raidz_reflow_arg_t *rra = zio->io_private;
+ vdev_raidz_expand_t *vre = rra->rra_vre;
+
+ /*
+ * If the read failed, or if it was done on a vdev that is not fully
+ * healthy (e.g. a child that has a resilver in progress), we may not
+ * have the correct data. Note that it's OK if the write proceeds.
+ * It may write garbage but the location is otherwise unused and we
+ * will retry later due to vre_failed_offset.
+ */
+ if (zio->io_error != 0 || !vdev_dtl_empty(zio->io_vd, DTL_MISSING)) {
+ zfs_dbgmsg("reflow read failed off=%llu size=%llu txg=%llu "
+ "err=%u partial_dtl_empty=%u missing_dtl_empty=%u",
+ (long long)rra->rra_lr->lr_offset,
+ (long long)rra->rra_lr->lr_length,
+ (long long)rra->rra_txg,
+ zio->io_error,
+ vdev_dtl_empty(zio->io_vd, DTL_PARTIAL),
+ vdev_dtl_empty(zio->io_vd, DTL_MISSING));
+ mutex_enter(&vre->vre_lock);
+ /* Force a reflow pause on errors */
+ vre->vre_failed_offset =
+ MIN(vre->vre_failed_offset, rra->rra_lr->lr_offset);
+ mutex_exit(&vre->vre_lock);
+ }
+
+ zio_nowait(zio_unique_parent(zio));
+}
+
+static void
+raidz_reflow_record_progress(vdev_raidz_expand_t *vre, uint64_t offset,
+ dmu_tx_t *tx)
+{
+ int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
+ spa_t *spa = dmu_tx_pool(tx)->dp_spa;
+
+ if (offset == 0)
+ return;
+
+ mutex_enter(&vre->vre_lock);
+ ASSERT3U(vre->vre_offset, <=, offset);
+ vre->vre_offset = offset;
+ mutex_exit(&vre->vre_lock);
+
+ if (vre->vre_offset_pertxg[txgoff] == 0) {
+ dsl_sync_task_nowait(dmu_tx_pool(tx), raidz_reflow_sync,
+ spa, tx);
+ }
+ vre->vre_offset_pertxg[txgoff] = offset;
+}
+
+static boolean_t
+vdev_raidz_expand_child_replacing(vdev_t *raidz_vd)
+{
+ for (int i = 0; i < raidz_vd->vdev_children; i++) {
+ /* Quick check if a child is being replaced */
+ if (!raidz_vd->vdev_child[i]->vdev_ops->vdev_op_leaf)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+static boolean_t
+raidz_reflow_impl(vdev_t *vd, vdev_raidz_expand_t *vre, range_tree_t *rt,
+ dmu_tx_t *tx)
+{
+ spa_t *spa = vd->vdev_spa;
+ int ashift = vd->vdev_top->vdev_ashift;
+ uint64_t offset, size;
+
+ if (!range_tree_find_in(rt, 0, vd->vdev_top->vdev_asize,
+ &offset, &size)) {
+ return (B_FALSE);
+ }
+ ASSERT(IS_P2ALIGNED(offset, 1 << ashift));
+ ASSERT3U(size, >=, 1 << ashift);
+ uint64_t length = 1 << ashift;
+ int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
+
+ uint64_t blkid = offset >> ashift;
+
+ int old_children = vd->vdev_children - 1;
+
+ /*
+ * We can only progress to the point that writes will not overlap
+ * with blocks whose progress has not yet been recorded on disk.
+ * Since partially-copied rows are still read from the old location,
+ * we need to stop one row before the sector-wise overlap, to prevent
+ * row-wise overlap.
+ *
+ * Note that even if we are skipping over a large unallocated region,
+ * we can't move the on-disk progress to `offset`, because concurrent
+ * writes/allocations could still use the currently-unallocated
+ * region.
+ */
+ uint64_t ubsync_blkid =
+ RRSS_GET_OFFSET(&spa->spa_ubsync) >> ashift;
+ uint64_t next_overwrite_blkid = ubsync_blkid +
+ ubsync_blkid / old_children - old_children;
+ VERIFY3U(next_overwrite_blkid, >, ubsync_blkid);
+
+ if (blkid >= next_overwrite_blkid) {
+ raidz_reflow_record_progress(vre,
+ next_overwrite_blkid << ashift, tx);
+ return (B_TRUE);
+ }
+
+ range_tree_remove(rt, offset, length);
+
+ raidz_reflow_arg_t *rra = kmem_zalloc(sizeof (*rra), KM_SLEEP);
+ rra->rra_vre = vre;
+ rra->rra_lr = zfs_rangelock_enter(&vre->vre_rangelock,
+ offset, length, RL_WRITER);
+ rra->rra_txg = dmu_tx_get_txg(tx);
+
+ raidz_reflow_record_progress(vre, offset + length, tx);
+
+ mutex_enter(&vre->vre_lock);
+ vre->vre_outstanding_bytes += length;
+ mutex_exit(&vre->vre_lock);
+
+ /*
+ * SCL_STATE will be released when the read and write are done,
+ * by raidz_reflow_write_done().
+ */
+ spa_config_enter(spa, SCL_STATE, spa, RW_READER);
+
+ /* check if a replacing vdev was added, if so treat it as an error */
+ if (vdev_raidz_expand_child_replacing(vd)) {
+ zfs_dbgmsg("replacing vdev encountered, reflow paused at "
+ "offset=%llu txg=%llu",
+ (long long)rra->rra_lr->lr_offset,
+ (long long)rra->rra_txg);
+
+ mutex_enter(&vre->vre_lock);
+ vre->vre_failed_offset =
+ MIN(vre->vre_failed_offset, rra->rra_lr->lr_offset);
+ cv_signal(&vre->vre_cv);
+ mutex_exit(&vre->vre_lock);
+
+ /* drop everything we acquired */
+ zfs_rangelock_exit(rra->rra_lr);
+ kmem_free(rra, sizeof (*rra));
+ spa_config_exit(spa, SCL_STATE, spa);
+ return (B_TRUE);
+ }
+
+ zio_t *pio = spa->spa_txg_zio[txgoff];
+ abd_t *abd = abd_alloc_for_io(length, B_FALSE);
+ zio_t *write_zio = zio_vdev_child_io(pio, NULL,
+ vd->vdev_child[blkid % vd->vdev_children],
+ (blkid / vd->vdev_children) << ashift,
+ abd, length,
+ ZIO_TYPE_WRITE, ZIO_PRIORITY_REMOVAL,
+ ZIO_FLAG_CANFAIL,
+ raidz_reflow_write_done, rra);
+
+ zio_nowait(zio_vdev_child_io(write_zio, NULL,
+ vd->vdev_child[blkid % old_children],
+ (blkid / old_children) << ashift,
+ abd, length,
+ ZIO_TYPE_READ, ZIO_PRIORITY_REMOVAL,
+ ZIO_FLAG_CANFAIL,
+ raidz_reflow_read_done, rra));
+
+ return (B_FALSE);
+}
+
+/*
+ * For testing (ztest specific)
+ */
+static void
+raidz_expand_pause(uint_t pause_point)
+{
+ while (raidz_expand_pause_point != 0 &&
+ raidz_expand_pause_point <= pause_point)
+ delay(hz);
+}
+
+static void
+raidz_scratch_child_done(zio_t *zio)
+{
+ zio_t *pio = zio->io_private;
+
+ mutex_enter(&pio->io_lock);
+ pio->io_error = zio_worst_error(pio->io_error, zio->io_error);
+ mutex_exit(&pio->io_lock);
+}
+
+/*
+ * Reflow the beginning portion of the vdev into an intermediate scratch area
+ * in memory and on disk. This operation must be persisted on disk before we
+ * proceed to overwrite the beginning portion with the reflowed data.
+ *
+ * This multi-step task can fail to complete if disk errors are encountered
+ * and we can return here after a pause (waiting for disk to become healthy).
+ */
+static void
+raidz_reflow_scratch_sync(void *arg, dmu_tx_t *tx)
+{
+ vdev_raidz_expand_t *vre = arg;
+ spa_t *spa = dmu_tx_pool(tx)->dp_spa;
+ zio_t *pio;
+ int error;
+
+ spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
+ vdev_t *raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ int ashift = raidvd->vdev_ashift;
+ uint64_t write_size = P2ALIGN(VDEV_BOOT_SIZE, 1 << ashift);
+ uint64_t logical_size = write_size * raidvd->vdev_children;
+ uint64_t read_size =
+ P2ROUNDUP(DIV_ROUND_UP(logical_size, (raidvd->vdev_children - 1)),
+ 1 << ashift);
+
+ /*
+ * The scratch space must be large enough to get us to the point
+ * that one row does not overlap itself when moved. This is checked
+ * by vdev_raidz_attach_check().
+ */
+ VERIFY3U(write_size, >=, raidvd->vdev_children << ashift);
+ VERIFY3U(write_size, <=, VDEV_BOOT_SIZE);
+ VERIFY3U(write_size, <=, read_size);
+
+ zfs_locked_range_t *lr = zfs_rangelock_enter(&vre->vre_rangelock,
+ 0, logical_size, RL_WRITER);
+
+ abd_t **abds = kmem_alloc(raidvd->vdev_children * sizeof (abd_t *),
+ KM_SLEEP);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ abds[i] = abd_alloc_linear(read_size, B_FALSE);
+ }
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_1);
+
+ /*
+ * If we have already written the scratch area then we must read from
+ * there, since new writes were redirected there while we were paused
+ * or the original location may have been partially overwritten with
+ * reflowed data.
+ */
+ if (RRSS_GET_STATE(&spa->spa_ubsync) == RRSS_SCRATCH_VALID) {
+ VERIFY3U(RRSS_GET_OFFSET(&spa->spa_ubsync), ==, logical_size);
+ /*
+ * Read from scratch space.
+ */
+ pio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ /*
+ * Note: zio_vdev_child_io() adds VDEV_LABEL_START_SIZE
+ * to the offset to calculate the physical offset to
+ * write to. Passing in a negative offset makes us
+ * access the scratch area.
+ */
+ zio_nowait(zio_vdev_child_io(pio, NULL,
+ raidvd->vdev_child[i],
+ VDEV_BOOT_OFFSET - VDEV_LABEL_START_SIZE, abds[i],
+ write_size, ZIO_TYPE_READ, ZIO_PRIORITY_ASYNC_READ,
+ ZIO_FLAG_CANFAIL, raidz_scratch_child_done, pio));
+ }
+ error = zio_wait(pio);
+ if (error != 0) {
+ zfs_dbgmsg("reflow: error %d reading scratch location",
+ error);
+ goto io_error_exit;
+ }
+ goto overwrite;
+ }
+
+ /*
+ * Read from original location.
+ */
+ pio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
+ for (int i = 0; i < raidvd->vdev_children - 1; i++) {
+ ASSERT0(vdev_is_dead(raidvd->vdev_child[i]));
+ zio_nowait(zio_vdev_child_io(pio, NULL, raidvd->vdev_child[i],
+ 0, abds[i], read_size, ZIO_TYPE_READ,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL,
+ raidz_scratch_child_done, pio));
+ }
+ error = zio_wait(pio);
+ if (error != 0) {
+ zfs_dbgmsg("reflow: error %d reading original location", error);
+io_error_exit:
+ for (int i = 0; i < raidvd->vdev_children; i++)
+ abd_free(abds[i]);
+ kmem_free(abds, raidvd->vdev_children * sizeof (abd_t *));
+ zfs_rangelock_exit(lr);
+ spa_config_exit(spa, SCL_STATE, FTAG);
+ return;
+ }
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_2);
+
+ /*
+ * Reflow in memory.
+ */
+ uint64_t logical_sectors = logical_size >> ashift;
+ for (int i = raidvd->vdev_children - 1; i < logical_sectors; i++) {
+ int oldchild = i % (raidvd->vdev_children - 1);
+ uint64_t oldoff = (i / (raidvd->vdev_children - 1)) << ashift;
+
+ int newchild = i % raidvd->vdev_children;
+ uint64_t newoff = (i / raidvd->vdev_children) << ashift;
+
+ /* a single sector should not be copying over itself */
+ ASSERT(!(newchild == oldchild && newoff == oldoff));
+
+ abd_copy_off(abds[newchild], abds[oldchild],
+ newoff, oldoff, 1 << ashift);
+ }
+
+ /*
+ * Verify that we filled in everything we intended to (write_size on
+ * each child).
+ */
+ VERIFY0(logical_sectors % raidvd->vdev_children);
+ VERIFY3U((logical_sectors / raidvd->vdev_children) << ashift, ==,
+ write_size);
+
+ /*
+ * Write to scratch location (boot area).
+ */
+ pio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ /*
+ * Note: zio_vdev_child_io() adds VDEV_LABEL_START_SIZE to
+ * the offset to calculate the physical offset to write to.
+ * Passing in a negative offset lets us access the boot area.
+ */
+ zio_nowait(zio_vdev_child_io(pio, NULL, raidvd->vdev_child[i],
+ VDEV_BOOT_OFFSET - VDEV_LABEL_START_SIZE, abds[i],
+ write_size, ZIO_TYPE_WRITE, ZIO_PRIORITY_ASYNC_WRITE,
+ ZIO_FLAG_CANFAIL, raidz_scratch_child_done, pio));
+ }
+ error = zio_wait(pio);
+ if (error != 0) {
+ zfs_dbgmsg("reflow: error %d writing scratch location", error);
+ goto io_error_exit;
+ }
+ pio = zio_root(spa, NULL, NULL, 0);
+ zio_flush(pio, raidvd);
+ zio_wait(pio);
+
+ zfs_dbgmsg("reflow: wrote %llu bytes (logical) to scratch area",
+ (long long)logical_size);
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_3);
+
+ /*
+ * Update uberblock to indicate that scratch space is valid. This is
+ * needed because after this point, the real location may be
+ * overwritten. If we crash, we need to get the data from the
+ * scratch space, rather than the real location.
+ *
+ * Note: ub_timestamp is bumped so that vdev_uberblock_compare()
+ * will prefer this uberblock.
+ */
+ RAIDZ_REFLOW_SET(&spa->spa_ubsync, RRSS_SCRATCH_VALID, logical_size);
+ spa->spa_ubsync.ub_timestamp++;
+ ASSERT0(vdev_uberblock_sync_list(&spa->spa_root_vdev, 1,
+ &spa->spa_ubsync, ZIO_FLAG_CONFIG_WRITER));
+ if (spa_multihost(spa))
+ mmp_update_uberblock(spa, &spa->spa_ubsync);
+
+ zfs_dbgmsg("reflow: uberblock updated "
+ "(txg %llu, SCRATCH_VALID, size %llu, ts %llu)",
+ (long long)spa->spa_ubsync.ub_txg,
+ (long long)logical_size,
+ (long long)spa->spa_ubsync.ub_timestamp);
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_SCRATCH_VALID);
+
+ /*
+ * Overwrite with reflow'ed data.
+ */
+overwrite:
+ pio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ zio_nowait(zio_vdev_child_io(pio, NULL, raidvd->vdev_child[i],
+ 0, abds[i], write_size, ZIO_TYPE_WRITE,
+ ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_CANFAIL,
+ raidz_scratch_child_done, pio));
+ }
+ error = zio_wait(pio);
+ if (error != 0) {
+ /*
+ * When we exit early here and drop the range lock, new
+ * writes will go into the scratch area so we'll need to
+ * read from there when we return after pausing.
+ */
+ zfs_dbgmsg("reflow: error %d writing real location", error);
+ /*
+ * Update the uberblock that is written when this txg completes.
+ */
+ RAIDZ_REFLOW_SET(&spa->spa_uberblock, RRSS_SCRATCH_VALID,
+ logical_size);
+ goto io_error_exit;
+ }
+ pio = zio_root(spa, NULL, NULL, 0);
+ zio_flush(pio, raidvd);
+ zio_wait(pio);
+
+ zfs_dbgmsg("reflow: overwrote %llu bytes (logical) to real location",
+ (long long)logical_size);
+ for (int i = 0; i < raidvd->vdev_children; i++)
+ abd_free(abds[i]);
+ kmem_free(abds, raidvd->vdev_children * sizeof (abd_t *));
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_SCRATCH_REFLOWED);
+
+ /*
+ * Update uberblock to indicate that the initial part has been
+ * reflow'ed. This is needed because after this point (when we exit
+ * the rangelock), we allow regular writes to this region, which will
+ * be written to the new location only (because reflow_offset_next ==
+ * reflow_offset_synced). If we crashed and re-copied from the
+ * scratch space, we would lose the regular writes.
+ */
+ RAIDZ_REFLOW_SET(&spa->spa_ubsync, RRSS_SCRATCH_INVALID_SYNCED,
+ logical_size);
+ spa->spa_ubsync.ub_timestamp++;
+ ASSERT0(vdev_uberblock_sync_list(&spa->spa_root_vdev, 1,
+ &spa->spa_ubsync, ZIO_FLAG_CONFIG_WRITER));
+ if (spa_multihost(spa))
+ mmp_update_uberblock(spa, &spa->spa_ubsync);
+
+ zfs_dbgmsg("reflow: uberblock updated "
+ "(txg %llu, SCRATCH_NOT_IN_USE, size %llu, ts %llu)",
+ (long long)spa->spa_ubsync.ub_txg,
+ (long long)logical_size,
+ (long long)spa->spa_ubsync.ub_timestamp);
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_1);
+
+ /*
+ * Update progress.
+ */
+ vre->vre_offset = logical_size;
+ zfs_rangelock_exit(lr);
+ spa_config_exit(spa, SCL_STATE, FTAG);
+
+ int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
+ vre->vre_offset_pertxg[txgoff] = vre->vre_offset;
+ vre->vre_bytes_copied_pertxg[txgoff] = vre->vre_bytes_copied;
+ /*
+ * Note - raidz_reflow_sync() will update the uberblock state to
+ * RRSS_SCRATCH_INVALID_SYNCED_REFLOW
+ */
+ raidz_reflow_sync(spa, tx);
+
+ raidz_expand_pause(RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_2);
+}
+
+/*
+ * We crashed in the middle of raidz_reflow_scratch_sync(); complete its work
+ * here. No other i/o can be in progress, so we don't need the vre_rangelock.
+ */
+void
+vdev_raidz_reflow_copy_scratch(spa_t *spa)
+{
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+ uint64_t logical_size = RRSS_GET_OFFSET(&spa->spa_uberblock);
+ ASSERT3U(RRSS_GET_STATE(&spa->spa_uberblock), ==, RRSS_SCRATCH_VALID);
+
+ spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
+ vdev_t *raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ ASSERT0(logical_size % raidvd->vdev_children);
+ uint64_t write_size = logical_size / raidvd->vdev_children;
+
+ zio_t *pio;
+
+ /*
+ * Read from scratch space.
+ */
+ abd_t **abds = kmem_alloc(raidvd->vdev_children * sizeof (abd_t *),
+ KM_SLEEP);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ abds[i] = abd_alloc_linear(write_size, B_FALSE);
+ }
+
+ pio = zio_root(spa, NULL, NULL, 0);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ /*
+ * Note: zio_vdev_child_io() adds VDEV_LABEL_START_SIZE to
+ * the offset to calculate the physical offset to write to.
+ * Passing in a negative offset lets us access the boot area.
+ */
+ zio_nowait(zio_vdev_child_io(pio, NULL, raidvd->vdev_child[i],
+ VDEV_BOOT_OFFSET - VDEV_LABEL_START_SIZE, abds[i],
+ write_size, ZIO_TYPE_READ,
+ ZIO_PRIORITY_ASYNC_READ, 0,
+ raidz_scratch_child_done, pio));
+ }
+ zio_wait(pio);
+
+ /*
+ * Overwrite real location with reflow'ed data.
+ */
+ pio = zio_root(spa, NULL, NULL, 0);
+ for (int i = 0; i < raidvd->vdev_children; i++) {
+ zio_nowait(zio_vdev_child_io(pio, NULL, raidvd->vdev_child[i],
+ 0, abds[i], write_size, ZIO_TYPE_WRITE,
+ ZIO_PRIORITY_ASYNC_WRITE, 0,
+ raidz_scratch_child_done, pio));
+ }
+ zio_wait(pio);
+ pio = zio_root(spa, NULL, NULL, 0);
+ zio_flush(pio, raidvd);
+ zio_wait(pio);
+
+ zfs_dbgmsg("reflow recovery: overwrote %llu bytes (logical) "
+ "to real location", (long long)logical_size);
+
+ for (int i = 0; i < raidvd->vdev_children; i++)
+ abd_free(abds[i]);
+ kmem_free(abds, raidvd->vdev_children * sizeof (abd_t *));
+
+ /*
+ * Update uberblock.
+ */
+ RAIDZ_REFLOW_SET(&spa->spa_ubsync,
+ RRSS_SCRATCH_INVALID_SYNCED_ON_IMPORT, logical_size);
+ spa->spa_ubsync.ub_timestamp++;
+ VERIFY0(vdev_uberblock_sync_list(&spa->spa_root_vdev, 1,
+ &spa->spa_ubsync, ZIO_FLAG_CONFIG_WRITER));
+ if (spa_multihost(spa))
+ mmp_update_uberblock(spa, &spa->spa_ubsync);
+
+ zfs_dbgmsg("reflow recovery: uberblock updated "
+ "(txg %llu, SCRATCH_NOT_IN_USE, size %llu, ts %llu)",
+ (long long)spa->spa_ubsync.ub_txg,
+ (long long)logical_size,
+ (long long)spa->spa_ubsync.ub_timestamp);
+
+ dmu_tx_t *tx = dmu_tx_create_assigned(spa->spa_dsl_pool,
+ spa_first_txg(spa));
+ int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
+ vre->vre_offset = logical_size;
+ vre->vre_offset_pertxg[txgoff] = vre->vre_offset;
+ vre->vre_bytes_copied_pertxg[txgoff] = vre->vre_bytes_copied;
+ /*
+ * Note that raidz_reflow_sync() will update the uberblock once more
+ */
+ raidz_reflow_sync(spa, tx);
+
+ dmu_tx_commit(tx);
+
+ spa_config_exit(spa, SCL_STATE, FTAG);
+}
+
+static boolean_t
+spa_raidz_expand_thread_check(void *arg, zthr_t *zthr)
+{
+ (void) zthr;
+ spa_t *spa = arg;
+
+ return (spa->spa_raidz_expand != NULL &&
+ !spa->spa_raidz_expand->vre_waiting_for_resilver);
+}
+
+/*
+ * RAIDZ expansion background thread
+ *
+ * Can be called multiple times if the reflow is paused
+ */
+static void
+spa_raidz_expand_thread(void *arg, zthr_t *zthr)
+{
+ spa_t *spa = arg;
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+
+ if (RRSS_GET_STATE(&spa->spa_ubsync) == RRSS_SCRATCH_VALID)
+ vre->vre_offset = 0;
+ else
+ vre->vre_offset = RRSS_GET_OFFSET(&spa->spa_ubsync);
+
+ /* Reflow the begining portion using the scratch area */
+ if (vre->vre_offset == 0) {
+ VERIFY0(dsl_sync_task(spa_name(spa),
+ NULL, raidz_reflow_scratch_sync,
+ vre, 0, ZFS_SPACE_CHECK_NONE));
+
+ /* if we encountered errors then pause */
+ if (vre->vre_offset == 0) {
+ mutex_enter(&vre->vre_lock);
+ vre->vre_waiting_for_resilver = B_TRUE;
+ mutex_exit(&vre->vre_lock);
+ return;
+ }
+ }
+
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ vdev_t *raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+
+ uint64_t guid = raidvd->vdev_guid;
+
+ /* Iterate over all the remaining metaslabs */
+ for (uint64_t i = vre->vre_offset >> raidvd->vdev_ms_shift;
+ i < raidvd->vdev_ms_count &&
+ !zthr_iscancelled(zthr) &&
+ vre->vre_failed_offset == UINT64_MAX; i++) {
+ metaslab_t *msp = raidvd->vdev_ms[i];
+
+ metaslab_disable(msp);
+ mutex_enter(&msp->ms_lock);
+
+ /*
+ * The metaslab may be newly created (for the expanded
+ * space), in which case its trees won't exist yet,
+ * so we need to bail out early.
+ */
+ if (msp->ms_new) {
+ mutex_exit(&msp->ms_lock);
+ metaslab_enable(msp, B_FALSE, B_FALSE);
+ continue;
+ }
+
+ VERIFY0(metaslab_load(msp));
+
+ /*
+ * We want to copy everything except the free (allocatable)
+ * space. Note that there may be a little bit more free
+ * space (e.g. in ms_defer), and it's fine to copy that too.
+ */
+ range_tree_t *rt = range_tree_create(NULL, RANGE_SEG64,
+ NULL, 0, 0);
+ range_tree_add(rt, msp->ms_start, msp->ms_size);
+ range_tree_walk(msp->ms_allocatable, range_tree_remove, rt);
+ mutex_exit(&msp->ms_lock);
+
+ /*
+ * Force the last sector of each metaslab to be copied. This
+ * ensures that we advance the on-disk progress to the end of
+ * this metaslab while the metaslab is disabled. Otherwise, we
+ * could move past this metaslab without advancing the on-disk
+ * progress, and then an allocation to this metaslab would not
+ * be copied.
+ */
+ int sectorsz = 1 << raidvd->vdev_ashift;
+ uint64_t ms_last_offset = msp->ms_start +
+ msp->ms_size - sectorsz;
+ if (!range_tree_contains(rt, ms_last_offset, sectorsz)) {
+ range_tree_add(rt, ms_last_offset, sectorsz);
+ }
+
+ /*
+ * When we are resuming from a paused expansion (i.e.
+ * when importing a pool with a expansion in progress),
+ * discard any state that we have already processed.
+ */
+ range_tree_clear(rt, 0, vre->vre_offset);
+
+ while (!zthr_iscancelled(zthr) &&
+ !range_tree_is_empty(rt) &&
+ vre->vre_failed_offset == UINT64_MAX) {
+
+ /*
+ * We need to periodically drop the config lock so that
+ * writers can get in. Additionally, we can't wait
+ * for a txg to sync while holding a config lock
+ * (since a waiting writer could cause a 3-way deadlock
+ * with the sync thread, which also gets a config
+ * lock for reader). So we can't hold the config lock
+ * while calling dmu_tx_assign().
+ */
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+
+ /*
+ * If requested, pause the reflow when the amount
+ * specified by raidz_expand_max_reflow_bytes is reached
+ *
+ * This pause is only used during testing or debugging.
+ */
+ while (raidz_expand_max_reflow_bytes != 0 &&
+ raidz_expand_max_reflow_bytes <=
+ vre->vre_bytes_copied && !zthr_iscancelled(zthr)) {
+ delay(hz);
+ }
+
+ mutex_enter(&vre->vre_lock);
+ while (vre->vre_outstanding_bytes >
+ raidz_expand_max_copy_bytes) {
+ cv_wait(&vre->vre_cv, &vre->vre_lock);
+ }
+ mutex_exit(&vre->vre_lock);
+
+ dmu_tx_t *tx =
+ dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
+
+ VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
+ uint64_t txg = dmu_tx_get_txg(tx);
+
+ /*
+ * Reacquire the vdev_config lock. Theoretically, the
+ * vdev_t that we're expanding may have changed.
+ */
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+
+ boolean_t needsync =
+ raidz_reflow_impl(raidvd, vre, rt, tx);
+
+ dmu_tx_commit(tx);
+
+ if (needsync) {
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ txg_wait_synced(spa->spa_dsl_pool, txg);
+ spa_config_enter(spa, SCL_CONFIG, FTAG,
+ RW_READER);
+ }
+ }
+
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+
+ metaslab_enable(msp, B_FALSE, B_FALSE);
+ range_tree_vacate(rt, NULL, NULL);
+ range_tree_destroy(rt);
+
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ }
+
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+
+ /*
+ * The txg_wait_synced() here ensures that all reflow zio's have
+ * completed, and vre_failed_offset has been set if necessary. It
+ * also ensures that the progress of the last raidz_reflow_sync() is
+ * written to disk before raidz_reflow_complete_sync() changes the
+ * in-memory vre_state. vdev_raidz_io_start() uses vre_state to
+ * determine if a reflow is in progress, in which case we may need to
+ * write to both old and new locations. Therefore we can only change
+ * vre_state once this is not necessary, which is once the on-disk
+ * progress (in spa_ubsync) has been set past any possible writes (to
+ * the end of the last metaslab).
+ */
+ txg_wait_synced(spa->spa_dsl_pool, 0);
+
+ if (!zthr_iscancelled(zthr) &&
+ vre->vre_offset == raidvd->vdev_ms_count << raidvd->vdev_ms_shift) {
+ /*
+ * We are not being canceled or paused, so the reflow must be
+ * complete. In that case also mark it as completed on disk.
+ */
+ ASSERT3U(vre->vre_failed_offset, ==, UINT64_MAX);
+ VERIFY0(dsl_sync_task(spa_name(spa), NULL,
+ raidz_reflow_complete_sync, spa,
+ 0, ZFS_SPACE_CHECK_NONE));
+ (void) vdev_online(spa, guid, ZFS_ONLINE_EXPAND, NULL);
+ } else {
+ /*
+ * Wait for all copy zio's to complete and for all the
+ * raidz_reflow_sync() synctasks to be run.
+ */
+ spa_history_log_internal(spa, "reflow pause",
+ NULL, "offset=%llu failed_offset=%lld",
+ (long long)vre->vre_offset,
+ (long long)vre->vre_failed_offset);
+ mutex_enter(&vre->vre_lock);
+ if (vre->vre_failed_offset != UINT64_MAX) {
+ /*
+ * Reset progress so that we will retry everything
+ * after the point that something failed.
+ */
+ vre->vre_offset = vre->vre_failed_offset;
+ vre->vre_failed_offset = UINT64_MAX;
+ vre->vre_waiting_for_resilver = B_TRUE;
+ }
+ mutex_exit(&vre->vre_lock);
+ }
+}
+
+void
+spa_start_raidz_expansion_thread(spa_t *spa)
+{
+ ASSERT3P(spa->spa_raidz_expand_zthr, ==, NULL);
+ spa->spa_raidz_expand_zthr = zthr_create("raidz_expand",
+ spa_raidz_expand_thread_check, spa_raidz_expand_thread,
+ spa, defclsyspri);
+}
+
+void
+raidz_dtl_reassessed(vdev_t *vd)
+{
+ spa_t *spa = vd->vdev_spa;
+ if (spa->spa_raidz_expand != NULL) {
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+ /*
+ * we get called often from vdev_dtl_reassess() so make
+ * sure it's our vdev and any replacing is complete
+ */
+ if (vd->vdev_top->vdev_id == vre->vre_vdev_id &&
+ !vdev_raidz_expand_child_replacing(vd->vdev_top)) {
+ mutex_enter(&vre->vre_lock);
+ if (vre->vre_waiting_for_resilver) {
+ vdev_dbgmsg(vd, "DTL reassessed, "
+ "continuing raidz expansion");
+ vre->vre_waiting_for_resilver = B_FALSE;
+ zthr_wakeup(spa->spa_raidz_expand_zthr);
+ }
+ mutex_exit(&vre->vre_lock);
+ }
+ }
+}
+
+int
+vdev_raidz_attach_check(vdev_t *new_child)
+{
+ vdev_t *raidvd = new_child->vdev_parent;
+ uint64_t new_children = raidvd->vdev_children;
+
+ /*
+ * We use the "boot" space as scratch space to handle overwriting the
+ * initial part of the vdev. If it is too small, then this expansion
+ * is not allowed. This would be very unusual (e.g. ashift > 13 and
+ * >200 children).
+ */
+ if (new_children << raidvd->vdev_ashift > VDEV_BOOT_SIZE) {
+ return (EINVAL);
+ }
+ return (0);
+}
+
+void
+vdev_raidz_attach_sync(void *arg, dmu_tx_t *tx)
+{
+ vdev_t *new_child = arg;
+ spa_t *spa = new_child->vdev_spa;
+ vdev_t *raidvd = new_child->vdev_parent;
+ vdev_raidz_t *vdrz = raidvd->vdev_tsd;
+ ASSERT3P(raidvd->vdev_ops, ==, &vdev_raidz_ops);
+ ASSERT3P(raidvd->vdev_top, ==, raidvd);
+ ASSERT3U(raidvd->vdev_children, >, vdrz->vd_original_width);
+ ASSERT3U(raidvd->vdev_children, ==, vdrz->vd_physical_width + 1);
+ ASSERT3P(raidvd->vdev_child[raidvd->vdev_children - 1], ==,
+ new_child);
+
+ spa_feature_incr(spa, SPA_FEATURE_RAIDZ_EXPANSION, tx);
+
+ vdrz->vd_physical_width++;
+
+ VERIFY0(spa->spa_uberblock.ub_raidz_reflow_info);
+ vdrz->vn_vre.vre_vdev_id = raidvd->vdev_id;
+ vdrz->vn_vre.vre_offset = 0;
+ vdrz->vn_vre.vre_failed_offset = UINT64_MAX;
+ spa->spa_raidz_expand = &vdrz->vn_vre;
+ zthr_wakeup(spa->spa_raidz_expand_zthr);
+
+ /*
+ * Dirty the config so that ZPOOL_CONFIG_RAIDZ_EXPANDING will get
+ * written to the config.
+ */
+ vdev_config_dirty(raidvd);
+
+ vdrz->vn_vre.vre_start_time = gethrestime_sec();
+ vdrz->vn_vre.vre_end_time = 0;
+ vdrz->vn_vre.vre_state = DSS_SCANNING;
+ vdrz->vn_vre.vre_bytes_copied = 0;
+
+ uint64_t state = vdrz->vn_vre.vre_state;
+ VERIFY0(zap_update(spa->spa_meta_objset,
+ raidvd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE,
+ sizeof (state), 1, &state, tx));
+
+ uint64_t start_time = vdrz->vn_vre.vre_start_time;
+ VERIFY0(zap_update(spa->spa_meta_objset,
+ raidvd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_START_TIME,
+ sizeof (start_time), 1, &start_time, tx));
+
+ (void) zap_remove(spa->spa_meta_objset,
+ raidvd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_END_TIME, tx);
+ (void) zap_remove(spa->spa_meta_objset,
+ raidvd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_BYTES_COPIED, tx);
+
+ spa_history_log_internal(spa, "raidz vdev expansion started", tx,
+ "%s vdev %llu new width %llu", spa_name(spa),
+ (unsigned long long)raidvd->vdev_id,
+ (unsigned long long)raidvd->vdev_children);
+}
+
+int
+vdev_raidz_load(vdev_t *vd)
+{
+ vdev_raidz_t *vdrz = vd->vdev_tsd;
+ int err;
+
+ uint64_t state = DSS_NONE;
+ uint64_t start_time = 0;
+ uint64_t end_time = 0;
+ uint64_t bytes_copied = 0;
+
+ if (vd->vdev_top_zap != 0) {
+ err = zap_lookup(vd->vdev_spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_STATE,
+ sizeof (state), 1, &state);
+ if (err != 0 && err != ENOENT)
+ return (err);
+
+ err = zap_lookup(vd->vdev_spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_START_TIME,
+ sizeof (start_time), 1, &start_time);
+ if (err != 0 && err != ENOENT)
+ return (err);
+
+ err = zap_lookup(vd->vdev_spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_END_TIME,
+ sizeof (end_time), 1, &end_time);
+ if (err != 0 && err != ENOENT)
+ return (err);
+
+ err = zap_lookup(vd->vdev_spa->spa_meta_objset,
+ vd->vdev_top_zap, VDEV_TOP_ZAP_RAIDZ_EXPAND_BYTES_COPIED,
+ sizeof (bytes_copied), 1, &bytes_copied);
+ if (err != 0 && err != ENOENT)
+ return (err);
+ }
+
+ /*
+ * If we are in the middle of expansion, vre_state should have
+ * already been set by vdev_raidz_init().
+ */
+ EQUIV(vdrz->vn_vre.vre_state == DSS_SCANNING, state == DSS_SCANNING);
+ vdrz->vn_vre.vre_state = (dsl_scan_state_t)state;
+ vdrz->vn_vre.vre_start_time = start_time;
+ vdrz->vn_vre.vre_end_time = end_time;
+ vdrz->vn_vre.vre_bytes_copied = bytes_copied;
+
+ return (0);
+}
+
+int
+spa_raidz_expand_get_stats(spa_t *spa, pool_raidz_expand_stat_t *pres)
+{
+ vdev_raidz_expand_t *vre = spa->spa_raidz_expand;
+
+ if (vre == NULL) {
+ /* no removal in progress; find most recent completed */
+ for (int c = 0; c < spa->spa_root_vdev->vdev_children; c++) {
+ vdev_t *vd = spa->spa_root_vdev->vdev_child[c];
+ if (vd->vdev_ops == &vdev_raidz_ops) {
+ vdev_raidz_t *vdrz = vd->vdev_tsd;
+
+ if (vdrz->vn_vre.vre_end_time != 0 &&
+ (vre == NULL ||
+ vdrz->vn_vre.vre_end_time >
+ vre->vre_end_time)) {
+ vre = &vdrz->vn_vre;
+ }
+ }
+ }
+ }
+
+ if (vre == NULL) {
+ return (SET_ERROR(ENOENT));
+ }
+
+ pres->pres_state = vre->vre_state;
+ pres->pres_expanding_vdev = vre->vre_vdev_id;
+
+ vdev_t *vd = vdev_lookup_top(spa, vre->vre_vdev_id);
+ pres->pres_to_reflow = vd->vdev_stat.vs_alloc;
+
+ mutex_enter(&vre->vre_lock);
+ pres->pres_reflowed = vre->vre_bytes_copied;
+ for (int i = 0; i < TXG_SIZE; i++)
+ pres->pres_reflowed += vre->vre_bytes_copied_pertxg[i];
+ mutex_exit(&vre->vre_lock);
+
+ pres->pres_start_time = vre->vre_start_time;
+ pres->pres_end_time = vre->vre_end_time;
+ pres->pres_waiting_for_resilver = vre->vre_waiting_for_resilver;
+
+ return (0);
+}
+
/*
* Initialize private RAIDZ specific fields from the nvlist.
*/
static int
vdev_raidz_init(spa_t *spa, nvlist_t *nv, void **tsd)
{
- vdev_raidz_t *vdrz;
- uint64_t nparity;
-
uint_t children;
nvlist_t **child;
int error = nvlist_lookup_nvlist_array(nv,
@@ -2560,6 +4819,7 @@ vdev_raidz_init(spa_t *spa, nvlist_t *nv, void **tsd)
if (error != 0)
return (SET_ERROR(EINVAL));
+ uint64_t nparity;
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY, &nparity) == 0) {
if (nparity == 0 || nparity > VDEV_RAIDZ_MAXPARITY)
return (SET_ERROR(EINVAL));
@@ -2586,10 +4846,56 @@ vdev_raidz_init(spa_t *spa, nvlist_t *nv, void **tsd)
nparity = 1;
}
- vdrz = kmem_zalloc(sizeof (*vdrz), KM_SLEEP);
- vdrz->vd_logical_width = children;
+ vdev_raidz_t *vdrz = kmem_zalloc(sizeof (*vdrz), KM_SLEEP);
+ vdrz->vn_vre.vre_vdev_id = -1;
+ vdrz->vn_vre.vre_offset = UINT64_MAX;
+ vdrz->vn_vre.vre_failed_offset = UINT64_MAX;
+ mutex_init(&vdrz->vn_vre.vre_lock, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&vdrz->vn_vre.vre_cv, NULL, CV_DEFAULT, NULL);
+ zfs_rangelock_init(&vdrz->vn_vre.vre_rangelock, NULL, NULL);
+ mutex_init(&vdrz->vd_expand_lock, NULL, MUTEX_DEFAULT, NULL);
+ avl_create(&vdrz->vd_expand_txgs, vdev_raidz_reflow_compare,
+ sizeof (reflow_node_t), offsetof(reflow_node_t, re_link));
+
+ vdrz->vd_physical_width = children;
vdrz->vd_nparity = nparity;
+ /* note, the ID does not exist when creating a pool */
+ (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
+ &vdrz->vn_vre.vre_vdev_id);
+
+ boolean_t reflow_in_progress =
+ nvlist_exists(nv, ZPOOL_CONFIG_RAIDZ_EXPANDING);
+ if (reflow_in_progress) {
+ spa->spa_raidz_expand = &vdrz->vn_vre;
+ vdrz->vn_vre.vre_state = DSS_SCANNING;
+ }
+
+ vdrz->vd_original_width = children;
+ uint64_t *txgs;
+ unsigned int txgs_size = 0;
+ error = nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_RAIDZ_EXPAND_TXGS,
+ &txgs, &txgs_size);
+ if (error == 0) {
+ for (int i = 0; i < txgs_size; i++) {
+ reflow_node_t *re = kmem_zalloc(sizeof (*re), KM_SLEEP);
+ re->re_txg = txgs[txgs_size - i - 1];
+ re->re_logical_width = vdrz->vd_physical_width - i;
+
+ if (reflow_in_progress)
+ re->re_logical_width--;
+
+ avl_add(&vdrz->vd_expand_txgs, re);
+ }
+
+ vdrz->vd_original_width = vdrz->vd_physical_width - txgs_size;
+ }
+ if (reflow_in_progress) {
+ vdrz->vd_original_width--;
+ zfs_dbgmsg("reflow_in_progress, %u wide, %d prior expansions",
+ children, txgs_size);
+ }
+
*tsd = vdrz;
return (0);
@@ -2598,7 +4904,20 @@ vdev_raidz_init(spa_t *spa, nvlist_t *nv, void **tsd)
static void
vdev_raidz_fini(vdev_t *vd)
{
- kmem_free(vd->vdev_tsd, sizeof (vdev_raidz_t));
+ vdev_raidz_t *vdrz = vd->vdev_tsd;
+ if (vd->vdev_spa->spa_raidz_expand == &vdrz->vn_vre)
+ vd->vdev_spa->spa_raidz_expand = NULL;
+ reflow_node_t *re;
+ void *cookie = NULL;
+ avl_tree_t *tree = &vdrz->vd_expand_txgs;
+ while ((re = avl_destroy_nodes(tree, &cookie)) != NULL)
+ kmem_free(re, sizeof (*re));
+ avl_destroy(&vdrz->vd_expand_txgs);
+ mutex_destroy(&vdrz->vd_expand_lock);
+ mutex_destroy(&vdrz->vn_vre.vre_lock);
+ cv_destroy(&vdrz->vn_vre.vre_cv);
+ zfs_rangelock_fini(&vdrz->vn_vre.vre_rangelock);
+ kmem_free(vdrz, sizeof (*vdrz));
}
/*
@@ -2626,6 +4945,29 @@ vdev_raidz_config_generate(vdev_t *vd, nvlist_t *nv)
* it.
*/
fnvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY, vdrz->vd_nparity);
+
+ if (vdrz->vn_vre.vre_state == DSS_SCANNING) {
+ fnvlist_add_boolean(nv, ZPOOL_CONFIG_RAIDZ_EXPANDING);
+ }
+
+ mutex_enter(&vdrz->vd_expand_lock);
+ if (!avl_is_empty(&vdrz->vd_expand_txgs)) {
+ uint64_t count = avl_numnodes(&vdrz->vd_expand_txgs);
+ uint64_t *txgs = kmem_alloc(sizeof (uint64_t) * count,
+ KM_SLEEP);
+ uint64_t i = 0;
+
+ for (reflow_node_t *re = avl_first(&vdrz->vd_expand_txgs);
+ re != NULL; re = AVL_NEXT(&vdrz->vd_expand_txgs, re)) {
+ txgs[i++] = re->re_txg;
+ }
+
+ fnvlist_add_uint64_array(nv, ZPOOL_CONFIG_RAIDZ_EXPAND_TXGS,
+ txgs, count);
+
+ kmem_free(txgs, sizeof (uint64_t) * count);
+ }
+ mutex_exit(&vdrz->vd_expand_lock);
}
static uint64_t
@@ -2665,3 +5007,15 @@ vdev_ops_t vdev_raidz_ops = {
.vdev_op_type = VDEV_TYPE_RAIDZ, /* name of this vdev type */
.vdev_op_leaf = B_FALSE /* not a leaf vdev */
};
+
+/* BEGIN CSTYLED */
+ZFS_MODULE_PARAM(zfs_vdev, raidz_, expand_max_reflow_bytes, ULONG, ZMOD_RW,
+ "For testing, pause RAIDZ expansion after reflowing this many bytes");
+ZFS_MODULE_PARAM(zfs_vdev, raidz_, expand_max_copy_bytes, ULONG, ZMOD_RW,
+ "Max amount of concurrent i/o for RAIDZ expansion");
+ZFS_MODULE_PARAM(zfs_vdev, raidz_, io_aggregate_rows, ULONG, ZMOD_RW,
+ "For expanded RAIDZ, aggregate reads that have more rows than this");
+ZFS_MODULE_PARAM(zfs, zfs_, scrub_after_expand, INT, ZMOD_RW,
+ "For expanded RAIDZ, automatically start a pool scrub when expansion "
+ "completes");
+/* END CSTYLED */
diff --git a/module/zfs/vdev_raidz_math.c b/module/zfs/vdev_raidz_math.c
index c588959739fb..e12b96170f55 100644
--- a/module/zfs/vdev_raidz_math.c
+++ b/module/zfs/vdev_raidz_math.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (C) 2016 Gvozden Nešković. All rights reserved.
*/
+#include <sys/simd.h>
#include <sys/zfs_context.h>
#include <sys/types.h>
#include <sys/zio.h>
@@ -29,7 +30,6 @@
#include <sys/zfs_debug.h>
#include <sys/vdev_raidz.h>
#include <sys/vdev_raidz_impl.h>
-#include <sys/simd.h>
/* Opaque implementation with NULL methods to represent original methods */
static const raidz_impl_ops_t vdev_raidz_original_impl = {
@@ -285,17 +285,17 @@ raidz_math_kstat_headers(char *buf, size_t size)
{
ASSERT3U(size, >=, RAIDZ_KSTAT_LINE_LEN);
- ssize_t off = snprintf(buf, size, "%-17s", "implementation");
+ ssize_t off = kmem_scnprintf(buf, size, "%-17s", "implementation");
for (int i = 0; i < ARRAY_SIZE(raidz_gen_name); i++)
- off += snprintf(buf + off, size - off, "%-16s",
+ off += kmem_scnprintf(buf + off, size - off, "%-16s",
raidz_gen_name[i]);
for (int i = 0; i < ARRAY_SIZE(raidz_rec_name); i++)
- off += snprintf(buf + off, size - off, "%-16s",
+ off += kmem_scnprintf(buf + off, size - off, "%-16s",
raidz_rec_name[i]);
- (void) snprintf(buf + off, size - off, "\n");
+ (void) kmem_scnprintf(buf + off, size - off, "\n");
return (0);
}
@@ -311,34 +311,35 @@ raidz_math_kstat_data(char *buf, size_t size, void *data)
ASSERT3U(size, >=, RAIDZ_KSTAT_LINE_LEN);
if (cstat == fstat) {
- off += snprintf(buf + off, size - off, "%-17s", "fastest");
+ off += kmem_scnprintf(buf + off, size - off, "%-17s",
+ "fastest");
for (i = 0; i < ARRAY_SIZE(raidz_gen_name); i++) {
int id = fstat->gen[i];
- off += snprintf(buf + off, size - off, "%-16s",
+ off += kmem_scnprintf(buf + off, size - off, "%-16s",
raidz_supp_impl[id]->name);
}
for (i = 0; i < ARRAY_SIZE(raidz_rec_name); i++) {
int id = fstat->rec[i];
- off += snprintf(buf + off, size - off, "%-16s",
+ off += kmem_scnprintf(buf + off, size - off, "%-16s",
raidz_supp_impl[id]->name);
}
} else {
ptrdiff_t id = cstat - raidz_impl_kstats;
- off += snprintf(buf + off, size - off, "%-17s",
+ off += kmem_scnprintf(buf + off, size - off, "%-17s",
raidz_supp_impl[id]->name);
for (i = 0; i < ARRAY_SIZE(raidz_gen_name); i++)
- off += snprintf(buf + off, size - off, "%-16llu",
+ off += kmem_scnprintf(buf + off, size - off, "%-16llu",
(u_longlong_t)cstat->gen[i]);
for (i = 0; i < ARRAY_SIZE(raidz_rec_name); i++)
- off += snprintf(buf + off, size - off, "%-16llu",
+ off += kmem_scnprintf(buf + off, size - off, "%-16llu",
(u_longlong_t)cstat->rec[i]);
}
- (void) snprintf(buf + off, size - off, "\n");
+ (void) kmem_scnprintf(buf + off, size - off, "\n");
return (0);
}
@@ -652,13 +653,15 @@ zfs_vdev_raidz_impl_get(char *buffer, zfs_kernel_param_t *kp)
/* list mandatory options */
for (i = 0; i < ARRAY_SIZE(math_impl_opts) - 2; i++) {
fmt = (impl == math_impl_opts[i].sel) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, math_impl_opts[i].name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ math_impl_opts[i].name);
}
/* list all supported implementations */
for (i = 0; i < raidz_supp_impl_cnt; i++) {
fmt = (i == impl) ? "[%s] " : "%s ";
- cnt += sprintf(buffer + cnt, fmt, raidz_supp_impl[i]->name);
+ cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt,
+ raidz_supp_impl[i]->name);
}
return (cnt);
diff --git a/module/zfs/vdev_raidz_math_aarch64_neon.c b/module/zfs/vdev_raidz_math_aarch64_neon.c
index 0a67ceb84920..4aa7bc2b9708 100644
--- a/module/zfs/vdev_raidz_math_aarch64_neon.c
+++ b/module/zfs/vdev_raidz_math_aarch64_neon.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_aarch64_neon_common.h b/module/zfs/vdev_raidz_math_aarch64_neon_common.h
index e46b2536546c..f0f6546f7f71 100644
--- a/module/zfs/vdev_raidz_math_aarch64_neon_common.h
+++ b/module/zfs/vdev_raidz_math_aarch64_neon_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_aarch64_neonx2.c b/module/zfs/vdev_raidz_math_aarch64_neonx2.c
index e072f51cd635..bd9de91a4ba8 100644
--- a/module/zfs/vdev_raidz_math_aarch64_neonx2.c
+++ b/module/zfs/vdev_raidz_math_aarch64_neonx2.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -210,9 +210,13 @@ DEFINE_GEN_METHODS(aarch64_neonx2);
* If compiled with -O0, gcc doesn't do any stack frame coalescing
* and -Wframe-larger-than=1024 is triggered in debug mode.
*/
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wframe-larger-than="
+#endif
DEFINE_REC_METHODS(aarch64_neonx2);
+#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
+#endif
static boolean_t
raidz_will_aarch64_neonx2_work(void)
diff --git a/module/zfs/vdev_raidz_math_avx2.c b/module/zfs/vdev_raidz_math_avx2.c
index 65e4bebce8fa..e5bbc7decbfa 100644
--- a/module/zfs/vdev_raidz_math_avx2.c
+++ b/module/zfs/vdev_raidz_math_avx2.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_avx512bw.c b/module/zfs/vdev_raidz_math_avx512bw.c
index f06b469023eb..3b709ed34fc4 100644
--- a/module/zfs/vdev_raidz_math_avx512bw.c
+++ b/module/zfs/vdev_raidz_math_avx512bw.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_avx512f.c b/module/zfs/vdev_raidz_math_avx512f.c
index aab653b77491..5ec71a04133a 100644
--- a/module/zfs/vdev_raidz_math_avx512f.c
+++ b/module/zfs/vdev_raidz_math_avx512f.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_impl.h b/module/zfs/vdev_raidz_math_impl.h
index 35e016fc65a5..5d77c5d046d5 100644
--- a/module/zfs/vdev_raidz_math_impl.h
+++ b/module/zfs/vdev_raidz_math_impl.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -214,9 +214,10 @@ raidz_copy_abd_cb(void *dc, void *sc, size_t size, void *private)
}
-#define raidz_copy(dabd, sabd, size) \
+#define raidz_copy(dabd, sabd, off, size) \
{ \
- abd_iterate_func2(dabd, sabd, 0, 0, size, raidz_copy_abd_cb, NULL);\
+ abd_iterate_func2(dabd, sabd, off, off, size, raidz_copy_abd_cb, \
+ NULL); \
}
/*
@@ -254,9 +255,10 @@ raidz_add_abd_cb(void *dc, void *sc, size_t size, void *private)
return (0);
}
-#define raidz_add(dabd, sabd, size) \
+#define raidz_add(dabd, sabd, off, size) \
{ \
- abd_iterate_func2(dabd, sabd, 0, 0, size, raidz_add_abd_cb, NULL);\
+ abd_iterate_func2(dabd, sabd, off, off, size, raidz_add_abd_cb, \
+ NULL); \
}
/*
@@ -343,7 +345,10 @@ raidz_mul_abd_cb(void *dc, size_t size, void *private)
* the parity/syndrome if data column is shorter.
*
* P parity is calculated using raidz_add_abd().
+ *
+ * For CPU L2 cache blocking we process 64KB at a time.
*/
+#define CHUNK 65536
/*
* Generate P parity (RAIDZ1)
@@ -357,20 +362,26 @@ raidz_generate_p_impl(raidz_row_t * const rr)
const size_t ncols = rr->rr_cols;
const size_t psize = rr->rr_col[CODE_P].rc_size;
abd_t *pabd = rr->rr_col[CODE_P].rc_abd;
- size_t size;
- abd_t *dabd;
+ size_t off, size;
raidz_math_begin();
- /* start with first data column */
- raidz_copy(pabd, rr->rr_col[1].rc_abd, psize);
+ for (off = 0; off < psize; off += CHUNK) {
+
+ /* start with first data column */
+ size = MIN(CHUNK, psize - off);
+ raidz_copy(pabd, rr->rr_col[1].rc_abd, off, size);
- for (c = 2; c < ncols; c++) {
- dabd = rr->rr_col[c].rc_abd;
- size = rr->rr_col[c].rc_size;
+ for (c = 2; c < ncols; c++) {
+ size = rr->rr_col[c].rc_size;
+ if (size <= off)
+ continue;
- /* add data column */
- raidz_add(pabd, dabd, size);
+ /* add data column */
+ size = MIN(CHUNK, size - off);
+ abd_t *dabd = rr->rr_col[c].rc_abd;
+ raidz_add(pabd, dabd, off, size);
+ }
}
raidz_math_end();
@@ -423,7 +434,7 @@ raidz_generate_pq_impl(raidz_row_t * const rr)
size_t c;
const size_t ncols = rr->rr_cols;
const size_t csize = rr->rr_col[CODE_P].rc_size;
- size_t dsize;
+ size_t off, size, dsize;
abd_t *dabd;
abd_t *cabds[] = {
rr->rr_col[CODE_P].rc_abd,
@@ -432,15 +443,20 @@ raidz_generate_pq_impl(raidz_row_t * const rr)
raidz_math_begin();
- raidz_copy(cabds[CODE_P], rr->rr_col[2].rc_abd, csize);
- raidz_copy(cabds[CODE_Q], rr->rr_col[2].rc_abd, csize);
+ for (off = 0; off < csize; off += CHUNK) {
- for (c = 3; c < ncols; c++) {
- dabd = rr->rr_col[c].rc_abd;
- dsize = rr->rr_col[c].rc_size;
+ size = MIN(CHUNK, csize - off);
+ raidz_copy(cabds[CODE_P], rr->rr_col[2].rc_abd, off, size);
+ raidz_copy(cabds[CODE_Q], rr->rr_col[2].rc_abd, off, size);
- abd_raidz_gen_iterate(cabds, dabd, csize, dsize, 2,
- raidz_gen_pq_add);
+ for (c = 3; c < ncols; c++) {
+ dabd = rr->rr_col[c].rc_abd;
+ dsize = rr->rr_col[c].rc_size;
+ dsize = (dsize > off) ? MIN(CHUNK, dsize - off) : 0;
+
+ abd_raidz_gen_iterate(cabds, dabd, off, size, dsize, 2,
+ raidz_gen_pq_add);
+ }
}
raidz_math_end();
@@ -460,8 +476,8 @@ static void
raidz_gen_pqr_add(void **c, const void *dc, const size_t csize,
const size_t dsize)
{
- v_t *p = (v_t *)c[0];
- v_t *q = (v_t *)c[1];
+ v_t *p = (v_t *)c[CODE_P];
+ v_t *q = (v_t *)c[CODE_Q];
v_t *r = (v_t *)c[CODE_R];
const v_t *d = (const v_t *)dc;
const v_t * const dend = d + (dsize / sizeof (v_t));
@@ -486,7 +502,7 @@ raidz_gen_pqr_add(void **c, const void *dc, const size_t csize,
/*
- * Generate PQR parity (RAIDZ2)
+ * Generate PQR parity (RAIDZ3)
*
* @rr RAIDZ row
*/
@@ -496,7 +512,7 @@ raidz_generate_pqr_impl(raidz_row_t * const rr)
size_t c;
const size_t ncols = rr->rr_cols;
const size_t csize = rr->rr_col[CODE_P].rc_size;
- size_t dsize;
+ size_t off, size, dsize;
abd_t *dabd;
abd_t *cabds[] = {
rr->rr_col[CODE_P].rc_abd,
@@ -506,16 +522,21 @@ raidz_generate_pqr_impl(raidz_row_t * const rr)
raidz_math_begin();
- raidz_copy(cabds[CODE_P], rr->rr_col[3].rc_abd, csize);
- raidz_copy(cabds[CODE_Q], rr->rr_col[3].rc_abd, csize);
- raidz_copy(cabds[CODE_R], rr->rr_col[3].rc_abd, csize);
+ for (off = 0; off < csize; off += CHUNK) {
- for (c = 4; c < ncols; c++) {
- dabd = rr->rr_col[c].rc_abd;
- dsize = rr->rr_col[c].rc_size;
+ size = MIN(CHUNK, csize - off);
+ raidz_copy(cabds[CODE_P], rr->rr_col[3].rc_abd, off, size);
+ raidz_copy(cabds[CODE_Q], rr->rr_col[3].rc_abd, off, size);
+ raidz_copy(cabds[CODE_R], rr->rr_col[3].rc_abd, off, size);
- abd_raidz_gen_iterate(cabds, dabd, csize, dsize, 3,
- raidz_gen_pqr_add);
+ for (c = 4; c < ncols; c++) {
+ dabd = rr->rr_col[c].rc_abd;
+ dsize = rr->rr_col[c].rc_size;
+ dsize = (dsize > off) ? MIN(CHUNK, dsize - off) : 0;
+
+ abd_raidz_gen_iterate(cabds, dabd, off, size, dsize, 3,
+ raidz_gen_pqr_add);
+ }
}
raidz_math_end();
@@ -592,26 +613,31 @@ raidz_reconstruct_p_impl(raidz_row_t *rr, const int *tgtidx)
const size_t x = tgtidx[TARGET_X];
const size_t xsize = rr->rr_col[x].rc_size;
abd_t *xabd = rr->rr_col[x].rc_abd;
- size_t size;
- abd_t *dabd;
+ size_t off, size;
if (xabd == NULL)
return (1 << CODE_P);
raidz_math_begin();
- /* copy P into target */
- raidz_copy(xabd, rr->rr_col[CODE_P].rc_abd, xsize);
+ for (off = 0; off < xsize; off += CHUNK) {
- /* generate p_syndrome */
- for (c = firstdc; c < ncols; c++) {
- if (c == x)
- continue;
+ /* copy P into target */
+ size = MIN(CHUNK, xsize - off);
+ raidz_copy(xabd, rr->rr_col[CODE_P].rc_abd, off, size);
- dabd = rr->rr_col[c].rc_abd;
- size = MIN(rr->rr_col[c].rc_size, xsize);
+ /* generate p_syndrome */
+ for (c = firstdc; c < ncols; c++) {
+ if (c == x)
+ continue;
+ size = rr->rr_col[c].rc_size;
+ if (size <= off)
+ continue;
- raidz_add(xabd, dabd, size);
+ size = MIN(CHUNK, MIN(size, xsize) - off);
+ abd_t *dabd = rr->rr_col[c].rc_abd;
+ raidz_add(xabd, dabd, off, size);
+ }
}
raidz_math_end();
@@ -683,7 +709,7 @@ raidz_reconstruct_q_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
}
@@ -698,12 +724,12 @@ raidz_reconstruct_q_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 1,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 1,
raidz_syn_q_abd);
}
/* add Q to the syndrome */
- raidz_add(xabd, rr->rr_col[CODE_Q].rc_abd, xsize);
+ raidz_add(xabd, rr->rr_col[CODE_Q].rc_abd, 0, xsize);
/* transform the syndrome */
abd_iterate_func(xabd, 0, xsize, raidz_mul_abd_cb, (void*) coeff);
@@ -777,7 +803,7 @@ raidz_reconstruct_r_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
}
@@ -793,12 +819,12 @@ raidz_reconstruct_r_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 1,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 1,
raidz_syn_r_abd);
}
/* add R to the syndrome */
- raidz_add(xabd, rr->rr_col[CODE_R].rc_abd, xsize);
+ raidz_add(xabd, rr->rr_col[CODE_R].rc_abd, 0, xsize);
/* transform the syndrome */
abd_iterate_func(xabd, 0, xsize, raidz_mul_abd_cb, (void *)coeff);
@@ -934,8 +960,8 @@ raidz_reconstruct_pq_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
- raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
+ raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
raidz_zero(yabd, xsize);
@@ -951,7 +977,7 @@ raidz_reconstruct_pq_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 2,
raidz_syn_pq_abd);
}
@@ -959,7 +985,7 @@ raidz_reconstruct_pq_impl(raidz_row_t *rr, const int *tgtidx)
/* Copy shorter targets back to the original abd buffer */
if (ysize < xsize)
- raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
+ raidz_copy(rr->rr_col[y].rc_abd, yabd, 0, ysize);
raidz_math_end();
@@ -1094,8 +1120,8 @@ raidz_reconstruct_pr_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
- raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
+ raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
raidz_zero(yabd, xsize);
@@ -1111,7 +1137,7 @@ raidz_reconstruct_pr_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 2,
raidz_syn_pr_abd);
}
@@ -1121,7 +1147,7 @@ raidz_reconstruct_pr_impl(raidz_row_t *rr, const int *tgtidx)
* Copy shorter targets back to the original abd buffer
*/
if (ysize < xsize)
- raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
+ raidz_copy(rr->rr_col[y].rc_abd, yabd, 0, ysize);
raidz_math_end();
@@ -1261,8 +1287,8 @@ raidz_reconstruct_qr_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
- raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
+ raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
raidz_zero(yabd, xsize);
@@ -1278,7 +1304,7 @@ raidz_reconstruct_qr_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 2,
raidz_syn_qr_abd);
}
@@ -1288,7 +1314,7 @@ raidz_reconstruct_qr_impl(raidz_row_t *rr, const int *tgtidx)
* Copy shorter targets back to the original abd buffer
*/
if (ysize < xsize)
- raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
+ raidz_copy(rr->rr_col[y].rc_abd, yabd, 0, ysize);
raidz_math_end();
@@ -1456,9 +1482,9 @@ raidz_reconstruct_pqr_impl(raidz_row_t *rr, const int *tgtidx)
/* Start with first data column if present */
if (firstdc != x) {
- raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
- raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
- raidz_copy(zabd, rr->rr_col[firstdc].rc_abd, xsize);
+ raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
+ raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
+ raidz_copy(zabd, rr->rr_col[firstdc].rc_abd, 0, xsize);
} else {
raidz_zero(xabd, xsize);
raidz_zero(yabd, xsize);
@@ -1475,7 +1501,7 @@ raidz_reconstruct_pqr_impl(raidz_row_t *rr, const int *tgtidx)
dsize = rr->rr_col[c].rc_size;
}
- abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 3,
+ abd_raidz_gen_iterate(tabds, dabd, 0, xsize, dsize, 3,
raidz_syn_pqr_abd);
}
@@ -1485,9 +1511,9 @@ raidz_reconstruct_pqr_impl(raidz_row_t *rr, const int *tgtidx)
* Copy shorter targets back to the original abd buffer
*/
if (ysize < xsize)
- raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
+ raidz_copy(rr->rr_col[y].rc_abd, yabd, 0, ysize);
if (zsize < xsize)
- raidz_copy(rr->rr_col[z].rc_abd, zabd, zsize);
+ raidz_copy(rr->rr_col[z].rc_abd, zabd, 0, zsize);
raidz_math_end();
diff --git a/module/zfs/vdev_raidz_math_powerpc_altivec.c b/module/zfs/vdev_raidz_math_powerpc_altivec.c
index 1db2c4cd3a47..ff493b8b7bc0 100644
--- a/module/zfs/vdev_raidz_math_powerpc_altivec.c
+++ b/module/zfs/vdev_raidz_math_powerpc_altivec.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_powerpc_altivec_common.h b/module/zfs/vdev_raidz_math_powerpc_altivec_common.h
index 3842f5fd637c..f76eb47a9c66 100644
--- a/module/zfs/vdev_raidz_math_powerpc_altivec_common.h
+++ b/module/zfs/vdev_raidz_math_powerpc_altivec_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -26,10 +26,6 @@
#include <sys/types.h>
#include <sys/simd.h>
-#ifdef __linux__
-#define __asm __asm__ __volatile__
-#endif
-
#define _REG_CNT(_0, _1, _2, _3, _4, _5, _6, _7, N, ...) N
#define REG_CNT(r...) _REG_CNT(r, 8, 7, 6, 5, 4, 3, 2, 1)
@@ -142,7 +138,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"lvx 21,0,%[SRC0]\n" \
"lvx 20,0,%[SRC1]\n" \
"lvx 19,0,%[SRC2]\n" \
@@ -172,7 +168,7 @@ typedef struct v {
: "v18", "v19", "v20", "v21"); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"lvx 21,0,%[SRC0]\n" \
"lvx 20,0,%[SRC1]\n" \
"lvx 19,0,%[SRC2]\n" \
@@ -189,7 +185,7 @@ typedef struct v {
: "v18", "v19", "v20", "v21"); \
break; \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
"lvx 21,0,%[SRC0]\n" \
"lvx 20,0,%[SRC1]\n" \
"vxor " VR0(r) "," VR0(r) ",21\n" \
@@ -208,7 +204,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"vxor " VR4(r) "," VR4(r) "," VR0(r) "\n" \
"vxor " VR5(r) "," VR5(r) "," VR1(r) "\n" \
"vxor " VR6(r) "," VR6(r) "," VR2(r) "\n" \
@@ -217,7 +213,7 @@ typedef struct v {
: RVR0(r), RVR1(r), RVR2(r), RVR3(r)); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"vxor " VR2(r) "," VR2(r) "," VR0(r) "\n" \
"vxor " VR3(r) "," VR3(r) "," VR1(r) "\n" \
: UVR2(r), UVR3(r) \
@@ -232,7 +228,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"vxor " VR0(r) "," VR0(r) "," VR0(r) "\n" \
"vxor " VR1(r) "," VR1(r) "," VR1(r) "\n" \
"vxor " VR2(r) "," VR2(r) "," VR2(r) "\n" \
@@ -245,7 +241,7 @@ typedef struct v {
WVR4(r), WVR5(r), WVR6(r), WVR7(r)); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"vxor " VR0(r) "," VR0(r) "," VR0(r) "\n" \
"vxor " VR1(r) "," VR1(r) "," VR1(r) "\n" \
"vxor " VR2(r) "," VR2(r) "," VR2(r) "\n" \
@@ -253,7 +249,7 @@ typedef struct v {
: WVR0(r), WVR1(r), WVR2(r), WVR3(r)); \
break; \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
"vxor " VR0(r) "," VR0(r) "," VR0(r) "\n" \
"vxor " VR1(r) "," VR1(r) "," VR1(r) "\n" \
: WVR0(r), WVR1(r)); \
@@ -267,7 +263,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"vor " VR4(r) "," VR0(r) "," VR0(r) "\n" \
"vor " VR5(r) "," VR1(r) "," VR1(r) "\n" \
"vor " VR6(r) "," VR2(r) "," VR2(r) "\n" \
@@ -276,7 +272,7 @@ typedef struct v {
: RVR0(r), RVR1(r), RVR2(r), RVR3(r)); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"vor " VR2(r) "," VR0(r) "," VR0(r) "\n" \
"vor " VR3(r) "," VR1(r) "," VR1(r) "\n" \
: WVR2(r), WVR3(r) \
@@ -291,7 +287,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"lvx " VR0(r) " ,0,%[SRC0]\n" \
"lvx " VR1(r) " ,0,%[SRC1]\n" \
"lvx " VR2(r) " ,0,%[SRC2]\n" \
@@ -312,7 +308,7 @@ typedef struct v {
[SRC7] "r" ((OFFSET(src, 112)))); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"lvx " VR0(r) " ,0,%[SRC0]\n" \
"lvx " VR1(r) " ,0,%[SRC1]\n" \
"lvx " VR2(r) " ,0,%[SRC2]\n" \
@@ -324,7 +320,7 @@ typedef struct v {
[SRC3] "r" ((OFFSET(src, 48)))); \
break; \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
"lvx " VR0(r) " ,0,%[SRC0]\n" \
"lvx " VR1(r) " ,0,%[SRC1]\n" \
: WVR0(r), WVR1(r) \
@@ -340,7 +336,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 8: \
- __asm( \
+ __asm__ __volatile__( \
"stvx " VR0(r) " ,0,%[DST0]\n" \
"stvx " VR1(r) " ,0,%[DST1]\n" \
"stvx " VR2(r) " ,0,%[DST2]\n" \
@@ -362,7 +358,7 @@ typedef struct v {
: "memory"); \
break; \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"stvx " VR0(r) " ,0,%[DST0]\n" \
"stvx " VR1(r) " ,0,%[DST1]\n" \
"stvx " VR2(r) " ,0,%[DST2]\n" \
@@ -375,7 +371,7 @@ typedef struct v {
: "memory"); \
break; \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
"stvx " VR0(r) " ,0,%[DST0]\n" \
"stvx " VR1(r) " ,0,%[DST1]\n" \
: : [DST0] "r" ((OFFSET(dst, 0))), \
@@ -400,7 +396,7 @@ typedef struct v {
#define MUL2_SETUP() \
{ \
- __asm( \
+ __asm__ __volatile__( \
"vspltisb " VR(16) ",14\n" \
"vspltisb " VR(17) ",15\n" \
"vaddubm " VR(16) "," VR(17) "," VR(16) "\n" \
@@ -412,7 +408,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 4: \
- __asm( \
+ __asm__ __volatile__( \
"vcmpgtsb 19," VR(17) "," VR0(r) "\n" \
"vcmpgtsb 18," VR(17) "," VR1(r) "\n" \
"vcmpgtsb 21," VR(17) "," VR2(r) "\n" \
@@ -434,7 +430,7 @@ typedef struct v {
: "v18", "v19", "v20", "v21"); \
break; \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
"vcmpgtsb 19," VR(17) "," VR0(r) "\n" \
"vcmpgtsb 18," VR(17) "," VR1(r) "\n" \
"vand 19,19," VR(16) "\n" \
@@ -478,7 +474,7 @@ typedef struct v {
{ \
switch (REG_CNT(r)) { \
case 2: \
- __asm( \
+ __asm__ __volatile__( \
/* lts for upper part */ \
"vspltisb 15,15\n" \
"lvx 10,0,%[lt0]\n" \
diff --git a/module/zfs/vdev_raidz_math_scalar.c b/module/zfs/vdev_raidz_math_scalar.c
index 35fafe230ca1..b51352b4e90b 100644
--- a/module/zfs/vdev_raidz_math_scalar.c
+++ b/module/zfs/vdev_raidz_math_scalar.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_sse2.c b/module/zfs/vdev_raidz_math_sse2.c
index 56a0b123d952..02b5d6a609ab 100644
--- a/module/zfs/vdev_raidz_math_sse2.c
+++ b/module/zfs/vdev_raidz_math_sse2.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_raidz_math_ssse3.c b/module/zfs/vdev_raidz_math_ssse3.c
index 5ddc079a4f5d..244f137b3d09 100644
--- a/module/zfs/vdev_raidz_math_ssse3.c
+++ b/module/zfs/vdev_raidz_math_ssse3.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_rebuild.c b/module/zfs/vdev_rebuild.c
index aa7ed24deaeb..00ebd4c9fca4 100644
--- a/module/zfs/vdev_rebuild.c
+++ b/module/zfs/vdev_rebuild.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,8 @@
*
* Copyright (c) 2018, Intel Corporation.
* Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+ * Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
+ * Copyright (c) 2024 by Delphix. All rights reserved.
*/
#include <sys/vdev_impl.h>
@@ -33,6 +35,7 @@
#include <sys/zio.h>
#include <sys/dmu_tx.h>
#include <sys/arc.h>
+#include <sys/arc_impl.h>
#include <sys/zap.h>
/*
@@ -103,7 +106,7 @@
* Size of rebuild reads; defaults to 1MiB per data disk and is capped at
* SPA_MAXBLOCKSIZE.
*/
-static unsigned long zfs_rebuild_max_segment = 1024 * 1024;
+static uint64_t zfs_rebuild_max_segment = 1024 * 1024;
/*
* Maximum number of parallelly executed bytes per leaf vdev caused by a
@@ -115,13 +118,12 @@ static unsigned long zfs_rebuild_max_segment = 1024 * 1024;
* segment size is also large (zfs_rebuild_max_segment=1M). This helps keep
* the queue depth short.
*
- * 32MB was selected as the default value to achieve good performance with
- * a large 90-drive dRAID HDD configuration (draid2:8d:90c:2s). A sequential
- * rebuild was unable to saturate all of the drives using smaller values.
- * With a value of 32MB the sequential resilver write rate was measured at
- * 800MB/s sustained while rebuilding to a distributed spare.
+ * 64MB was observed to deliver the best performance and set as the default.
+ * Testing was performed with a 106-drive dRAID HDD pool (draid2:11d:106c)
+ * and a rebuild rate of 1.2GB/s was measured to the distribute spare.
+ * Smaller values were unable to fully saturate the available pool I/O.
*/
-static unsigned long zfs_rebuild_vdev_limit = 32 << 20;
+static uint64_t zfs_rebuild_vdev_limit = 64 << 20;
/*
* Automatically start a pool scrub when the last active sequential resilver
@@ -134,6 +136,7 @@ static int zfs_rebuild_scrub_enabled = 1;
* For vdev_rebuild_initiate_sync() and vdev_rebuild_reset_sync().
*/
static __attribute__((noreturn)) 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 +310,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();
@@ -558,8 +572,10 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size)
vdev_rebuild_blkptr_init(&blk, vd, start, size);
uint64_t psize = BP_GET_PSIZE(&blk);
- if (!vdev_dtl_need_resilver(vd, &blk.blk_dva[0], psize, TXG_UNKNOWN))
+ if (!vdev_dtl_need_resilver(vd, &blk.blk_dva[0], psize, TXG_UNKNOWN)) {
+ vr->vr_pass_bytes_skipped += size;
return (0);
+ }
mutex_enter(&vr->vr_io_lock);
@@ -741,6 +757,7 @@ vdev_rebuild_thread(void *arg)
{
vdev_t *vd = arg;
spa_t *spa = vd->vdev_spa;
+ vdev_t *rvd = spa->spa_root_vdev;
int error = 0;
/*
@@ -760,7 +777,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;
@@ -773,9 +789,7 @@ vdev_rebuild_thread(void *arg)
vr->vr_pass_start_time = gethrtime();
vr->vr_pass_bytes_scanned = 0;
vr->vr_pass_bytes_issued = 0;
-
- vr->vr_bytes_inflight_max = MAX(1ULL << 20,
- zfs_rebuild_vdev_limit * vd->vdev_children);
+ vr->vr_pass_bytes_skipped = 0;
uint64_t update_est_time = gethrtime();
vdev_rebuild_update_bytes_est(vd, 0);
@@ -793,6 +807,17 @@ vdev_rebuild_thread(void *arg)
vr->vr_scan_msp = msp;
/*
+ * Calculate the max number of in-flight bytes for top-level
+ * vdev scanning operations (minimum 1MB, maximum 1/2 of
+ * arc_c_max shared by all top-level vdevs). Limits for the
+ * issuing phase are done per top-level vdev and are handled
+ * separately.
+ */
+ uint64_t limit = (arc_c_max / 2) / MAX(rvd->vdev_children, 1);
+ vr->vr_bytes_inflight_max = MIN(limit, MAX(1ULL << 20,
+ zfs_rebuild_vdev_limit * vd->vdev_children));
+
+ /*
* Removal of vdevs from the vdev tree may eliminate the need
* for the rebuild, in which case it should be canceled. The
* vdev_rebuild_cancel_wanted flag is set until the sync task
@@ -1047,7 +1072,8 @@ vdev_rebuild_restart_impl(vdev_t *vd)
void
vdev_rebuild_restart(spa_t *spa)
{
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
+ spa->spa_load_thread == curthread);
vdev_rebuild_restart_impl(spa->spa_root_vdev);
}
@@ -1132,16 +1158,17 @@ vdev_rebuild_get_stats(vdev_t *tvd, vdev_rebuild_stat_t *vrs)
vr->vr_pass_start_time);
vrs->vrs_pass_bytes_scanned = vr->vr_pass_bytes_scanned;
vrs->vrs_pass_bytes_issued = vr->vr_pass_bytes_issued;
+ vrs->vrs_pass_bytes_skipped = vr->vr_pass_bytes_skipped;
mutex_exit(&tvd->vdev_rebuild_lock);
}
return (error);
}
-ZFS_MODULE_PARAM(zfs, zfs_, rebuild_max_segment, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, rebuild_max_segment, U64, ZMOD_RW,
"Max segment size in bytes of rebuild reads");
-ZFS_MODULE_PARAM(zfs, zfs_, rebuild_vdev_limit, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, rebuild_vdev_limit, U64, ZMOD_RW,
"Max bytes in flight per leaf vdev for sequential resilvers");
ZFS_MODULE_PARAM(zfs, zfs_, rebuild_scrub_enabled, INT, ZMOD_RW,
diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c
index 7fbe38b42a36..1249657f9d72 100644
--- a/module/zfs/vdev_removal.c
+++ b/module/zfs/vdev_removal.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -94,7 +94,7 @@ typedef struct vdev_copy_arg {
* doing a device removal. This determines how much i/o we can have
* in flight concurrently.
*/
-static const int zfs_remove_max_copy_bytes = 64 * 1024 * 1024;
+static const uint_t zfs_remove_max_copy_bytes = 64 * 1024 * 1024;
/*
* The largest contiguous segment that we will attempt to allocate when
@@ -104,7 +104,7 @@ static const int zfs_remove_max_copy_bytes = 64 * 1024 * 1024;
*
* See also the accessor function spa_remove_max_segment().
*/
-int zfs_remove_max_segment = SPA_MAXBLOCKSIZE;
+uint_t zfs_remove_max_segment = SPA_MAXBLOCKSIZE;
/*
* Ignore hard IO errors during device removal. When set if a device
@@ -130,7 +130,7 @@ static int zfs_removal_ignore_errors = 0;
* - we'll do larger allocations, which may fail and fall back on smaller
* allocations
*/
-int vdev_removal_max_span = 32 * 1024;
+uint_t vdev_removal_max_span = 32 * 1024;
/*
* This is used by the test suite so that it can ensure that certain
@@ -1168,11 +1168,11 @@ spa_vdev_copy_segment(vdev_t *vd, range_tree_t *segs,
metaslab_class_t *mc = mg->mg_class;
if (mc->mc_groups == 0)
mc = spa_normal_class(spa);
- int error = metaslab_alloc_dva(spa, mc, size, &dst, 0, NULL, txg, 0,
- zal, 0);
+ int error = metaslab_alloc_dva(spa, mc, size, &dst, 0, NULL, txg,
+ METASLAB_DONT_THROTTLE, zal, 0);
if (error == ENOSPC && mc != spa_normal_class(spa)) {
error = metaslab_alloc_dva(spa, spa_normal_class(spa), size,
- &dst, 0, NULL, txg, 0, zal, 0);
+ &dst, 0, NULL, txg, METASLAB_DONT_THROTTLE, zal, 0);
}
if (error != 0)
return (error);
@@ -2414,7 +2414,7 @@ spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
* in this pool.
*/
if (vd == NULL || unspare) {
- char *type;
+ const char *type;
boolean_t draid_spare = B_FALSE;
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type)
@@ -2545,14 +2545,14 @@ spa_removal_get_stats(spa_t *spa, pool_removal_stat_t *prs)
ZFS_MODULE_PARAM(zfs_vdev, zfs_, removal_ignore_errors, INT, ZMOD_RW,
"Ignore hard IO errors when removing device");
-ZFS_MODULE_PARAM(zfs_vdev, zfs_, remove_max_segment, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_, remove_max_segment, UINT, ZMOD_RW,
"Largest contiguous segment to allocate when removing device");
-ZFS_MODULE_PARAM(zfs_vdev, vdev_, removal_max_span, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, vdev_, removal_max_span, UINT, ZMOD_RW,
"Largest span of free chunks a remap segment can span");
/* BEGIN CSTYLED */
-ZFS_MODULE_PARAM(zfs_vdev, zfs_, removal_suspend_progress, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vdev, zfs_, removal_suspend_progress, UINT, ZMOD_RW,
"Pause device removal after this many bytes are copied "
"(debug use only - causes removal to hang)");
/* END CSTYLED */
diff --git a/module/zfs/vdev_root.c b/module/zfs/vdev_root.c
index 45ddc2f71927..e132643dc330 100644
--- a/module/zfs/vdev_root.c
+++ b/module/zfs/vdev_root.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/vdev_trim.c b/module/zfs/vdev_trim.c
index ed98df782918..9753d5a1ea04 100644
--- a/module/zfs/vdev_trim.c
+++ b/module/zfs/vdev_trim.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,9 +20,10 @@
*/
/*
- * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2016, 2024 by Delphix. All rights reserved.
* Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
* Copyright (c) 2021 Hewlett Packard Enterprise Development LP
+ * Copyright 2023 RackTop Systems, Inc.
*/
#include <sys/spa.h>
@@ -168,7 +169,8 @@ static boolean_t
vdev_trim_should_stop(vdev_t *vd)
{
return (vd->vdev_trim_exit_wanted || !vdev_writeable(vd) ||
- vd->vdev_detached || vd->vdev_top->vdev_removing);
+ vd->vdev_detached || vd->vdev_top->vdev_removing ||
+ vd->vdev_top->vdev_rz_expanding);
}
/*
@@ -179,10 +181,31 @@ vdev_autotrim_should_stop(vdev_t *tvd)
{
return (tvd->vdev_autotrim_exit_wanted ||
!vdev_writeable(tvd) || tvd->vdev_removing ||
+ tvd->vdev_rz_expanding ||
spa_get_autotrim(tvd->vdev_spa) == SPA_AUTOTRIM_OFF);
}
/*
+ * Wait for given number of kicks, return true if the wait is aborted due to
+ * vdev_autotrim_exit_wanted.
+ */
+static boolean_t
+vdev_autotrim_wait_kick(vdev_t *vd, int num_of_kick)
+{
+ mutex_enter(&vd->vdev_autotrim_lock);
+ for (int i = 0; i < num_of_kick; i++) {
+ if (vd->vdev_autotrim_exit_wanted)
+ break;
+ cv_wait_idle(&vd->vdev_autotrim_kick_cv,
+ &vd->vdev_autotrim_lock);
+ }
+ boolean_t exit_wanted = vd->vdev_autotrim_exit_wanted;
+ mutex_exit(&vd->vdev_autotrim_lock);
+
+ return (exit_wanted);
+}
+
+/*
* The sync task for updating the on-disk state of a manual TRIM. This
* is scheduled by vdev_trim_change_state().
*/
@@ -202,7 +225,8 @@ vdev_trim_zap_update_sync(void *arg, dmu_tx_t *tx)
kmem_free(arg, sizeof (uint64_t));
vdev_t *vd = spa_lookup_by_guid(tx->tx_pool->dp_spa, guid, B_FALSE);
- if (vd == NULL || vd->vdev_top->vdev_removing || !vdev_is_concrete(vd))
+ if (vd == NULL || vd->vdev_top->vdev_removing ||
+ !vdev_is_concrete(vd) || vd->vdev_top->vdev_rz_expanding)
return;
uint64_t last_offset = vd->vdev_trim_offset[txg & TXG_MASK];
@@ -572,6 +596,7 @@ vdev_trim_ranges(trim_args_t *ta)
uint64_t extent_bytes_max = ta->trim_extent_bytes_max;
uint64_t extent_bytes_min = ta->trim_extent_bytes_min;
spa_t *spa = vd->vdev_spa;
+ int error = 0;
ta->trim_start_time = gethrtime();
ta->trim_bytes_done = 0;
@@ -591,19 +616,32 @@ vdev_trim_ranges(trim_args_t *ta)
uint64_t writes_required = ((size - 1) / extent_bytes_max) + 1;
for (uint64_t w = 0; w < writes_required; w++) {
- int error;
-
error = vdev_trim_range(ta, VDEV_LABEL_START_SIZE +
rs_get_start(rs, ta->trim_tree) +
(w *extent_bytes_max), MIN(size -
(w * extent_bytes_max), extent_bytes_max));
if (error != 0) {
- return (error);
+ goto done;
}
}
}
- return (0);
+done:
+ /*
+ * Make sure all TRIMs for this metaslab have completed before
+ * returning. TRIM zios have lower priority over regular or syncing
+ * zios, so all TRIM zios for this metaslab must complete before the
+ * metaslab is re-enabled. Otherwise it's possible write zios to
+ * this metaslab could cut ahead of still queued TRIM zios for this
+ * metaslab causing corruption if the ranges overlap.
+ */
+ mutex_enter(&vd->vdev_trim_io_lock);
+ while (vd->vdev_trim_inflight[0] > 0) {
+ cv_wait(&vd->vdev_trim_io_cv, &vd->vdev_trim_io_lock);
+ }
+ mutex_exit(&vd->vdev_trim_io_lock);
+
+ return (error);
}
static void
@@ -922,11 +960,6 @@ vdev_trim_thread(void *arg)
}
spa_config_exit(spa, SCL_CONFIG, FTAG);
- mutex_enter(&vd->vdev_trim_io_lock);
- while (vd->vdev_trim_inflight[0] > 0) {
- cv_wait(&vd->vdev_trim_io_cv, &vd->vdev_trim_io_lock);
- }
- mutex_exit(&vd->vdev_trim_io_lock);
range_tree_destroy(ta.trim_tree);
@@ -976,6 +1009,7 @@ vdev_trim(vdev_t *vd, uint64_t rate, boolean_t partial, boolean_t secure)
ASSERT(!vd->vdev_detached);
ASSERT(!vd->vdev_trim_exit_wanted);
ASSERT(!vd->vdev_top->vdev_removing);
+ ASSERT(!vd->vdev_rz_expanding);
vdev_trim_change_state(vd, VDEV_TRIM_ACTIVE, rate, partial, secure);
vd->vdev_trim_thread = thread_create(NULL, 0,
@@ -1114,7 +1148,8 @@ vdev_trim_stop_all(vdev_t *vd, vdev_trim_state_t tgt_state)
void
vdev_trim_restart(vdev_t *vd)
{
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
+ vd->vdev_spa->spa_load_thread == curthread);
ASSERT(!spa_config_held(vd->vdev_spa, SCL_ALL, RW_WRITER));
if (vd->vdev_leaf_zap != 0) {
@@ -1133,12 +1168,13 @@ vdev_trim_restart(vdev_t *vd)
ASSERT(err == 0 || err == ENOENT);
vd->vdev_trim_action_time = timestamp;
- if (vd->vdev_trim_state == VDEV_TRIM_SUSPENDED ||
- vd->vdev_offline) {
+ if ((vd->vdev_trim_state == VDEV_TRIM_SUSPENDED ||
+ vd->vdev_offline) && !vd->vdev_top->vdev_rz_expanding) {
/* load progress for reporting, but don't resume */
VERIFY0(vdev_trim_load(vd));
} else if (vd->vdev_trim_state == VDEV_TRIM_ACTIVE &&
vdev_writeable(vd) && !vd->vdev_top->vdev_removing &&
+ !vd->vdev_top->vdev_rz_expanding &&
vd->vdev_trim_thread == NULL) {
VERIFY0(vdev_trim_load(vd));
vdev_trim(vd, vd->vdev_trim_rate,
@@ -1188,12 +1224,10 @@ 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
@@ -1225,6 +1259,8 @@ vdev_autotrim_thread(void *arg)
i += txgs_per_trim) {
metaslab_t *msp = vd->vdev_ms[i];
range_tree_t *trim_tree;
+ boolean_t issued_trim = B_FALSE;
+ boolean_t wait_aborted = B_FALSE;
spa_config_exit(spa, SCL_CONFIG, FTAG);
metaslab_disable(msp);
@@ -1375,7 +1411,18 @@ vdev_autotrim_thread(void *arg)
range_tree_vacate(trim_tree, NULL, NULL);
range_tree_destroy(trim_tree);
- metaslab_enable(msp, issued_trim, B_FALSE);
+ /*
+ * Wait for couples of kicks, to ensure the trim io is
+ * synced. If the wait is aborted due to
+ * vdev_autotrim_exit_wanted, we need to signal
+ * metaslab_enable() to wait for sync.
+ */
+ if (issued_trim) {
+ wait_aborted = vdev_autotrim_wait_kick(vd,
+ TXG_CONCURRENT_STATES + TXG_DEFER_SIZE);
+ }
+
+ metaslab_enable(msp, wait_aborted, B_FALSE);
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
for (uint64_t c = 0; c < children; c++) {
@@ -1389,17 +1436,14 @@ vdev_autotrim_thread(void *arg)
}
kmem_free(tap, sizeof (trim_args_t) * children);
+
+ if (vdev_autotrim_should_stop(vd))
+ break;
}
spa_config_exit(spa, SCL_CONFIG, FTAG);
- /*
- * After completing the group of metaslabs wait for the next
- * open txg. This is done to make sure that a minimum of
- * zfs_trim_txg_batch txgs will occur before these metaslabs
- * are trimmed again.
- */
- txg_wait_open(spa_get_dsl(spa), 0, issued_trim);
+ vdev_autotrim_wait_kick(vd, 1);
shift++;
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
@@ -1455,7 +1499,8 @@ vdev_autotrim(spa_t *spa)
mutex_enter(&tvd->vdev_autotrim_lock);
if (vdev_writeable(tvd) && !tvd->vdev_removing &&
- tvd->vdev_autotrim_thread == NULL) {
+ tvd->vdev_autotrim_thread == NULL &&
+ !tvd->vdev_rz_expanding) {
ASSERT3P(tvd->vdev_top, ==, tvd);
tvd->vdev_autotrim_thread = thread_create(NULL, 0,
@@ -1477,11 +1522,9 @@ vdev_autotrim_stop_wait(vdev_t *tvd)
mutex_enter(&tvd->vdev_autotrim_lock);
if (tvd->vdev_autotrim_thread != NULL) {
tvd->vdev_autotrim_exit_wanted = B_TRUE;
-
- while (tvd->vdev_autotrim_thread != NULL) {
- cv_wait(&tvd->vdev_autotrim_cv,
- &tvd->vdev_autotrim_lock);
- }
+ cv_broadcast(&tvd->vdev_autotrim_kick_cv);
+ cv_wait(&tvd->vdev_autotrim_cv,
+ &tvd->vdev_autotrim_lock);
ASSERT3P(tvd->vdev_autotrim_thread, ==, NULL);
tvd->vdev_autotrim_exit_wanted = B_FALSE;
@@ -1489,6 +1532,24 @@ vdev_autotrim_stop_wait(vdev_t *tvd)
mutex_exit(&tvd->vdev_autotrim_lock);
}
+void
+vdev_autotrim_kick(spa_t *spa)
+{
+ ASSERT(spa_config_held(spa, SCL_CONFIG, RW_READER));
+
+ vdev_t *root_vd = spa->spa_root_vdev;
+ vdev_t *tvd;
+
+ for (uint64_t i = 0; i < root_vd->vdev_children; i++) {
+ tvd = root_vd->vdev_child[i];
+
+ mutex_enter(&tvd->vdev_autotrim_lock);
+ if (tvd->vdev_autotrim_thread != NULL)
+ cv_broadcast(&tvd->vdev_autotrim_kick_cv);
+ mutex_exit(&tvd->vdev_autotrim_lock);
+ }
+}
+
/*
* Wait for all of the vdev_autotrim_thread associated with the pool to
* be terminated (canceled or stopped).
@@ -1508,8 +1569,8 @@ vdev_autotrim_stop_all(spa_t *spa)
void
vdev_autotrim_restart(spa_t *spa)
{
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
-
+ ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
+ spa->spa_load_thread == curthread);
if (spa->spa_autotrim)
vdev_autotrim(spa);
}
@@ -1664,6 +1725,7 @@ vdev_trim_simple(vdev_t *vd, uint64_t start, uint64_t size)
ASSERT(vd->vdev_ops->vdev_op_leaf);
ASSERT(!vd->vdev_detached);
ASSERT(!vd->vdev_top->vdev_removing);
+ ASSERT(!vd->vdev_top->vdev_rz_expanding);
ta.trim_vdev = vd;
ta.trim_tree = range_tree_create(NULL, RANGE_SEG64, NULL, 0, 0);
diff --git a/module/zfs/zap.c b/module/zfs/zap.c
index d533f17cca9f..1b6b16fc6662 100644
--- a/module/zfs/zap.c
+++ b/module/zfs/zap.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,8 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright 2023 Alexander Stetsenko <alex.stetsenko@gmail.com>
+ * Copyright (c) 2023, Klara Inc.
*/
/*
@@ -41,6 +43,7 @@
#include <sys/spa.h>
#include <sys/dmu.h>
+#include <sys/dnode.h>
#include <sys/zfs_context.h>
#include <sys/zfs_znode.h>
#include <sys/fs/zfs.h>
@@ -78,9 +81,16 @@
*/
static int zap_iterate_prefetch = B_TRUE;
+/*
+ * Enable ZAP shrinking. When enabled, empty sibling leaf blocks will be
+ * collapsed into a single block.
+ */
+int zap_shrink_enabled = B_TRUE;
+
int fzap_default_block_shift = 14; /* 16k blocksize */
static uint64_t zap_allocate_blocks(zap_t *zap, int nblocks);
+static int zap_shrink(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx);
void
fzap_byteswap(void *vbuf, size_t size)
@@ -133,7 +143,7 @@ fzap_upgrade(zap_t *zap, dmu_tx_t *tx, zap_flags_t flags)
* set up block 1 - the first leaf
*/
dmu_buf_t *db;
- VERIFY0(dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ VERIFY0(dmu_buf_hold_by_dnode(zap->zap_dnode,
1<<FZAP_BLOCK_SHIFT(zap), FTAG, &db, DMU_READ_NO_PREFETCH));
dmu_buf_will_dirty(db, tx);
@@ -182,7 +192,7 @@ zap_table_grow(zap_t *zap, zap_table_phys_t *tbl,
newblk = zap_allocate_blocks(zap, tbl->zt_numblks * 2);
tbl->zt_nextblk = newblk;
ASSERT0(tbl->zt_blks_copied);
- dmu_prefetch(zap->zap_objset, zap->zap_object, 0,
+ dmu_prefetch_by_dnode(zap->zap_dnode, 0,
tbl->zt_blk << bs, tbl->zt_numblks << bs,
ZIO_PRIORITY_SYNC_READ);
}
@@ -193,21 +203,21 @@ zap_table_grow(zap_t *zap, zap_table_phys_t *tbl,
uint64_t b = tbl->zt_blks_copied;
dmu_buf_t *db_old;
- int err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ int err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(tbl->zt_blk + b) << bs, FTAG, &db_old, DMU_READ_NO_PREFETCH);
if (err != 0)
return (err);
/* first half of entries in old[b] go to new[2*b+0] */
dmu_buf_t *db_new;
- VERIFY0(dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ VERIFY0(dmu_buf_hold_by_dnode(zap->zap_dnode,
(newblk + 2*b+0) << bs, FTAG, &db_new, DMU_READ_NO_PREFETCH));
dmu_buf_will_dirty(db_new, tx);
transfer_func(db_old->db_data, db_new->db_data, hepb);
dmu_buf_rele(db_new, FTAG);
/* second half of entries in old[b] go to new[2*b+1] */
- VERIFY0(dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ VERIFY0(dmu_buf_hold_by_dnode(zap->zap_dnode,
(newblk + 2*b+1) << bs, FTAG, &db_new, DMU_READ_NO_PREFETCH));
dmu_buf_will_dirty(db_new, tx);
transfer_func((uint64_t *)db_old->db_data + hepb,
@@ -255,7 +265,7 @@ zap_table_store(zap_t *zap, zap_table_phys_t *tbl, uint64_t idx, uint64_t val,
uint64_t off = idx & ((1<<(bs-3))-1);
dmu_buf_t *db;
- int err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ int err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(tbl->zt_blk + blk) << bs, FTAG, &db, DMU_READ_NO_PREFETCH);
if (err != 0)
return (err);
@@ -267,7 +277,7 @@ zap_table_store(zap_t *zap, zap_table_phys_t *tbl, uint64_t idx, uint64_t val,
uint64_t off2 = idx2 & ((1<<(bs-3))-1);
dmu_buf_t *db2;
- err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(tbl->zt_nextblk + blk2) << bs, FTAG, &db2,
DMU_READ_NO_PREFETCH);
if (err != 0) {
@@ -296,16 +306,9 @@ zap_table_load(zap_t *zap, zap_table_phys_t *tbl, uint64_t idx, uint64_t *valp)
uint64_t blk = idx >> (bs-3);
uint64_t off = idx & ((1<<(bs-3))-1);
- /*
- * Note: this is equivalent to dmu_buf_hold(), but we use
- * _dnode_enter / _by_dnode because it's faster because we don't
- * have to hold the dnode.
- */
- dnode_t *dn = dmu_buf_dnode_enter(zap->zap_dbuf);
dmu_buf_t *db;
- int err = dmu_buf_hold_by_dnode(dn,
+ int err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(tbl->zt_blk + blk) << bs, FTAG, &db, DMU_READ_NO_PREFETCH);
- dmu_buf_dnode_exit(zap->zap_dbuf);
if (err != 0)
return (err);
*valp = ((uint64_t *)db->db_data)[off];
@@ -319,11 +322,9 @@ zap_table_load(zap_t *zap, zap_table_phys_t *tbl, uint64_t idx, uint64_t *valp)
*/
blk = (idx*2) >> (bs-3);
- dn = dmu_buf_dnode_enter(zap->zap_dbuf);
- err = dmu_buf_hold_by_dnode(dn,
+ err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(tbl->zt_nextblk + blk) << bs, FTAG, &db,
DMU_READ_NO_PREFETCH);
- dmu_buf_dnode_exit(zap->zap_dbuf);
if (err == 0)
dmu_buf_rele(db, FTAG);
}
@@ -368,7 +369,7 @@ zap_grow_ptrtbl(zap_t *zap, dmu_tx_t *tx)
uint64_t newblk = zap_allocate_blocks(zap, 1);
dmu_buf_t *db_new;
- int err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ int err = dmu_buf_hold_by_dnode(zap->zap_dnode,
newblk << FZAP_BLOCK_SHIFT(zap), FTAG, &db_new,
DMU_READ_NO_PREFETCH);
if (err != 0)
@@ -433,7 +434,7 @@ zap_create_leaf(zap_t *zap, dmu_tx_t *tx)
l->l_blkid = zap_allocate_blocks(zap, 1);
l->l_dbuf = NULL;
- VERIFY0(dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ VERIFY0(dmu_buf_hold_by_dnode(zap->zap_dnode,
l->l_blkid << FZAP_BLOCK_SHIFT(zap), NULL, &l->l_dbuf,
DMU_READ_NO_PREFETCH));
dmu_buf_init_user(&l->l_dbu, zap_leaf_evict_sync, NULL, &l->l_dbuf);
@@ -533,10 +534,8 @@ zap_get_leaf_byblk(zap_t *zap, uint64_t blkid, dmu_tx_t *tx, krw_t lt,
return (SET_ERROR(ENOENT));
int bs = FZAP_BLOCK_SHIFT(zap);
- dnode_t *dn = dmu_buf_dnode_enter(zap->zap_dbuf);
- int err = dmu_buf_hold_by_dnode(dn,
+ int err = dmu_buf_hold_by_dnode(zap->zap_dnode,
blkid << bs, NULL, &db, DMU_READ_NO_PREFETCH);
- dmu_buf_dnode_exit(zap->zap_dbuf);
if (err != 0)
return (err);
@@ -598,6 +597,72 @@ zap_set_idx_to_blk(zap_t *zap, uint64_t idx, uint64_t blk, dmu_tx_t *tx)
}
static int
+zap_set_idx_range_to_blk(zap_t *zap, uint64_t idx, uint64_t nptrs, uint64_t blk,
+ dmu_tx_t *tx)
+{
+ int bs = FZAP_BLOCK_SHIFT(zap);
+ int epb = bs >> 3; /* entries per block */
+ int err = 0;
+
+ ASSERT(tx != NULL);
+ ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
+
+ /*
+ * Check for i/o errors
+ */
+ for (int i = 0; i < nptrs; i += epb) {
+ uint64_t blk;
+ err = zap_idx_to_blk(zap, idx + i, &blk);
+ if (err != 0) {
+ return (err);
+ }
+ }
+
+ for (int i = 0; i < nptrs; i++) {
+ err = zap_set_idx_to_blk(zap, idx + i, blk, tx);
+ ASSERT0(err); /* we checked for i/o errors above */
+ if (err != 0)
+ break;
+ }
+
+ return (err);
+}
+
+#define ZAP_PREFIX_HASH(pref, pref_len) ((pref) << (64 - (pref_len)))
+
+/*
+ * Each leaf has single range of entries (block pointers) in the ZAP ptrtbl.
+ * If two leaves are siblings, their ranges are adjecent and contain the same
+ * number of entries. In order to find out if a leaf has a sibling, we need to
+ * check the range corresponding to the sibling leaf. There is no need to check
+ * all entries in the range, we only need to check the frist and the last one.
+ */
+static uint64_t
+check_sibling_ptrtbl_range(zap_t *zap, uint64_t prefix, uint64_t prefix_len)
+{
+ ASSERT(RW_LOCK_HELD(&zap->zap_rwlock));
+
+ uint64_t h = ZAP_PREFIX_HASH(prefix, prefix_len);
+ uint64_t idx = ZAP_HASH_IDX(h, zap_f_phys(zap)->zap_ptrtbl.zt_shift);
+ uint64_t pref_diff = zap_f_phys(zap)->zap_ptrtbl.zt_shift - prefix_len;
+ uint64_t nptrs = (1 << pref_diff);
+ uint64_t first;
+ uint64_t last;
+
+ ASSERT3U(idx+nptrs, <=, (1UL << zap_f_phys(zap)->zap_ptrtbl.zt_shift));
+
+ if (zap_idx_to_blk(zap, idx, &first) != 0)
+ return (0);
+
+ if (zap_idx_to_blk(zap, idx + nptrs - 1, &last) != 0)
+ return (0);
+
+ if (first != last)
+ return (0);
+ return (first);
+}
+
+static int
zap_deref_leaf(zap_t *zap, uint64_t h, dmu_tx_t *tx, krw_t lt, zap_leaf_t **lp)
{
uint64_t blk;
@@ -946,9 +1011,9 @@ fzap_length(zap_name_t *zn,
if (err != 0)
goto out;
- if (integer_size != 0)
+ if (integer_size != NULL)
*integer_size = zeh.zeh_integer_size;
- if (num_integers != 0)
+ if (num_integers != NULL)
*num_integers = zeh.zeh_num_integers;
out:
zap_put_leaf(l);
@@ -969,6 +1034,10 @@ fzap_remove(zap_name_t *zn, dmu_tx_t *tx)
if (err == 0) {
zap_entry_remove(&zeh);
zap_increment_num_entries(zn->zn_zap, -1, tx);
+
+ if (zap_leaf_phys(l)->l_hdr.lh_nentries == 0 &&
+ zap_shrink_enabled)
+ return (zap_shrink(zn, l, tx));
}
zap_put_leaf(l);
return (err);
@@ -985,7 +1054,7 @@ fzap_prefetch(zap_name_t *zn)
if (zap_idx_to_blk(zap, idx, &blk) != 0)
return;
int bs = FZAP_BLOCK_SHIFT(zap);
- dmu_prefetch(zap->zap_objset, zap->zap_object, 0, blk << bs, 1 << bs,
+ dmu_prefetch_by_dnode(zap->zap_dnode, 0, blk << bs, 1 << bs,
ZIO_PRIORITY_SYNC_READ);
}
@@ -1228,18 +1297,24 @@ fzap_cursor_retrieve(zap_t *zap, zap_cursor_t *zc, zap_attribute_t *za)
*/
if (zc->zc_hash == 0 && zap_iterate_prefetch &&
zc->zc_prefetch && zap_f_phys(zap)->zap_freeblk > 2) {
- dmu_prefetch(zc->zc_objset, zc->zc_zapobj, 0, 0,
+ dmu_prefetch_by_dnode(zap->zap_dnode, 0, 0,
zap_f_phys(zap)->zap_freeblk << FZAP_BLOCK_SHIFT(zap),
ZIO_PRIORITY_ASYNC_READ);
}
- if (zc->zc_leaf &&
- (ZAP_HASH_IDX(zc->zc_hash,
- zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix_len) !=
- zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix)) {
+ if (zc->zc_leaf) {
rw_enter(&zc->zc_leaf->l_rwlock, RW_READER);
- zap_put_leaf(zc->zc_leaf);
- zc->zc_leaf = NULL;
+
+ /*
+ * The leaf was either shrunk or split.
+ */
+ if ((zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_block_type == 0) ||
+ (ZAP_HASH_IDX(zc->zc_hash,
+ zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix_len) !=
+ zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix)) {
+ zap_put_leaf(zc->zc_leaf);
+ zc->zc_leaf = NULL;
+ }
}
again:
@@ -1248,8 +1323,6 @@ again:
&zc->zc_leaf);
if (err != 0)
return (err);
- } else {
- rw_enter(&zc->zc_leaf->l_rwlock, RW_READER);
}
l = zc->zc_leaf;
@@ -1356,7 +1429,7 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs)
zap_stats_ptrtbl(zap, &ZAP_EMBEDDED_PTRTBL_ENT(zap, 0),
1 << ZAP_EMBEDDED_PTRTBL_SHIFT(zap), zs);
} else {
- dmu_prefetch(zap->zap_objset, zap->zap_object, 0,
+ dmu_prefetch_by_dnode(zap->zap_dnode, 0,
zap_f_phys(zap)->zap_ptrtbl.zt_blk << bs,
zap_f_phys(zap)->zap_ptrtbl.zt_numblks << bs,
ZIO_PRIORITY_SYNC_READ);
@@ -1366,7 +1439,7 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs)
dmu_buf_t *db;
int err;
- err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
+ err = dmu_buf_hold_by_dnode(zap->zap_dnode,
(zap_f_phys(zap)->zap_ptrtbl.zt_blk + b) << bs,
FTAG, &db, DMU_READ_NO_PREFETCH);
if (err == 0) {
@@ -1378,6 +1451,242 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs)
}
}
+/*
+ * Find last allocated block and update freeblk.
+ */
+static void
+zap_trunc(zap_t *zap)
+{
+ uint64_t nentries;
+ uint64_t lastblk;
+
+ ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
+
+ if (zap_f_phys(zap)->zap_ptrtbl.zt_blk > 0) {
+ /* External ptrtbl */
+ nentries = (1 << zap_f_phys(zap)->zap_ptrtbl.zt_shift);
+ lastblk = zap_f_phys(zap)->zap_ptrtbl.zt_blk +
+ zap_f_phys(zap)->zap_ptrtbl.zt_numblks - 1;
+ } else {
+ /* Embedded ptrtbl */
+ nentries = (1 << ZAP_EMBEDDED_PTRTBL_SHIFT(zap));
+ lastblk = 0;
+ }
+
+ for (uint64_t idx = 0; idx < nentries; idx++) {
+ uint64_t blk;
+ if (zap_idx_to_blk(zap, idx, &blk) != 0)
+ return;
+ if (blk > lastblk)
+ lastblk = blk;
+ }
+
+ ASSERT3U(lastblk, <, zap_f_phys(zap)->zap_freeblk);
+
+ zap_f_phys(zap)->zap_freeblk = lastblk + 1;
+}
+
+/*
+ * ZAP shrinking algorithm.
+ *
+ * We shrink ZAP recuresively removing empty leaves. We can remove an empty leaf
+ * only if it has a sibling. Sibling leaves have the same prefix length and
+ * their prefixes differ only by the least significant (sibling) bit. We require
+ * both siblings to be empty. This eliminates a need to rehash the non-empty
+ * remaining leaf. When we have removed one of two empty sibling, we set ptrtbl
+ * entries of the removed leaf to point out to the remaining leaf. Prefix length
+ * of the remaining leaf is decremented. As a result, it has a new prefix and it
+ * might have a new sibling. So, we repeat the process.
+ *
+ * Steps:
+ * 1. Check if a sibling leaf (sl) exists and it is empty.
+ * 2. Release the leaf (l) if it has the sibling bit (slbit) equal to 1.
+ * 3. Release the sibling (sl) to derefer it again with WRITER lock.
+ * 4. Upgrade zapdir lock to WRITER (once).
+ * 5. Derefer released leaves again.
+ * 6. If it is needed, recheck whether both leaves are still siblings and empty.
+ * 7. Set ptrtbl pointers of the removed leaf (slbit 1) to point out to blkid of
+ * the remaining leaf (slbit 0).
+ * 8. Free disk block of the removed leaf (dmu_free_range).
+ * 9. Decrement prefix_len of the remaining leaf.
+ * 10. Repeat the steps.
+ */
+static int
+zap_shrink(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx)
+{
+ zap_t *zap = zn->zn_zap;
+ int64_t zt_shift = zap_f_phys(zap)->zap_ptrtbl.zt_shift;
+ uint64_t hash = zn->zn_hash;
+ uint64_t prefix = zap_leaf_phys(l)->l_hdr.lh_prefix;
+ uint64_t prefix_len = zap_leaf_phys(l)->l_hdr.lh_prefix_len;
+ boolean_t trunc = B_FALSE;
+ int err = 0;
+
+ ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_nentries, ==, 0);
+ ASSERT3U(prefix_len, <=, zap_f_phys(zap)->zap_ptrtbl.zt_shift);
+ ASSERT(RW_LOCK_HELD(&zap->zap_rwlock));
+ ASSERT3U(ZAP_HASH_IDX(hash, prefix_len), ==, prefix);
+
+ boolean_t writer = B_FALSE;
+
+ /*
+ * To avoid deadlock always deref leaves in the same order -
+ * sibling 0 first, then sibling 1.
+ */
+ while (prefix_len) {
+ zap_leaf_t *sl;
+ int64_t prefix_diff = zt_shift - prefix_len;
+ uint64_t sl_prefix = prefix ^ 1;
+ uint64_t sl_hash = ZAP_PREFIX_HASH(sl_prefix, prefix_len);
+ int slbit = prefix & 1;
+
+ ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_nentries, ==, 0);
+
+ /*
+ * Check if there is a sibling by reading ptrtbl ptrs.
+ */
+ if (check_sibling_ptrtbl_range(zap, sl_prefix, prefix_len) == 0)
+ break;
+
+ /*
+ * sibling 1, unlock it - we haven't yet dereferenced sibling 0.
+ */
+ if (slbit == 1) {
+ zap_put_leaf(l);
+ l = NULL;
+ }
+
+ /*
+ * Dereference sibling leaf and check if it is empty.
+ */
+ if ((err = zap_deref_leaf(zap, sl_hash, tx, RW_READER,
+ &sl)) != 0)
+ break;
+
+ ASSERT3U(ZAP_HASH_IDX(sl_hash, prefix_len), ==, sl_prefix);
+
+ /*
+ * Check if we have a sibling and it is empty.
+ */
+ if (zap_leaf_phys(sl)->l_hdr.lh_prefix_len != prefix_len ||
+ zap_leaf_phys(sl)->l_hdr.lh_nentries != 0) {
+ zap_put_leaf(sl);
+ break;
+ }
+
+ zap_put_leaf(sl);
+
+ /*
+ * If there two empty sibling, we have work to do, so
+ * we need to lock ZAP ptrtbl as WRITER.
+ */
+ if (!writer && (writer = zap_tryupgradedir(zap, tx)) == 0) {
+ /* We failed to upgrade */
+ if (l != NULL) {
+ zap_put_leaf(l);
+ l = NULL;
+ }
+
+ /*
+ * Usually, the right way to upgrade from a READER lock
+ * to a WRITER lock is to call zap_unlockdir() and
+ * zap_lockdir(), but we do not have a tag. Instead,
+ * we do it in more sophisticated way.
+ */
+ rw_exit(&zap->zap_rwlock);
+ rw_enter(&zap->zap_rwlock, RW_WRITER);
+ dmu_buf_will_dirty(zap->zap_dbuf, tx);
+
+ zt_shift = zap_f_phys(zap)->zap_ptrtbl.zt_shift;
+ writer = B_TRUE;
+ }
+
+ /*
+ * Here we have WRITER lock for ptrtbl.
+ * Now, we need a WRITER lock for both siblings leaves.
+ * Also, we have to recheck if the leaves are still siblings
+ * and still empty.
+ */
+ if (l == NULL) {
+ /* sibling 0 */
+ if ((err = zap_deref_leaf(zap, (slbit ? sl_hash : hash),
+ tx, RW_WRITER, &l)) != 0)
+ break;
+
+ /*
+ * The leaf isn't empty anymore or
+ * it was shrunk/split while our locks were down.
+ */
+ if (zap_leaf_phys(l)->l_hdr.lh_nentries != 0 ||
+ zap_leaf_phys(l)->l_hdr.lh_prefix_len != prefix_len)
+ break;
+ }
+
+ /* sibling 1 */
+ if ((err = zap_deref_leaf(zap, (slbit ? hash : sl_hash), tx,
+ RW_WRITER, &sl)) != 0)
+ break;
+
+ /*
+ * The leaf isn't empty anymore or
+ * it was shrunk/split while our locks were down.
+ */
+ if (zap_leaf_phys(sl)->l_hdr.lh_nentries != 0 ||
+ zap_leaf_phys(sl)->l_hdr.lh_prefix_len != prefix_len) {
+ zap_put_leaf(sl);
+ break;
+ }
+
+ /* If we have gotten here, we have a leaf to collapse */
+ uint64_t idx = (slbit ? prefix : sl_prefix) << prefix_diff;
+ uint64_t nptrs = (1ULL << prefix_diff);
+ uint64_t sl_blkid = sl->l_blkid;
+
+ /*
+ * Set ptrtbl entries to point out to the slibling 0 blkid
+ */
+ if ((err = zap_set_idx_range_to_blk(zap, idx, nptrs, l->l_blkid,
+ tx)) != 0) {
+ zap_put_leaf(sl);
+ break;
+ }
+
+ /*
+ * Free sibling 1 disk block.
+ */
+ int bs = FZAP_BLOCK_SHIFT(zap);
+ if (sl_blkid == zap_f_phys(zap)->zap_freeblk - 1)
+ trunc = B_TRUE;
+
+ (void) dmu_free_range(zap->zap_objset, zap->zap_object,
+ sl_blkid << bs, 1 << bs, tx);
+ zap_put_leaf(sl);
+
+ zap_f_phys(zap)->zap_num_leafs--;
+
+ /*
+ * Update prefix and prefix_len.
+ */
+ zap_leaf_phys(l)->l_hdr.lh_prefix >>= 1;
+ zap_leaf_phys(l)->l_hdr.lh_prefix_len--;
+
+ prefix = zap_leaf_phys(l)->l_hdr.lh_prefix;
+ prefix_len = zap_leaf_phys(l)->l_hdr.lh_prefix_len;
+ }
+
+ if (trunc)
+ zap_trunc(zap);
+
+ if (l != NULL)
+ zap_put_leaf(l);
+
+ return (err);
+}
+
/* CSTYLED */
ZFS_MODULE_PARAM(zfs, , zap_iterate_prefetch, INT, ZMOD_RW,
"When iterating ZAP object, prefetch it");
+
+/* CSTYLED */
+ZFS_MODULE_PARAM(zfs, , zap_shrink_enabled, INT, ZMOD_RW,
+ "Enable ZAP shrinking");
diff --git a/module/zfs/zap_leaf.c b/module/zfs/zap_leaf.c
index d161c19c9cbe..032aca92695e 100644
--- a/module/zfs/zap_leaf.c
+++ b/module/zfs/zap_leaf.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -41,7 +41,8 @@
#include <sys/zap_leaf.h>
#include <sys/arc.h>
-static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry);
+static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, struct zap_leaf_entry *le,
+ uint16_t entry);
#define CHAIN_END 0xffff /* end of the chunk chain */
@@ -53,16 +54,6 @@ static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry);
#define LEAF_HASH_ENTPTR(l, h) (&zap_leaf_phys(l)->l_hash[LEAF_HASH(l, h)])
static void
-zap_memset(void *a, int c, size_t n)
-{
- char *cp = a;
- char *cpend = cp + n;
-
- while (cp < cpend)
- *cp++ = c;
-}
-
-static void
stv(int len, void *addr, uint64_t value)
{
switch (len) {
@@ -79,7 +70,7 @@ stv(int len, void *addr, uint64_t value)
*(uint64_t *)addr = value;
return;
default:
- cmn_err(CE_PANIC, "bad int len %d", len);
+ PANIC("bad int len %d", len);
}
}
@@ -96,13 +87,13 @@ ldv(int len, const void *addr)
case 8:
return (*(uint64_t *)addr);
default:
- cmn_err(CE_PANIC, "bad int len %d", len);
+ PANIC("bad int len %d", len);
}
return (0xFEEDFACEDEADBEEFULL);
}
void
-zap_leaf_byteswap(zap_leaf_phys_t *buf, int size)
+zap_leaf_byteswap(zap_leaf_phys_t *buf, size_t size)
{
zap_leaf_t l;
dmu_buf_t l_dbuf;
@@ -119,10 +110,10 @@ zap_leaf_byteswap(zap_leaf_phys_t *buf, int size)
buf->l_hdr.lh_prefix_len = BSWAP_16(buf->l_hdr.lh_prefix_len);
buf->l_hdr.lh_freelist = BSWAP_16(buf->l_hdr.lh_freelist);
- for (int i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++)
+ for (uint_t i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++)
buf->l_hash[i] = BSWAP_16(buf->l_hash[i]);
- for (int i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) {
+ for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) {
zap_leaf_chunk_t *lc = &ZAP_LEAF_CHUNK(&l, i);
struct zap_leaf_entry *le;
@@ -160,11 +151,11 @@ void
zap_leaf_init(zap_leaf_t *l, boolean_t sort)
{
l->l_bs = highbit64(l->l_dbuf->db_size) - 1;
- zap_memset(&zap_leaf_phys(l)->l_hdr, 0,
+ memset(&zap_leaf_phys(l)->l_hdr, 0,
sizeof (struct zap_leaf_header));
- zap_memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
+ memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
2*ZAP_LEAF_HASH_NUMENTRIES(l));
- for (int i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
+ for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE;
ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1;
}
@@ -185,7 +176,7 @@ zap_leaf_chunk_alloc(zap_leaf_t *l)
{
ASSERT(zap_leaf_phys(l)->l_hdr.lh_nfree > 0);
- int chunk = zap_leaf_phys(l)->l_hdr.lh_freelist;
+ uint_t chunk = zap_leaf_phys(l)->l_hdr.lh_freelist;
ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE);
@@ -223,28 +214,29 @@ zap_leaf_array_create(zap_leaf_t *l, const char *buf,
{
uint16_t chunk_head;
uint16_t *chunkp = &chunk_head;
- int byten = 0;
+ int byten = integer_size;
uint64_t value = 0;
int shift = (integer_size - 1) * 8;
int len = num_integers;
ASSERT3U(num_integers * integer_size, <=, ZAP_MAXVALUELEN);
+ if (len > 0)
+ value = ldv(integer_size, buf);
while (len > 0) {
uint16_t chunk = zap_leaf_chunk_alloc(l);
struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
la->la_type = ZAP_CHUNK_ARRAY;
for (int i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) {
- if (byten == 0)
- value = ldv(integer_size, buf);
la->la_array[i] = value >> shift;
value <<= 8;
- if (++byten == integer_size) {
- byten = 0;
- buf += integer_size;
+ if (--byten == 0) {
if (--len == 0)
break;
+ byten = integer_size;
+ buf += integer_size;
+ value = ldv(integer_size, buf);
}
}
@@ -264,7 +256,7 @@ zap_leaf_array_free(zap_leaf_t *l, uint16_t *chunkp)
*chunkp = CHAIN_END;
while (chunk != CHAIN_END) {
- int nextchunk = ZAP_LEAF_CHUNK(l, chunk).l_array.la_next;
+ uint_t nextchunk = ZAP_LEAF_CHUNK(l, chunk).l_array.la_next;
ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_array.la_type, ==,
ZAP_CHUNK_ARRAY);
zap_leaf_chunk_free(l, chunk);
@@ -315,7 +307,7 @@ zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
- for (int i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) {
+ for (int i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) {
value = (value << 8) | la->la_array[i];
byten++;
if (byten == array_int_len) {
@@ -333,7 +325,7 @@ zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
static boolean_t
zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
- int chunk, int array_numints)
+ uint_t chunk, int array_numints)
{
int bseen = 0;
@@ -562,7 +554,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
uint64_t valuelen = integer_size * num_integers;
- int numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(zn->zn_key_orig_numints *
+ uint_t numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(zn->zn_key_orig_numints *
zn->zn_key_intlen) + ZAP_LEAF_ARRAY_NCHUNKS(valuelen);
if (numchunks > ZAP_LEAF_NUMCHUNKS(l))
return (SET_ERROR(E2BIG));
@@ -624,7 +616,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
/* link it into the hash chain */
/* XXX if we did the search above, we could just use that */
- uint16_t *chunkp = zap_leaf_rehash_entry(l, chunk);
+ uint16_t *chunkp = zap_leaf_rehash_entry(l, le, chunk);
zap_leaf_phys(l)->l_hdr.lh_nentries++;
@@ -646,7 +638,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
* form of the name. But all callers have one of these on hand anyway,
* so might as well take advantage. A cleaner but slower interface
* would accept neither argument, and compute the normalized name as
- * needed (using zap_name_alloc(zap_entry_read_name(zeh))).
+ * needed (using zap_name_alloc_str(zap_entry_read_name(zeh))).
*/
boolean_t
zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
@@ -667,7 +659,7 @@ zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
continue;
if (zn == NULL) {
- zn = zap_name_alloc(zap, name, MT_NORMALIZE);
+ zn = zap_name_alloc_str(zap, name, MT_NORMALIZE);
allocdzn = B_TRUE;
}
if (zap_leaf_array_match(zeh->zeh_leaf, zn,
@@ -687,9 +679,8 @@ zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
*/
static uint16_t *
-zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry)
+zap_leaf_rehash_entry(zap_leaf_t *l, struct zap_leaf_entry *le, uint16_t entry)
{
- struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry);
struct zap_leaf_entry *le2;
uint16_t *chunkp;
@@ -722,7 +713,7 @@ zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl)
&ZAP_LEAF_CHUNK(nl, nchunk).l_array;
struct zap_leaf_array *la =
&ZAP_LEAF_CHUNK(l, chunk).l_array;
- int nextchunk = la->la_next;
+ uint_t nextchunk = la->la_next;
ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
ASSERT3U(nchunk, <, ZAP_LEAF_NUMCHUNKS(l));
@@ -739,7 +730,7 @@ zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl)
}
static void
-zap_leaf_transfer_entry(zap_leaf_t *l, int entry, zap_leaf_t *nl)
+zap_leaf_transfer_entry(zap_leaf_t *l, uint_t entry, zap_leaf_t *nl)
{
struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry);
ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
@@ -748,7 +739,7 @@ zap_leaf_transfer_entry(zap_leaf_t *l, int entry, zap_leaf_t *nl)
struct zap_leaf_entry *nle = ZAP_LEAF_ENTRY(nl, chunk);
*nle = *le; /* structure assignment */
- (void) zap_leaf_rehash_entry(nl, chunk);
+ (void) zap_leaf_rehash_entry(nl, nle, chunk);
nle->le_name_chunk = zap_leaf_transfer_array(l, le->le_name_chunk, nl);
nle->le_value_chunk =
@@ -766,7 +757,7 @@ zap_leaf_transfer_entry(zap_leaf_t *l, int entry, zap_leaf_t *nl)
void
zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
{
- int bit = 64 - 1 - zap_leaf_phys(l)->l_hdr.lh_prefix_len;
+ uint_t bit = 64 - 1 - zap_leaf_phys(l)->l_hdr.lh_prefix_len;
/* set new prefix and prefix_len */
zap_leaf_phys(l)->l_hdr.lh_prefix <<= 1;
@@ -777,7 +768,7 @@ zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
zap_leaf_phys(l)->l_hdr.lh_prefix_len;
/* break existing hash chains */
- zap_memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
+ memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
2*ZAP_LEAF_HASH_NUMENTRIES(l));
if (sort)
@@ -792,7 +783,7 @@ zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
* but this accesses memory more sequentially, and when we're
* called, the block is usually pretty full.
*/
- for (int i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
+ for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, i);
if (le->le_type != ZAP_CHUNK_ENTRY)
continue;
@@ -800,14 +791,14 @@ zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
if (le->le_hash & (1ULL << bit))
zap_leaf_transfer_entry(l, i, nl);
else
- (void) zap_leaf_rehash_entry(l, i);
+ (void) zap_leaf_rehash_entry(l, le, i);
}
}
void
zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs)
{
- int n = zap_f_phys(zap)->zap_ptrtbl.zt_shift -
+ uint_t n = zap_f_phys(zap)->zap_ptrtbl.zt_shift -
zap_leaf_phys(l)->l_hdr.lh_prefix_len;
n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
zs->zs_leafs_with_2n_pointers[n]++;
@@ -823,9 +814,9 @@ zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs)
n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
zs->zs_blocks_n_tenths_full[n]++;
- for (int i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) {
- int nentries = 0;
- int chunk = zap_leaf_phys(l)->l_hash[i];
+ for (uint_t i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) {
+ uint_t nentries = 0;
+ uint_t chunk = zap_leaf_phys(l)->l_hash[i];
while (chunk != CHAIN_END) {
struct zap_leaf_entry *le =
diff --git a/module/zfs/zap_micro.c b/module/zfs/zap_micro.c
index 09780a6c5989..d806988af96d 100644
--- a/module/zfs/zap_micro.c
+++ b/module/zfs/zap_micro.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,7 +33,7 @@
#include <sys/zap.h>
#include <sys/zap_impl.h>
#include <sys/zap_leaf.h>
-#include <sys/avl.h>
+#include <sys/btree.h>
#include <sys/arc.h>
#include <sys/dmu_objset.h>
@@ -41,6 +41,8 @@
#include <sys/sunddi.h>
#endif
+int zap_micro_max_size = MZAP_MAX_BLKSZ;
+
static int mzap_upgrade(zap_t **zapp,
const void *tag, dmu_tx_t *tx, zap_flags_t flags);
@@ -92,7 +94,7 @@ zap_hash(zap_name_t *zn)
wp++, i++) {
uint64_t word = *wp;
- for (int j = 0; j < zn->zn_key_intlen; j++) {
+ for (int j = 0; j < 8; j++) {
h = (h >> 8) ^
zfs_crc64_table[(h ^ word) & 0xFF];
word >>= NBBY;
@@ -162,18 +164,25 @@ zap_match(zap_name_t *zn, const char *matchname)
}
}
+static zap_name_t *
+zap_name_alloc(zap_t *zap)
+{
+ zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP);
+ zn->zn_zap = zap;
+ return (zn);
+}
+
void
zap_name_free(zap_name_t *zn)
{
kmem_free(zn, sizeof (zap_name_t));
}
-zap_name_t *
-zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
+static int
+zap_name_init_str(zap_name_t *zn, const char *key, matchtype_t mt)
{
- zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP);
+ zap_t *zap = zn->zn_zap;
- zn->zn_zap = zap;
zn->zn_key_intlen = sizeof (*key);
zn->zn_key_orig = key;
zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1;
@@ -194,17 +203,13 @@ zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
* what the hash is computed from.
*/
if (zap_normalize(zap, key, zn->zn_normbuf,
- zap->zap_normflags) != 0) {
- zap_name_free(zn);
- return (NULL);
- }
+ zap->zap_normflags) != 0)
+ return (SET_ERROR(ENOTSUP));
zn->zn_key_norm = zn->zn_normbuf;
zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
} else {
- if (mt != 0) {
- zap_name_free(zn);
- return (NULL);
- }
+ if (mt != 0)
+ return (SET_ERROR(ENOTSUP));
zn->zn_key_norm = zn->zn_key_orig;
zn->zn_key_norm_numints = zn->zn_key_orig_numints;
}
@@ -217,13 +222,22 @@ zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
* what the matching is based on. (Not the hash!)
*/
if (zap_normalize(zap, key, zn->zn_normbuf,
- zn->zn_normflags) != 0) {
- zap_name_free(zn);
- return (NULL);
- }
+ zn->zn_normflags) != 0)
+ return (SET_ERROR(ENOTSUP));
zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
}
+ return (0);
+}
+
+zap_name_t *
+zap_name_alloc_str(zap_t *zap, const char *key, matchtype_t mt)
+{
+ zap_name_t *zn = zap_name_alloc(zap);
+ if (zap_name_init_str(zn, key, mt) != 0) {
+ zap_name_free(zn);
+ return (NULL);
+ }
return (zn);
}
@@ -271,51 +285,56 @@ zap_byteswap(void *buf, size_t size)
}
}
+__attribute__((always_inline)) inline
static int
mze_compare(const void *arg1, const void *arg2)
{
const mzap_ent_t *mze1 = arg1;
const mzap_ent_t *mze2 = arg2;
- int cmp = TREE_CMP(mze1->mze_hash, mze2->mze_hash);
- if (likely(cmp))
- return (cmp);
-
- return (TREE_CMP(mze1->mze_cd, mze2->mze_cd));
+ return (TREE_CMP((uint64_t)(mze1->mze_hash) << 32 | mze1->mze_cd,
+ (uint64_t)(mze2->mze_hash) << 32 | mze2->mze_cd));
}
+ZFS_BTREE_FIND_IN_BUF_FUNC(mze_find_in_buf, mzap_ent_t,
+ mze_compare)
+
static void
-mze_insert(zap_t *zap, int chunkid, uint64_t hash)
+mze_insert(zap_t *zap, uint16_t chunkid, uint64_t hash)
{
+ mzap_ent_t mze;
+
ASSERT(zap->zap_ismicro);
ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
- mzap_ent_t *mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP);
- mze->mze_chunkid = chunkid;
- mze->mze_hash = hash;
- mze->mze_cd = MZE_PHYS(zap, mze)->mze_cd;
- ASSERT(MZE_PHYS(zap, mze)->mze_name[0] != 0);
- avl_add(&zap->zap_m.zap_avl, mze);
+ mze.mze_chunkid = chunkid;
+ ASSERT0(hash & 0xffffffff);
+ mze.mze_hash = hash >> 32;
+ ASSERT3U(MZE_PHYS(zap, &mze)->mze_cd, <=, 0xffff);
+ mze.mze_cd = (uint16_t)MZE_PHYS(zap, &mze)->mze_cd;
+ ASSERT(MZE_PHYS(zap, &mze)->mze_name[0] != 0);
+ zfs_btree_add(&zap->zap_m.zap_tree, &mze);
}
static mzap_ent_t *
-mze_find(zap_name_t *zn)
+mze_find(zap_name_t *zn, zfs_btree_index_t *idx)
{
mzap_ent_t mze_tofind;
mzap_ent_t *mze;
- avl_index_t idx;
- avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl;
+ zfs_btree_t *tree = &zn->zn_zap->zap_m.zap_tree;
ASSERT(zn->zn_zap->zap_ismicro);
ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock));
- mze_tofind.mze_hash = zn->zn_hash;
+ ASSERT0(zn->zn_hash & 0xffffffff);
+ mze_tofind.mze_hash = zn->zn_hash >> 32;
mze_tofind.mze_cd = 0;
- mze = avl_find(avl, &mze_tofind, &idx);
+ mze = zfs_btree_find(tree, &mze_tofind, idx);
if (mze == NULL)
- mze = avl_nearest(avl, idx, AVL_AFTER);
- for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) {
+ mze = zfs_btree_next(tree, idx, idx);
+ for (; mze && mze->mze_hash == mze_tofind.mze_hash;
+ mze = zfs_btree_next(tree, idx, idx)) {
ASSERT3U(mze->mze_cd, ==, MZE_PHYS(zn->zn_zap, mze)->mze_cd);
if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name))
return (mze);
@@ -328,18 +347,21 @@ static uint32_t
mze_find_unused_cd(zap_t *zap, uint64_t hash)
{
mzap_ent_t mze_tofind;
- avl_index_t idx;
- avl_tree_t *avl = &zap->zap_m.zap_avl;
+ zfs_btree_index_t idx;
+ zfs_btree_t *tree = &zap->zap_m.zap_tree;
ASSERT(zap->zap_ismicro);
ASSERT(RW_LOCK_HELD(&zap->zap_rwlock));
+ ASSERT0(hash & 0xffffffff);
+ hash >>= 32;
mze_tofind.mze_hash = hash;
mze_tofind.mze_cd = 0;
uint32_t cd = 0;
- for (mzap_ent_t *mze = avl_find(avl, &mze_tofind, &idx);
- mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) {
+ for (mzap_ent_t *mze = zfs_btree_find(tree, &mze_tofind, &idx);
+ mze && mze->mze_hash == hash;
+ mze = zfs_btree_next(tree, &idx, &idx)) {
if (mze->mze_cd != cd)
break;
cd++;
@@ -364,16 +386,18 @@ mze_canfit_fzap_leaf(zap_name_t *zn, uint64_t hash)
{
zap_t *zap = zn->zn_zap;
mzap_ent_t mze_tofind;
- mzap_ent_t *mze;
- avl_index_t idx;
- avl_tree_t *avl = &zap->zap_m.zap_avl;
+ zfs_btree_index_t idx;
+ zfs_btree_t *tree = &zap->zap_m.zap_tree;
uint32_t mzap_ents = 0;
+ ASSERT0(hash & 0xffffffff);
+ hash >>= 32;
mze_tofind.mze_hash = hash;
mze_tofind.mze_cd = 0;
- for (mze = avl_find(avl, &mze_tofind, &idx);
- mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) {
+ for (mzap_ent_t *mze = zfs_btree_find(tree, &mze_tofind, &idx);
+ mze && mze->mze_hash == hash;
+ mze = zfs_btree_next(tree, &idx, &idx)) {
mzap_ents++;
}
@@ -384,28 +408,14 @@ mze_canfit_fzap_leaf(zap_name_t *zn, uint64_t hash)
}
static void
-mze_remove(zap_t *zap, mzap_ent_t *mze)
-{
- ASSERT(zap->zap_ismicro);
- ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
-
- avl_remove(&zap->zap_m.zap_avl, mze);
- kmem_free(mze, sizeof (mzap_ent_t));
-}
-
-static void
mze_destroy(zap_t *zap)
{
- mzap_ent_t *mze;
- void *avlcookie = NULL;
-
- while ((mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie)))
- kmem_free(mze, sizeof (mzap_ent_t));
- avl_destroy(&zap->zap_m.zap_avl);
+ zfs_btree_clear(&zap->zap_m.zap_tree);
+ zfs_btree_destroy(&zap->zap_m.zap_tree);
}
static zap_t *
-mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
+mzap_open(dmu_buf_t *db)
{
zap_t *winner;
uint64_t *zap_hdr = (uint64_t *)db->db_data;
@@ -417,8 +427,8 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
zap_t *zap = kmem_zalloc(sizeof (zap_t), KM_SLEEP);
rw_init(&zap->zap_rwlock, NULL, RW_DEFAULT, NULL);
rw_enter(&zap->zap_rwlock, RW_WRITER);
- zap->zap_objset = os;
- zap->zap_object = obj;
+ zap->zap_objset = dmu_buf_get_objset(db);
+ zap->zap_object = db->db_object;
zap->zap_dbuf = db;
if (zap_block_type != ZBT_MICRO) {
@@ -448,21 +458,26 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
zap->zap_salt = zap_m_phys(zap)->mz_salt;
zap->zap_normflags = zap_m_phys(zap)->mz_normflags;
zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1;
- avl_create(&zap->zap_m.zap_avl, mze_compare,
- sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node));
- for (int i = 0; i < zap->zap_m.zap_num_chunks; i++) {
+ /*
+ * Reduce B-tree leaf from 4KB to 512 bytes to reduce memmove()
+ * overhead on massive inserts below. It still allows to store
+ * 62 entries before we have to add 2KB B-tree core node.
+ */
+ zfs_btree_create_custom(&zap->zap_m.zap_tree, mze_compare,
+ mze_find_in_buf, sizeof (mzap_ent_t), 512);
+
+ zap_name_t *zn = zap_name_alloc(zap);
+ for (uint16_t i = 0; i < zap->zap_m.zap_num_chunks; i++) {
mzap_ent_phys_t *mze =
&zap_m_phys(zap)->mz_chunk[i];
if (mze->mze_name[0]) {
- zap_name_t *zn;
-
zap->zap_m.zap_num_entries++;
- zn = zap_name_alloc(zap, mze->mze_name, 0);
+ zap_name_init_str(zn, mze->mze_name, 0);
mze_insert(zap, i, zn->zn_hash);
- zap_name_free(zn);
}
}
+ zap_name_free(zn);
} else {
zap->zap_salt = zap_f_phys(zap)->zap_salt;
zap->zap_normflags = zap_f_phys(zap)->zap_normflags;
@@ -503,7 +518,7 @@ handle_winner:
* have the specified tag.
*/
static int
-zap_lockdir_impl(dmu_buf_t *db, const void *tag, dmu_tx_t *tx,
+zap_lockdir_impl(dnode_t *dn, dmu_buf_t *db, const void *tag, dmu_tx_t *tx,
krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp)
{
ASSERT0(db->db_offset);
@@ -513,13 +528,13 @@ zap_lockdir_impl(dmu_buf_t *db, const void *tag, dmu_tx_t *tx,
*zapp = NULL;
- dmu_object_info_from_db(db, &doi);
+ dmu_object_info_from_dnode(dn, &doi);
if (DMU_OT_BYTESWAP(doi.doi_type) != DMU_BSWAP_ZAP)
return (SET_ERROR(EINVAL));
zap_t *zap = dmu_buf_get_user(db);
if (zap == NULL) {
- zap = mzap_open(os, obj, db);
+ zap = mzap_open(db);
if (zap == NULL) {
/*
* mzap_open() didn't like what it saw on-disk.
@@ -548,6 +563,7 @@ zap_lockdir_impl(dmu_buf_t *db, const void *tag, dmu_tx_t *tx,
}
zap->zap_objset = os;
+ zap->zap_dnode = dn;
if (lt == RW_WRITER)
dmu_buf_will_dirty(db, tx);
@@ -559,7 +575,7 @@ zap_lockdir_impl(dmu_buf_t *db, const void *tag, dmu_tx_t *tx,
if (zap->zap_ismicro && tx && adding &&
zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) {
uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE;
- if (newsz > MZAP_MAX_BLKSZ) {
+ if (newsz > zap_micro_max_size) {
dprintf("upgrading obj %llu: num_entries=%u\n",
(u_longlong_t)obj, zap->zap_m.zap_num_entries);
*zapp = zap;
@@ -583,23 +599,16 @@ zap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx,
zap_t **zapp)
{
dmu_buf_t *db;
+ int err;
- int err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH);
- if (err != 0) {
+ err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH);
+ if (err != 0)
return (err);
- }
-#ifdef ZFS_DEBUG
- {
- dmu_object_info_t doi;
- dmu_object_info_from_db(db, &doi);
- ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
- }
-#endif
-
- err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
- if (err != 0) {
+ err = zap_lockdir_impl(dn, db, tag, tx, lti, fatreader, adding, zapp);
+ if (err != 0)
dmu_buf_rele(db, tag);
- }
+ else
+ VERIFY(dnode_add_ref(dn, tag));
return (err);
}
@@ -608,21 +617,23 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
krw_t lti, boolean_t fatreader, boolean_t adding, const void *tag,
zap_t **zapp)
{
+ dnode_t *dn;
dmu_buf_t *db;
+ int err;
- int err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH);
+ err = dnode_hold(os, obj, tag, &dn);
if (err != 0)
return (err);
-#ifdef ZFS_DEBUG
- {
- dmu_object_info_t doi;
- dmu_object_info_from_db(db, &doi);
- ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
+ err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH);
+ if (err != 0) {
+ dnode_rele(dn, tag);
+ return (err);
}
-#endif
- err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
- if (err != 0)
+ err = zap_lockdir_impl(dn, db, tag, tx, lti, fatreader, adding, zapp);
+ if (err != 0) {
dmu_buf_rele(db, tag);
+ dnode_rele(dn, tag);
+ }
return (err);
}
@@ -630,6 +641,7 @@ void
zap_unlockdir(zap_t *zap, const void *tag)
{
rw_exit(&zap->zap_rwlock);
+ dnode_rele(zap->zap_dnode, tag);
dmu_buf_rele(zap->zap_dbuf, tag);
}
@@ -657,24 +669,25 @@ mzap_upgrade(zap_t **zapp, const void *tag, dmu_tx_t *tx, zap_flags_t flags)
dprintf("upgrading obj=%llu with %u chunks\n",
(u_longlong_t)zap->zap_object, nchunks);
- /* XXX destroy the avl later, so we can use the stored hash value */
+ /* XXX destroy the tree later, so we can use the stored hash value */
mze_destroy(zap);
fzap_upgrade(zap, tx, flags);
+ zap_name_t *zn = zap_name_alloc(zap);
for (int i = 0; i < nchunks; i++) {
mzap_ent_phys_t *mze = &mzp->mz_chunk[i];
if (mze->mze_name[0] == 0)
continue;
dprintf("adding %s=%llu\n",
mze->mze_name, (u_longlong_t)mze->mze_value);
- zap_name_t *zn = zap_name_alloc(zap, mze->mze_name, 0);
+ zap_name_init_str(zn, mze->mze_name, 0);
/* If we fail here, we would end up losing entries */
VERIFY0(fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd,
tag, tx));
zap = zn->zn_zap; /* fzap_add_cd() may change zap */
- zap_name_free(zn);
}
+ zap_name_free(zn);
vmem_free(mzp, sz);
*zapp = zap;
return (0);
@@ -714,7 +727,8 @@ mzap_create_impl(dnode_t *dn, int normflags, zap_flags_t flags, dmu_tx_t *tx)
if (flags != 0) {
zap_t *zap;
/* Only fat zap supports flags; upgrade immediately. */
- VERIFY0(zap_lockdir_impl(db, FTAG, tx, RW_WRITER,
+ VERIFY(dnode_add_ref(dn, FTAG));
+ VERIFY0(zap_lockdir_impl(dn, db, FTAG, tx, RW_WRITER,
B_FALSE, B_FALSE, &zap));
VERIFY0(mzap_upgrade(&zap, FTAG, tx, flags));
zap_unlockdir(zap, FTAG);
@@ -916,22 +930,23 @@ zap_count(objset_t *os, uint64_t zapobj, uint64_t *count)
* See also the comment above zap_entry_normalization_conflict().
*/
static boolean_t
-mzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze)
+mzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze,
+ zfs_btree_index_t *idx)
{
- int direction = AVL_BEFORE;
boolean_t allocdzn = B_FALSE;
+ mzap_ent_t *other;
+ zfs_btree_index_t oidx;
if (zap->zap_normflags == 0)
return (B_FALSE);
-again:
- for (mzap_ent_t *other = avl_walk(&zap->zap_m.zap_avl, mze, direction);
+ for (other = zfs_btree_prev(&zap->zap_m.zap_tree, idx, &oidx);
other && other->mze_hash == mze->mze_hash;
- other = avl_walk(&zap->zap_m.zap_avl, other, direction)) {
+ other = zfs_btree_prev(&zap->zap_m.zap_tree, &oidx, &oidx)) {
if (zn == NULL) {
- zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name,
- MT_NORMALIZE);
+ zn = zap_name_alloc_str(zap,
+ MZE_PHYS(zap, mze)->mze_name, MT_NORMALIZE);
allocdzn = B_TRUE;
}
if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) {
@@ -941,9 +956,20 @@ again:
}
}
- if (direction == AVL_BEFORE) {
- direction = AVL_AFTER;
- goto again;
+ for (other = zfs_btree_next(&zap->zap_m.zap_tree, idx, &oidx);
+ other && other->mze_hash == mze->mze_hash;
+ other = zfs_btree_next(&zap->zap_m.zap_tree, &oidx, &oidx)) {
+
+ if (zn == NULL) {
+ zn = zap_name_alloc_str(zap,
+ MZE_PHYS(zap, mze)->mze_name, MT_NORMALIZE);
+ allocdzn = B_TRUE;
+ }
+ if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) {
+ if (allocdzn)
+ zap_name_free(zn);
+ return (B_TRUE);
+ }
}
if (allocdzn)
@@ -971,7 +997,7 @@ zap_lookup_impl(zap_t *zap, const char *name,
{
int err = 0;
- zap_name_t *zn = zap_name_alloc(zap, name, mt);
+ zap_name_t *zn = zap_name_alloc_str(zap, name, mt);
if (zn == NULL)
return (SET_ERROR(ENOTSUP));
@@ -979,7 +1005,8 @@ zap_lookup_impl(zap_t *zap, const char *name,
err = fzap_lookup(zn, integer_size, num_integers, buf,
realname, rn_len, ncp);
} else {
- mzap_ent_t *mze = mze_find(zn);
+ zfs_btree_index_t idx;
+ mzap_ent_t *mze = mze_find(zn, &idx);
if (mze == NULL) {
err = SET_ERROR(ENOENT);
} else {
@@ -990,11 +1017,13 @@ 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);
+ zn, mze, &idx);
}
}
}
@@ -1031,7 +1060,7 @@ zap_prefetch(objset_t *os, uint64_t zapobj, const char *name)
err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
if (err)
return (err);
- zn = zap_name_alloc(zap, name, 0);
+ zn = zap_name_alloc_str(zap, name, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1134,7 +1163,7 @@ zap_length(objset_t *os, uint64_t zapobj, const char *name,
zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
if (err != 0)
return (err);
- zap_name_t *zn = zap_name_alloc(zap, name, 0);
+ zap_name_t *zn = zap_name_alloc_str(zap, name, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1142,7 +1171,8 @@ zap_length(objset_t *os, uint64_t zapobj, const char *name,
if (!zap->zap_ismicro) {
err = fzap_length(zn, integer_size, num_integers);
} else {
- mzap_ent_t *mze = mze_find(zn);
+ zfs_btree_index_t idx;
+ mzap_ent_t *mze = mze_find(zn, &idx);
if (mze == NULL) {
err = SET_ERROR(ENOENT);
} else {
@@ -1182,7 +1212,7 @@ static void
mzap_addent(zap_name_t *zn, uint64_t value)
{
zap_t *zap = zn->zn_zap;
- int start = zap->zap_m.zap_alloc_next;
+ uint16_t start = zap->zap_m.zap_alloc_next;
ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
@@ -1198,7 +1228,7 @@ mzap_addent(zap_name_t *zn, uint64_t value)
ASSERT(cd < zap_maxcd(zap));
again:
- for (int i = start; i < zap->zap_m.zap_num_chunks; i++) {
+ for (uint16_t i = start; i < zap->zap_m.zap_num_chunks; i++) {
mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i];
if (mze->mze_name[0] == 0) {
mze->mze_value = value;
@@ -1229,7 +1259,7 @@ zap_add_impl(zap_t *zap, const char *key,
const uint64_t *intval = val;
int err = 0;
- zap_name_t *zn = zap_name_alloc(zap, key, 0);
+ zap_name_t *zn = zap_name_alloc_str(zap, key, 0);
if (zn == NULL) {
zap_unlockdir(zap, tag);
return (SET_ERROR(ENOTSUP));
@@ -1247,7 +1277,8 @@ zap_add_impl(zap_t *zap, const char *key,
}
zap = zn->zn_zap; /* fzap_add() may change zap */
} else {
- if (mze_find(zn) != NULL) {
+ zfs_btree_index_t idx;
+ if (mze_find(zn, &idx) != NULL) {
err = SET_ERROR(EEXIST);
} else {
mzap_addent(zn, *intval);
@@ -1292,6 +1323,26 @@ zap_add_by_dnode(dnode_t *dn, const char *key,
return (err);
}
+static int
+zap_add_uint64_impl(zap_t *zap, const uint64_t *key,
+ int key_numints, int integer_size, uint64_t num_integers,
+ const void *val, dmu_tx_t *tx, const void *tag)
+{
+ int err;
+
+ zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints);
+ if (zn == NULL) {
+ zap_unlockdir(zap, tag);
+ return (SET_ERROR(ENOTSUP));
+ }
+ err = fzap_add(zn, integer_size, num_integers, val, tag, tx);
+ zap = zn->zn_zap; /* fzap_add() may change zap */
+ zap_name_free(zn);
+ if (zap != NULL) /* may be NULL if fzap_add() failed */
+ zap_unlockdir(zap, tag);
+ return (err);
+}
+
int
zap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
int key_numints, int integer_size, uint64_t num_integers,
@@ -1303,16 +1354,26 @@ zap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
if (err != 0)
return (err);
- zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints);
- if (zn == NULL) {
- zap_unlockdir(zap, FTAG);
- return (SET_ERROR(ENOTSUP));
- }
- err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx);
- zap = zn->zn_zap; /* fzap_add() may change zap */
- zap_name_free(zn);
- if (zap != NULL) /* may be NULL if fzap_add() failed */
- zap_unlockdir(zap, FTAG);
+ err = zap_add_uint64_impl(zap, key, key_numints,
+ integer_size, num_integers, val, tx, FTAG);
+ /* zap_add_uint64_impl() calls zap_unlockdir() */
+ return (err);
+}
+
+int
+zap_add_uint64_by_dnode(dnode_t *dn, const uint64_t *key,
+ int key_numints, int integer_size, uint64_t num_integers,
+ const void *val, dmu_tx_t *tx)
+{
+ zap_t *zap;
+
+ int err =
+ zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
+ if (err != 0)
+ return (err);
+ err = zap_add_uint64_impl(zap, key, key_numints,
+ integer_size, num_integers, val, tx, FTAG);
+ /* zap_add_uint64_impl() calls zap_unlockdir() */
return (err);
}
@@ -1327,7 +1388,7 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
if (err != 0)
return (err);
- zap_name_t *zn = zap_name_alloc(zap, name, 0);
+ zap_name_t *zn = zap_name_alloc_str(zap, name, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1348,7 +1409,8 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
}
zap = zn->zn_zap; /* fzap_update() may change zap */
} else {
- mzap_ent_t *mze = mze_find(zn);
+ zfs_btree_index_t idx;
+ mzap_ent_t *mze = mze_find(zn, &idx);
if (mze != NULL) {
MZE_PHYS(zap, mze)->mze_value = *intval;
} else {
@@ -1362,27 +1424,56 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
return (err);
}
-int
-zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
- int key_numints,
- int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
+static int
+zap_update_uint64_impl(zap_t *zap, const uint64_t *key, int key_numints,
+ int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx,
+ const void *tag)
{
- zap_t *zap;
+ int err;
- int err =
- zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
- if (err != 0)
- return (err);
zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints);
if (zn == NULL) {
- zap_unlockdir(zap, FTAG);
+ zap_unlockdir(zap, tag);
return (SET_ERROR(ENOTSUP));
}
- err = fzap_update(zn, integer_size, num_integers, val, FTAG, tx);
+ err = fzap_update(zn, integer_size, num_integers, val, tag, tx);
zap = zn->zn_zap; /* fzap_update() may change zap */
zap_name_free(zn);
if (zap != NULL) /* may be NULL if fzap_upgrade() failed */
- zap_unlockdir(zap, FTAG);
+ zap_unlockdir(zap, tag);
+ return (err);
+}
+
+int
+zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
+ int key_numints, int integer_size, uint64_t num_integers, const void *val,
+ dmu_tx_t *tx)
+{
+ zap_t *zap;
+
+ int err =
+ zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
+ if (err != 0)
+ return (err);
+ err = zap_update_uint64_impl(zap, key, key_numints,
+ integer_size, num_integers, val, tx, FTAG);
+ /* zap_update_uint64_impl() calls zap_unlockdir() */
+ return (err);
+}
+
+int
+zap_update_uint64_by_dnode(dnode_t *dn, const uint64_t *key, int key_numints,
+ int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
+{
+ zap_t *zap;
+
+ int err =
+ zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
+ if (err != 0)
+ return (err);
+ err = zap_update_uint64_impl(zap, key, key_numints,
+ integer_size, num_integers, val, tx, FTAG);
+ /* zap_update_uint64_impl() calls zap_unlockdir() */
return (err);
}
@@ -1398,20 +1489,20 @@ zap_remove_impl(zap_t *zap, const char *name,
{
int err = 0;
- zap_name_t *zn = zap_name_alloc(zap, name, mt);
+ zap_name_t *zn = zap_name_alloc_str(zap, name, mt);
if (zn == NULL)
return (SET_ERROR(ENOTSUP));
if (!zap->zap_ismicro) {
err = fzap_remove(zn, tx);
} else {
- mzap_ent_t *mze = mze_find(zn);
+ zfs_btree_index_t idx;
+ mzap_ent_t *mze = mze_find(zn, &idx);
if (mze == NULL) {
err = SET_ERROR(ENOENT);
} else {
zap->zap_m.zap_num_entries--;
- memset(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid], 0,
- sizeof (mzap_ent_phys_t));
- mze_remove(zap, mze);
+ memset(MZE_PHYS(zap, mze), 0, sizeof (mzap_ent_phys_t));
+ zfs_btree_remove_idx(&zap->zap_m.zap_tree, &idx);
}
}
zap_name_free(zn);
@@ -1447,6 +1538,23 @@ zap_remove_by_dnode(dnode_t *dn, const char *name, dmu_tx_t *tx)
return (err);
}
+static int
+zap_remove_uint64_impl(zap_t *zap, const uint64_t *key, int key_numints,
+ dmu_tx_t *tx, const void *tag)
+{
+ int err;
+
+ zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints);
+ if (zn == NULL) {
+ zap_unlockdir(zap, tag);
+ return (SET_ERROR(ENOTSUP));
+ }
+ err = fzap_remove(zn, tx);
+ zap_name_free(zn);
+ zap_unlockdir(zap, tag);
+ return (err);
+}
+
int
zap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
int key_numints, dmu_tx_t *tx)
@@ -1457,14 +1565,23 @@ zap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap);
if (err != 0)
return (err);
- zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints);
- if (zn == NULL) {
- zap_unlockdir(zap, FTAG);
- return (SET_ERROR(ENOTSUP));
- }
- err = fzap_remove(zn, tx);
- zap_name_free(zn);
- zap_unlockdir(zap, FTAG);
+ err = zap_remove_uint64_impl(zap, key, key_numints, tx, FTAG);
+ /* zap_remove_uint64_impl() calls zap_unlockdir() */
+ return (err);
+}
+
+int
+zap_remove_uint64_by_dnode(dnode_t *dn, const uint64_t *key, int key_numints,
+ dmu_tx_t *tx)
+{
+ zap_t *zap;
+
+ int err =
+ zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap);
+ if (err != 0)
+ return (err);
+ err = zap_remove_uint64_impl(zap, key, key_numints, tx, FTAG);
+ /* zap_remove_uint64_impl() calls zap_unlockdir() */
return (err);
}
@@ -1582,29 +1699,30 @@ zap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za)
if (!zc->zc_zap->zap_ismicro) {
err = fzap_cursor_retrieve(zc->zc_zap, zc, za);
} else {
- avl_index_t idx;
+ zfs_btree_index_t idx;
mzap_ent_t mze_tofind;
- mze_tofind.mze_hash = zc->zc_hash;
+ mze_tofind.mze_hash = zc->zc_hash >> 32;
mze_tofind.mze_cd = zc->zc_cd;
- mzap_ent_t *mze =
- avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx);
+ mzap_ent_t *mze = zfs_btree_find(&zc->zc_zap->zap_m.zap_tree,
+ &mze_tofind, &idx);
if (mze == NULL) {
- mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl,
- idx, AVL_AFTER);
+ mze = zfs_btree_next(&zc->zc_zap->zap_m.zap_tree,
+ &idx, &idx);
}
if (mze) {
mzap_ent_phys_t *mzep = MZE_PHYS(zc->zc_zap, mze);
ASSERT3U(mze->mze_cd, ==, mzep->mze_cd);
za->za_normalization_conflict =
- mzap_normalization_conflict(zc->zc_zap, NULL, mze);
+ mzap_normalization_conflict(zc->zc_zap, NULL,
+ mze, &idx);
za->za_integer_length = 8;
za->za_num_integers = 1;
za->za_first_integer = mzep->mze_value;
(void) strlcpy(za->za_name, mzep->mze_name,
sizeof (za->za_name));
- zc->zc_hash = mze->mze_hash;
+ zc->zc_hash = (uint64_t)mze->mze_hash << 32;
zc->zc_cd = mze->mze_cd;
err = 0;
} else {
@@ -1669,14 +1787,17 @@ EXPORT_SYMBOL(zap_prefetch_uint64);
EXPORT_SYMBOL(zap_add);
EXPORT_SYMBOL(zap_add_by_dnode);
EXPORT_SYMBOL(zap_add_uint64);
+EXPORT_SYMBOL(zap_add_uint64_by_dnode);
EXPORT_SYMBOL(zap_update);
EXPORT_SYMBOL(zap_update_uint64);
+EXPORT_SYMBOL(zap_update_uint64_by_dnode);
EXPORT_SYMBOL(zap_length);
EXPORT_SYMBOL(zap_length_uint64);
EXPORT_SYMBOL(zap_remove);
EXPORT_SYMBOL(zap_remove_by_dnode);
EXPORT_SYMBOL(zap_remove_norm);
EXPORT_SYMBOL(zap_remove_uint64);
+EXPORT_SYMBOL(zap_remove_uint64_by_dnode);
EXPORT_SYMBOL(zap_count);
EXPORT_SYMBOL(zap_value_search);
EXPORT_SYMBOL(zap_join);
@@ -1695,4 +1816,8 @@ EXPORT_SYMBOL(zap_cursor_advance);
EXPORT_SYMBOL(zap_cursor_serialize);
EXPORT_SYMBOL(zap_cursor_init_serialized);
EXPORT_SYMBOL(zap_get_stats);
+
+/* CSTYLED */
+ZFS_MODULE_PARAM(zfs, , zap_micro_max_size, INT, ZMOD_RW,
+ "Maximum micro ZAP size, before converting to a fat ZAP, in bytes");
#endif
diff --git a/module/zfs/zcp.c b/module/zfs/zcp.c
index fe90242ca40d..959404f665ab 100644
--- a/module/zfs/zcp.c
+++ b/module/zfs/zcp.c
@@ -109,8 +109,8 @@
#define ZCP_NVLIST_MAX_DEPTH 20
static const uint64_t zfs_lua_check_instrlimit_interval = 100;
-unsigned long zfs_lua_max_instrlimit = ZCP_MAX_INSTRLIMIT;
-unsigned long zfs_lua_max_memlimit = ZCP_MAX_MEMLIMIT;
+uint64_t zfs_lua_max_instrlimit = ZCP_MAX_INSTRLIMIT;
+uint64_t zfs_lua_max_memlimit = ZCP_MAX_MEMLIMIT;
/*
* Forward declarations for mutually recursive functions
@@ -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;
@@ -544,7 +544,7 @@ zcp_nvpair_value_to_lua(lua_State *state, nvpair_t *pair,
fnvpair_value_nvlist(pair), errbuf, errbuf_len);
break;
case DATA_TYPE_STRING_ARRAY: {
- char **strarr;
+ const char **strarr;
uint_t nelem;
(void) nvpair_value_string_array(pair, &strarr, &nelem);
lua_newtable(state);
@@ -958,12 +958,12 @@ zcp_eval_impl(dmu_tx_t *tx, zcp_run_info_t *ri)
}
static void
-zcp_pool_error(zcp_run_info_t *ri, const char *poolname)
+zcp_pool_error(zcp_run_info_t *ri, const char *poolname, int error)
{
ri->zri_result = SET_ERROR(ECHRNG);
lua_settop(ri->zri_state, 0);
- (void) lua_pushfstring(ri->zri_state, "Could not open pool: %s",
- poolname);
+ (void) lua_pushfstring(ri->zri_state, "Could not open pool: %s "
+ "errno: %d", poolname, error);
zcp_convert_return_values(ri->zri_state, ri->zri_outnvl,
ZCP_RET_ERROR, &ri->zri_result);
@@ -1013,7 +1013,7 @@ zcp_eval_open(zcp_run_info_t *ri, const char *poolname)
error = dsl_pool_hold(poolname, FTAG, &dp);
if (error != 0) {
- zcp_pool_error(ri, poolname);
+ zcp_pool_error(ri, poolname, error);
return;
}
@@ -1159,7 +1159,7 @@ zcp_eval(const char *poolname, const char *program, boolean_t sync,
err = dsl_sync_task_sig(poolname, NULL, zcp_eval_sync,
zcp_eval_sig, &runinfo, 0, ZFS_SPACE_CHECK_ZCP_EVAL);
if (err != 0)
- zcp_pool_error(&runinfo, poolname);
+ zcp_pool_error(&runinfo, poolname, err);
} else {
zcp_eval_open(&runinfo, poolname);
}
@@ -1443,8 +1443,8 @@ zcp_parse_args(lua_State *state, const char *fname, const zcp_arg_t *pargs,
}
}
-ZFS_MODULE_PARAM(zfs_lua, zfs_lua_, max_instrlimit, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_lua, zfs_lua_, max_instrlimit, U64, ZMOD_RW,
"Max instruction limit that can be specified for a channel program");
-ZFS_MODULE_PARAM(zfs_lua, zfs_lua_, max_memlimit, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_lua, zfs_lua_, max_memlimit, U64, ZMOD_RW,
"Max memory limit that can be specified for a channel program");
diff --git a/module/zfs/zcp_get.c b/module/zfs/zcp_get.c
index af495ce85140..6fd45151d92a 100644
--- a/module/zfs/zcp_get.c
+++ b/module/zfs/zcp_get.c
@@ -391,7 +391,7 @@ get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname,
dsl_dataset_crypt_stats(ds, nvl);
if (nvlist_lookup_nvlist(nvl, zfs_prop_to_name(zfs_prop),
&propval) == 0) {
- char *source;
+ const char *source;
(void) nvlist_lookup_uint64(propval, ZPROP_VALUE,
&numval);
@@ -403,6 +403,10 @@ get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname,
break;
}
+ case ZFS_PROP_SNAPSHOTS_CHANGED:
+ numval = dsl_dir_snap_cmtime(ds->ds_dir).tv_sec;
+ break;
+
default:
/* Did not match these props, check in the dsl_dir */
error = get_dsl_dir_prop(ds, zfs_prop, &numval);
@@ -463,11 +467,13 @@ get_zap_prop(lua_State *state, dsl_dataset_t *ds, zfs_prop_t zfs_prop)
} else {
error = dsl_prop_get_ds(ds, prop_name, sizeof (numval),
1, &numval, setpoint);
-
+ if (error != 0)
+ goto out;
#ifdef _KERNEL
/* Fill in temporary value for prop, if applicable */
(void) zfs_get_temporary_prop(ds, zfs_prop, &numval, setpoint);
#else
+ kmem_free(strval, ZAP_MAXVALUELEN);
return (luaL_error(state,
"temporary properties only supported in kernel mode",
prop_name));
@@ -484,6 +490,7 @@ get_zap_prop(lua_State *state, dsl_dataset_t *ds, zfs_prop_t zfs_prop)
(void) lua_pushnumber(state, numval);
}
}
+out:
kmem_free(strval, ZAP_MAXVALUELEN);
if (error == 0)
get_prop_src(state, setpoint, zfs_prop);
@@ -603,8 +610,7 @@ parse_userquota_prop(const char *prop_name, zfs_userquota_prop_t *type,
*/
int domain_len = strrchr(cp, '-') - cp;
domain_val = kmem_alloc(domain_len + 1, KM_SLEEP);
- (void) strncpy(domain_val, cp, domain_len);
- domain_val[domain_len] = '\0';
+ (void) strlcpy(domain_val, cp, domain_len + 1);
cp += domain_len + 1;
(void) ddi_strtoll(cp, &end, 10, (longlong_t *)rid);
diff --git a/module/zfs/zcp_iter.c b/module/zfs/zcp_iter.c
index ed575738fc8b..2da0bf9740e5 100644
--- a/module/zfs/zcp_iter.c
+++ b/module/zfs/zcp_iter.c
@@ -333,7 +333,7 @@ zcp_user_props_list_gc(lua_State *state)
static int
zcp_user_props_iter(lua_State *state)
{
- char *source, *val;
+ const char *source, *val;
nvlist_t *nvprop;
nvlist_t **props = lua_touserdata(state, lua_upvalueindex(1));
nvpair_t *pair = lua_touserdata(state, lua_upvalueindex(2));
diff --git a/module/zfs/zcp_synctask.c b/module/zfs/zcp_synctask.c
index 24210117eca0..058910054d97 100644
--- a/module/zfs/zcp_synctask.c
+++ b/module/zfs/zcp_synctask.c
@@ -302,6 +302,42 @@ zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details)
return (err);
}
+static int zcp_synctask_rename_snapshot(lua_State *, boolean_t, nvlist_t *);
+static const zcp_synctask_info_t zcp_synctask_rename_snapshot_info = {
+ .name = "rename_snapshot",
+ .func = zcp_synctask_rename_snapshot,
+ .pargs = {
+ {.za_name = "filesystem | volume", .za_lua_type = LUA_TSTRING },
+ {.za_name = "oldsnapname", .za_lua_type = LUA_TSTRING },
+ {.za_name = "newsnapname", .za_lua_type = LUA_TSTRING },
+ {NULL, 0}
+ },
+ .space_check = ZFS_SPACE_CHECK_RESERVED,
+ .blocks_modified = 1
+};
+
+static int
+zcp_synctask_rename_snapshot(lua_State *state, boolean_t sync,
+ nvlist_t *err_details)
+{
+ (void) err_details;
+ int err;
+ const char *fsname = lua_tostring(state, 1);
+ const char *oldsnapname = lua_tostring(state, 2);
+ const char *newsnapname = lua_tostring(state, 3);
+
+ struct dsl_dataset_rename_snapshot_arg ddrsa = { 0 };
+ ddrsa.ddrsa_fsname = fsname;
+ ddrsa.ddrsa_oldsnapname = oldsnapname;
+ ddrsa.ddrsa_newsnapname = newsnapname;
+ ddrsa.ddrsa_recursive = B_FALSE;
+
+ err = zcp_sync_task(state, dsl_dataset_rename_snapshot_check,
+ dsl_dataset_rename_snapshot_sync, &ddrsa, sync, NULL);
+
+ return (err);
+}
+
static int zcp_synctask_inherit_prop(lua_State *, boolean_t,
nvlist_t *err_details);
static const zcp_synctask_info_t zcp_synctask_inherit_prop_info = {
@@ -529,6 +565,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync)
&zcp_synctask_promote_info,
&zcp_synctask_rollback_info,
&zcp_synctask_snapshot_info,
+ &zcp_synctask_rename_snapshot_info,
&zcp_synctask_inherit_prop_info,
&zcp_synctask_bookmark_info,
&zcp_synctask_set_prop_info,
diff --git a/module/zfs/zfeature.c b/module/zfs/zfeature.c
index fc9167aa6611..1d25bc406866 100644
--- a/module/zfs/zfeature.c
+++ b/module/zfs/zfeature.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zfs_byteswap.c b/module/zfs/zfs_byteswap.c
index fcedf295c1f7..8666883f09a2 100644
--- a/module/zfs/zfs_byteswap.c
+++ b/module/zfs/zfs_byteswap.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zfs_chksum.c b/module/zfs/zfs_chksum.c
index 639784287d72..acedeab7a163 100644
--- a/module/zfs/zfs_chksum.c
+++ b/module/zfs/zfs_chksum.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,18 +20,19 @@
*/
/*
- * Copyright (c) 2021 Tino Reichardt <milky-zfs@mcmilk.de>
+ * Copyright (c) 2021-2022 Tino Reichardt <milky-zfs@mcmilk.de>
*/
-#include <sys/types.h>
-#include <sys/spa.h>
#include <sys/zio_checksum.h>
#include <sys/zfs_context.h>
#include <sys/zfs_chksum.h>
+#include <sys/zfs_impl.h>
#include <sys/blake3.h>
+#include <sys/sha2.h>
-static kstat_t *chksum_kstat = NULL;
+/* limit benchmarking to max 256KiB, when EdonR is slower then this: */
+#define LIMIT_PERF_MBS 300
typedef struct {
const char *name;
@@ -43,83 +44,89 @@ typedef struct {
uint64_t bs256k;
uint64_t bs1m;
uint64_t bs4m;
+ uint64_t bs16m;
zio_cksum_salt_t salt;
zio_checksum_t *(func);
zio_checksum_tmpl_init_t *(init);
zio_checksum_tmpl_free_t *(free);
} chksum_stat_t;
-static int chksum_stat_cnt = 0;
static chksum_stat_t *chksum_stat_data = 0;
+static int chksum_stat_cnt = 0;
+static kstat_t *chksum_kstat = NULL;
/*
- * i3-1005G1 test output:
+ * Sample output on i3-1005G1 System:
*
- * implementation 1k 4k 16k 64k 256k 1m 4m
- * fletcher-4 5421 15001 26468 32555 34720 32801 18847
- * edonr-generic 1196 1602 1761 1749 1762 1759 1751
- * skein-generic 546 591 608 615 619 612 616
- * sha256-generic 246 270 274 274 277 275 276
- * sha256-avx 262 296 304 307 307 307 306
- * sha256-sha-ni 769 1072 1172 1220 1219 1232 1228
- * sha256-openssl 240 300 316 314 304 285 276
- * sha512-generic 333 374 385 392 391 393 392
- * sha512-openssl 353 441 467 476 472 467 426
- * sha512-avx 362 444 473 475 479 476 478
- * sha512-avx2 394 500 530 538 543 545 542
- * blake3-generic 308 313 313 313 312 313 312
- * blake3-sse2 402 1289 1423 1446 1432 1458 1413
- * blake3-sse41 427 1470 1625 1704 1679 1607 1629
- * blake3-avx2 428 1920 3095 3343 3356 3318 3204
- * blake3-avx512 473 2687 4905 5836 5844 5643 5374
+ * implementation 1k 4k 16k 64k 256k 1m 4m 16m
+ * edonr-generic 1278 1625 1769 1776 1783 1778 1771 1767
+ * skein-generic 548 594 613 623 621 623 621 486
+ * sha256-generic 255 270 281 278 279 281 283 283
+ * sha256-x64 288 310 316 317 318 317 317 316
+ * sha256-ssse3 304 342 351 355 356 357 356 356
+ * sha256-avx 311 348 359 362 362 363 363 362
+ * sha256-avx2 330 378 389 395 395 395 395 395
+ * sha256-shani 908 1127 1212 1230 1233 1234 1223 1230
+ * sha512-generic 359 409 431 427 429 430 428 423
+ * sha512-x64 420 473 490 496 497 497 496 495
+ * sha512-avx 406 522 546 560 560 560 556 560
+ * sha512-avx2 464 568 601 606 609 610 607 608
+ * blake3-generic 330 327 324 323 324 320 323 322
+ * blake3-sse2 424 1366 1449 1468 1458 1453 1395 1408
+ * blake3-sse41 453 1554 1658 1703 1689 1669 1622 1630
+ * blake3-avx2 452 2013 3225 3351 3356 3261 3076 3101
+ * blake3-avx512 498 2869 5269 5926 5872 5643 5014 5005
*/
static int
-chksum_stat_kstat_headers(char *buf, size_t size)
+chksum_kstat_headers(char *buf, size_t size)
{
ssize_t off = 0;
- off += snprintf(buf + off, size, "%-23s", "implementation");
- off += snprintf(buf + off, size - off, "%8s", "1k");
- off += snprintf(buf + off, size - off, "%8s", "4k");
- off += snprintf(buf + off, size - off, "%8s", "16k");
- off += snprintf(buf + off, size - off, "%8s", "64k");
- off += snprintf(buf + off, size - off, "%8s", "256k");
- off += snprintf(buf + off, size - off, "%8s", "1m");
- (void) snprintf(buf + off, size - off, "%8s\n", "4m");
+ off += kmem_scnprintf(buf + off, size, "%-23s", "implementation");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "1k");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "4k");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "16k");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "64k");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "256k");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "1m");
+ off += kmem_scnprintf(buf + off, size - off, "%8s", "4m");
+ (void) kmem_scnprintf(buf + off, size - off, "%8s\n", "16m");
return (0);
}
static int
-chksum_stat_kstat_data(char *buf, size_t size, void *data)
+chksum_kstat_data(char *buf, size_t size, void *data)
{
chksum_stat_t *cs;
ssize_t off = 0;
char b[24];
cs = (chksum_stat_t *)data;
- snprintf(b, 23, "%s-%s", cs->name, cs->impl);
- off += snprintf(buf + off, size - off, "%-23s", b);
- off += snprintf(buf + off, size - off, "%8llu",
+ kmem_scnprintf(b, 23, "%s-%s", cs->name, cs->impl);
+ off += kmem_scnprintf(buf + off, size - off, "%-23s", b);
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs1k);
- off += snprintf(buf + off, size - off, "%8llu",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs4k);
- off += snprintf(buf + off, size - off, "%8llu",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs16k);
- off += snprintf(buf + off, size - off, "%8llu",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs64k);
- off += snprintf(buf + off, size - off, "%8llu",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs256k);
- off += snprintf(buf + off, size - off, "%8llu",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs1m);
- (void) snprintf(buf + off, size - off, "%8llu\n",
+ off += kmem_scnprintf(buf + off, size - off, "%8llu",
(u_longlong_t)cs->bs4m);
+ (void) kmem_scnprintf(buf + off, size - off, "%8llu\n",
+ (u_longlong_t)cs->bs16m);
return (0);
}
static void *
-chksum_stat_kstat_addr(kstat_t *ksp, loff_t n)
+chksum_kstat_addr(kstat_t *ksp, loff_t n)
{
if (n < chksum_stat_cnt)
ksp->ks_private = (void *)(chksum_stat_data + n);
@@ -153,6 +160,8 @@ chksum_run(chksum_stat_t *cs, abd_t *abd, void *ctx, int round,
size = 1<<20; loops = 4; break;
case 7: /* 4m */
size = 1<<22; loops = 1; break;
+ case 8: /* 16m */
+ size = 1<<24; loops = 1; break;
}
kpreempt_disable();
@@ -170,33 +179,57 @@ chksum_run(chksum_stat_t *cs, abd_t *abd, void *ctx, int round,
*result = run_bw/1024/1024; /* MiB/s */
}
+#define LIMIT_INIT 0
+#define LIMIT_NEEDED 1
+#define LIMIT_NOLIMIT 2
+
static void
chksum_benchit(chksum_stat_t *cs)
{
abd_t *abd;
void *ctx = 0;
void *salt = &cs->salt.zcs_bytes;
+ static int chksum_stat_limit = LIMIT_INIT;
- /* allocate test memory via default abd interface */
- abd = abd_alloc_linear(1<<22, B_FALSE);
memset(salt, 0, sizeof (cs->salt.zcs_bytes));
- if (cs->init) {
+ if (cs->init)
ctx = cs->init(&cs->salt);
- }
+ /* allocate test memory via abd linear interface */
+ abd = abd_alloc_linear(1<<20, B_FALSE);
chksum_run(cs, abd, ctx, 1, &cs->bs1k);
chksum_run(cs, abd, ctx, 2, &cs->bs4k);
chksum_run(cs, abd, ctx, 3, &cs->bs16k);
chksum_run(cs, abd, ctx, 4, &cs->bs64k);
chksum_run(cs, abd, ctx, 5, &cs->bs256k);
+
+ /* check if we ran on a slow cpu */
+ if (chksum_stat_limit == LIMIT_INIT) {
+ if (cs->bs1k < LIMIT_PERF_MBS) {
+ chksum_stat_limit = LIMIT_NEEDED;
+ } else {
+ chksum_stat_limit = LIMIT_NOLIMIT;
+ }
+ }
+
+ /* skip benchmarks >= 1MiB when the CPU is to slow */
+ if (chksum_stat_limit == LIMIT_NEEDED)
+ goto abort;
+
chksum_run(cs, abd, ctx, 6, &cs->bs1m);
+ abd_free(abd);
+
+ /* allocate test memory via abd non linear interface */
+ abd = abd_alloc(1<<24, B_FALSE);
chksum_run(cs, abd, ctx, 7, &cs->bs4m);
+ chksum_run(cs, abd, ctx, 8, &cs->bs16m);
+
+abort:
+ abd_free(abd);
/* free up temp memory */
- if (cs->free) {
+ if (cs->free)
cs->free(ctx);
- }
- abd_free(abd);
}
/*
@@ -205,24 +238,30 @@ chksum_benchit(chksum_stat_t *cs)
static void
chksum_benchmark(void)
{
-
#ifndef _KERNEL
/* we need the benchmark only for the kernel module */
return;
#endif
chksum_stat_t *cs;
- int cbid = 0, id;
- uint64_t max = 0;
-
- /* space for the benchmark times */
- chksum_stat_cnt = 4;
- chksum_stat_cnt += blake3_get_impl_count();
- chksum_stat_data = (chksum_stat_t *)kmem_zalloc(
+ uint64_t max;
+ uint32_t id, cbid = 0, id_save;
+ const zfs_impl_t *blake3 = zfs_impl_get_ops("blake3");
+ const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256");
+ const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512");
+
+ /* count implementations */
+ chksum_stat_cnt = 2;
+ chksum_stat_cnt += sha256->getcnt();
+ chksum_stat_cnt += sha512->getcnt();
+ chksum_stat_cnt += blake3->getcnt();
+ chksum_stat_data = kmem_zalloc(
sizeof (chksum_stat_t) * chksum_stat_cnt, KM_SLEEP);
- /* edonr */
+ /* edonr - needs to be the first one here (slow CPU check) */
cs = &chksum_stat_data[cbid++];
+
+ /* edonr */
cs->init = abd_checksum_edonr_tmpl_init;
cs->func = abd_checksum_edonr_native;
cs->free = abd_checksum_edonr_tmpl_free;
@@ -240,38 +279,58 @@ chksum_benchmark(void)
chksum_benchit(cs);
/* sha256 */
- cs = &chksum_stat_data[cbid++];
- cs->init = 0;
- cs->func = abd_checksum_SHA256;
- cs->free = 0;
- cs->name = "sha256";
- cs->impl = "generic";
- chksum_benchit(cs);
+ id_save = sha256->getid();
+ for (max = 0, id = 0; id < sha256->getcnt(); id++) {
+ sha256->setid(id);
+ cs = &chksum_stat_data[cbid++];
+ cs->init = 0;
+ cs->func = abd_checksum_sha256;
+ cs->free = 0;
+ cs->name = sha256->name;
+ cs->impl = sha256->getname();
+ chksum_benchit(cs);
+ if (cs->bs256k > max) {
+ max = cs->bs256k;
+ sha256->set_fastest(id);
+ }
+ }
+ sha256->setid(id_save);
/* sha512 */
- cs = &chksum_stat_data[cbid++];
- cs->init = 0;
- cs->func = abd_checksum_SHA512_native;
- cs->free = 0;
- cs->name = "sha512";
- cs->impl = "generic";
- chksum_benchit(cs);
+ id_save = sha512->getid();
+ for (max = 0, id = 0; id < sha512->getcnt(); id++) {
+ sha512->setid(id);
+ cs = &chksum_stat_data[cbid++];
+ cs->init = 0;
+ cs->func = abd_checksum_sha512_native;
+ cs->free = 0;
+ cs->name = sha512->name;
+ cs->impl = sha512->getname();
+ chksum_benchit(cs);
+ if (cs->bs256k > max) {
+ max = cs->bs256k;
+ sha512->set_fastest(id);
+ }
+ }
+ sha512->setid(id_save);
/* blake3 */
- for (id = 0; id < blake3_get_impl_count(); id++) {
- blake3_set_impl_id(id);
+ id_save = blake3->getid();
+ for (max = 0, id = 0; id < blake3->getcnt(); id++) {
+ blake3->setid(id);
cs = &chksum_stat_data[cbid++];
cs->init = abd_checksum_blake3_tmpl_init;
cs->func = abd_checksum_blake3_native;
cs->free = abd_checksum_blake3_tmpl_free;
- cs->name = "blake3";
- cs->impl = blake3_get_impl_name();
+ cs->name = blake3->name;
+ cs->impl = blake3->getname();
chksum_benchit(cs);
if (cs->bs256k > max) {
max = cs->bs256k;
- blake3_set_impl_fastest(id);
+ blake3->set_fastest(id);
}
}
+ blake3->setid(id_save);
}
void
@@ -292,14 +351,11 @@ chksum_init(void)
chksum_kstat->ks_data = NULL;
chksum_kstat->ks_ndata = UINT32_MAX;
kstat_set_raw_ops(chksum_kstat,
- chksum_stat_kstat_headers,
- chksum_stat_kstat_data,
- chksum_stat_kstat_addr);
+ chksum_kstat_headers,
+ chksum_kstat_data,
+ chksum_kstat_addr);
kstat_install(chksum_kstat);
}
-
- /* setup implementations */
- blake3_setup_impl();
}
void
diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c
index adc9f4bc5ecb..2f43c4aa41b8 100644
--- a/module/zfs/zfs_fm.c
+++ b/module/zfs/zfs_fm.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -200,6 +200,48 @@ recent_events_compare(const void *a, const void *b)
return (0);
}
+/*
+ * workaround: vdev properties don't have inheritance
+ */
+static uint64_t
+vdev_prop_get_inherited(vdev_t *vd, vdev_prop_t prop)
+{
+ uint64_t propdef, propval;
+
+ propdef = vdev_prop_default_numeric(prop);
+ switch (prop) {
+ case VDEV_PROP_CHECKSUM_N:
+ propval = vd->vdev_checksum_n;
+ break;
+ case VDEV_PROP_CHECKSUM_T:
+ propval = vd->vdev_checksum_t;
+ break;
+ case VDEV_PROP_IO_N:
+ propval = vd->vdev_io_n;
+ break;
+ case VDEV_PROP_IO_T:
+ propval = vd->vdev_io_t;
+ break;
+ case VDEV_PROP_SLOW_IO_N:
+ propval = vd->vdev_slow_io_n;
+ break;
+ case VDEV_PROP_SLOW_IO_T:
+ propval = vd->vdev_slow_io_t;
+ break;
+ default:
+ propval = propdef;
+ break;
+ }
+
+ if (propval != propdef)
+ return (propval);
+
+ if (vd->vdev_parent == NULL)
+ return (propdef);
+
+ return (vdev_prop_get_inherited(vd->vdev_parent, prop));
+}
+
static void zfs_ereport_schedule_cleaner(void);
/*
@@ -253,7 +295,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 +318,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++;
}
}
@@ -664,6 +704,69 @@ zfs_ereport_start(nvlist_t **ereport_out, nvlist_t **detector_out,
DATA_TYPE_UINT64, zb->zb_blkid, NULL);
}
+ /*
+ * Payload for tuning the zed
+ */
+ if (vd != NULL && strcmp(subclass, FM_EREPORT_ZFS_CHECKSUM) == 0) {
+ uint64_t cksum_n, cksum_t;
+
+ cksum_n = vdev_prop_get_inherited(vd, VDEV_PROP_CHECKSUM_N);
+ if (cksum_n != vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_N))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N,
+ DATA_TYPE_UINT64,
+ cksum_n,
+ NULL);
+
+ cksum_t = vdev_prop_get_inherited(vd, VDEV_PROP_CHECKSUM_T);
+ if (cksum_t != vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_T))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T,
+ DATA_TYPE_UINT64,
+ cksum_t,
+ NULL);
+ }
+
+ if (vd != NULL && strcmp(subclass, FM_EREPORT_ZFS_IO) == 0) {
+ uint64_t io_n, io_t;
+
+ io_n = vdev_prop_get_inherited(vd, VDEV_PROP_IO_N);
+ if (io_n != vdev_prop_default_numeric(VDEV_PROP_IO_N))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N,
+ DATA_TYPE_UINT64,
+ io_n,
+ NULL);
+
+ io_t = vdev_prop_get_inherited(vd, VDEV_PROP_IO_T);
+ if (io_t != vdev_prop_default_numeric(VDEV_PROP_IO_T))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T,
+ DATA_TYPE_UINT64,
+ io_t,
+ NULL);
+ }
+
+ if (vd != NULL && strcmp(subclass, FM_EREPORT_ZFS_DELAY) == 0) {
+ uint64_t slow_io_n, slow_io_t;
+
+ slow_io_n = vdev_prop_get_inherited(vd, VDEV_PROP_SLOW_IO_N);
+ if (slow_io_n != vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_N))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_N,
+ DATA_TYPE_UINT64,
+ slow_io_n,
+ NULL);
+
+ slow_io_t = vdev_prop_get_inherited(vd, VDEV_PROP_SLOW_IO_T);
+ if (slow_io_t != vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_T))
+ fm_payload_set(ereport,
+ FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_T,
+ DATA_TYPE_UINT64,
+ slow_io_t,
+ NULL);
+ }
+
mutex_exit(&spa->spa_errlist_lock);
*ereport_out = ereport;
@@ -677,10 +780,6 @@ zfs_ereport_start(nvlist_t **ereport_out, nvlist_t **detector_out,
#define MAX_RANGES 16
typedef struct zfs_ecksum_info {
- /* histograms of set and cleared bits by bit number in a 64-bit word */
- uint32_t zei_histogram_set[sizeof (uint64_t) * NBBY];
- uint32_t zei_histogram_cleared[sizeof (uint64_t) * NBBY];
-
/* inline arrays of bits set and cleared. */
uint64_t zei_bits_set[ZFM_MAX_INLINE];
uint64_t zei_bits_cleared[ZFM_MAX_INLINE];
@@ -704,7 +803,7 @@ typedef struct zfs_ecksum_info {
} zfs_ecksum_info_t;
static void
-update_histogram(uint64_t value_arg, uint32_t *hist, uint32_t *count)
+update_bad_bits(uint64_t value_arg, uint32_t *count)
{
size_t i;
size_t bits = 0;
@@ -712,10 +811,8 @@ update_histogram(uint64_t value_arg, uint32_t *hist, uint32_t *count)
/* We store the bits in big-endian (largest-first) order */
for (i = 0; i < 64; i++) {
- if (value & (1ull << i)) {
- hist[63 - i]++;
+ if (value & (1ull << i))
++bits;
- }
}
/* update the count of bits changed */
*count += bits;
@@ -843,14 +940,6 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
if (info != NULL && info->zbc_has_cksum) {
fm_payload_set(ereport,
- FM_EREPORT_PAYLOAD_ZFS_CKSUM_EXPECTED,
- DATA_TYPE_UINT64_ARRAY,
- sizeof (info->zbc_expected) / sizeof (uint64_t),
- (uint64_t *)&info->zbc_expected,
- FM_EREPORT_PAYLOAD_ZFS_CKSUM_ACTUAL,
- DATA_TYPE_UINT64_ARRAY,
- sizeof (info->zbc_actual) / sizeof (uint64_t),
- (uint64_t *)&info->zbc_actual,
FM_EREPORT_PAYLOAD_ZFS_CKSUM_ALGO,
DATA_TYPE_STRING,
info->zbc_checksum_name,
@@ -933,10 +1022,8 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
offset++;
}
- update_histogram(set, eip->zei_histogram_set,
- &eip->zei_range_sets[range]);
- update_histogram(cleared, eip->zei_histogram_cleared,
- &eip->zei_range_clears[range]);
+ update_bad_bits(set, &eip->zei_range_sets[range]);
+ update_bad_bits(cleared, &eip->zei_range_clears[range]);
}
/* convert to byte offsets */
@@ -972,15 +1059,6 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
DATA_TYPE_UINT8_ARRAY,
inline_size, (uint8_t *)eip->zei_bits_cleared,
NULL);
- } else {
- fm_payload_set(ereport,
- FM_EREPORT_PAYLOAD_ZFS_BAD_SET_HISTOGRAM,
- DATA_TYPE_UINT32_ARRAY,
- NBBY * sizeof (uint64_t), eip->zei_histogram_set,
- FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_HISTOGRAM,
- DATA_TYPE_UINT32_ARRAY,
- NBBY * sizeof (uint64_t), eip->zei_histogram_cleared,
- NULL);
}
return (eip);
}
@@ -1018,10 +1096,7 @@ zfs_ereport_is_valid(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio)
return (B_FALSE);
if (zio != NULL) {
- /*
- * If this is not a read or write zio, ignore the error. This
- * can occur if the DKIOCFLUSHWRITECACHE ioctl fails.
- */
+ /* If this is not a read or write zio, ignore the error */
if (zio->io_type != ZIO_TYPE_READ &&
zio->io_type != ZIO_TYPE_WRITE)
return (B_FALSE);
@@ -1389,17 +1464,17 @@ zfs_post_state_change(spa_t *spa, vdev_t *vd, uint64_t laststate)
aux = fm_nvlist_create(NULL);
if (vd && aux) {
if (vd->vdev_physpath) {
- (void) nvlist_add_string(aux,
+ fnvlist_add_string(aux,
FM_EREPORT_PAYLOAD_ZFS_VDEV_PHYSPATH,
vd->vdev_physpath);
}
if (vd->vdev_enc_sysfs_path) {
- (void) nvlist_add_string(aux,
+ fnvlist_add_string(aux,
FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH,
vd->vdev_enc_sysfs_path);
}
- (void) nvlist_add_uint64(aux,
+ fnvlist_add_uint64(aux,
FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE, laststate);
}
@@ -1445,9 +1520,8 @@ zfs_ereport_fini(void)
{
recent_events_node_t *entry;
- while ((entry = list_head(&recent_events_list)) != NULL) {
+ while ((entry = list_remove_head(&recent_events_list)) != NULL) {
avl_remove(&recent_events_tree, entry);
- list_remove(&recent_events_list, entry);
kmem_free(entry, sizeof (*entry));
}
avl_destroy(&recent_events_tree);
@@ -1461,7 +1535,7 @@ zfs_ereport_snapshot_post(const char *subclass, spa_t *spa, const char *name)
nvlist_t *aux;
aux = fm_nvlist_create(NULL);
- nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME, name);
+ fnvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME, name);
zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux);
fm_nvlist_destroy(aux, FM_NVA_FREE);
@@ -1496,12 +1570,12 @@ zfs_ereport_zvol_post(const char *subclass, const char *name,
return;
aux = fm_nvlist_create(NULL);
- nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME, dev_name);
- nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME,
+ fnvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME, dev_name);
+ fnvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME,
raw_name);
r = strchr(name, '/');
if (r && r[1])
- nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_VOLUME, &r[1]);
+ fnvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_VOLUME, &r[1]);
zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux);
fm_nvlist_destroy(aux, FM_NVA_FREE);
diff --git a/module/zfs/zfs_fuid.c b/module/zfs/zfs_fuid.c
index 976333ee822c..add4241dcc99 100644
--- a/module/zfs/zfs_fuid.c
+++ b/module/zfs/zfs_fuid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -133,7 +133,7 @@ zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree,
for (i = 0; i != count; i++) {
fuid_domain_t *domnode;
- char *domain;
+ const char *domain;
uint64_t idx;
VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
@@ -622,7 +622,7 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
rid = FUID_RID(fuidp->z_fuid_group);
idx = FUID_INDEX(fuidp->z_fuid_group);
break;
- };
+ }
domain = fuidp->z_domain_table[idx - 1];
} else {
if (type == ZFS_OWNER || type == ZFS_ACE_USER)
@@ -699,19 +699,15 @@ zfs_fuid_info_free(zfs_fuid_info_t *fuidp)
zfs_fuid_t *zfuid;
zfs_fuid_domain_t *zdomain;
- while ((zfuid = list_head(&fuidp->z_fuids)) != NULL) {
- list_remove(&fuidp->z_fuids, zfuid);
+ while ((zfuid = list_remove_head(&fuidp->z_fuids)) != NULL)
kmem_free(zfuid, sizeof (zfs_fuid_t));
- }
if (fuidp->z_domain_table != NULL)
kmem_free(fuidp->z_domain_table,
(sizeof (char *)) * fuidp->z_domain_cnt);
- while ((zdomain = list_head(&fuidp->z_domains)) != NULL) {
- list_remove(&fuidp->z_domains, zdomain);
+ while ((zdomain = list_remove_head(&fuidp->z_domains)) != NULL)
kmem_free(zdomain, sizeof (zfs_fuid_domain_t));
- }
kmem_free(fuidp, sizeof (zfs_fuid_info_t));
}
diff --git a/module/zfs/zfs_impl.c b/module/zfs/zfs_impl.c
new file mode 100644
index 000000000000..20322ff98b31
--- /dev/null
+++ b/module/zfs/zfs_impl.c
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de>
+ */
+
+#include <sys/zio_checksum.h>
+#include <sys/zfs_context.h>
+#include <sys/zfs_impl.h>
+
+#include <sys/blake3.h>
+#include <sys/sha2.h>
+
+/*
+ * impl_ops - backend for implementations of algorithms
+ */
+const zfs_impl_t *impl_ops[] = {
+ &zfs_blake3_ops,
+ &zfs_sha256_ops,
+ &zfs_sha512_ops,
+ NULL
+};
+
+/*
+ * zfs_impl_get_ops - Get the API functions for an impl backend
+ */
+const zfs_impl_t *
+zfs_impl_get_ops(const char *algo)
+{
+ const zfs_impl_t **ops = impl_ops;
+
+ if (!algo || !*algo)
+ return (*ops);
+
+ for (; *ops; ops++) {
+ if (strcmp(algo, (*ops)->name) == 0)
+ break;
+ }
+
+ ASSERT3P(ops, !=, NULL);
+ return (*ops);
+}
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 3b71dcb0e788..908b9efc1813 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -23,11 +23,11 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright 2011 Martin Matuska
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
- * Portions Copyright 2012 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * Copyright (c) 2012 Pawel Jakub Dawidek
* Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2024 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -40,6 +40,7 @@
* Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
* Copyright (c) 2019, 2021, Klara Inc.
* Copyright (c) 2019, Allan Jude
+ * Copyright 2024 Oxide Computer Company
*/
/*
@@ -222,23 +223,22 @@
#include <sys/zfs_ioctl_impl.h>
kmutex_t zfsdev_state_lock;
-static zfsdev_state_t *zfsdev_state_list;
+static zfsdev_state_t zfsdev_state_listhead;
/*
* Limit maximum nvlist size. We don't want users passing in insane values
* for zc->zc_nvlist_src_size, since we will need to allocate that much memory.
* Defaults to 0=auto which is handled by platform code.
*/
-unsigned long zfs_max_nvlist_src_size = 0;
+uint64_t zfs_max_nvlist_src_size = 0;
/*
* When logging the output nvlist of an ioctl in the on-disk history, limit
* the logged size to this many bytes. This must be less than DMU_MAX_ACCESS.
* This applies primarily to zfs_ioc_channel_program().
*/
-static unsigned long zfs_history_output_max = 1024 * 1024;
+static uint64_t zfs_history_output_max = 1024 * 1024;
-uint_t zfs_fsyncer_key;
uint_t zfs_allow_log_key;
/* DATA_TYPE_ANY is used when zkey_type can vary. */
@@ -604,7 +604,7 @@ static int
zfs_secpolicy_setprop(const char *dsname, zfs_prop_t prop, nvpair_t *propval,
cred_t *cr)
{
- char *strval;
+ const char *strval;
/*
* Check permissions for special properties.
@@ -741,7 +741,7 @@ zfs_get_parent(const char *datasetname, char *parent, int parentsize)
/*
* Remove the @bla or /bla from the end of the name to get the parent.
*/
- (void) strncpy(parent, datasetname, parentsize);
+ (void) strlcpy(parent, datasetname, parentsize);
cp = strrchr(parent, '@');
if (cp != NULL) {
cp[0] = '\0';
@@ -935,7 +935,7 @@ zfs_secpolicy_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
pair = nvlist_next_nvpair(snaps, pair)) {
- char *name = nvpair_name(pair);
+ char *name = (char *)nvpair_name(pair);
char *atp = strchr(name, '@');
if (atp == NULL) {
@@ -962,7 +962,7 @@ zfs_secpolicy_bookmark(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
for (nvpair_t *pair = nvlist_next_nvpair(innvl, NULL);
pair != NULL; pair = nvlist_next_nvpair(innvl, pair)) {
- char *name = nvpair_name(pair);
+ char *name = (char *)nvpair_name(pair);
char *hashp = strchr(name, '#');
if (hashp == NULL) {
@@ -988,7 +988,7 @@ zfs_secpolicy_destroy_bookmarks(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
for (pair = nvlist_next_nvpair(innvl, NULL); pair != NULL;
pair = nextpair) {
- char *name = nvpair_name(pair);
+ char *name = (char *)nvpair_name(pair);
char *hashp = strchr(name, '#');
nextpair = nvlist_next_nvpair(innvl, pair);
@@ -1036,9 +1036,9 @@ zfs_secpolicy_log_history(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
static int
zfs_secpolicy_create_clone(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
{
- char parentname[ZFS_MAX_DATASET_NAME_LEN];
- int error;
- char *origin;
+ char parentname[ZFS_MAX_DATASET_NAME_LEN];
+ int error;
+ const char *origin;
if ((error = zfs_get_parent(zc->zc_name, parentname,
sizeof (parentname))) != 0)
@@ -1081,7 +1081,7 @@ zfs_secpolicy_diff(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
(void) innvl;
int error;
- if ((error = secpolicy_sys_config(cr, B_FALSE)) == 0)
+ if (secpolicy_sys_config(cr, B_FALSE) == 0)
return (0);
error = zfs_secpolicy_write_perms(zc->zc_name, ZFS_DELEG_PERM_DIFF, cr);
@@ -1230,8 +1230,8 @@ zfs_secpolicy_tmp_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
*/
int error;
- if ((error = zfs_secpolicy_write_perms(zc->zc_name,
- ZFS_DELEG_PERM_DIFF, cr)) == 0)
+ if (zfs_secpolicy_write_perms(zc->zc_name,
+ ZFS_DELEG_PERM_DIFF, cr) == 0)
return (0);
error = zfs_secpolicy_snapshot_perms(zc->zc_name, cr);
@@ -1279,8 +1279,7 @@ get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp)
packed = vmem_alloc(size, KM_SLEEP);
- if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
- iflag)) != 0) {
+ if (ddi_copyin((void *)(uintptr_t)nvl, packed, size, iflag) != 0) {
vmem_free(packed, size);
return (SET_ERROR(EFAULT));
}
@@ -1461,7 +1460,7 @@ zfs_ioc_pool_create(zfs_cmd_t *zc)
nvlist_t *nvl = NULL;
nvlist_t *hidden_args = NULL;
uint64_t version = SPA_VERSION;
- char *tname;
+ const char *tname;
(void) nvlist_lookup_uint64(props,
zpool_prop_to_name(ZPOOL_PROP_VERSION), &version);
@@ -1583,8 +1582,9 @@ zfs_ioc_pool_configs(zfs_cmd_t *zc)
nvlist_t *configs;
int error;
- if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
- return (SET_ERROR(EEXIST));
+ error = spa_all_configs(&zc->zc_cookie, &configs);
+ if (error)
+ return (error);
error = put_nvlist(zc, configs);
@@ -1686,6 +1686,47 @@ zfs_ioc_pool_scan(zfs_cmd_t *zc)
return (error);
}
+/*
+ * inputs:
+ * poolname name of the pool
+ * scan_type scan func (pool_scan_func_t)
+ * scan_command scrub pause/resume flag (pool_scrub_cmd_t)
+ */
+static const zfs_ioc_key_t zfs_keys_pool_scrub[] = {
+ {"scan_type", DATA_TYPE_UINT64, 0},
+ {"scan_command", DATA_TYPE_UINT64, 0},
+};
+
+static int
+zfs_ioc_pool_scrub(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
+{
+ spa_t *spa;
+ int error;
+ uint64_t scan_type, scan_cmd;
+
+ if (nvlist_lookup_uint64(innvl, "scan_type", &scan_type) != 0)
+ return (SET_ERROR(EINVAL));
+ if (nvlist_lookup_uint64(innvl, "scan_command", &scan_cmd) != 0)
+ return (SET_ERROR(EINVAL));
+
+ if (scan_cmd >= POOL_SCRUB_FLAGS_END)
+ return (SET_ERROR(EINVAL));
+
+ if ((error = spa_open(poolname, &spa, FTAG)) != 0)
+ return (error);
+
+ if (scan_cmd == POOL_SCRUB_PAUSE) {
+ error = spa_scrub_pause_resume(spa, POOL_SCRUB_PAUSE);
+ } else if (scan_type == POOL_SCAN_NONE) {
+ error = spa_scan_stop(spa);
+ } else {
+ error = spa_scan(spa, scan_type);
+ }
+
+ spa_close(spa, FTAG);
+ return (error);
+}
+
static int
zfs_ioc_pool_freeze(zfs_cmd_t *zc)
{
@@ -1846,7 +1887,7 @@ zfs_ioc_vdev_add(zfs_cmd_t *zc)
error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
zc->zc_iflags, &config);
if (error == 0) {
- error = spa_vdev_add(spa, config);
+ error = spa_vdev_add(spa, config, zc->zc_flags);
nvlist_free(config);
}
spa_close(spa, FTAG);
@@ -1912,6 +1953,10 @@ zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
error = vdev_degrade(spa, zc->zc_guid, zc->zc_obj);
break;
+ case VDEV_STATE_REMOVED:
+ error = vdev_remove_wanted(spa, zc->zc_guid);
+ break;
+
default:
error = SET_ERROR(EINVAL);
}
@@ -2035,7 +2080,7 @@ zfs_ioc_objset_stats_impl(zfs_cmd_t *zc, objset_t *os)
dmu_objset_fast_stat(os, &zc->zc_objset_stats);
- if (zc->zc_nvlist_dst != 0 &&
+ if (!zc->zc_simple && zc->zc_nvlist_dst != 0 &&
(error = dsl_prop_get_all(os, &nv)) == 0) {
dmu_objset_stats(os, nv);
/*
@@ -2322,6 +2367,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
}
if (zc->zc_simple) {
+ dsl_dataset_fast_stat(ds, &zc->zc_objset_stats);
dsl_dataset_rele(ds, FTAG);
break;
}
@@ -2477,11 +2523,27 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
case ZFS_PROP_VOLSIZE:
err = zvol_set_volsize(dsname, intval);
break;
- case ZFS_PROP_SNAPDEV:
- err = zvol_set_snapdev(dsname, source, intval);
+ case ZFS_PROP_VOLTHREADING:
+ err = zvol_set_volthreading(dsname, intval);
+ /*
+ * Set err to -1 to force the zfs_set_prop_nvlist code down the
+ * default path to set the value in the nvlist.
+ */
+ if (err == 0)
+ err = -1;
break;
+ case ZFS_PROP_SNAPDEV:
case ZFS_PROP_VOLMODE:
- err = zvol_set_volmode(dsname, source, intval);
+ err = zvol_set_common(dsname, prop, source, intval);
+ break;
+ case ZFS_PROP_READONLY:
+ err = zvol_set_ro(dsname, intval);
+ /*
+ * Set err to -1 to force the zfs_set_prop_nvlist code down the
+ * default path to set the value in the nvlist.
+ */
+ if (err == 0)
+ err = -1;
break;
case ZFS_PROP_VERSION:
{
@@ -2677,7 +2739,6 @@ retry:
pair = NULL;
while ((pair = nvlist_next_nvpair(genericnvl, pair)) != NULL) {
const char *propname = nvpair_name(pair);
- err = 0;
propval = pair;
if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
@@ -2926,7 +2987,7 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc)
mutex_enter(&spa_namespace_lock);
if ((spa = spa_lookup(zc->zc_name)) != NULL) {
spa_configfile_set(spa, props, B_FALSE);
- spa_write_cachefile(spa, B_FALSE, B_TRUE);
+ spa_write_cachefile(spa, B_FALSE, B_TRUE, B_FALSE);
}
mutex_exit(&spa_namespace_lock);
if (spa != NULL) {
@@ -3090,7 +3151,7 @@ zfs_ioc_set_fsacl(zfs_cmd_t *zc)
/*
* Verify nvlist is constructed correctly
*/
- if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) {
+ if (zfs_deleg_verify_nvlist(fsaclnv) != 0) {
nvlist_free(fsaclnv);
return (SET_ERROR(EINVAL));
}
@@ -3913,7 +3974,7 @@ static int
zfs_ioc_channel_program(const char *poolname, nvlist_t *innvl,
nvlist_t *outnvl)
{
- char *program;
+ const char *program;
uint64_t instrlimit, memlimit;
boolean_t sync_flag;
nvpair_t *nvarg = NULL;
@@ -4067,7 +4128,8 @@ zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
if (!(cmd_type == POOL_INITIALIZE_CANCEL ||
cmd_type == POOL_INITIALIZE_START ||
- cmd_type == POOL_INITIALIZE_SUSPEND)) {
+ cmd_type == POOL_INITIALIZE_SUSPEND ||
+ cmd_type == POOL_INITIALIZE_UNINIT)) {
return (SET_ERROR(EINVAL));
}
@@ -4333,7 +4395,7 @@ zfs_ioc_rollback(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
{
zfsvfs_t *zfsvfs;
zvol_state_handle_t *zv;
- char *target = NULL;
+ const char *target = NULL;
int error;
(void) nvlist_lookup_string(innvl, "target", &target);
@@ -4409,7 +4471,7 @@ zfs_ioc_redact(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
{
(void) outnvl;
nvlist_t *redactnvl = NULL;
- char *redactbook = NULL;
+ const char *redactbook = NULL;
if (nvlist_lookup_nvlist(innvl, "snapnv", &redactnvl) != 0)
return (SET_ERROR(EINVAL));
@@ -4805,10 +4867,10 @@ propval_equals(nvpair_t *p1, nvpair_t *p2)
return (B_FALSE);
if (nvpair_type(p1) == DATA_TYPE_STRING) {
- char *valstr1, *valstr2;
+ const char *valstr1, *valstr2;
- VERIFY(nvpair_value_string(p1, (char **)&valstr1) == 0);
- VERIFY(nvpair_value_string(p2, (char **)&valstr2) == 0);
+ VERIFY(nvpair_value_string(p1, &valstr1) == 0);
+ VERIFY(nvpair_value_string(p2, &valstr2) == 0);
return (strcmp(valstr1, valstr2) == 0);
} else {
uint64_t intval1, intval2;
@@ -4873,6 +4935,11 @@ extract_delay_props(nvlist_t *props)
static const zfs_prop_t delayable[] = {
ZFS_PROP_REFQUOTA,
ZFS_PROP_KEYLOCATION,
+ /*
+ * Setting ZFS_PROP_SHARESMB requires the objset type to be
+ * known, which is not possible prior to receipt of raw sends.
+ */
+ ZFS_PROP_SHARESMB,
0
};
int i;
@@ -4924,9 +4991,9 @@ static boolean_t zfs_ioc_recv_inject_err;
* encountered errors, if any. It's the callers responsibility to free.
*/
static int
-zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
- nvlist_t *localprops, nvlist_t *hidden_args, boolean_t force,
- boolean_t resumable, int input_fd,
+zfs_ioc_recv_impl(char *tofs, char *tosnap, const char *origin,
+ nvlist_t *recvprops, nvlist_t *localprops, nvlist_t *hidden_args,
+ boolean_t force, boolean_t heal, boolean_t resumable, int input_fd,
dmu_replay_record_t *begin_record, uint64_t *read_bytes,
uint64_t *errflags, nvlist_t **errors)
{
@@ -4936,6 +5003,7 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
offset_t off, noff;
nvlist_t *local_delayprops = NULL;
nvlist_t *recv_delayprops = NULL;
+ nvlist_t *inherited_delayprops = NULL;
nvlist_t *origprops = NULL; /* existing properties */
nvlist_t *origrecvd = NULL; /* existing received properties */
boolean_t first_recvd_props = B_FALSE;
@@ -4951,7 +5019,7 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
return (SET_ERROR(EBADF));
noff = off = zfs_file_off(input_fp);
- error = dmu_recv_begin(tofs, tosnap, begin_record, force,
+ error = dmu_recv_begin(tofs, tosnap, begin_record, force, heal,
resumable, localprops, hidden_args, origin, &drc, input_fp,
&off);
if (error != 0)
@@ -5050,6 +5118,7 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
local_delayprops = extract_delay_props(oprops);
(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_LOCAL,
oprops, *errors);
+ inherited_delayprops = extract_delay_props(xprops);
(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_INHERITED,
xprops, *errors);
@@ -5107,6 +5176,10 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_LOCAL,
local_delayprops, *errors);
}
+ if (inherited_delayprops != NULL && error == 0) {
+ (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_INHERITED,
+ inherited_delayprops, *errors);
+ }
}
/*
@@ -5126,6 +5199,10 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops,
ASSERT(nvlist_merge(localprops, local_delayprops, 0) == 0);
nvlist_free(local_delayprops);
}
+ if (inherited_delayprops != NULL) {
+ ASSERT(nvlist_merge(localprops, inherited_delayprops, 0) == 0);
+ nvlist_free(inherited_delayprops);
+ }
*read_bytes = off - noff;
#ifdef ZFS_DEBUG
@@ -5262,15 +5339,16 @@ zfs_ioc_recv(zfs_cmd_t *zc)
nvlist_t *errors = NULL;
nvlist_t *recvdprops = NULL;
nvlist_t *localprops = NULL;
- char *origin = NULL;
+ const char *origin = NULL;
char *tosnap;
char tofs[ZFS_MAX_DATASET_NAME_LEN];
int error = 0;
if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
strchr(zc->zc_value, '@') == NULL ||
- strchr(zc->zc_value, '%'))
+ strchr(zc->zc_value, '%') != NULL) {
return (SET_ERROR(EINVAL));
+ }
(void) strlcpy(tofs, zc->zc_value, sizeof (tofs));
tosnap = strchr(tofs, '@');
@@ -5278,13 +5356,15 @@ zfs_ioc_recv(zfs_cmd_t *zc)
if (zc->zc_nvlist_src != 0 &&
(error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
- zc->zc_iflags, &recvdprops)) != 0)
- return (error);
+ zc->zc_iflags, &recvdprops)) != 0) {
+ goto out;
+ }
if (zc->zc_nvlist_conf != 0 &&
(error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
- zc->zc_iflags, &localprops)) != 0)
- return (error);
+ zc->zc_iflags, &localprops)) != 0) {
+ goto out;
+ }
if (zc->zc_string[0])
origin = zc->zc_string;
@@ -5294,10 +5374,8 @@ zfs_ioc_recv(zfs_cmd_t *zc)
begin_record.drr_u.drr_begin = zc->zc_begin_record;
error = zfs_ioc_recv_impl(tofs, tosnap, origin, recvdprops, localprops,
- NULL, zc->zc_guid, B_FALSE, zc->zc_cookie, &begin_record,
+ NULL, zc->zc_guid, B_FALSE, B_FALSE, zc->zc_cookie, &begin_record,
&zc->zc_cookie, &zc->zc_obj, &errors);
- nvlist_free(recvdprops);
- nvlist_free(localprops);
/*
* Now that all props, initial and delayed, are set, report the prop
@@ -5313,7 +5391,10 @@ zfs_ioc_recv(zfs_cmd_t *zc)
error = SET_ERROR(EINVAL);
}
+out:
nvlist_free(errors);
+ nvlist_free(recvdprops);
+ nvlist_free(localprops);
return (error);
}
@@ -5327,6 +5408,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
* "begin_record" -> non-byteswapped dmu_replay_record_t
* "input_fd" -> file descriptor to read stream from (int32)
* (optional) "force" -> force flag (value ignored)
+ * (optional) "heal" -> use send stream to heal data corruption
* (optional) "resumable" -> resumable flag (value ignored)
* (optional) "cleanup_fd" -> unused
* (optional) "action_handle" -> unused
@@ -5347,6 +5429,7 @@ static const zfs_ioc_key_t zfs_keys_recv_new[] = {
{"begin_record", DATA_TYPE_BYTE_ARRAY, 0},
{"input_fd", DATA_TYPE_INT32, 0},
{"force", DATA_TYPE_BOOLEAN, ZK_OPTIONAL},
+ {"heal", DATA_TYPE_BOOLEAN, ZK_OPTIONAL},
{"resumable", DATA_TYPE_BOOLEAN, ZK_OPTIONAL},
{"cleanup_fd", DATA_TYPE_INT32, ZK_OPTIONAL},
{"action_handle", DATA_TYPE_UINT64, ZK_OPTIONAL},
@@ -5362,11 +5445,12 @@ zfs_ioc_recv_new(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
nvlist_t *recvprops = NULL;
nvlist_t *localprops = NULL;
nvlist_t *hidden_args = NULL;
- char *snapname;
- char *origin = NULL;
+ const char *snapname;
+ const char *origin = NULL;
char *tosnap;
char tofs[ZFS_MAX_DATASET_NAME_LEN];
boolean_t force;
+ boolean_t heal;
boolean_t resumable;
uint64_t read_bytes = 0;
uint64_t errflags = 0;
@@ -5377,8 +5461,9 @@ zfs_ioc_recv_new(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
if (dataset_namecheck(snapname, NULL, NULL) != 0 ||
strchr(snapname, '@') == NULL ||
- strchr(snapname, '%'))
+ strchr(snapname, '%') != NULL) {
return (SET_ERROR(EINVAL));
+ }
(void) strlcpy(tofs, snapname, sizeof (tofs));
tosnap = strchr(tofs, '@');
@@ -5396,32 +5481,35 @@ zfs_ioc_recv_new(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
input_fd = fnvlist_lookup_int32(innvl, "input_fd");
force = nvlist_exists(innvl, "force");
+ heal = nvlist_exists(innvl, "heal");
resumable = nvlist_exists(innvl, "resumable");
/* we still use "props" here for backwards compatibility */
error = nvlist_lookup_nvlist(innvl, "props", &recvprops);
if (error && error != ENOENT)
- return (error);
+ goto out;
error = nvlist_lookup_nvlist(innvl, "localprops", &localprops);
if (error && error != ENOENT)
- return (error);
+ goto out;
error = nvlist_lookup_nvlist(innvl, ZPOOL_HIDDEN_ARGS, &hidden_args);
if (error && error != ENOENT)
- return (error);
+ goto out;
error = zfs_ioc_recv_impl(tofs, tosnap, origin, recvprops, localprops,
- hidden_args, force, resumable, input_fd, begin_record,
+ hidden_args, force, heal, resumable, input_fd, begin_record,
&read_bytes, &errflags, &errors);
fnvlist_add_uint64(outnvl, "read_bytes", read_bytes);
fnvlist_add_uint64(outnvl, "error_flags", errflags);
fnvlist_add_nvlist(outnvl, "errors", errors);
+out:
nvlist_free(errors);
nvlist_free(recvprops);
nvlist_free(localprops);
+ nvlist_free(hidden_args);
return (error);
}
@@ -5671,17 +5759,12 @@ zfs_ioc_error_log(zfs_cmd_t *zc)
{
spa_t *spa;
int error;
- uint64_t count = zc->zc_nvlist_dst_size;
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);
error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst,
- &count);
- if (error == 0)
- zc->zc_nvlist_dst_size = count;
- else
- zc->zc_nvlist_dst_size = spa_get_errlog_size(spa);
+ &zc->zc_nvlist_dst_size);
spa_close(spa, FTAG);
@@ -5740,10 +5823,13 @@ zfs_ioc_clear(zfs_cmd_t *zc)
/*
* If multihost is enabled, resuming I/O is unsafe as another
- * host may have imported the pool.
+ * host may have imported the pool. Check for remote activity.
*/
- if (spa_multihost(spa) && spa_suspended(spa))
- return (SET_ERROR(EINVAL));
+ if (spa_multihost(spa) && spa_suspended(spa) &&
+ spa_mmp_remote_host_activity(spa)) {
+ spa_close(spa, FTAG);
+ return (SET_ERROR(EREMOTEIO));
+ }
spa_vdev_state_enter(spa, SCL_NONE);
@@ -6215,7 +6301,7 @@ zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist)
/* make sure the user didn't pass us any invalid (empty) tags */
for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
pair = nvlist_next_nvpair(holds, pair)) {
- char *htag;
+ const char *htag;
error = nvpair_value_string(pair, &htag);
if (error != 0)
@@ -6334,7 +6420,7 @@ zfs_ioc_events_next(zfs_cmd_t *zc)
static int
zfs_ioc_events_clear(zfs_cmd_t *zc)
{
- int count;
+ uint_t count;
zfs_zevent_drain_all(&count);
zc->zc_cookie = count;
@@ -6435,7 +6521,7 @@ zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl)
int error;
dsl_pool_t *dp;
dsl_dataset_t *new, *old;
- char *firstsnap;
+ const char *firstsnap;
uint64_t used, comp, uncomp;
firstsnap = fnvlist_lookup_string(innvl, "firstsnap");
@@ -6516,7 +6602,7 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
(void) outnvl;
int error;
offset_t off;
- char *fromname = NULL;
+ const char *fromname = NULL;
int fd;
zfs_file_t *fp;
boolean_t largeblockok;
@@ -6526,7 +6612,7 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
boolean_t savedok;
uint64_t resumeobj = 0;
uint64_t resumeoff = 0;
- char *redactbook = NULL;
+ const char *redactbook = NULL;
fd = fnvlist_lookup_int32(innvl, "fd");
@@ -6616,8 +6702,8 @@ zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
dsl_dataset_t *tosnap;
dsl_dataset_t *fromsnap = NULL;
int error;
- char *fromname = NULL;
- char *redactlist_book = NULL;
+ const char *fromname = NULL;
+ const char *redactlist_book = NULL;
boolean_t largeblockok;
boolean_t embedok;
boolean_t compressok;
@@ -7200,6 +7286,11 @@ zfs_ioctl_init(void)
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE,
zfs_keys_vdev_set_props, ARRAY_SIZE(zfs_keys_vdev_set_props));
+ zfs_ioctl_register("scrub", ZFS_IOC_POOL_SCRUB,
+ zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME,
+ POOL_CHECK_NONE, B_TRUE, B_TRUE,
+ zfs_keys_pool_scrub, ARRAY_SIZE(zfs_keys_pool_scrub));
+
/* IOCTLS that use the legacy function signature */
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
@@ -7361,7 +7452,7 @@ zfs_check_input_nvpairs(nvlist_t *innvl, const zfs_ioc_vec_t *vec)
*/
for (nvpair_t *pair = nvlist_next_nvpair(innvl, NULL);
pair != NULL; pair = nvlist_next_nvpair(innvl, pair)) {
- char *name = nvpair_name(pair);
+ const char *name = nvpair_name(pair);
data_type_t type = nvpair_type(pair);
boolean_t identified = B_FALSE;
@@ -7452,7 +7543,7 @@ zfsdev_getminor(zfs_file_t *fp, minor_t *minorp)
mutex_enter(&zfsdev_state_lock);
- for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
+ for (zs = &zfsdev_state_listhead; zs != NULL; zs = zs->zs_next) {
if (zs->zs_minor == -1)
continue;
@@ -7474,9 +7565,9 @@ zfsdev_get_state(minor_t minor, enum zfsdev_state_type which)
{
zfsdev_state_t *zs;
- for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
+ for (zs = &zfsdev_state_listhead; zs != NULL; zs = zs->zs_next) {
if (zs->zs_minor == minor) {
- smp_rmb();
+ membar_consumer();
switch (which) {
case ZST_ONEXIT:
return (zs->zs_onexit);
@@ -7528,7 +7619,7 @@ zfsdev_state_init(void *priv)
if (minor == 0)
return (SET_ERROR(ENXIO));
- for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
+ for (zs = &zfsdev_state_listhead; zs != NULL; zs = zs->zs_next) {
if (zs->zs_minor == -1)
break;
zsprev = zs;
@@ -7812,13 +7903,11 @@ zfs_kmod_init(void)
zfs_ioctl_init();
mutex_init(&zfsdev_state_lock, NULL, MUTEX_DEFAULT, NULL);
- zfsdev_state_list = kmem_zalloc(sizeof (zfsdev_state_t), KM_SLEEP);
- zfsdev_state_list->zs_minor = -1;
+ zfsdev_state_listhead.zs_minor = -1;
if ((error = zfsdev_attach()) != 0)
goto out;
- tsd_create(&zfs_fsyncer_key, NULL);
tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
@@ -7840,13 +7929,14 @@ zfs_kmod_fini(void)
mutex_destroy(&zfsdev_state_lock);
- for (zs = zfsdev_state_list; zs != NULL; zs = zsnext) {
+ for (zs = &zfsdev_state_listhead; zs != NULL; zs = zsnext) {
zsnext = zs->zs_next;
if (zs->zs_onexit)
zfs_onexit_destroy(zs->zs_onexit);
if (zs->zs_zevent)
zfs_zevent_destroy(zs->zs_zevent);
- kmem_free(zs, sizeof (zfsdev_state_t));
+ if (zs != &zfsdev_state_listhead)
+ kmem_free(zs, sizeof (zfsdev_state_t));
}
zfs_ereport_taskq_fini(); /* run before zfs_fini() on Linux */
@@ -7854,13 +7944,12 @@ zfs_kmod_fini(void)
spa_fini();
zvol_fini();
- tsd_destroy(&zfs_fsyncer_key);
tsd_destroy(&rrw_tsd_key);
tsd_destroy(&zfs_allow_log_key);
}
-ZFS_MODULE_PARAM(zfs, zfs_, max_nvlist_src_size, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, max_nvlist_src_size, U64, ZMOD_RW,
"Maximum size in bytes allowed for src nvlist passed with ZFS ioctls");
-ZFS_MODULE_PARAM(zfs, zfs_, history_output_max, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, history_output_max, U64, ZMOD_RW,
"Maximum size in bytes of ZFS ioctl output that will be logged");
diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c
index b56a1caacac6..433a653e5500 100644
--- a/module/zfs/zfs_log.c
+++ b/module/zfs/zfs_log.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2022 by Pawel Jakub Dawidek
*/
@@ -494,6 +495,29 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
zil_itx_assign(zilog, itx, tx);
}
+static void
+do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp,
+ const char *sname, znode_t *tdzp, const char *dname, znode_t *szp)
+{
+ itx_t *itx;
+ lr_rename_t *lr;
+ size_t snamesize = strlen(sname) + 1;
+ size_t dnamesize = strlen(dname) + 1;
+
+ if (zil_replaying(zilog, tx))
+ return;
+
+ itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
+ lr = (lr_rename_t *)&itx->itx_lr;
+ lr->lr_sdoid = sdzp->z_id;
+ lr->lr_tdoid = tdzp->z_id;
+ memcpy((char *)(lr + 1), sname, snamesize);
+ memcpy((char *)(lr + 1) + snamesize, dname, dnamesize);
+ itx->itx_oid = szp->z_id;
+
+ zil_itx_assign(zilog, itx, tx);
+}
+
/*
* Handles TX_RENAME transactions.
*/
@@ -501,18 +525,71 @@ void
zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp,
const char *sname, znode_t *tdzp, const char *dname, znode_t *szp)
{
+ txtype |= TX_RENAME;
+ do_zfs_log_rename(zilog, tx, txtype, sdzp, sname, tdzp, dname, szp);
+}
+
+/*
+ * Handles TX_RENAME_EXCHANGE transactions.
+ */
+void
+zfs_log_rename_exchange(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
+ znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname,
+ znode_t *szp)
+{
+ txtype |= TX_RENAME_EXCHANGE;
+ do_zfs_log_rename(zilog, tx, txtype, sdzp, sname, tdzp, dname, szp);
+}
+
+/*
+ * Handles TX_RENAME_WHITEOUT transactions.
+ *
+ * Unfortunately we cannot reuse do_zfs_log_rename because we we need to call
+ * zfs_mknode() on replay which requires stashing bits as with TX_CREATE.
+ */
+void
+zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
+ znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname,
+ znode_t *szp, znode_t *wzp)
+{
itx_t *itx;
- lr_rename_t *lr;
+ lr_rename_whiteout_t *lr;
size_t snamesize = strlen(sname) + 1;
size_t dnamesize = strlen(dname) + 1;
if (zil_replaying(zilog, tx))
return;
+ txtype |= TX_RENAME_WHITEOUT;
itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
- lr = (lr_rename_t *)&itx->itx_lr;
- lr->lr_sdoid = sdzp->z_id;
- lr->lr_tdoid = tdzp->z_id;
+ lr = (lr_rename_whiteout_t *)&itx->itx_lr;
+ lr->lr_rename.lr_sdoid = sdzp->z_id;
+ lr->lr_rename.lr_tdoid = tdzp->z_id;
+
+ /*
+ * RENAME_WHITEOUT will create an entry at the source znode, so we need
+ * to store the same data that the equivalent call to zfs_log_create()
+ * would.
+ */
+ lr->lr_wfoid = wzp->z_id;
+ LR_FOID_SET_SLOTS(lr->lr_wfoid, wzp->z_dnodesize >> DNODE_SHIFT);
+ (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(wzp)), &lr->lr_wgen,
+ sizeof (uint64_t));
+ (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(wzp)),
+ lr->lr_wcrtime, sizeof (uint64_t) * 2);
+ lr->lr_wmode = wzp->z_mode;
+ lr->lr_wuid = (uint64_t)KUID_TO_SUID(ZTOUID(wzp));
+ lr->lr_wgid = (uint64_t)KGID_TO_SGID(ZTOGID(wzp));
+
+ /*
+ * This rdev will always be makdevice(0, 0) but because the ZIL log and
+ * replay code needs to be platform independent (and there is no
+ * platform independent makdev()) we need to copy the one created
+ * during the rename operation.
+ */
+ (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(wzp)), &lr->lr_wrdev,
+ sizeof (lr->lr_wrdev));
+
memcpy((char *)(lr + 1), sname, snamesize);
memcpy((char *)(lr + 1) + snamesize, dname, dnamesize);
itx->itx_oid = szp->z_id;
@@ -525,17 +602,16 @@ zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp,
* called as soon as the write is on stable storage (be it via a DMU sync or a
* ZIL commit).
*/
-static long zfs_immediate_write_sz = 32768;
+static int64_t zfs_immediate_write_sz = 32768;
void
zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
- znode_t *zp, offset_t off, ssize_t resid, int ioflag,
+ znode_t *zp, offset_t off, ssize_t resid, boolean_t commit,
zil_callback_t callback, void *callback_data)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
uint32_t blocksize = zp->z_blksz;
itx_wr_state_t write_state;
- uintptr_t fsync_cnt;
uint64_t gen = 0;
ssize_t size = resid;
@@ -551,15 +627,11 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
else if (!spa_has_slogs(zilog->zl_spa) &&
resid >= zfs_immediate_write_sz)
write_state = WR_INDIRECT;
- else if (ioflag & (O_SYNC | O_DSYNC))
+ else if (commit)
write_state = WR_COPIED;
else
write_state = WR_NEED_COPY;
- if ((fsync_cnt = (uintptr_t)tsd_get(zfs_fsyncer_key)) != 0) {
- (void) tsd_set(zfs_fsyncer_key, (void *)(fsync_cnt - 1));
- }
-
(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &gen,
sizeof (gen));
@@ -610,12 +682,9 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
BP_ZERO(&lr->lr_blkptr);
itx->itx_private = ZTOZSB(zp);
+ itx->itx_sync = (zp->z_sync_cnt != 0);
itx->itx_gen = gen;
- if (!(ioflag & (O_SYNC | O_DSYNC)) && (zp->z_sync_cnt == 0) &&
- (fsync_cnt == 0))
- itx->itx_sync = B_FALSE;
-
itx->itx_callback = callback;
itx->itx_callback_data = callback_data;
zil_itx_assign(zilog, itx, tx);
@@ -815,5 +884,54 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
zil_itx_assign(zilog, itx, tx);
}
-ZFS_MODULE_PARAM(zfs, zfs_, immediate_write_sz, LONG, ZMOD_RW,
+/*
+ * Handles TX_CLONE_RANGE transactions.
+ */
+void
+zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp,
+ uint64_t off, uint64_t len, uint64_t blksz, const blkptr_t *bps,
+ size_t nbps)
+{
+ itx_t *itx;
+ lr_clone_range_t *lr;
+ uint64_t partlen, max_log_data;
+ size_t i, partnbps;
+
+ if (zil_replaying(zilog, tx) || zp->z_unlinked)
+ return;
+
+ max_log_data = zil_max_log_data(zilog, sizeof (lr_clone_range_t));
+
+ while (nbps > 0) {
+ partnbps = MIN(nbps, max_log_data / sizeof (bps[0]));
+ partlen = 0;
+ for (i = 0; i < partnbps; i++) {
+ partlen += BP_GET_LSIZE(&bps[i]);
+ }
+ partlen = MIN(partlen, len);
+
+ itx = zil_itx_create(txtype,
+ sizeof (*lr) + sizeof (bps[0]) * partnbps);
+ lr = (lr_clone_range_t *)&itx->itx_lr;
+ lr->lr_foid = zp->z_id;
+ lr->lr_offset = off;
+ lr->lr_length = partlen;
+ lr->lr_blksz = blksz;
+ lr->lr_nbps = partnbps;
+ memcpy(lr->lr_bps, bps, sizeof (bps[0]) * partnbps);
+
+ itx->itx_sync = (zp->z_sync_cnt != 0);
+
+ zil_itx_assign(zilog, itx, tx);
+
+ bps += partnbps;
+ ASSERT3U(nbps, >=, partnbps);
+ nbps -= partnbps;
+ off += partlen;
+ ASSERT3U(len, >=, partlen);
+ len -= partlen;
+ }
+}
+
+ZFS_MODULE_PARAM(zfs, zfs_, immediate_write_sz, S64, ZMOD_RW,
"Largest data block to write to zil");
diff --git a/module/zfs/zfs_onexit.c b/module/zfs/zfs_onexit.c
index 7c56dd9c97f5..7bf804b67790 100644
--- a/module/zfs/zfs_onexit.c
+++ b/module/zfs/zfs_onexit.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -87,8 +87,7 @@ zfs_onexit_destroy(zfs_onexit_t *zo)
zfs_onexit_action_node_t *ap;
mutex_enter(&zo->zo_lock);
- while ((ap = list_head(&zo->zo_actions)) != NULL) {
- list_remove(&zo->zo_actions, ap);
+ while ((ap = list_remove_head(&zo->zo_actions)) != NULL) {
mutex_exit(&zo->zo_lock);
ap->za_func(ap->za_data);
kmem_free(ap, sizeof (zfs_onexit_action_node_t));
@@ -151,7 +150,7 @@ zfs_onexit_minor_to_state(minor_t minor, zfs_onexit_t **zo)
*/
int
zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
- uint64_t *action_handle)
+ uintptr_t *action_handle)
{
zfs_onexit_t *zo;
zfs_onexit_action_node_t *ap;
@@ -170,7 +169,7 @@ zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
list_insert_tail(&zo->zo_actions, ap);
mutex_exit(&zo->zo_lock);
if (action_handle)
- *action_handle = (uint64_t)(uintptr_t)ap;
+ *action_handle = (uintptr_t)ap;
return (0);
}
diff --git a/module/zfs/zfs_quota.c b/module/zfs/zfs_quota.c
index e61db5c7ab83..9b351eefc04e 100644
--- a/module/zfs/zfs_quota.c
+++ b/module/zfs/zfs_quota.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,8 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
- * All rights reserved.
+ * Copyright (c) 2011 Pawel Jakub Dawidek
* Copyright (c) 2012, 2015, 2018 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
diff --git a/module/zfs/zfs_ratelimit.c b/module/zfs/zfs_ratelimit.c
index b18b480ce527..091562ca6852 100644
--- a/module/zfs/zfs_ratelimit.c
+++ b/module/zfs/zfs_ratelimit.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c
index e9c5eeb55b07..2e0af60f6db4 100644
--- a/module/zfs/zfs_replay.c
+++ b/module/zfs/zfs_replay.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Cyril Plisko. All rights reserved.
* Copyright (c) 2013, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2021, 2022 by Pawel Jakub Dawidek
*/
#include <sys/types.h>
@@ -308,6 +309,8 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
uint64_t dnodesize;
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lracl));
+
txtype = (lr->lr_common.lrc_txtype & ~TX_CI);
if (byteswap) {
byteswap_uint64_array(lracl, sizeof (*lracl));
@@ -386,8 +389,13 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
lr->lr_uid, lr->lr_gid);
}
+#if defined(__linux__)
+ error = zfs_create(dzp, name, &xva.xva_vattr,
+ 0, 0, &zp, kcred, vflg, &vsec, zfs_init_idmap);
+#else
error = zfs_create(dzp, name, &xva.xva_vattr,
- 0, 0, &zp, kcred, vflg, &vsec);
+ 0, 0, &zp, kcred, vflg, &vsec, NULL);
+#endif
break;
case TX_MKDIR_ACL:
aclstart = (caddr_t)(lracl + 1);
@@ -416,8 +424,13 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
lr->lr_uid, lr->lr_gid);
}
+#if defined(__linux__)
+ error = zfs_mkdir(dzp, name, &xva.xva_vattr,
+ &zp, kcred, vflg, &vsec, zfs_init_idmap);
+#else
error = zfs_mkdir(dzp, name, &xva.xva_vattr,
- &zp, kcred, vflg, &vsec);
+ &zp, kcred, vflg, &vsec, NULL);
+#endif
break;
default:
error = SET_ERROR(ENOTSUP);
@@ -459,6 +472,8 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
uint64_t dnodesize;
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
+
txtype = (lr->lr_common.lrc_txtype & ~TX_CI);
if (byteswap) {
byteswap_uint64_array(lr, sizeof (*lr));
@@ -502,9 +517,9 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
*
* The _ATTR versions will grab the fuid info in their subcases.
*/
- if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK &&
- (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR &&
- (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) {
+ if (txtype != TX_SYMLINK &&
+ txtype != TX_MKDIR_ATTR &&
+ txtype != TX_CREATE_ATTR) {
start = (lr + 1);
zfsvfs->z_fuid_replay =
zfs_replay_fuid_domain(start, &start,
@@ -527,8 +542,13 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
if (name == NULL)
name = (char *)start;
+#if defined(__linux__)
error = zfs_create(dzp, name, &xva.xva_vattr,
- 0, 0, &zp, kcred, vflg, NULL);
+ 0, 0, &zp, kcred, vflg, NULL, zfs_init_idmap);
+#else
+ error = zfs_create(dzp, name, &xva.xva_vattr,
+ 0, 0, &zp, kcred, vflg, NULL, NULL);
+#endif
break;
case TX_MKDIR_ATTR:
lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
@@ -545,8 +565,14 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
if (name == NULL)
name = (char *)(lr + 1);
+#if defined(__linux__)
error = zfs_mkdir(dzp, name, &xva.xva_vattr,
- &zp, kcred, vflg, NULL);
+ &zp, kcred, vflg, NULL, zfs_init_idmap);
+#else
+ error = zfs_mkdir(dzp, name, &xva.xva_vattr,
+ &zp, kcred, vflg, NULL, NULL);
+#endif
+
break;
case TX_MKXATTR:
error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred);
@@ -554,8 +580,13 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
case TX_SYMLINK:
name = (char *)(lr + 1);
link = name + strlen(name) + 1;
+#if defined(__linux__)
+ error = zfs_symlink(dzp, name, &xva.xva_vattr,
+ link, &zp, kcred, vflg, zfs_init_idmap);
+#else
error = zfs_symlink(dzp, name, &xva.xva_vattr,
- link, &zp, kcred, vflg);
+ link, &zp, kcred, vflg, NULL);
+#endif
break;
default:
error = SET_ERROR(ENOTSUP);
@@ -586,6 +617,8 @@ zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
int error;
int vflg = 0;
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -621,6 +654,8 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap)
int error;
int vflg = 0;
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -643,18 +678,21 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap)
}
static int
-zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap)
+do_zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, char *sname,
+ char *tname, uint64_t rflags, vattr_t *wo_vap)
{
- zfsvfs_t *zfsvfs = arg1;
- lr_rename_t *lr = arg2;
- char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
- char *tname = sname + strlen(sname) + 1;
znode_t *sdzp, *tdzp;
- int error;
- int vflg = 0;
+ int error, vflg = 0;
- if (byteswap)
- byteswap_uint64_array(lr, sizeof (*lr));
+ /* Only Linux currently supports RENAME_* flags. */
+#ifdef __linux__
+ VERIFY0(rflags & ~(RENAME_EXCHANGE | RENAME_WHITEOUT));
+
+ /* wo_vap must be non-NULL iff. we're doing RENAME_WHITEOUT */
+ VERIFY_EQUIV(rflags & RENAME_WHITEOUT, wo_vap != NULL);
+#else
+ VERIFY0(rflags);
+#endif
if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0)
return (error);
@@ -667,7 +705,13 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap)
if (lr->lr_common.lrc_txtype & TX_CI)
vflg |= FIGNORECASE;
- error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg);
+#if defined(__linux__)
+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, rflags,
+ wo_vap, zfs_init_idmap);
+#else
+ error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, rflags,
+ wo_vap, NULL);
+#endif
zrele(tdzp);
zrele(sdzp);
@@ -675,6 +719,92 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap)
}
static int
+zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap)
+{
+ zfsvfs_t *zfsvfs = arg1;
+ lr_rename_t *lr = arg2;
+
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
+
+ if (byteswap)
+ byteswap_uint64_array(lr, sizeof (*lr));
+
+ char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
+ char *tname = sname + strlen(sname) + 1;
+ return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, 0, NULL));
+}
+
+static int
+zfs_replay_rename_exchange(void *arg1, void *arg2, boolean_t byteswap)
+{
+#ifdef __linux__
+ zfsvfs_t *zfsvfs = arg1;
+ lr_rename_t *lr = arg2;
+
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
+
+ if (byteswap)
+ byteswap_uint64_array(lr, sizeof (*lr));
+
+ char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
+ char *tname = sname + strlen(sname) + 1;
+ return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, RENAME_EXCHANGE,
+ NULL));
+#else
+ return (SET_ERROR(ENOTSUP));
+#endif
+}
+
+static int
+zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap)
+{
+#ifdef __linux__
+ zfsvfs_t *zfsvfs = arg1;
+ lr_rename_whiteout_t *lr = arg2;
+ int error;
+ /* For the whiteout file. */
+ xvattr_t xva;
+ uint64_t objid;
+ uint64_t dnodesize;
+
+ ASSERT3U(lr->lr_rename.lr_common.lrc_reclen, >, sizeof (*lr));
+
+ if (byteswap)
+ byteswap_uint64_array(lr, sizeof (*lr));
+
+ objid = LR_FOID_GET_OBJ(lr->lr_wfoid);
+ dnodesize = LR_FOID_GET_SLOTS(lr->lr_wfoid) << DNODE_SHIFT;
+
+ xva_init(&xva);
+ zfs_init_vattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID,
+ lr->lr_wmode, lr->lr_wuid, lr->lr_wgid, lr->lr_wrdev, objid);
+
+ /*
+ * As with TX_CREATE, RENAME_WHITEOUT ends up in zfs_mknode(), which
+ * assigns the object's creation time, generation number, and dnode
+ * slot count. The generic zfs_rename() has no concept of these
+ * attributes, so we smuggle the values inside the vattr's otherwise
+ * unused va_ctime, va_nblocks, and va_fsid fields.
+ */
+ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_wcrtime);
+ xva.xva_vattr.va_nblocks = lr->lr_wgen;
+ xva.xva_vattr.va_fsid = dnodesize;
+
+ error = dnode_try_claim(zfsvfs->z_os, objid, dnodesize >> DNODE_SHIFT);
+ if (error)
+ return (error);
+
+ /* sname and tname follow lr_rename_whiteout_t */
+ char *sname = (char *)(lr + 1);
+ char *tname = sname + strlen(sname) + 1;
+ return (do_zfs_replay_rename(zfsvfs, &lr->lr_rename, sname, tname,
+ RENAME_WHITEOUT, &xva.xva_vattr));
+#else
+ return (SET_ERROR(ENOTSUP));
+#endif
+}
+
+static int
zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
@@ -684,6 +814,8 @@ zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap)
int error;
uint64_t eod, offset, length;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -747,6 +879,8 @@ zfs_replay_write2(void *arg1, void *arg2, boolean_t byteswap)
int error;
uint64_t end;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -794,6 +928,8 @@ zfs_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
flock64_t fl = {0};
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -824,6 +960,8 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
int error;
void *start;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
xva_init(&xva);
if (byteswap) {
byteswap_uint64_array(lr, sizeof (*lr));
@@ -860,7 +998,11 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
- error = zfs_setattr(zp, vap, 0, kcred);
+#if defined(__linux__)
+ error = zfs_setattr(zp, vap, 0, kcred, zfs_init_idmap);
+#else
+ error = zfs_setattr(zp, vap, 0, kcred, NULL);
+#endif
zfs_fuid_info_free(zfsvfs->z_fuid_replay);
zfsvfs->z_fuid_replay = NULL;
@@ -882,6 +1024,9 @@ zfs_replay_setsaxattr(void *arg1, void *arg2, boolean_t byteswap)
size_t size;
int error = 0;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr) + lr->lr_size);
+
ASSERT(spa_feature_is_active(zfsvfs->z_os->os_spa,
SPA_FEATURE_ZILSAXATTR));
if (byteswap)
@@ -959,6 +1104,10 @@ zfs_replay_acl_v0(void *arg1, void *arg2, boolean_t byteswap)
znode_t *zp;
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr) +
+ sizeof (ace_t) * lr->lr_aclcnt);
+
if (byteswap) {
byteswap_uint64_array(lr, sizeof (*lr));
zfs_oldace_byteswap(ace, lr->lr_aclcnt);
@@ -1004,6 +1153,9 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap)
znode_t *zp;
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr) + lr->lr_acl_bytes);
+
if (byteswap) {
byteswap_uint64_array(lr, sizeof (*lr));
zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE);
@@ -1043,6 +1195,38 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap)
return (error);
}
+static int
+zfs_replay_clone_range(void *arg1, void *arg2, boolean_t byteswap)
+{
+ zfsvfs_t *zfsvfs = arg1;
+ lr_clone_range_t *lr = arg2;
+ znode_t *zp;
+ int error;
+
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, offsetof(lr_clone_range_t,
+ lr_bps[lr->lr_nbps]));
+
+ if (byteswap)
+ byteswap_uint64_array(lr, sizeof (*lr));
+
+ if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) {
+ /*
+ * Clones can be logged out of order, so don't be surprised if
+ * the file is gone - just return success.
+ */
+ if (error == ENOENT)
+ error = 0;
+ return (error);
+ }
+
+ error = zfs_clone_range_replay(zp, lr->lr_offset, lr->lr_length,
+ lr->lr_blksz, lr->lr_bps, lr->lr_nbps);
+
+ zrele(zp);
+ return (error);
+}
+
/*
* Callback vectors for replaying records
*/
@@ -1069,4 +1253,7 @@ zil_replay_func_t *const zfs_replay_vector[TX_MAX_TYPE] = {
zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */
zfs_replay_write2, /* TX_WRITE2 */
zfs_replay_setsaxattr, /* TX_SETSAXATTR */
+ zfs_replay_rename_exchange, /* TX_RENAME_EXCHANGE */
+ zfs_replay_rename_whiteout, /* TX_RENAME_WHITEOUT */
+ zfs_replay_clone_range, /* TX_CLONE_RANGE */
};
diff --git a/module/zfs/zfs_rlock.c b/module/zfs/zfs_rlock.c
index 06a5e031a7df..f42661df82e4 100644
--- a/module/zfs/zfs_rlock.c
+++ b/module/zfs/zfs_rlock.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zfs_sa.c b/module/zfs/zfs_sa.c
index d0c7e169fde4..fb2443b756f8 100644
--- a/module/zfs/zfs_sa.c
+++ b/module/zfs/zfs_sa.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c
index a039b4da2833..babb07ca25a9 100644
--- a/module/zfs/zfs_vnops.c
+++ b/module/zfs/zfs_vnops.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -24,6 +24,7 @@
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
* Copyright (c) 2015 by Chunwei Chen. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc.
+ * Copyright (c) 2021, 2022 by Pawel Jakub Dawidek
*/
/* Portions Copyright 2007 Jeremy Teo */
@@ -46,36 +47,53 @@
#include <sys/fs/zfs.h>
#include <sys/dmu.h>
#include <sys/dmu_objset.h>
+#include <sys/dsl_crypt.h>
#include <sys/spa.h>
#include <sys/txg.h>
#include <sys/dbuf.h>
#include <sys/policy.h>
+#include <sys/zfeature.h>
#include <sys/zfs_vnops.h>
#include <sys/zfs_quota.h>
#include <sys/zfs_vfsops.h>
#include <sys/zfs_znode.h>
+/*
+ * Enable the experimental block cloning feature. If this setting is 0, then
+ * even if feature@block_cloning is enabled, attempts to clone blocks will act
+ * as though the feature is disabled.
+ */
+int zfs_bclone_enabled = 1;
+
+/*
+ * When set zfs_clone_range() waits for dirty data to be written to disk.
+ * This allows the clone operation to reliably succeed when a file is modified
+ * and then immediately cloned. For small files this may be slower than making
+ * a copy of the file and is therefore not the default. However, in certain
+ * scenarios this behavior may be desirable so a tunable is provided.
+ */
+static int zfs_bclone_wait_dirty = 0;
-static ulong_t zfs_fsync_sync_cnt = 4;
+/*
+ * Maximum bytes to read per chunk in zfs_read().
+ */
+static uint64_t zfs_vnops_read_chunk_size = 1024 * 1024;
int
zfs_fsync(znode_t *zp, int syncflag, cred_t *cr)
{
+ int error = 0;
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- (void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt);
-
if (zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) {
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
atomic_inc_32(&zp->z_sync_writes_cnt);
zil_commit(zfsvfs->z_log, zp->z_id);
atomic_dec_32(&zp->z_sync_writes_cnt);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
}
- tsd_set(zfs_fsyncer_key, NULL);
-
- return (0);
+ return (error);
}
@@ -104,10 +122,10 @@ zfs_holey_common(znode_t *zp, ulong_t cmd, loff_t *off)
hole = B_FALSE;
/* Flush any mmap()'d data to disk */
- if (zn_has_cached_data(zp))
- zn_flush_cached_data(zp, B_FALSE);
+ if (zn_has_cached_data(zp, 0, file_sz - 1))
+ zn_flush_cached_data(zp, B_TRUE);
- lr = zfs_rangelock_enter(&zp->z_rangelock, 0, file_sz, RL_READER);
+ lr = zfs_rangelock_enter(&zp->z_rangelock, 0, UINT64_MAX, RL_READER);
error = dmu_offset_next(ZTOZSB(zp)->z_os, zp->z_id, hole, &noff);
zfs_rangelock_exit(lr);
@@ -146,12 +164,12 @@ zfs_holey(znode_t *zp, ulong_t cmd, loff_t *off)
zfsvfs_t *zfsvfs = ZTOZSB(zp);
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
error = zfs_holey_common(zp, cmd, off);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
#endif /* SEEK_HOLE && SEEK_DATA */
@@ -162,20 +180,28 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr)
zfsvfs_t *zfsvfs = ZTOZSB(zp);
int error;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if (flag & V_ACE_MASK)
- error = zfs_zaccess(zp, mode, flag, B_FALSE, cr);
+#if defined(__linux__)
+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr,
+ zfs_init_idmap);
+#else
+ error = zfs_zaccess(zp, mode, flag, B_FALSE, cr,
+ NULL);
+#endif
else
- error = zfs_zaccess_rwx(zp, mode, flag, cr);
+#if defined(__linux__)
+ error = zfs_zaccess_rwx(zp, mode, flag, cr, zfs_init_idmap);
+#else
+ error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL);
+#endif
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
-static unsigned long zfs_vnops_read_chunk_size = 1024 * 1024; /* Tunable */
-
/*
* Read bytes from specified file into supplied buffer.
*
@@ -201,17 +227,17 @@ zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
boolean_t frsync = B_FALSE;
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
if (zp->z_pflags & ZFS_AV_QUARANTINED) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EACCES));
}
/* We don't copy out anything useful for directories. */
if (Z_ISDIR(ZTOTYPE(zp))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EISDIR));
}
@@ -219,7 +245,7 @@ zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* Validate file offset
*/
if (zfs_uio_offset(uio) < (offset_t)0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -227,7 +253,7 @@ zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* Fasttrack empty reads
*/
if (zfs_uio_resid(uio) == 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -276,7 +302,8 @@ zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
error = mappedread_sf(zp, nbytes, uio);
else
#endif
- if (zn_has_cached_data(zp) && !(ioflag & O_DIRECT)) {
+ if (zn_has_cached_data(zp, zfs_uio_offset(uio),
+ zfs_uio_offset(uio) + nbytes - 1) && !(ioflag & O_DIRECT)) {
error = mappedread(zp, nbytes, uio);
} else {
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
@@ -312,7 +339,7 @@ out:
zfs_rangelock_exit(lr);
ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -404,8 +431,8 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
return (0);
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
sa_bulk_attr_t bulk[4];
int count = 0;
@@ -422,7 +449,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* so check it explicitly here.
*/
if (zfs_is_readonly(zfsvfs)) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EROFS));
}
@@ -434,7 +461,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
if ((zp->z_pflags & ZFS_IMMUTABLE) ||
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
(zfs_uio_offset(uio) < zp->z_size))) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EPERM));
}
@@ -443,19 +470,17 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
*/
offset_t woff = ioflag & O_APPEND ? zp->z_size : zfs_uio_offset(uio);
if (woff < 0) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EINVAL));
}
- const uint64_t max_blksz = zfsvfs->z_max_blksz;
-
/*
* Pre-fault the pages to ensure slow (eg NFS) pages
* don't hold up txg.
- * Skip this if uio contains loaned arc_buf.
*/
- if (zfs_uio_prefaultpages(MIN(n, max_blksz), uio)) {
- ZFS_EXIT(zfsvfs);
+ ssize_t pfbytes = MIN(n, DMU_MAX_ACCESS >> 1);
+ if (zfs_uio_prefaultpages(pfbytes, uio)) {
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EFAULT));
}
@@ -488,9 +513,9 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
lr = zfs_rangelock_enter(&zp->z_rangelock, woff, n, RL_WRITER);
}
- if (zn_rlimit_fsize(zp, uio)) {
+ if (zn_rlimit_fsize_uio(zp, uio)) {
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EFBIG));
}
@@ -498,7 +523,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
if (woff >= limit) {
zfs_rangelock_exit(lr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (SET_ERROR(EFBIG));
}
@@ -507,6 +532,8 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
uint64_t end_size = MAX(zp->z_size, woff + n);
zilog_t *zilog = zfsvfs->z_log;
+ boolean_t commit = (ioflag & (O_SYNC | O_DSYNC)) ||
+ (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS);
const uint64_t uid = KUID_TO_SUID(ZTOUID(zp));
const uint64_t gid = KGID_TO_SGID(ZTOGID(zp));
@@ -529,10 +556,31 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
break;
}
+ uint64_t blksz;
+ if (lr->lr_length == UINT64_MAX && zp->z_size <= zp->z_blksz) {
+ if (zp->z_blksz > zfsvfs->z_max_blksz &&
+ !ISP2(zp->z_blksz)) {
+ /*
+ * File's blocksize is already larger than the
+ * "recordsize" property. Only let it grow to
+ * the next power of 2.
+ */
+ blksz = 1 << highbit64(zp->z_blksz);
+ } else {
+ blksz = zfsvfs->z_max_blksz;
+ }
+ blksz = MIN(blksz, P2ROUNDUP(end_size,
+ SPA_MINBLOCKSIZE));
+ blksz = MAX(blksz, zp->z_blksz);
+ } else {
+ blksz = zp->z_blksz;
+ }
+
arc_buf_t *abuf = NULL;
- if (n >= max_blksz && woff >= zp->z_size &&
- P2PHASE(woff, max_blksz) == 0 &&
- zp->z_blksz == max_blksz) {
+ ssize_t nbytes = n;
+ if (n >= blksz && woff >= zp->z_size &&
+ P2PHASE(woff, blksz) == 0 &&
+ (blksz >= SPA_OLD_MAXBLOCKSIZE || n < 4 * blksz)) {
/*
* This write covers a full block. "Borrow" a buffer
* from the dmu so that we can fill it before we enter
@@ -540,18 +588,26 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* holding up the transaction if the data copy hangs
* up on a pagefault (e.g., from an NFS server mapping).
*/
- size_t cbytes;
-
abuf = dmu_request_arcbuf(sa_get_db(zp->z_sa_hdl),
- max_blksz);
+ blksz);
ASSERT(abuf != NULL);
- ASSERT(arc_buf_size(abuf) == max_blksz);
- if ((error = zfs_uiocopy(abuf->b_data, max_blksz,
- UIO_WRITE, uio, &cbytes))) {
+ ASSERT(arc_buf_size(abuf) == blksz);
+ if ((error = zfs_uiocopy(abuf->b_data, blksz,
+ UIO_WRITE, uio, &nbytes))) {
dmu_return_arcbuf(abuf);
break;
}
- ASSERT3S(cbytes, ==, max_blksz);
+ ASSERT3S(nbytes, ==, blksz);
+ } else {
+ nbytes = MIN(n, (DMU_MAX_ACCESS >> 1) -
+ P2PHASE(woff, blksz));
+ if (pfbytes < nbytes) {
+ if (zfs_uio_prefaultpages(nbytes, uio)) {
+ error = SET_ERROR(EFAULT);
+ break;
+ }
+ pfbytes = nbytes;
+ }
}
/*
@@ -561,8 +617,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
DB_DNODE_ENTER(db);
- dmu_tx_hold_write_by_dnode(tx, DB_DNODE(db), woff,
- MIN(n, max_blksz));
+ dmu_tx_hold_write_by_dnode(tx, DB_DNODE(db), woff, nbytes);
DB_DNODE_EXIT(db);
zfs_sa_upgrade_txholds(tx, zp);
error = dmu_tx_assign(tx, TXG_WAIT);
@@ -585,31 +640,10 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* shrink down lr_length to the appropriate size.
*/
if (lr->lr_length == UINT64_MAX) {
- uint64_t new_blksz;
-
- if (zp->z_blksz > max_blksz) {
- /*
- * File's blocksize is already larger than the
- * "recordsize" property. Only let it grow to
- * the next power of 2.
- */
- ASSERT(!ISP2(zp->z_blksz));
- new_blksz = MIN(end_size,
- 1 << highbit64(zp->z_blksz));
- } else {
- new_blksz = MIN(end_size, max_blksz);
- }
- zfs_grow_blocksize(zp, new_blksz, tx);
+ zfs_grow_blocksize(zp, blksz, tx);
zfs_rangelock_reduce(lr, woff, n);
}
- /*
- * XXX - should we really limit each write to z_max_blksz?
- * Perhaps we should use SPA_MAXBLOCKSIZE chunks?
- */
- const ssize_t nbytes =
- MIN(n, max_blksz - P2PHASE(woff, max_blksz));
-
ssize_t tx_bytes;
if (abuf == NULL) {
tx_bytes = zfs_uio_resid(uio);
@@ -629,12 +663,8 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* zfs_uio_prefaultpages, or prefaultpages may
* error, and we may break the loop early.
*/
- if (tx_bytes != zfs_uio_resid(uio))
- n -= tx_bytes - zfs_uio_resid(uio);
- if (zfs_uio_prefaultpages(MIN(n, max_blksz),
- uio)) {
- break;
- }
+ n -= tx_bytes - zfs_uio_resid(uio);
+ pfbytes -= tx_bytes - zfs_uio_resid(uio);
continue;
}
#endif
@@ -650,15 +680,6 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
}
tx_bytes -= zfs_uio_resid(uio);
} else {
- /* Implied by abuf != NULL: */
- ASSERT3S(n, >=, max_blksz);
- ASSERT0(P2PHASE(woff, max_blksz));
- /*
- * We can simplify nbytes to MIN(n, max_blksz) since
- * P2PHASE(woff, max_blksz) is 0, and knowing
- * n >= max_blksz lets us simplify further:
- */
- ASSERT3S(nbytes, ==, max_blksz);
/*
* Thus, we're writing a full block at a block-aligned
* offset and extending the file past EOF.
@@ -684,7 +705,8 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
zfs_uioskip(uio, nbytes);
tx_bytes = nbytes;
}
- if (tx_bytes && zn_has_cached_data(zp) &&
+ if (tx_bytes &&
+ zn_has_cached_data(zp, woff, woff + tx_bytes - 1) &&
!(ioflag & O_DIRECT)) {
update_pages(zp, woff, tx_bytes, zfsvfs->z_os);
}
@@ -733,7 +755,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
* zfs_clear_setid_bits_if_necessary must precede any of
* the TX_WRITE records logged here.
*/
- zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag,
+ zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, commit,
NULL, NULL);
dmu_tx_commit(tx);
@@ -742,13 +764,7 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
break;
ASSERT3S(tx_bytes, ==, nbytes);
n -= nbytes;
-
- if (n > 0) {
- if (zfs_uio_prefaultpages(MIN(n, max_blksz), uio)) {
- error = SET_ERROR(EFAULT);
- break;
- }
- }
+ pfbytes -= nbytes;
}
zfs_znode_update_vfs(zp);
@@ -761,19 +777,18 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
*/
if (zfsvfs->z_replay || zfs_uio_resid(uio) == start_resid ||
error == EFAULT) {
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
- if (ioflag & (O_SYNC | O_DSYNC) ||
- zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+ if (commit)
zil_commit(zilog, zp->z_id);
const int64_t nwritten = start_resid - zfs_uio_resid(uio);
dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, nwritten);
task_io_account_write(nwritten);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (0);
}
@@ -784,10 +799,10 @@ zfs_getsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr)
int error;
boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
error = zfs_getacl(zp, vsecp, skipaclchk, cr);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -798,17 +813,17 @@ zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr)
zfsvfs_t *zfsvfs = ZTOZSB(zp);
int error;
boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
- zilog_t *zilog = zfsvfs->z_log;
-
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
+ zilog_t *zilog;
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
+ zilog = zfsvfs->z_log;
error = zfs_setacl(zp, vsecp, skipaclchk, cr);
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
- ZFS_EXIT(zfsvfs);
+ zfs_exit(zfsvfs, FTAG);
return (error);
}
@@ -837,7 +852,6 @@ zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf,
uint64_t zp_gen;
ASSERT3P(lwb, !=, NULL);
- ASSERT3P(zio, !=, NULL);
ASSERT3U(size, !=, 0);
/*
@@ -864,7 +878,7 @@ zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf,
return (SET_ERROR(ENOENT));
}
- zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
+ zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
zgd->zgd_lwb = lwb;
zgd->zgd_private = zp;
@@ -887,6 +901,7 @@ zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf,
}
ASSERT(error == 0 || error == ENOENT);
} else { /* indirect write */
+ ASSERT3P(zio, !=, NULL);
/*
* Have to lock the whole block to ensure when it's
* written out and its checksum is being calculated
@@ -915,8 +930,8 @@ zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf,
}
#endif
if (error == 0)
- error = dmu_buf_hold(os, object, offset, zgd, &db,
- DMU_READ_NO_PREFETCH);
+ error = dmu_buf_hold_noread(os, object, offset, zgd,
+ &db);
if (error == 0) {
blkptr_t *bp = &lr->lr_blkptr;
@@ -981,6 +996,546 @@ zfs_get_done(zgd_t *zgd, int error)
kmem_free(zgd, sizeof (zgd_t));
}
+static int
+zfs_enter_two(zfsvfs_t *zfsvfs1, zfsvfs_t *zfsvfs2, const char *tag)
+{
+ int error;
+
+ /* Swap. Not sure if the order of zfs_enter()s is important. */
+ if (zfsvfs1 > zfsvfs2) {
+ zfsvfs_t *tmpzfsvfs;
+
+ tmpzfsvfs = zfsvfs2;
+ zfsvfs2 = zfsvfs1;
+ zfsvfs1 = tmpzfsvfs;
+ }
+
+ error = zfs_enter(zfsvfs1, tag);
+ if (error != 0)
+ return (error);
+ if (zfsvfs1 != zfsvfs2) {
+ error = zfs_enter(zfsvfs2, tag);
+ if (error != 0) {
+ zfs_exit(zfsvfs1, tag);
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+static void
+zfs_exit_two(zfsvfs_t *zfsvfs1, zfsvfs_t *zfsvfs2, const char *tag)
+{
+
+ zfs_exit(zfsvfs1, tag);
+ if (zfsvfs1 != zfsvfs2)
+ zfs_exit(zfsvfs2, tag);
+}
+
+/*
+ * We split each clone request in chunks that can fit into a single ZIL
+ * log entry. Each ZIL log entry can fit 130816 bytes for a block cloning
+ * operation (see zil_max_log_data() and zfs_log_clone_range()). This gives
+ * us room for storing 1022 block pointers.
+ *
+ * On success, the function return the number of bytes copied in *lenp.
+ * Note, it doesn't return how much bytes are left to be copied.
+ * On errors which are caused by any file system limitations or
+ * brt limitations `EINVAL` is returned. In the most cases a user
+ * requested bad parameters, it could be possible to clone the file but
+ * some parameters don't match the requirements.
+ */
+int
+zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
+ uint64_t *outoffp, uint64_t *lenp, cred_t *cr)
+{
+ zfsvfs_t *inzfsvfs, *outzfsvfs;
+ objset_t *inos, *outos;
+ zfs_locked_range_t *inlr, *outlr;
+ dmu_buf_impl_t *db;
+ dmu_tx_t *tx;
+ zilog_t *zilog;
+ uint64_t inoff, outoff, len, done;
+ uint64_t outsize, size;
+ int error;
+ int count = 0;
+ sa_bulk_attr_t bulk[3];
+ uint64_t mtime[2], ctime[2];
+ uint64_t uid, gid, projid;
+ blkptr_t *bps;
+ size_t maxblocks, nbps;
+ uint_t inblksz;
+ uint64_t clear_setid_bits_txg = 0;
+ uint64_t last_synced_txg = 0;
+
+ inoff = *inoffp;
+ outoff = *outoffp;
+ len = *lenp;
+ done = 0;
+
+ inzfsvfs = ZTOZSB(inzp);
+ outzfsvfs = ZTOZSB(outzp);
+
+ /*
+ * We need to call zfs_enter() potentially on two different datasets,
+ * so we need a dedicated function for that.
+ */
+ error = zfs_enter_two(inzfsvfs, outzfsvfs, FTAG);
+ if (error != 0)
+ return (error);
+
+ inos = inzfsvfs->z_os;
+ outos = outzfsvfs->z_os;
+
+ /*
+ * Both source and destination have to belong to the same storage pool.
+ */
+ if (dmu_objset_spa(inos) != dmu_objset_spa(outos)) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EXDEV));
+ }
+
+ /*
+ * outos and inos belongs to the same storage pool.
+ * see a few lines above, only one check.
+ */
+ if (!spa_feature_is_enabled(dmu_objset_spa(outos),
+ SPA_FEATURE_BLOCK_CLONING)) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EOPNOTSUPP));
+ }
+
+ ASSERT(!outzfsvfs->z_replay);
+
+ /*
+ * Block cloning from an unencrypted dataset into an encrypted
+ * dataset and vice versa is not supported.
+ */
+ if (inos->os_encrypted != outos->os_encrypted) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EXDEV));
+ }
+
+ /*
+ * Cloning across encrypted datasets is possible only if they
+ * share the same master key.
+ */
+ if (inos != outos && inos->os_encrypted &&
+ !dmu_objset_crypto_key_equal(inos, outos)) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EXDEV));
+ }
+
+ error = zfs_verify_zp(inzp);
+ if (error == 0)
+ error = zfs_verify_zp(outzp);
+ if (error != 0) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (error);
+ }
+
+ /*
+ * We don't copy source file's flags that's why we don't allow to clone
+ * files that are in quarantine.
+ */
+ if (inzp->z_pflags & ZFS_AV_QUARANTINED) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EACCES));
+ }
+
+ if (inoff >= inzp->z_size) {
+ *lenp = 0;
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (0);
+ }
+ if (len > inzp->z_size - inoff) {
+ len = inzp->z_size - inoff;
+ }
+ if (len == 0) {
+ *lenp = 0;
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (0);
+ }
+
+ /*
+ * Callers might not be able to detect properly that we are read-only,
+ * so check it explicitly here.
+ */
+ if (zfs_is_readonly(outzfsvfs)) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EROFS));
+ }
+
+ /*
+ * If immutable or not appending then return EPERM.
+ * Intentionally allow ZFS_READONLY through here.
+ * See zfs_zaccess_common()
+ */
+ if ((outzp->z_pflags & ZFS_IMMUTABLE) != 0) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EPERM));
+ }
+
+ /*
+ * No overlapping if we are cloning within the same file.
+ */
+ if (inzp == outzp) {
+ if (inoff < outoff + len && outoff < inoff + len) {
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+ return (SET_ERROR(EINVAL));
+ }
+ }
+
+ /* Flush any mmap()'d data to disk */
+ if (zn_has_cached_data(inzp, inoff, inoff + len - 1))
+ zn_flush_cached_data(inzp, B_TRUE);
+
+ /*
+ * Maintain predictable lock order.
+ */
+ if (inzp < outzp || (inzp == outzp && inoff < outoff)) {
+ inlr = zfs_rangelock_enter(&inzp->z_rangelock, inoff, len,
+ RL_READER);
+ outlr = zfs_rangelock_enter(&outzp->z_rangelock, outoff, len,
+ RL_WRITER);
+ } else {
+ outlr = zfs_rangelock_enter(&outzp->z_rangelock, outoff, len,
+ RL_WRITER);
+ inlr = zfs_rangelock_enter(&inzp->z_rangelock, inoff, len,
+ RL_READER);
+ }
+
+ inblksz = inzp->z_blksz;
+
+ /*
+ * We cannot clone into a file with different block size if we can't
+ * grow it (block size is already bigger, has more than one block, or
+ * not locked for growth). There are other possible reasons for the
+ * grow to fail, but we cover what we can before opening transaction
+ * and the rest detect after we try to do it.
+ */
+ if (inblksz < outzp->z_blksz) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+ if (inblksz != outzp->z_blksz && (outzp->z_size > outzp->z_blksz ||
+ outlr->lr_length != UINT64_MAX)) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+
+ /*
+ * Block size must be power-of-2 if destination offset != 0.
+ * There can be no multiple blocks of non-power-of-2 size.
+ */
+ if (outoff != 0 && !ISP2(inblksz)) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+
+ /*
+ * Offsets and len must be at block boundries.
+ */
+ if ((inoff % inblksz) != 0 || (outoff % inblksz) != 0) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+ /*
+ * Length must be multipe of blksz, except for the end of the file.
+ */
+ if ((len % inblksz) != 0 &&
+ (len < inzp->z_size - inoff || len < outzp->z_size - outoff)) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+
+ /*
+ * If we are copying only one block and it is smaller than recordsize
+ * property, do not allow destination to grow beyond one block if it
+ * is not there yet. Otherwise the destination will get stuck with
+ * that block size forever, that can be as small as 512 bytes, no
+ * matter how big the destination grow later.
+ */
+ if (len <= inblksz && inblksz < outzfsvfs->z_max_blksz &&
+ outzp->z_size <= inblksz && outoff + len > inblksz) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+
+ error = zn_rlimit_fsize(outoff + len);
+ if (error != 0) {
+ goto unlock;
+ }
+
+ if (inoff >= MAXOFFSET_T || outoff >= MAXOFFSET_T) {
+ error = SET_ERROR(EFBIG);
+ goto unlock;
+ }
+
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(outzfsvfs), NULL,
+ &mtime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(outzfsvfs), NULL,
+ &ctime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(outzfsvfs), NULL,
+ &outzp->z_size, 8);
+
+ zilog = outzfsvfs->z_log;
+ maxblocks = zil_max_log_data(zilog, sizeof (lr_clone_range_t)) /
+ sizeof (bps[0]);
+
+ uid = KUID_TO_SUID(ZTOUID(outzp));
+ gid = KGID_TO_SGID(ZTOGID(outzp));
+ projid = outzp->z_projid;
+
+ bps = vmem_alloc(sizeof (bps[0]) * maxblocks, KM_SLEEP);
+
+ /*
+ * Clone the file in reasonable size chunks. Each chunk is cloned
+ * in a separate transaction; this keeps the intent log records small
+ * and allows us to do more fine-grained space accounting.
+ */
+ while (len > 0) {
+ size = MIN(inblksz * maxblocks, len);
+
+ if (zfs_id_overblockquota(outzfsvfs, DMU_USERUSED_OBJECT,
+ uid) ||
+ zfs_id_overblockquota(outzfsvfs, DMU_GROUPUSED_OBJECT,
+ gid) ||
+ (projid != ZFS_DEFAULT_PROJID &&
+ zfs_id_overblockquota(outzfsvfs, DMU_PROJECTUSED_OBJECT,
+ projid))) {
+ error = SET_ERROR(EDQUOT);
+ break;
+ }
+
+ nbps = maxblocks;
+ last_synced_txg = spa_last_synced_txg(dmu_objset_spa(inos));
+ error = dmu_read_l0_bps(inos, inzp->z_id, inoff, size, bps,
+ &nbps);
+ if (error != 0) {
+ /*
+ * If we are trying to clone a block that was created
+ * in the current transaction group, the error will be
+ * EAGAIN here. Based on zfs_bclone_wait_dirty either
+ * return a shortened range to the caller so it can
+ * fallback, or wait for the next TXG and check again.
+ */
+ if (error == EAGAIN && zfs_bclone_wait_dirty) {
+ txg_wait_synced(dmu_objset_pool(inos),
+ last_synced_txg + 1);
+ continue;
+ }
+
+ break;
+ }
+
+ /*
+ * Start a transaction.
+ */
+ tx = dmu_tx_create(outos);
+ dmu_tx_hold_sa(tx, outzp->z_sa_hdl, B_FALSE);
+ db = (dmu_buf_impl_t *)sa_get_db(outzp->z_sa_hdl);
+ DB_DNODE_ENTER(db);
+ dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), outoff, size);
+ DB_DNODE_EXIT(db);
+ zfs_sa_upgrade_txholds(tx, outzp);
+ error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error != 0) {
+ dmu_tx_abort(tx);
+ break;
+ }
+
+ /*
+ * Copy source znode's block size. This is done only if the
+ * whole znode is locked (see zfs_rangelock_cb()) and only
+ * on the first iteration since zfs_rangelock_reduce() will
+ * shrink down lr_length to the appropriate size.
+ */
+ if (outlr->lr_length == UINT64_MAX) {
+ zfs_grow_blocksize(outzp, inblksz, tx);
+
+ /*
+ * Block growth may fail for many reasons we can not
+ * predict here. If it happen the cloning is doomed.
+ */
+ if (inblksz != outzp->z_blksz) {
+ error = SET_ERROR(EINVAL);
+ dmu_tx_abort(tx);
+ break;
+ }
+
+ /*
+ * Round range lock up to the block boundary, so we
+ * prevent appends until we are done.
+ */
+ zfs_rangelock_reduce(outlr, outoff,
+ ((len - 1) / inblksz + 1) * inblksz);
+ }
+
+ error = dmu_brt_clone(outos, outzp->z_id, outoff, size, tx,
+ bps, nbps);
+ if (error != 0) {
+ dmu_tx_commit(tx);
+ break;
+ }
+
+ if (zn_has_cached_data(outzp, outoff, outoff + size - 1)) {
+ update_pages(outzp, outoff, size, outos);
+ }
+
+ zfs_clear_setid_bits_if_necessary(outzfsvfs, outzp, cr,
+ &clear_setid_bits_txg, tx);
+
+ zfs_tstamp_update_setup(outzp, CONTENT_MODIFIED, mtime, ctime);
+
+ /*
+ * Update the file size (zp_size) if it has changed;
+ * account for possible concurrent updates.
+ */
+ while ((outsize = outzp->z_size) < outoff + size) {
+ (void) atomic_cas_64(&outzp->z_size, outsize,
+ outoff + size);
+ }
+
+ error = sa_bulk_update(outzp->z_sa_hdl, bulk, count, tx);
+
+ zfs_log_clone_range(zilog, tx, TX_CLONE_RANGE, outzp, outoff,
+ size, inblksz, bps, nbps);
+
+ dmu_tx_commit(tx);
+
+ if (error != 0)
+ break;
+
+ inoff += size;
+ outoff += size;
+ len -= size;
+ done += size;
+ }
+
+ vmem_free(bps, sizeof (bps[0]) * maxblocks);
+ zfs_znode_update_vfs(outzp);
+
+unlock:
+ zfs_rangelock_exit(outlr);
+ zfs_rangelock_exit(inlr);
+
+ if (done > 0) {
+ /*
+ * If we have made at least partial progress, reset the error.
+ */
+ error = 0;
+
+ ZFS_ACCESSTIME_STAMP(inzfsvfs, inzp);
+
+ if (outos->os_sync == ZFS_SYNC_ALWAYS) {
+ zil_commit(zilog, outzp->z_id);
+ }
+
+ *inoffp += done;
+ *outoffp += done;
+ *lenp = done;
+ } else {
+ /*
+ * If we made no progress, there must be a good reason.
+ * EOF is handled explicitly above, before the loop.
+ */
+ ASSERT3S(error, !=, 0);
+ }
+
+ zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
+
+ return (error);
+}
+
+/*
+ * Usual pattern would be to call zfs_clone_range() from zfs_replay_clone(),
+ * but we cannot do that, because when replaying we don't have source znode
+ * available. This is why we need a dedicated replay function.
+ */
+int
+zfs_clone_range_replay(znode_t *zp, uint64_t off, uint64_t len, uint64_t blksz,
+ const blkptr_t *bps, size_t nbps)
+{
+ zfsvfs_t *zfsvfs;
+ dmu_buf_impl_t *db;
+ dmu_tx_t *tx;
+ int error;
+ int count = 0;
+ sa_bulk_attr_t bulk[3];
+ uint64_t mtime[2], ctime[2];
+
+ ASSERT3U(off, <, MAXOFFSET_T);
+ ASSERT3U(len, >, 0);
+ ASSERT3U(nbps, >, 0);
+
+ zfsvfs = ZTOZSB(zp);
+
+ ASSERT(spa_feature_is_enabled(dmu_objset_spa(zfsvfs->z_os),
+ SPA_FEATURE_BLOCK_CLONING));
+
+ if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
+ return (error);
+
+ ASSERT(zfsvfs->z_replay);
+ ASSERT(!zfs_is_readonly(zfsvfs));
+
+ if ((off % blksz) != 0) {
+ zfs_exit(zfsvfs, FTAG);
+ return (SET_ERROR(EINVAL));
+ }
+
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
+ &zp->z_size, 8);
+
+ /*
+ * Start a transaction.
+ */
+ tx = dmu_tx_create(zfsvfs->z_os);
+
+ dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
+ db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
+ DB_DNODE_ENTER(db);
+ dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), off, len);
+ DB_DNODE_EXIT(db);
+ zfs_sa_upgrade_txholds(tx, zp);
+ error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error != 0) {
+ dmu_tx_abort(tx);
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
+
+ if (zp->z_blksz < blksz)
+ zfs_grow_blocksize(zp, blksz, tx);
+
+ dmu_brt_clone(zfsvfs->z_os, zp->z_id, off, len, tx, bps, nbps);
+
+ zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime);
+
+ if (zp->z_size < off + len)
+ zp->z_size = off + len;
+
+ error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
+
+ /*
+ * zil_replaying() not only check if we are replaying ZIL, but also
+ * updates the ZIL header to record replay progress.
+ */
+ VERIFY(zil_replaying(zfsvfs->z_log, tx));
+
+ dmu_tx_commit(tx);
+
+ zfs_znode_update_vfs(zp);
+
+ zfs_exit(zfsvfs, FTAG);
+
+ return (error);
+}
+
EXPORT_SYMBOL(zfs_access);
EXPORT_SYMBOL(zfs_fsync);
EXPORT_SYMBOL(zfs_holey);
@@ -988,6 +1543,14 @@ EXPORT_SYMBOL(zfs_read);
EXPORT_SYMBOL(zfs_write);
EXPORT_SYMBOL(zfs_getsecattr);
EXPORT_SYMBOL(zfs_setsecattr);
+EXPORT_SYMBOL(zfs_clone_range);
+EXPORT_SYMBOL(zfs_clone_range_replay);
-ZFS_MODULE_PARAM(zfs_vnops, zfs_vnops_, read_chunk_size, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_vnops, zfs_vnops_, read_chunk_size, U64, ZMOD_RW,
"Bytes to read per chunk");
+
+ZFS_MODULE_PARAM(zfs, zfs_, bclone_enabled, INT, ZMOD_RW,
+ "Enable block cloning");
+
+ZFS_MODULE_PARAM(zfs, zfs_, bclone_wait_dirty, INT, ZMOD_RW,
+ "Wait for dirty blocks when cloning");
diff --git a/module/zfs/zil.c b/module/zfs/zil.c
index 9de60896d9af..34be54b337fd 100644
--- a/module/zfs/zil.c
+++ b/module/zfs/zil.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -43,6 +43,8 @@
#include <sys/metaslab.h>
#include <sys/trace_zfs.h>
#include <sys/abd.h>
+#include <sys/brt.h>
+#include <sys/wmsum.h>
/*
* The ZFS Intent Log (ZIL) saves "transaction records" (itxs) of system
@@ -89,12 +91,12 @@
* committed to stable storage. Please refer to the zil_commit_waiter()
* function (and the comments within it) for more details.
*/
-static int zfs_commit_timeout_pct = 5;
+static uint_t zfs_commit_timeout_pct = 10;
/*
* See zil.h for more information about these fields.
*/
-static zil_stats_t zil_stats = {
+static zil_kstat_values_t zil_stats = {
{ "zil_commit_count", KSTAT_DATA_UINT64 },
{ "zil_commit_writer_count", KSTAT_DATA_UINT64 },
{ "zil_itx_count", KSTAT_DATA_UINT64 },
@@ -106,11 +108,16 @@ static zil_stats_t zil_stats = {
{ "zil_itx_needcopy_bytes", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_normal_count", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_normal_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_write", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_normal_alloc", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_slog_count", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_write", KSTAT_DATA_UINT64 },
+ { "zil_itx_metaslab_slog_alloc", KSTAT_DATA_UINT64 },
};
-static kstat_t *zil_ksp;
+static zil_sums_t zil_sums_global;
+static kstat_t *zil_kstats_global;
/*
* Disable intent logging replay. This global ZIL switch affects all pools.
@@ -118,10 +125,9 @@ static kstat_t *zil_ksp;
int zil_replay_disable = 0;
/*
- * Disable the DKIOCFLUSHWRITECACHE commands that are normally sent to
- * the disk(s) by the ZIL after an LWB write has completed. Setting this
- * will cause ZIL corruption on power loss if a volatile out-of-order
- * write cache is enabled.
+ * Disable the flush commands that are normally sent to the disk(s) by the ZIL
+ * after an LWB write has completed. Setting this will cause ZIL corruption on
+ * power loss if a volatile out-of-order write cache is enabled.
*/
static int zil_nocacheflush = 0;
@@ -130,13 +136,14 @@ static int zil_nocacheflush = 0;
* Any writes above that will be executed with lower (asynchronous) priority
* to limit potential SLOG device abuse by single active ZIL writer.
*/
-static unsigned long zil_slog_bulk = 768 * 1024;
+static uint64_t zil_slog_bulk = 64 * 1024 * 1024;
static kmem_cache_t *zil_lwb_cache;
static kmem_cache_t *zil_zcw_cache;
-#define LWB_EMPTY(lwb) ((BP_GET_LSIZE(&lwb->lwb_blk) - \
- sizeof (zil_chain_t)) == (lwb->lwb_sz - lwb->lwb_nused))
+static void zil_lwb_commit(zilog_t *zilog, lwb_t *lwb, itx_t *itx);
+static itx_t *zil_itx_clone(itx_t *oitx);
+static uint64_t zil_max_waste_space(zilog_t *zilog);
static int
zil_bp_compare(const void *x1, const void *x2)
@@ -213,16 +220,30 @@ zil_init_log_chain(zilog_t *zilog, blkptr_t *bp)
zc->zc_word[ZIL_ZC_SEQ] = 1ULL;
}
+static int
+zil_kstats_global_update(kstat_t *ksp, int rw)
+{
+ zil_kstat_values_t *zs = ksp->ks_data;
+ ASSERT3P(&zil_stats, ==, zs);
+
+ if (rw == KSTAT_WRITE) {
+ return (SET_ERROR(EACCES));
+ }
+
+ zil_kstat_values_update(zs, &zil_sums_global);
+
+ return (0);
+}
+
/*
* Read a log block and make sure it's valid.
*/
static int
zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
- blkptr_t *nbp, void *dst, char **end)
+ blkptr_t *nbp, char **begin, char **end, arc_buf_t **abuf)
{
- enum zio_flag zio_flags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zio_flags = ZIO_FLAG_CANFAIL;
arc_flags_t aflags = ARC_FLAG_WAIT;
- arc_buf_t *abuf = NULL;
zbookmark_phys_t zb;
int error;
@@ -239,7 +260,7 @@ zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, bp->blk_cksum.zc_word[ZIL_ZC_SEQ]);
error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func,
- &abuf, ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
+ abuf, ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
if (error == 0) {
zio_cksum_t cksum = bp->blk_cksum;
@@ -254,39 +275,35 @@ zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
*/
cksum.zc_word[ZIL_ZC_SEQ]++;
+ uint64_t size = BP_GET_LSIZE(bp);
if (BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_ZILOG2) {
- zil_chain_t *zilc = abuf->b_data;
+ zil_chain_t *zilc = (*abuf)->b_data;
char *lr = (char *)(zilc + 1);
- uint64_t len = zilc->zc_nused - sizeof (zil_chain_t);
if (memcmp(&cksum, &zilc->zc_next_blk.blk_cksum,
- sizeof (cksum)) || BP_IS_HOLE(&zilc->zc_next_blk)) {
+ sizeof (cksum)) ||
+ zilc->zc_nused < sizeof (*zilc) ||
+ zilc->zc_nused > size) {
error = SET_ERROR(ECKSUM);
} else {
- ASSERT3U(len, <=, SPA_OLD_MAXBLOCKSIZE);
- memcpy(dst, lr, len);
- *end = (char *)dst + len;
+ *begin = lr;
+ *end = lr + zilc->zc_nused - sizeof (*zilc);
*nbp = zilc->zc_next_blk;
}
} else {
- char *lr = abuf->b_data;
- uint64_t size = BP_GET_LSIZE(bp);
+ char *lr = (*abuf)->b_data;
zil_chain_t *zilc = (zil_chain_t *)(lr + size) - 1;
if (memcmp(&cksum, &zilc->zc_next_blk.blk_cksum,
- sizeof (cksum)) || BP_IS_HOLE(&zilc->zc_next_blk) ||
+ sizeof (cksum)) ||
(zilc->zc_nused > (size - sizeof (*zilc)))) {
error = SET_ERROR(ECKSUM);
} else {
- ASSERT3U(zilc->zc_nused, <=,
- SPA_OLD_MAXBLOCKSIZE);
- memcpy(dst, lr, zilc->zc_nused);
- *end = (char *)dst + zilc->zc_nused;
+ *begin = lr;
+ *end = lr + zilc->zc_nused;
*nbp = zilc->zc_next_blk;
}
}
-
- arc_buf_destroy(abuf, &abuf);
}
return (error);
@@ -298,7 +315,7 @@ zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
static int
zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf)
{
- enum zio_flag zio_flags = ZIO_FLAG_CANFAIL;
+ zio_flag_t zio_flags = ZIO_FLAG_CANFAIL;
const blkptr_t *bp = &lr->lr_blkptr;
arc_flags_t aflags = ARC_FLAG_WAIT;
arc_buf_t *abuf = NULL;
@@ -322,6 +339,7 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf)
if (wbuf == NULL)
zio_flags |= ZIO_FLAG_RAW;
+ ASSERT3U(BP_GET_LSIZE(bp), !=, 0);
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os), lr->lr_foid,
ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp));
@@ -337,6 +355,89 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf)
return (error);
}
+void
+zil_sums_init(zil_sums_t *zs)
+{
+ wmsum_init(&zs->zil_commit_count, 0);
+ wmsum_init(&zs->zil_commit_writer_count, 0);
+ wmsum_init(&zs->zil_itx_count, 0);
+ wmsum_init(&zs->zil_itx_indirect_count, 0);
+ wmsum_init(&zs->zil_itx_indirect_bytes, 0);
+ wmsum_init(&zs->zil_itx_copied_count, 0);
+ wmsum_init(&zs->zil_itx_copied_bytes, 0);
+ wmsum_init(&zs->zil_itx_needcopy_count, 0);
+ wmsum_init(&zs->zil_itx_needcopy_bytes, 0);
+ wmsum_init(&zs->zil_itx_metaslab_normal_count, 0);
+ wmsum_init(&zs->zil_itx_metaslab_normal_bytes, 0);
+ wmsum_init(&zs->zil_itx_metaslab_normal_write, 0);
+ wmsum_init(&zs->zil_itx_metaslab_normal_alloc, 0);
+ wmsum_init(&zs->zil_itx_metaslab_slog_count, 0);
+ wmsum_init(&zs->zil_itx_metaslab_slog_bytes, 0);
+ wmsum_init(&zs->zil_itx_metaslab_slog_write, 0);
+ wmsum_init(&zs->zil_itx_metaslab_slog_alloc, 0);
+}
+
+void
+zil_sums_fini(zil_sums_t *zs)
+{
+ wmsum_fini(&zs->zil_commit_count);
+ wmsum_fini(&zs->zil_commit_writer_count);
+ wmsum_fini(&zs->zil_itx_count);
+ wmsum_fini(&zs->zil_itx_indirect_count);
+ wmsum_fini(&zs->zil_itx_indirect_bytes);
+ wmsum_fini(&zs->zil_itx_copied_count);
+ wmsum_fini(&zs->zil_itx_copied_bytes);
+ wmsum_fini(&zs->zil_itx_needcopy_count);
+ wmsum_fini(&zs->zil_itx_needcopy_bytes);
+ wmsum_fini(&zs->zil_itx_metaslab_normal_count);
+ wmsum_fini(&zs->zil_itx_metaslab_normal_bytes);
+ wmsum_fini(&zs->zil_itx_metaslab_normal_write);
+ wmsum_fini(&zs->zil_itx_metaslab_normal_alloc);
+ wmsum_fini(&zs->zil_itx_metaslab_slog_count);
+ wmsum_fini(&zs->zil_itx_metaslab_slog_bytes);
+ wmsum_fini(&zs->zil_itx_metaslab_slog_write);
+ wmsum_fini(&zs->zil_itx_metaslab_slog_alloc);
+}
+
+void
+zil_kstat_values_update(zil_kstat_values_t *zs, zil_sums_t *zil_sums)
+{
+ zs->zil_commit_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_commit_count);
+ zs->zil_commit_writer_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_commit_writer_count);
+ zs->zil_itx_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_count);
+ zs->zil_itx_indirect_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_indirect_count);
+ zs->zil_itx_indirect_bytes.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_indirect_bytes);
+ zs->zil_itx_copied_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_copied_count);
+ zs->zil_itx_copied_bytes.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_copied_bytes);
+ zs->zil_itx_needcopy_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_needcopy_count);
+ zs->zil_itx_needcopy_bytes.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_needcopy_bytes);
+ zs->zil_itx_metaslab_normal_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_normal_count);
+ zs->zil_itx_metaslab_normal_bytes.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_normal_bytes);
+ zs->zil_itx_metaslab_normal_write.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_normal_write);
+ zs->zil_itx_metaslab_normal_alloc.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_normal_alloc);
+ zs->zil_itx_metaslab_slog_count.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_slog_count);
+ zs->zil_itx_metaslab_slog_bytes.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_slog_bytes);
+ zs->zil_itx_metaslab_slog_write.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_slog_write);
+ zs->zil_itx_metaslab_slog_alloc.value.ui64 =
+ wmsum_value(&zil_sums->zil_itx_metaslab_slog_alloc);
+}
+
/*
* Parse the intent log, and call parse_func for each valid record within.
*/
@@ -354,7 +455,6 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
uint64_t blk_count = 0;
uint64_t lr_count = 0;
blkptr_t blk, next_blk = {{{{0}}}};
- char *lrbuf, *lrp;
int error = 0;
/*
@@ -372,13 +472,13 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
* If the log has been claimed, stop if we encounter a sequence
* number greater than the highest claimed sequence number.
*/
- lrbuf = zio_buf_alloc(SPA_OLD_MAXBLOCKSIZE);
zil_bp_tree_init(zilog);
for (blk = zh->zh_log; !BP_IS_HOLE(&blk); blk = next_blk) {
uint64_t blk_seq = blk.blk_cksum.zc_word[ZIL_ZC_SEQ];
int reclen;
- char *end = NULL;
+ char *lrp, *end;
+ arc_buf_t *abuf = NULL;
if (blk_seq > claim_blk_seq)
break;
@@ -394,24 +494,42 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
break;
error = zil_read_log_block(zilog, decrypt, &blk, &next_blk,
- lrbuf, &end);
- if (error != 0)
+ &lrp, &end, &abuf);
+ if (error != 0) {
+ if (abuf)
+ arc_buf_destroy(abuf, &abuf);
+ 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) {
+ for (; lrp < end; lrp += reclen) {
lr_t *lr = (lr_t *)lrp;
reclen = lr->lrc_reclen;
ASSERT3U(reclen, >=, sizeof (lr_t));
- if (lr->lrc_seq > claim_lr_seq)
+ ASSERT3U(reclen, <=, end - lrp);
+ if (lr->lrc_seq > claim_lr_seq) {
+ arc_buf_destroy(abuf, &abuf);
goto done;
+ }
error = parse_lr_func(zilog, lr, arg, txg);
- if (error != 0)
+ if (error != 0) {
+ arc_buf_destroy(abuf, &abuf);
goto done;
+ }
ASSERT3U(max_lr_seq, <, lr->lrc_seq);
max_lr_seq = lr->lrc_seq;
lr_count++;
}
+ arc_buf_destroy(abuf, &abuf);
}
done:
zilog->zl_parse_error = error;
@@ -420,12 +538,7 @@ done:
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);
return (error);
}
@@ -443,7 +556,7 @@ zil_clear_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
* that we rewind to is invalid. Thus, we return -1 so
* zil_parse() doesn't attempt to read it.
*/
- if (bp->blk_birth >= first_txg)
+ if (BP_GET_LOGICAL_BIRTH(bp) >= first_txg)
return (-1);
if (zil_bp_tree_add(zilog, bp) != 0)
@@ -469,7 +582,7 @@ zil_claim_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
* Claim log block if not already committed and not already claimed.
* If tx == NULL, just verify that the block is claimable.
*/
- if (BP_IS_HOLE(bp) || bp->blk_birth < first_txg ||
+ if (BP_IS_HOLE(bp) || BP_GET_LOGICAL_BIRTH(bp) < first_txg ||
zil_bp_tree_add(zilog, bp) != 0)
return (0);
@@ -479,14 +592,12 @@ zil_claim_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
}
static int
-zil_claim_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
- uint64_t first_txg)
+zil_claim_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t first_txg)
{
lr_write_t *lr = (lr_write_t *)lrc;
int error;
- if (lrc->lrc_txtype != TX_WRITE)
- return (0);
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
/*
* If the block is not readable, don't claim it. This can happen
@@ -496,7 +607,7 @@ zil_claim_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
* waited for all writes to be stable first), so it is semantically
* correct to declare this the end of the log.
*/
- if (lr->lr_blkptr.blk_birth >= first_txg) {
+ if (BP_GET_LOGICAL_BIRTH(&lr->lr_blkptr) >= first_txg) {
error = zil_read_log_data(zilog, lr, NULL);
if (error != 0)
return (error);
@@ -506,6 +617,77 @@ zil_claim_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
}
static int
+zil_claim_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx,
+ uint64_t first_txg)
+{
+ const lr_clone_range_t *lr = (const lr_clone_range_t *)lrc;
+ const blkptr_t *bp;
+ spa_t *spa = zilog->zl_spa;
+ uint_t ii;
+
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lrc->lrc_reclen, >=, offsetof(lr_clone_range_t,
+ lr_bps[lr->lr_nbps]));
+
+ if (tx == NULL) {
+ return (0);
+ }
+
+ /*
+ * XXX: Do we need to byteswap lr?
+ */
+
+ for (ii = 0; ii < lr->lr_nbps; ii++) {
+ bp = &lr->lr_bps[ii];
+
+ /*
+ * When data is embedded into the BP there is no need to create
+ * BRT entry as there is no data block. Just copy the BP as it
+ * contains the data.
+ */
+ if (BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
+ continue;
+
+ /*
+ * We can not handle block pointers from the future, since they
+ * are not yet allocated. It should not normally happen, but
+ * just in case lets be safe and just stop here now instead of
+ * corrupting the pool.
+ */
+ if (BP_GET_BIRTH(bp) >= first_txg)
+ return (SET_ERROR(ENOENT));
+
+ /*
+ * Assert the block is really allocated before we reference it.
+ */
+ metaslab_check_free(spa, bp);
+ }
+
+ for (ii = 0; ii < lr->lr_nbps; ii++) {
+ bp = &lr->lr_bps[ii];
+ if (!BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp))
+ brt_pending_add(spa, bp, tx);
+ }
+
+ return (0);
+}
+
+static int
+zil_claim_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
+ uint64_t first_txg)
+{
+
+ switch (lrc->lrc_txtype) {
+ case TX_WRITE:
+ return (zil_claim_write(zilog, lrc, tx, first_txg));
+ case TX_CLONE_RANGE:
+ return (zil_claim_clone_range(zilog, lrc, tx, first_txg));
+ default:
+ return (0);
+ }
+}
+
+static int
zil_free_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
uint64_t claim_txg)
{
@@ -517,24 +699,73 @@ zil_free_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
}
static int
-zil_free_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
- uint64_t claim_txg)
+zil_free_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t claim_txg)
{
lr_write_t *lr = (lr_write_t *)lrc;
blkptr_t *bp = &lr->lr_blkptr;
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
+
/*
* If we previously claimed it, we need to free it.
*/
- if (claim_txg != 0 && lrc->lrc_txtype == TX_WRITE &&
- bp->blk_birth >= claim_txg && zil_bp_tree_add(zilog, bp) == 0 &&
- !BP_IS_HOLE(bp))
+ if (BP_GET_LOGICAL_BIRTH(bp) >= claim_txg &&
+ zil_bp_tree_add(zilog, bp) == 0 && !BP_IS_HOLE(bp)) {
zio_free(zilog->zl_spa, dmu_tx_get_txg(tx), bp);
+ }
+
+ return (0);
+}
+
+static int
+zil_free_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx)
+{
+ const lr_clone_range_t *lr = (const lr_clone_range_t *)lrc;
+ const blkptr_t *bp;
+ spa_t *spa;
+ uint_t ii;
+
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lrc->lrc_reclen, >=, offsetof(lr_clone_range_t,
+ lr_bps[lr->lr_nbps]));
+
+ if (tx == NULL) {
+ return (0);
+ }
+
+ spa = zilog->zl_spa;
+
+ for (ii = 0; ii < lr->lr_nbps; ii++) {
+ bp = &lr->lr_bps[ii];
+
+ if (!BP_IS_HOLE(bp)) {
+ zio_free(spa, dmu_tx_get_txg(tx), bp);
+ }
+ }
return (0);
}
static int
+zil_free_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
+ uint64_t claim_txg)
+{
+
+ if (claim_txg == 0) {
+ return (0);
+ }
+
+ switch (lrc->lrc_txtype) {
+ case TX_WRITE:
+ return (zil_free_write(zilog, lrc, tx, claim_txg));
+ case TX_CLONE_RANGE:
+ return (zil_free_clone_range(zilog, lrc, tx));
+ default:
+ return (0);
+ }
+}
+
+static int
zil_lwb_vdev_compare(const void *x1, const void *x2)
{
const uint64_t v1 = ((zil_vdev_node_t *)x1)->zv_vdev;
@@ -543,41 +774,54 @@ zil_lwb_vdev_compare(const void *x1, const void *x2)
return (TREE_CMP(v1, v2));
}
+/*
+ * Allocate a new lwb. We may already have a block pointer for it, in which
+ * case we get size and version from there. Or we may not yet, in which case
+ * we choose them here and later make the block allocation match.
+ */
static lwb_t *
-zil_alloc_lwb(zilog_t *zilog, blkptr_t *bp, boolean_t slog, uint64_t txg,
- boolean_t fastwrite)
+zil_alloc_lwb(zilog_t *zilog, int sz, blkptr_t *bp, boolean_t slog,
+ uint64_t txg, lwb_state_t state)
{
lwb_t *lwb;
lwb = kmem_cache_alloc(zil_lwb_cache, KM_SLEEP);
lwb->lwb_zilog = zilog;
- lwb->lwb_blk = *bp;
- lwb->lwb_fastwrite = fastwrite;
+ if (bp) {
+ lwb->lwb_blk = *bp;
+ lwb->lwb_slim = (BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_ZILOG2);
+ sz = BP_GET_LSIZE(bp);
+ } else {
+ BP_ZERO(&lwb->lwb_blk);
+ lwb->lwb_slim = (spa_version(zilog->zl_spa) >=
+ SPA_VERSION_SLIM_ZIL);
+ }
lwb->lwb_slog = slog;
- lwb->lwb_state = LWB_STATE_CLOSED;
- lwb->lwb_buf = zio_buf_alloc(BP_GET_LSIZE(bp));
- lwb->lwb_max_txg = txg;
+ lwb->lwb_error = 0;
+ if (lwb->lwb_slim) {
+ lwb->lwb_nmax = sz;
+ lwb->lwb_nused = lwb->lwb_nfilled = sizeof (zil_chain_t);
+ } else {
+ lwb->lwb_nmax = sz - sizeof (zil_chain_t);
+ lwb->lwb_nused = lwb->lwb_nfilled = 0;
+ }
+ lwb->lwb_sz = sz;
+ lwb->lwb_state = state;
+ lwb->lwb_buf = zio_buf_alloc(sz);
+ lwb->lwb_child_zio = NULL;
lwb->lwb_write_zio = NULL;
lwb->lwb_root_zio = NULL;
lwb->lwb_issued_timestamp = 0;
lwb->lwb_issued_txg = 0;
- if (BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_ZILOG2) {
- lwb->lwb_nused = sizeof (zil_chain_t);
- lwb->lwb_sz = BP_GET_LSIZE(bp);
- } else {
- lwb->lwb_nused = 0;
- lwb->lwb_sz = BP_GET_LSIZE(bp) - sizeof (zil_chain_t);
- }
+ lwb->lwb_alloc_txg = txg;
+ lwb->lwb_max_txg = 0;
mutex_enter(&zilog->zl_lock);
list_insert_tail(&zilog->zl_lwb_list, lwb);
+ if (state != LWB_STATE_NEW)
+ zilog->zl_last_lwb_opened = lwb;
mutex_exit(&zilog->zl_lock);
- ASSERT(!MUTEX_HELD(&lwb->lwb_vdev_lock));
- ASSERT(avl_is_empty(&lwb->lwb_vdev_tree));
- VERIFY(list_is_empty(&lwb->lwb_waiters));
- VERIFY(list_is_empty(&lwb->lwb_itxs));
-
return (lwb);
}
@@ -585,15 +829,17 @@ static void
zil_free_lwb(zilog_t *zilog, lwb_t *lwb)
{
ASSERT(MUTEX_HELD(&zilog->zl_lock));
- ASSERT(!MUTEX_HELD(&lwb->lwb_vdev_lock));
- VERIFY(list_is_empty(&lwb->lwb_waiters));
- VERIFY(list_is_empty(&lwb->lwb_itxs));
- ASSERT(avl_is_empty(&lwb->lwb_vdev_tree));
+ ASSERT(lwb->lwb_state == LWB_STATE_NEW ||
+ lwb->lwb_state == LWB_STATE_FLUSH_DONE);
+ ASSERT3P(lwb->lwb_child_zio, ==, NULL);
ASSERT3P(lwb->lwb_write_zio, ==, NULL);
ASSERT3P(lwb->lwb_root_zio, ==, NULL);
+ ASSERT3U(lwb->lwb_alloc_txg, <=, spa_syncing_txg(zilog->zl_spa));
ASSERT3U(lwb->lwb_max_txg, <=, spa_syncing_txg(zilog->zl_spa));
- ASSERT(lwb->lwb_state == LWB_STATE_CLOSED ||
- lwb->lwb_state == LWB_STATE_FLUSH_DONE);
+ VERIFY(list_is_empty(&lwb->lwb_itxs));
+ VERIFY(list_is_empty(&lwb->lwb_waiters));
+ ASSERT(avl_is_empty(&lwb->lwb_vdev_tree));
+ ASSERT(!MUTEX_HELD(&lwb->lwb_vdev_lock));
/*
* Clear the zilog's field to indicate this lwb is no longer
@@ -674,11 +920,9 @@ zil_commit_activate_saxattr_feature(zilog_t *zilog)
uint64_t txg = 0;
dmu_tx_t *tx = NULL;
- if (spa_feature_is_enabled(zilog->zl_spa,
- SPA_FEATURE_ZILSAXATTR) &&
+ if (spa_feature_is_enabled(zilog->zl_spa, SPA_FEATURE_ZILSAXATTR) &&
dmu_objset_type(zilog->zl_os) != DMU_OST_ZVOL &&
- !dsl_dataset_feature_is_active(ds,
- SPA_FEATURE_ZILSAXATTR)) {
+ !dsl_dataset_feature_is_active(ds, SPA_FEATURE_ZILSAXATTR)) {
tx = dmu_tx_create(zilog->zl_os);
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
dsl_dataset_dirty(ds, tx);
@@ -705,7 +949,6 @@ zil_create(zilog_t *zilog)
dmu_tx_t *tx = NULL;
blkptr_t blk;
int error = 0;
- boolean_t fastwrite = FALSE;
boolean_t slog = FALSE;
dsl_dataset_t *ds = dmu_objset_ds(zilog->zl_os);
@@ -738,8 +981,6 @@ zil_create(zilog_t *zilog)
error = zio_alloc_zil(zilog->zl_spa, zilog->zl_os, txg, &blk,
ZIL_MIN_BLKSZ, &slog);
- fastwrite = TRUE;
-
if (error == 0)
zil_init_log_chain(zilog, &blk);
}
@@ -748,7 +989,7 @@ zil_create(zilog_t *zilog)
* Allocate a log write block (lwb) for the first log block.
*/
if (error == 0)
- lwb = zil_alloc_lwb(zilog, &blk, slog, txg, fastwrite);
+ lwb = zil_alloc_lwb(zilog, 0, &blk, slog, txg, LWB_STATE_NEW);
/*
* If we just allocated the first log block, commit our transaction
@@ -798,8 +1039,9 @@ zil_create(zilog_t *zilog)
* txg_wait_synced() here either when keep_first is set, because both
* zil_create() and zil_destroy() will wait for any in-progress destroys
* to complete.
+ * Return B_TRUE if there were any entries to replay.
*/
-void
+boolean_t
zil_destroy(zilog_t *zilog, boolean_t keep_first)
{
const zil_header_t *zh = zilog->zl_header;
@@ -815,7 +1057,7 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
zilog->zl_old_header = *zh; /* debugging aid */
if (BP_IS_HOLE(&zh->zh_log))
- return;
+ return (B_FALSE);
tx = dmu_tx_create(zilog->zl_os);
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
@@ -831,15 +1073,11 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
if (!list_is_empty(&zilog->zl_lwb_list)) {
ASSERT(zh->zh_claim_txg == 0);
VERIFY(!keep_first);
- while ((lwb = list_head(&zilog->zl_lwb_list)) != NULL) {
- if (lwb->lwb_fastwrite)
- metaslab_fastwrite_unmark(zilog->zl_spa,
- &lwb->lwb_blk);
-
- list_remove(&zilog->zl_lwb_list, lwb);
+ while ((lwb = list_remove_head(&zilog->zl_lwb_list)) != NULL) {
if (lwb->lwb_buf != NULL)
zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
- zio_free(zilog->zl_spa, txg, &lwb->lwb_blk);
+ if (!BP_IS_HOLE(&lwb->lwb_blk))
+ zio_free(zilog->zl_spa, txg, &lwb->lwb_blk);
zil_free_lwb(zilog, lwb);
}
} else if (!keep_first) {
@@ -848,6 +1086,8 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
mutex_exit(&zilog->zl_lock);
dmu_tx_commit(tx);
+
+ return (B_TRUE);
}
void
@@ -1065,21 +1305,21 @@ zil_commit_waiter_link_lwb(zil_commit_waiter_t *zcw, lwb_t *lwb)
{
/*
* The lwb_waiters field of the lwb is protected by the zilog's
- * zl_lock, thus it must be held when calling this function.
+ * zl_issuer_lock while the lwb is open and zl_lock otherwise.
+ * zl_issuer_lock also protects leaving the open state.
+ * zcw_lwb setting is protected by zl_issuer_lock and state !=
+ * flush_done, which transition is protected by zl_lock.
*/
- ASSERT(MUTEX_HELD(&lwb->lwb_zilog->zl_lock));
+ ASSERT(MUTEX_HELD(&lwb->lwb_zilog->zl_issuer_lock));
+ IMPLY(lwb->lwb_state != LWB_STATE_OPENED,
+ MUTEX_HELD(&lwb->lwb_zilog->zl_lock));
+ ASSERT3S(lwb->lwb_state, !=, LWB_STATE_NEW);
+ ASSERT3S(lwb->lwb_state, !=, LWB_STATE_FLUSH_DONE);
- mutex_enter(&zcw->zcw_lock);
ASSERT(!list_link_active(&zcw->zcw_node));
- ASSERT3P(zcw->zcw_lwb, ==, NULL);
- ASSERT3P(lwb, !=, NULL);
- ASSERT(lwb->lwb_state == LWB_STATE_OPENED ||
- lwb->lwb_state == LWB_STATE_ISSUED ||
- lwb->lwb_state == LWB_STATE_WRITE_DONE);
-
list_insert_tail(&lwb->lwb_waiters, zcw);
+ ASSERT3P(zcw->zcw_lwb, ==, NULL);
zcw->zcw_lwb = lwb;
- mutex_exit(&zcw->zcw_lock);
}
/*
@@ -1090,11 +1330,9 @@ zil_commit_waiter_link_lwb(zil_commit_waiter_t *zcw, lwb_t *lwb)
static void
zil_commit_waiter_link_nolwb(zil_commit_waiter_t *zcw, list_t *nolwb)
{
- mutex_enter(&zcw->zcw_lock);
ASSERT(!list_link_active(&zcw->zcw_node));
- ASSERT3P(zcw->zcw_lwb, ==, NULL);
list_insert_tail(nolwb, zcw);
- mutex_exit(&zcw->zcw_lock);
+ ASSERT3P(zcw->zcw_lwb, ==, NULL);
}
void
@@ -1106,6 +1344,9 @@ zil_lwb_add_block(lwb_t *lwb, const blkptr_t *bp)
int ndvas = BP_GET_NDVAS(bp);
int i;
+ ASSERT3S(lwb->lwb_state, !=, LWB_STATE_WRITE_DONE);
+ ASSERT3S(lwb->lwb_state, !=, LWB_STATE_FLUSH_DONE);
+
if (zil_nocacheflush)
return;
@@ -1164,19 +1405,17 @@ zil_lwb_add_txg(lwb_t *lwb, uint64_t txg)
}
/*
- * This function is a called after all vdevs associated with a given lwb
- * write have completed their DKIOCFLUSHWRITECACHE command; or as soon
- * as the lwb write completes, if "zil_nocacheflush" is set. Further,
- * all "previous" lwb's will have completed before this function is
- * called; i.e. this function is called for all previous lwbs before
- * it's called for "this" lwb (enforced via zio the dependencies
- * configured in zil_lwb_set_zio_dependency()).
+ * This function is a called after all vdevs associated with a given lwb write
+ * have completed their flush command; or as soon as the lwb write completes,
+ * if "zil_nocacheflush" is set. Further, all "previous" lwb's will have
+ * completed before this function is called; i.e. this function is called for
+ * all previous lwbs before it's called for "this" lwb (enforced via zio the
+ * dependencies configured in zil_lwb_set_zio_dependency()).
*
- * The intention is for this function to be called as soon as the
- * contents of an lwb are considered "stable" on disk, and will survive
- * any sudden loss of power. At this point, any threads waiting for the
- * lwb to reach this state are signalled, and the "waiter" structures
- * are marked "done".
+ * The intention is for this function to be called as soon as the contents of
+ * an lwb are considered "stable" on disk, and will survive any sudden loss of
+ * power. At this point, any threads waiting for the lwb to reach this state
+ * are signalled, and the "waiter" structures are marked "done".
*/
static void
zil_lwb_flush_vdevs_done(zio_t *zio)
@@ -1185,25 +1424,14 @@ zil_lwb_flush_vdevs_done(zio_t *zio)
zilog_t *zilog = lwb->lwb_zilog;
zil_commit_waiter_t *zcw;
itx_t *itx;
- uint64_t txg;
spa_config_exit(zilog->zl_spa, SCL_STATE, lwb);
- zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
+ hrtime_t t = gethrtime() - lwb->lwb_issued_timestamp;
mutex_enter(&zilog->zl_lock);
- /*
- * If we have had an allocation failure and the txg is
- * waiting to sync then we want zil_sync() to remove the lwb so
- * that it's not picked up as the next new one in
- * zil_process_commit_list(). zil_sync() will only remove the
- * lwb if lwb_buf is null.
- */
- lwb->lwb_buf = NULL;
-
- ASSERT3U(lwb->lwb_issued_timestamp, >, 0);
- zilog->zl_last_lwb_latency = gethrtime() - lwb->lwb_issued_timestamp;
+ zilog->zl_last_lwb_latency = (zilog->zl_last_lwb_latency * 7 + t) / 8;
lwb->lwb_root_zio = NULL;
@@ -1220,17 +1448,12 @@ zil_lwb_flush_vdevs_done(zio_t *zio)
zilog->zl_commit_lr_seq = zilog->zl_lr_seq;
}
- while ((itx = list_head(&lwb->lwb_itxs)) != NULL) {
- list_remove(&lwb->lwb_itxs, itx);
+ while ((itx = list_remove_head(&lwb->lwb_itxs)) != NULL)
zil_itx_destroy(itx);
- }
- while ((zcw = list_head(&lwb->lwb_waiters)) != NULL) {
+ while ((zcw = list_remove_head(&lwb->lwb_waiters)) != NULL) {
mutex_enter(&zcw->zcw_lock);
- ASSERT(list_link_active(&zcw->zcw_node));
- list_remove(&lwb->lwb_waiters, zcw);
-
ASSERT3P(zcw->zcw_lwb, ==, lwb);
zcw->zcw_lwb = NULL;
/*
@@ -1257,10 +1480,12 @@ zil_lwb_flush_vdevs_done(zio_t *zio)
mutex_exit(&zcw->zcw_lock);
}
+ uint64_t txg = lwb->lwb_issued_txg;
+
+ /* Once we drop the lock, lwb may be freed by zil_sync(). */
mutex_exit(&zilog->zl_lock);
mutex_enter(&zilog->zl_lwb_io_lock);
- txg = lwb->lwb_issued_txg;
ASSERT3U(zilog->zl_lwb_inflight[txg & TXG_MASK], >, 0);
zilog->zl_lwb_inflight[txg & TXG_MASK]--;
if (zilog->zl_lwb_inflight[txg & TXG_MASK] == 0)
@@ -1286,14 +1511,15 @@ zil_lwb_flush_wait_all(zilog_t *zilog, uint64_t txg)
mutex_enter(&zilog->zl_lock);
mutex_enter(&zilog->zl_lwb_io_lock);
lwb_t *lwb = list_head(&zilog->zl_lwb_list);
- while (lwb != NULL && lwb->lwb_max_txg <= txg) {
+ while (lwb != NULL) {
if (lwb->lwb_issued_txg <= txg) {
ASSERT(lwb->lwb_state != LWB_STATE_ISSUED);
ASSERT(lwb->lwb_state != LWB_STATE_WRITE_DONE);
IMPLY(lwb->lwb_issued_txg > 0,
lwb->lwb_state == LWB_STATE_FLUSH_DONE);
}
- IMPLY(lwb->lwb_state == LWB_STATE_FLUSH_DONE,
+ IMPLY(lwb->lwb_state == LWB_STATE_WRITE_DONE ||
+ lwb->lwb_state == LWB_STATE_FLUSH_DONE,
lwb->lwb_buf == NULL);
lwb = list_next(&zilog->zl_lwb_list, lwb);
}
@@ -1303,17 +1529,16 @@ zil_lwb_flush_wait_all(zilog_t *zilog, uint64_t txg)
}
/*
- * This is called when an lwb's write zio completes. The callback's
- * purpose is to issue the DKIOCFLUSHWRITECACHE commands for the vdevs
- * in the lwb's lwb_vdev_tree. The tree will contain the vdevs involved
- * in writing out this specific lwb's data, and in the case that cache
- * flushes have been deferred, vdevs involved in writing the data for
- * previous lwbs. The writes corresponding to all the vdevs in the
- * lwb_vdev_tree will have completed by the time this is called, due to
- * the zio dependencies configured in zil_lwb_set_zio_dependency(),
- * which takes deferred flushes into account. The lwb will be "done"
- * once zil_lwb_flush_vdevs_done() is called, which occurs in the zio
- * completion callback for the lwb's root zio.
+ * This is called when an lwb's write zio completes. The callback's purpose is
+ * to issue the flush commands for the vdevs in the lwb's lwb_vdev_tree. The
+ * tree will contain the vdevs involved in writing out this specific lwb's
+ * data, and in the case that cache flushes have been deferred, vdevs involved
+ * in writing the data for previous lwbs. The writes corresponding to all the
+ * vdevs in the lwb_vdev_tree will have completed by the time this is called,
+ * due to the zio dependencies configured in zil_lwb_set_zio_dependency(),
+ * which takes deferred flushes into account. The lwb will be "done" once
+ * zil_lwb_flush_vdevs_done() is called, which occurs in the zio completion
+ * callback for the lwb's root zio.
*/
static void
zil_lwb_write_done(zio_t *zio)
@@ -1328,22 +1553,25 @@ zil_lwb_write_done(zio_t *zio)
ASSERT3S(spa_config_held(spa, SCL_STATE, RW_READER), !=, 0);
- ASSERT(BP_GET_COMPRESS(zio->io_bp) == ZIO_COMPRESS_OFF);
- ASSERT(BP_GET_TYPE(zio->io_bp) == DMU_OT_INTENT_LOG);
- ASSERT(BP_GET_LEVEL(zio->io_bp) == 0);
- ASSERT(BP_GET_BYTEORDER(zio->io_bp) == ZFS_HOST_BYTEORDER);
- ASSERT(!BP_IS_GANG(zio->io_bp));
- ASSERT(!BP_IS_HOLE(zio->io_bp));
- ASSERT(BP_GET_FILL(zio->io_bp) == 0);
-
abd_free(zio->io_abd);
+ zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
+ lwb->lwb_buf = NULL;
mutex_enter(&zilog->zl_lock);
ASSERT3S(lwb->lwb_state, ==, LWB_STATE_ISSUED);
lwb->lwb_state = LWB_STATE_WRITE_DONE;
+ lwb->lwb_child_zio = NULL;
lwb->lwb_write_zio = NULL;
- lwb->lwb_fastwrite = FALSE;
+
+ /*
+ * If nlwb is not yet issued, zil_lwb_set_zio_dependency() is not
+ * called for it yet, and when it will be, it won't be able to make
+ * its write ZIO a parent this ZIO. In such case we can not defer
+ * our flushes or below may be a race between the done callbacks.
+ */
nlwb = list_next(&zilog->zl_lwb_list, lwb);
+ if (nlwb && nlwb->lwb_state != LWB_STATE_ISSUED)
+ nlwb = NULL;
mutex_exit(&zilog->zl_lock);
if (avl_numnodes(t) == 0)
@@ -1369,21 +1597,20 @@ zil_lwb_write_done(zio_t *zio)
}
/*
- * If this lwb does not have any threads waiting for it to
- * complete, we want to defer issuing the DKIOCFLUSHWRITECACHE
- * command to the vdevs written to by "this" lwb, and instead
- * rely on the "next" lwb to handle the DKIOCFLUSHWRITECACHE
- * command for those vdevs. Thus, we merge the vdev tree of
- * "this" lwb with the vdev tree of the "next" lwb in the list,
- * and assume the "next" lwb will handle flushing the vdevs (or
- * deferring the flush(s) again).
+ * If this lwb does not have any threads waiting for it to complete, we
+ * want to defer issuing the flush command to the vdevs written to by
+ * "this" lwb, and instead rely on the "next" lwb to handle the flush
+ * command for those vdevs. Thus, we merge the vdev tree of "this" lwb
+ * with the vdev tree of the "next" lwb in the list, and assume the
+ * "next" lwb will handle flushing the vdevs (or deferring the flush(s)
+ * again).
*
- * This is a useful performance optimization, especially for
- * workloads with lots of async write activity and few sync
- * write and/or fsync activity, as it has the potential to
- * coalesce multiple flush commands to a vdev into one.
+ * This is a useful performance optimization, especially for workloads
+ * with lots of async write activity and few sync write and/or fsync
+ * activity, as it has the potential to coalesce multiple flush
+ * commands to a vdev into one.
*/
- if (list_head(&lwb->lwb_waiters) == NULL && nlwb != NULL) {
+ if (list_is_empty(&lwb->lwb_waiters) && nlwb != NULL) {
zil_lwb_flush_defer(lwb, nlwb);
ASSERT(avl_is_empty(&lwb->lwb_vdev_tree));
return;
@@ -1406,339 +1633,487 @@ zil_lwb_write_done(zio_t *zio)
}
}
+/*
+ * Build the zio dependency chain, which is used to preserve the ordering of
+ * lwb completions that is required by the semantics of the ZIL. Each new lwb
+ * zio becomes a parent of the previous lwb zio, such that the new lwb's zio
+ * cannot complete until the previous lwb's zio completes.
+ *
+ * This is required by the semantics of zil_commit(): the commit waiters
+ * attached to the lwbs will be woken in the lwb zio's completion callback,
+ * so this zio dependency graph ensures the waiters are woken in the correct
+ * order (the same order the lwbs were created).
+ */
static void
zil_lwb_set_zio_dependency(zilog_t *zilog, lwb_t *lwb)
{
- lwb_t *last_lwb_opened = zilog->zl_last_lwb_opened;
-
- ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
ASSERT(MUTEX_HELD(&zilog->zl_lock));
+ lwb_t *prev_lwb = list_prev(&zilog->zl_lwb_list, lwb);
+ if (prev_lwb == NULL ||
+ prev_lwb->lwb_state == LWB_STATE_FLUSH_DONE)
+ return;
+
/*
- * The zilog's "zl_last_lwb_opened" field is used to build the
- * lwb/zio dependency chain, which is used to preserve the
- * ordering of lwb completions that is required by the semantics
- * of the ZIL. Each new lwb zio becomes a parent of the
- * "previous" lwb zio, such that the new lwb's zio cannot
- * complete until the "previous" lwb's zio completes.
+ * If the previous lwb's write hasn't already completed, we also want
+ * to order the completion of the lwb write zios (above, we only order
+ * the completion of the lwb root zios). This is required because of
+ * how we can defer the flush commands for each lwb.
*
- * This is required by the semantics of zil_commit(); the commit
- * waiters attached to the lwbs will be woken in the lwb zio's
- * completion callback, so this zio dependency graph ensures the
- * waiters are woken in the correct order (the same order the
- * lwbs were created).
- */
- if (last_lwb_opened != NULL &&
- last_lwb_opened->lwb_state != LWB_STATE_FLUSH_DONE) {
- ASSERT(last_lwb_opened->lwb_state == LWB_STATE_OPENED ||
- last_lwb_opened->lwb_state == LWB_STATE_ISSUED ||
- last_lwb_opened->lwb_state == LWB_STATE_WRITE_DONE);
-
- ASSERT3P(last_lwb_opened->lwb_root_zio, !=, NULL);
- zio_add_child(lwb->lwb_root_zio,
- last_lwb_opened->lwb_root_zio);
-
- /*
- * If the previous lwb's write hasn't already completed,
- * we also want to order the completion of the lwb write
- * zios (above, we only order the completion of the lwb
- * root zios). This is required because of how we can
- * defer the DKIOCFLUSHWRITECACHE commands for each lwb.
- *
- * When the DKIOCFLUSHWRITECACHE commands are deferred,
- * the previous lwb will rely on this lwb to flush the
- * vdevs written to by that previous lwb. Thus, we need
- * to ensure this lwb doesn't issue the flush until
- * after the previous lwb's write completes. We ensure
- * this ordering by setting the zio parent/child
- * relationship here.
- *
- * Without this relationship on the lwb's write zio,
- * it's possible for this lwb's write to complete prior
- * to the previous lwb's write completing; and thus, the
- * vdevs for the previous lwb would be flushed prior to
- * that lwb's data being written to those vdevs (the
- * vdevs are flushed in the lwb write zio's completion
- * handler, zil_lwb_write_done()).
- */
- if (last_lwb_opened->lwb_state != LWB_STATE_WRITE_DONE) {
- ASSERT(last_lwb_opened->lwb_state == LWB_STATE_OPENED ||
- last_lwb_opened->lwb_state == LWB_STATE_ISSUED);
-
- ASSERT3P(last_lwb_opened->lwb_write_zio, !=, NULL);
- zio_add_child(lwb->lwb_write_zio,
- last_lwb_opened->lwb_write_zio);
- }
+ * When the flush commands are deferred, the previous lwb will rely on
+ * this lwb to flush the vdevs written to by that previous lwb. Thus,
+ * we need to ensure this lwb doesn't issue the flush until after the
+ * previous lwb's write completes. We ensure this ordering by setting
+ * the zio parent/child relationship here.
+ *
+ * Without this relationship on the lwb's write zio, it's possible for
+ * this lwb's write to complete prior to the previous lwb's write
+ * completing; and thus, the vdevs for the previous lwb would be
+ * flushed prior to that lwb's data being written to those vdevs (the
+ * vdevs are flushed in the lwb write zio's completion handler,
+ * zil_lwb_write_done()).
+ */
+ if (prev_lwb->lwb_state == LWB_STATE_ISSUED) {
+ ASSERT3P(prev_lwb->lwb_write_zio, !=, NULL);
+ zio_add_child(lwb->lwb_write_zio, prev_lwb->lwb_write_zio);
+ } else {
+ ASSERT3S(prev_lwb->lwb_state, ==, LWB_STATE_WRITE_DONE);
}
+
+ ASSERT3P(prev_lwb->lwb_root_zio, !=, NULL);
+ zio_add_child(lwb->lwb_root_zio, prev_lwb->lwb_root_zio);
}
/*
* This function's purpose is to "open" an lwb such that it is ready to
- * accept new itxs being committed to it. To do this, the lwb's zio
- * structures are created, and linked to the lwb. This function is
- * idempotent; if the passed in lwb has already been opened, this
- * function is essentially a no-op.
+ * accept new itxs being committed to it. This function is idempotent; if
+ * the passed in lwb has already been opened, it is essentially a no-op.
*/
static void
zil_lwb_write_open(zilog_t *zilog, lwb_t *lwb)
{
- zbookmark_phys_t zb;
- zio_priority_t prio;
-
ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
- ASSERT3P(lwb, !=, NULL);
- EQUIV(lwb->lwb_root_zio == NULL, lwb->lwb_state == LWB_STATE_CLOSED);
- EQUIV(lwb->lwb_root_zio != NULL, lwb->lwb_state == LWB_STATE_OPENED);
- SET_BOOKMARK(&zb, lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_OBJSET],
- ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
- lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_SEQ]);
+ if (lwb->lwb_state != LWB_STATE_NEW) {
+ ASSERT3S(lwb->lwb_state, ==, LWB_STATE_OPENED);
+ return;
+ }
- /* Lock so zil_sync() doesn't fastwrite_unmark after zio is created */
mutex_enter(&zilog->zl_lock);
- if (lwb->lwb_root_zio == NULL) {
- abd_t *lwb_abd = abd_get_from_buf(lwb->lwb_buf,
- BP_GET_LSIZE(&lwb->lwb_blk));
+ lwb->lwb_state = LWB_STATE_OPENED;
+ zilog->zl_last_lwb_opened = lwb;
+ mutex_exit(&zilog->zl_lock);
+}
- if (!lwb->lwb_fastwrite) {
- metaslab_fastwrite_mark(zilog->zl_spa, &lwb->lwb_blk);
- lwb->lwb_fastwrite = 1;
- }
+/*
+ * Maximum block size used by the ZIL. This is picked up when the ZIL is
+ * initialized. Otherwise this should not be used directly; see
+ * zl_max_block_size instead.
+ */
+static uint_t zil_maxblocksize = SPA_OLD_MAXBLOCKSIZE;
- if (!lwb->lwb_slog || zilog->zl_cur_used <= zil_slog_bulk)
- prio = ZIO_PRIORITY_SYNC_WRITE;
- else
- prio = ZIO_PRIORITY_ASYNC_WRITE;
+/*
+ * Plan splitting of the provided burst size between several blocks.
+ */
+static uint_t
+zil_lwb_plan(zilog_t *zilog, uint64_t size, uint_t *minsize)
+{
+ uint_t md = zilog->zl_max_block_size - sizeof (zil_chain_t);
- lwb->lwb_root_zio = zio_root(zilog->zl_spa,
- zil_lwb_flush_vdevs_done, lwb, ZIO_FLAG_CANFAIL);
- ASSERT3P(lwb->lwb_root_zio, !=, NULL);
+ if (size <= md) {
+ /*
+ * Small bursts are written as-is in one block.
+ */
+ *minsize = size;
+ return (size);
+ } else if (size > 8 * md) {
+ /*
+ * Big bursts use maximum blocks. The first block size
+ * is hard to predict, but it does not really matter.
+ */
+ *minsize = 0;
+ return (md);
+ }
+
+ /*
+ * Medium bursts try to divide evenly to better utilize several SLOG
+ * VDEVs. The first block size we predict assuming the worst case of
+ * maxing out others. Fall back to using maximum blocks if due to
+ * large records or wasted space we can not predict anything better.
+ */
+ uint_t s = size;
+ uint_t n = DIV_ROUND_UP(s, md - sizeof (lr_write_t));
+ uint_t chunk = DIV_ROUND_UP(s, n);
+ uint_t waste = zil_max_waste_space(zilog);
+ waste = MAX(waste, zilog->zl_cur_max);
+ if (chunk <= md - waste) {
+ *minsize = MAX(s - (md - waste) * (n - 1), waste);
+ return (chunk);
+ } else {
+ *minsize = 0;
+ return (md);
+ }
+}
- lwb->lwb_write_zio = zio_rewrite(lwb->lwb_root_zio,
- zilog->zl_spa, 0, &lwb->lwb_blk, lwb_abd,
- BP_GET_LSIZE(&lwb->lwb_blk), zil_lwb_write_done, lwb,
- prio, ZIO_FLAG_CANFAIL | ZIO_FLAG_FASTWRITE, &zb);
- ASSERT3P(lwb->lwb_write_zio, !=, NULL);
+/*
+ * Try to predict next block size based on previous history. Make prediction
+ * sufficient for 7 of 8 previous bursts. Don't try to save if the saving is
+ * less then 50%, extra writes may cost more, but we don't want single spike
+ * to badly affect our predictions.
+ */
+static uint_t
+zil_lwb_predict(zilog_t *zilog)
+{
+ uint_t m, o;
- lwb->lwb_state = LWB_STATE_OPENED;
+ /* If we are in the middle of a burst, take it into account also. */
+ if (zilog->zl_cur_size > 0) {
+ o = zil_lwb_plan(zilog, zilog->zl_cur_size, &m);
+ } else {
+ o = UINT_MAX;
+ m = 0;
+ }
- zil_lwb_set_zio_dependency(zilog, lwb);
- zilog->zl_last_lwb_opened = lwb;
+ /* Find minimum optimal size. We don't need to go below that. */
+ for (int i = 0; i < ZIL_BURSTS; i++)
+ o = MIN(o, zilog->zl_prev_opt[i]);
+
+ /* Find two biggest minimal first block sizes above the optimal. */
+ uint_t m1 = MAX(m, o), m2 = o;
+ for (int i = 0; i < ZIL_BURSTS; i++) {
+ m = zilog->zl_prev_min[i];
+ if (m >= m1) {
+ m2 = m1;
+ m1 = m;
+ } else if (m > m2) {
+ m2 = m;
+ }
}
- mutex_exit(&zilog->zl_lock);
- ASSERT3P(lwb->lwb_root_zio, !=, NULL);
- ASSERT3P(lwb->lwb_write_zio, !=, NULL);
- ASSERT3S(lwb->lwb_state, ==, LWB_STATE_OPENED);
+ /*
+ * If second minimum size gives 50% saving -- use it. It may cost us
+ * one additional write later, but the space saving is just too big.
+ */
+ return ((m1 < m2 * 2) ? m1 : m2);
}
/*
- * Define a limited set of intent log block sizes.
- *
- * These must be a multiple of 4KB. Note only the amount used (again
- * aligned to 4KB) actually gets written. However, we can't always just
- * allocate SPA_OLD_MAXBLOCKSIZE as the slog space could be exhausted.
+ * Close the log block for being issued and allocate the next one.
+ * Has to be called under zl_issuer_lock to chain more lwbs.
*/
-static const struct {
- uint64_t limit;
- uint64_t blksz;
-} zil_block_buckets[] = {
- { 4096, 4096 }, /* non TX_WRITE */
- { 8192 + 4096, 8192 + 4096 }, /* database */
- { 32768 + 4096, 32768 + 4096 }, /* NFS writes */
- { 65536 + 4096, 65536 + 4096 }, /* 64KB writes */
- { 131072, 131072 }, /* < 128KB writes */
- { 131072 +4096, 65536 + 4096 }, /* 128KB writes */
- { UINT64_MAX, SPA_OLD_MAXBLOCKSIZE}, /* > 128KB writes */
-};
+static lwb_t *
+zil_lwb_write_close(zilog_t *zilog, lwb_t *lwb, lwb_state_t state)
+{
+ uint64_t blksz, plan, plan2;
-/*
- * Maximum block size used by the ZIL. This is picked up when the ZIL is
- * initialized. Otherwise this should not be used directly; see
- * zl_max_block_size instead.
- */
-static int zil_maxblocksize = SPA_OLD_MAXBLOCKSIZE;
+ ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
+ ASSERT3S(lwb->lwb_state, ==, LWB_STATE_OPENED);
+ lwb->lwb_state = LWB_STATE_CLOSED;
+
+ /*
+ * If there was an allocation failure then returned NULL will trigger
+ * zil_commit_writer_stall() at the caller. This is inherently racy,
+ * since allocation may not have happened yet.
+ */
+ if (lwb->lwb_error != 0)
+ return (NULL);
+
+ /*
+ * Log blocks are pre-allocated. Here we select the size of the next
+ * block, based on what's left of this burst and the previous history.
+ * While we try to only write used part of the block, we can't just
+ * always allocate the maximum block size because we can exhaust all
+ * available pool log space, so we try to be reasonable.
+ */
+ if (zilog->zl_cur_left > 0) {
+ /*
+ * We are in the middle of a burst and know how much is left.
+ * But if workload is multi-threaded there may be more soon.
+ * Try to predict what can it be and plan for the worst case.
+ */
+ uint_t m;
+ plan = zil_lwb_plan(zilog, zilog->zl_cur_left, &m);
+ if (zilog->zl_parallel) {
+ plan2 = zil_lwb_plan(zilog, zilog->zl_cur_left +
+ zil_lwb_predict(zilog), &m);
+ if (plan < plan2)
+ plan = plan2;
+ }
+ } else {
+ /*
+ * The previous burst is done and we can only predict what
+ * will come next.
+ */
+ plan = zil_lwb_predict(zilog);
+ }
+ blksz = plan + sizeof (zil_chain_t);
+ blksz = P2ROUNDUP_TYPED(blksz, ZIL_MIN_BLKSZ, uint64_t);
+ blksz = MIN(blksz, zilog->zl_max_block_size);
+ DTRACE_PROBE3(zil__block__size, zilog_t *, zilog, uint64_t, blksz,
+ uint64_t, plan);
+
+ return (zil_alloc_lwb(zilog, blksz, NULL, 0, 0, state));
+}
/*
- * Start a log block write and advance to the next log block.
- * Calls are serialized.
+ * Finalize previously closed block and issue the write zio.
*/
-static lwb_t *
+static void
zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
{
- lwb_t *nlwb = NULL;
- zil_chain_t *zilc;
spa_t *spa = zilog->zl_spa;
- blkptr_t *bp;
- dmu_tx_t *tx;
- uint64_t txg;
- uint64_t zil_blksz, wsz;
- int i, error;
+ zil_chain_t *zilc;
boolean_t slog;
+ zbookmark_phys_t zb;
+ zio_priority_t prio;
+ int error;
- ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
- ASSERT3P(lwb->lwb_root_zio, !=, NULL);
- ASSERT3P(lwb->lwb_write_zio, !=, NULL);
- ASSERT3S(lwb->lwb_state, ==, LWB_STATE_OPENED);
+ ASSERT3S(lwb->lwb_state, ==, LWB_STATE_CLOSED);
- if (BP_GET_CHECKSUM(&lwb->lwb_blk) == ZIO_CHECKSUM_ZILOG2) {
- zilc = (zil_chain_t *)lwb->lwb_buf;
- bp = &zilc->zc_next_blk;
- } else {
- zilc = (zil_chain_t *)(lwb->lwb_buf + lwb->lwb_sz);
- bp = &zilc->zc_next_blk;
- }
+ /* Actually fill the lwb with the data. */
+ for (itx_t *itx = list_head(&lwb->lwb_itxs); itx;
+ itx = list_next(&lwb->lwb_itxs, itx))
+ zil_lwb_commit(zilog, lwb, itx);
+ lwb->lwb_nused = lwb->lwb_nfilled;
+ ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_nmax);
- ASSERT(lwb->lwb_nused <= lwb->lwb_sz);
+ lwb->lwb_root_zio = zio_root(spa, zil_lwb_flush_vdevs_done, lwb,
+ ZIO_FLAG_CANFAIL);
/*
- * Allocate the next block and save its address in this block
- * before writing it in order to establish the log chain.
+ * The lwb is now ready to be issued, but it can be only if it already
+ * got its block pointer allocated or the allocation has failed.
+ * Otherwise leave it as-is, relying on some other thread to issue it
+ * after allocating its block pointer via calling zil_lwb_write_issue()
+ * for the previous lwb(s) in the chain.
*/
+ mutex_enter(&zilog->zl_lock);
+ lwb->lwb_state = LWB_STATE_READY;
+ if (BP_IS_HOLE(&lwb->lwb_blk) && lwb->lwb_error == 0) {
+ mutex_exit(&zilog->zl_lock);
+ return;
+ }
+ mutex_exit(&zilog->zl_lock);
- tx = dmu_tx_create(zilog->zl_os);
+next_lwb:
+ if (lwb->lwb_slim)
+ zilc = (zil_chain_t *)lwb->lwb_buf;
+ else
+ zilc = (zil_chain_t *)(lwb->lwb_buf + lwb->lwb_nmax);
+ int wsz = lwb->lwb_sz;
+ if (lwb->lwb_error == 0) {
+ abd_t *lwb_abd = abd_get_from_buf(lwb->lwb_buf, lwb->lwb_sz);
+ if (!lwb->lwb_slog || zilog->zl_cur_size <= zil_slog_bulk)
+ prio = ZIO_PRIORITY_SYNC_WRITE;
+ else
+ prio = ZIO_PRIORITY_ASYNC_WRITE;
+ SET_BOOKMARK(&zb, lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_OBJSET],
+ ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
+ lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_SEQ]);
+ lwb->lwb_write_zio = zio_rewrite(lwb->lwb_root_zio, spa, 0,
+ &lwb->lwb_blk, lwb_abd, lwb->lwb_sz, zil_lwb_write_done,
+ lwb, prio, ZIO_FLAG_CANFAIL, &zb);
+ zil_lwb_add_block(lwb, &lwb->lwb_blk);
+
+ if (lwb->lwb_slim) {
+ /* For Slim ZIL only write what is used. */
+ wsz = P2ROUNDUP_TYPED(lwb->lwb_nused, ZIL_MIN_BLKSZ,
+ int);
+ ASSERT3S(wsz, <=, lwb->lwb_sz);
+ zio_shrink(lwb->lwb_write_zio, wsz);
+ wsz = lwb->lwb_write_zio->io_size;
+ }
+ memset(lwb->lwb_buf + lwb->lwb_nused, 0, wsz - lwb->lwb_nused);
+ zilc->zc_pad = 0;
+ zilc->zc_nused = lwb->lwb_nused;
+ zilc->zc_eck.zec_cksum = lwb->lwb_blk.blk_cksum;
+ } else {
+ /*
+ * We can't write the lwb if there was an allocation failure,
+ * so create a null zio instead just to maintain dependencies.
+ */
+ lwb->lwb_write_zio = zio_null(lwb->lwb_root_zio, spa, NULL,
+ zil_lwb_write_done, lwb, ZIO_FLAG_CANFAIL);
+ lwb->lwb_write_zio->io_error = lwb->lwb_error;
+ }
+ if (lwb->lwb_child_zio)
+ zio_add_child(lwb->lwb_write_zio, lwb->lwb_child_zio);
/*
- * Since we are not going to create any new dirty data, and we
- * can even help with clearing the existing dirty data, we
- * should not be subject to the dirty data based delays. We
- * use TXG_NOTHROTTLE to bypass the delay mechanism.
+ * Open transaction to allocate the next block pointer.
*/
+ dmu_tx_t *tx = dmu_tx_create(zilog->zl_os);
VERIFY0(dmu_tx_assign(tx, TXG_WAIT | TXG_NOTHROTTLE));
-
dsl_dataset_dirty(dmu_objset_ds(zilog->zl_os), tx);
- txg = dmu_tx_get_txg(tx);
-
- mutex_enter(&zilog->zl_lwb_io_lock);
- lwb->lwb_issued_txg = txg;
- zilog->zl_lwb_inflight[txg & TXG_MASK]++;
- zilog->zl_lwb_max_issued_txg = MAX(txg, zilog->zl_lwb_max_issued_txg);
- mutex_exit(&zilog->zl_lwb_io_lock);
+ uint64_t txg = dmu_tx_get_txg(tx);
/*
- * Log blocks are pre-allocated. Here we select the size of the next
- * block, based on size used in the last block.
- * - first find the smallest bucket that will fit the block from a
- * limited set of block sizes. This is because it's faster to write
- * blocks allocated from the same metaslab as they are adjacent or
- * close.
- * - next find the maximum from the new suggested size and an array of
- * previous sizes. This lessens a picket fence effect of wrongly
- * guessing the size if we have a stream of say 2k, 64k, 2k, 64k
- * requests.
- *
- * Note we only write what is used, but we can't just allocate
- * the maximum block size because we can exhaust the available
- * pool log space.
- */
- zil_blksz = zilog->zl_cur_used + sizeof (zil_chain_t);
- for (i = 0; zil_blksz > zil_block_buckets[i].limit; i++)
- continue;
- zil_blksz = MIN(zil_block_buckets[i].blksz, zilog->zl_max_block_size);
- zilog->zl_prev_blks[zilog->zl_prev_rotor] = zil_blksz;
- for (i = 0; i < ZIL_PREV_BLKS; i++)
- zil_blksz = MAX(zil_blksz, zilog->zl_prev_blks[i]);
- zilog->zl_prev_rotor = (zilog->zl_prev_rotor + 1) & (ZIL_PREV_BLKS - 1);
-
+ * Allocate next the block pointer unless we are already in error.
+ */
+ lwb_t *nlwb = list_next(&zilog->zl_lwb_list, lwb);
+ blkptr_t *bp = &zilc->zc_next_blk;
BP_ZERO(bp);
- error = zio_alloc_zil(spa, zilog->zl_os, txg, bp, zil_blksz, &slog);
- if (slog) {
- ZIL_STAT_BUMP(zil_itx_metaslab_slog_count);
- ZIL_STAT_INCR(zil_itx_metaslab_slog_bytes, lwb->lwb_nused);
- } else {
- ZIL_STAT_BUMP(zil_itx_metaslab_normal_count);
- ZIL_STAT_INCR(zil_itx_metaslab_normal_bytes, lwb->lwb_nused);
+ error = lwb->lwb_error;
+ if (error == 0) {
+ error = zio_alloc_zil(spa, zilog->zl_os, txg, bp, nlwb->lwb_sz,
+ &slog);
}
if (error == 0) {
- ASSERT3U(bp->blk_birth, ==, txg);
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(bp), ==, txg);
+ BP_SET_CHECKSUM(bp, nlwb->lwb_slim ? ZIO_CHECKSUM_ZILOG2 :
+ ZIO_CHECKSUM_ZILOG);
bp->blk_cksum = lwb->lwb_blk.blk_cksum;
bp->blk_cksum.zc_word[ZIL_ZC_SEQ]++;
-
- /*
- * Allocate a new log write block (lwb).
- */
- nlwb = zil_alloc_lwb(zilog, bp, slog, txg, TRUE);
}
- if (BP_GET_CHECKSUM(&lwb->lwb_blk) == ZIO_CHECKSUM_ZILOG2) {
- /* For Slim ZIL only write what is used. */
- wsz = P2ROUNDUP_TYPED(lwb->lwb_nused, ZIL_MIN_BLKSZ, uint64_t);
- ASSERT3U(wsz, <=, lwb->lwb_sz);
- zio_shrink(lwb->lwb_write_zio, wsz);
-
- } else {
- wsz = lwb->lwb_sz;
- }
+ /*
+ * Reduce TXG open time by incrementing inflight counter and committing
+ * the transaciton. zil_sync() will wait for it to return to zero.
+ */
+ mutex_enter(&zilog->zl_lwb_io_lock);
+ lwb->lwb_issued_txg = txg;
+ zilog->zl_lwb_inflight[txg & TXG_MASK]++;
+ zilog->zl_lwb_max_issued_txg = MAX(txg, zilog->zl_lwb_max_issued_txg);
+ mutex_exit(&zilog->zl_lwb_io_lock);
+ dmu_tx_commit(tx);
- zilc->zc_pad = 0;
- zilc->zc_nused = lwb->lwb_nused;
- zilc->zc_eck.zec_cksum = lwb->lwb_blk.blk_cksum;
+ spa_config_enter(spa, SCL_STATE, lwb, RW_READER);
/*
- * clear unused data for security
+ * We've completed all potentially blocking operations. Update the
+ * nlwb and allow it proceed without possible lock order reversals.
*/
- memset(lwb->lwb_buf + lwb->lwb_nused, 0, wsz - lwb->lwb_nused);
+ mutex_enter(&zilog->zl_lock);
+ zil_lwb_set_zio_dependency(zilog, lwb);
+ lwb->lwb_state = LWB_STATE_ISSUED;
- spa_config_enter(zilog->zl_spa, SCL_STATE, lwb, RW_READER);
+ if (nlwb) {
+ nlwb->lwb_blk = *bp;
+ nlwb->lwb_error = error;
+ nlwb->lwb_slog = slog;
+ nlwb->lwb_alloc_txg = txg;
+ if (nlwb->lwb_state != LWB_STATE_READY)
+ nlwb = NULL;
+ }
+ mutex_exit(&zilog->zl_lock);
- zil_lwb_add_block(lwb, &lwb->lwb_blk);
+ if (lwb->lwb_slog) {
+ ZIL_STAT_BUMP(zilog, zil_itx_metaslab_slog_count);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_slog_bytes,
+ lwb->lwb_nused);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_slog_write,
+ wsz);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_slog_alloc,
+ BP_GET_LSIZE(&lwb->lwb_blk));
+ } else {
+ ZIL_STAT_BUMP(zilog, zil_itx_metaslab_normal_count);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_normal_bytes,
+ lwb->lwb_nused);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_normal_write,
+ wsz);
+ ZIL_STAT_INCR(zilog, zil_itx_metaslab_normal_alloc,
+ BP_GET_LSIZE(&lwb->lwb_blk));
+ }
lwb->lwb_issued_timestamp = gethrtime();
- lwb->lwb_state = LWB_STATE_ISSUED;
-
- zio_nowait(lwb->lwb_root_zio);
+ if (lwb->lwb_child_zio)
+ zio_nowait(lwb->lwb_child_zio);
zio_nowait(lwb->lwb_write_zio);
-
- dmu_tx_commit(tx);
+ zio_nowait(lwb->lwb_root_zio);
/*
- * If there was an allocation failure then nlwb will be null which
- * forces a txg_wait_synced().
+ * If nlwb was ready when we gave it the block pointer,
+ * it is on us to issue it and possibly following ones.
*/
- return (nlwb);
+ lwb = nlwb;
+ if (lwb)
+ goto next_lwb;
}
/*
- * Maximum amount of write data that can be put into single log block.
+ * Maximum amount of data that can be put into single log block.
*/
uint64_t
-zil_max_log_data(zilog_t *zilog)
+zil_max_log_data(zilog_t *zilog, size_t hdrsize)
{
- return (zilog->zl_max_block_size -
- sizeof (zil_chain_t) - sizeof (lr_write_t));
+ return (zilog->zl_max_block_size - sizeof (zil_chain_t) - hdrsize);
}
/*
* Maximum amount of log space we agree to waste to reduce number of
- * WR_NEED_COPY chunks to reduce zl_get_data() overhead (~12%).
+ * WR_NEED_COPY chunks to reduce zl_get_data() overhead (~6%).
*/
static inline uint64_t
zil_max_waste_space(zilog_t *zilog)
{
- return (zil_max_log_data(zilog) / 8);
+ return (zil_max_log_data(zilog, sizeof (lr_write_t)) / 16);
}
/*
* Maximum amount of write data for WR_COPIED. For correctness, consumers
* must fall back to WR_NEED_COPY if we can't fit the entire record into one
* maximum sized log block, because each WR_COPIED record must fit in a
- * single log block. For space efficiency, we want to fit two records into a
- * max-sized log block.
+ * single log block. Below that it is a tradeoff of additional memory copy
+ * and possibly worse log space efficiency vs additional range lock/unlock.
*/
+static uint_t zil_maxcopied = 7680;
+
uint64_t
zil_max_copied_data(zilog_t *zilog)
{
- return ((zilog->zl_max_block_size - sizeof (zil_chain_t)) / 2 -
- sizeof (lr_write_t));
+ uint64_t max_data = zil_max_log_data(zilog, sizeof (lr_write_t));
+ return (MIN(max_data, zil_maxcopied));
+}
+
+static uint64_t
+zil_itx_record_size(itx_t *itx)
+{
+ lr_t *lr = &itx->itx_lr;
+
+ if (lr->lrc_txtype == TX_COMMIT)
+ return (0);
+ ASSERT3U(lr->lrc_reclen, >=, sizeof (lr_t));
+ return (lr->lrc_reclen);
+}
+
+static uint64_t
+zil_itx_data_size(itx_t *itx)
+{
+ lr_t *lr = &itx->itx_lr;
+ lr_write_t *lrw = (lr_write_t *)lr;
+
+ if (lr->lrc_txtype == TX_WRITE && itx->itx_wr_state == WR_NEED_COPY) {
+ ASSERT3U(lr->lrc_reclen, ==, sizeof (lr_write_t));
+ return (P2ROUNDUP_TYPED(lrw->lr_length, sizeof (uint64_t),
+ uint64_t));
+ }
+ return (0);
+}
+
+static uint64_t
+zil_itx_full_size(itx_t *itx)
+{
+ lr_t *lr = &itx->itx_lr;
+
+ if (lr->lrc_txtype == TX_COMMIT)
+ return (0);
+ ASSERT3U(lr->lrc_reclen, >=, sizeof (lr_t));
+ return (lr->lrc_reclen + zil_itx_data_size(itx));
}
+/*
+ * Estimate space needed in the lwb for the itx. Allocate more lwbs or
+ * split the itx as needed, but don't touch the actual transaction data.
+ * Has to be called under zl_issuer_lock to call zil_lwb_write_close()
+ * to chain more lwbs.
+ */
static lwb_t *
-zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
+zil_lwb_assign(zilog_t *zilog, lwb_t *lwb, itx_t *itx, list_t *ilwbs)
{
- lr_t *lrcb, *lrc;
- lr_write_t *lrwb, *lrw;
- char *lr_buf;
- uint64_t dlen, dnow, dpad, lwb_sp, reclen, txg, max_log_data;
+ itx_t *citx;
+ lr_t *lr, *clr;
+ lr_write_t *lrw;
+ uint64_t dlen, dnow, lwb_sp, reclen, max_log_data;
ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
ASSERT3P(lwb, !=, NULL);
@@ -1746,8 +2121,8 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
zil_lwb_write_open(zilog, lwb);
- lrc = &itx->itx_lr;
- lrw = (lr_write_t *)lrc;
+ lr = &itx->itx_lr;
+ lrw = (lr_write_t *)lr;
/*
* A commit itx doesn't represent any on-disk state; instead
@@ -1761,150 +2136,207 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
*
* For more details, see the comment above zil_commit().
*/
- if (lrc->lrc_txtype == TX_COMMIT) {
- mutex_enter(&zilog->zl_lock);
+ if (lr->lrc_txtype == TX_COMMIT) {
zil_commit_waiter_link_lwb(itx->itx_private, lwb);
- itx->itx_private = NULL;
- mutex_exit(&zilog->zl_lock);
+ list_insert_tail(&lwb->lwb_itxs, itx);
return (lwb);
}
- if (lrc->lrc_txtype == TX_WRITE && itx->itx_wr_state == WR_NEED_COPY) {
- dlen = P2ROUNDUP_TYPED(
- lrw->lr_length, sizeof (uint64_t), uint64_t);
- dpad = dlen - lrw->lr_length;
- } else {
- dlen = dpad = 0;
- }
- reclen = lrc->lrc_reclen;
- zilog->zl_cur_used += (reclen + dlen);
- txg = lrc->lrc_txg;
-
- ASSERT3U(zilog->zl_cur_used, <, UINT64_MAX - (reclen + dlen));
+ reclen = lr->lrc_reclen;
+ ASSERT3U(reclen, >=, sizeof (lr_t));
+ ASSERT3U(reclen, <=, zil_max_log_data(zilog, 0));
+ dlen = zil_itx_data_size(itx);
cont:
/*
* If this record won't fit in the current log block, start a new one.
* For WR_NEED_COPY optimize layout for minimal number of chunks.
*/
- lwb_sp = lwb->lwb_sz - lwb->lwb_nused;
- max_log_data = zil_max_log_data(zilog);
+ lwb_sp = lwb->lwb_nmax - lwb->lwb_nused;
+ max_log_data = zil_max_log_data(zilog, sizeof (lr_write_t));
if (reclen > lwb_sp || (reclen + dlen > lwb_sp &&
lwb_sp < zil_max_waste_space(zilog) &&
(dlen % max_log_data == 0 ||
lwb_sp < reclen + dlen % max_log_data))) {
- lwb = zil_lwb_write_issue(zilog, lwb);
+ list_insert_tail(ilwbs, lwb);
+ lwb = zil_lwb_write_close(zilog, lwb, LWB_STATE_OPENED);
if (lwb == NULL)
return (NULL);
- zil_lwb_write_open(zilog, lwb);
- ASSERT(LWB_EMPTY(lwb));
- lwb_sp = lwb->lwb_sz - lwb->lwb_nused;
-
- /*
- * There must be enough space in the new, empty log block to
- * hold reclen. For WR_COPIED, we need to fit the whole
- * record in one block, and reclen is the header size + the
- * data size. For WR_NEED_COPY, we can create multiple
- * records, splitting the data into multiple blocks, so we
- * only need to fit one word of data per block; in this case
- * reclen is just the header size (no data).
- */
- ASSERT3U(reclen + MIN(dlen, sizeof (uint64_t)), <=, lwb_sp);
+ lwb_sp = lwb->lwb_nmax - lwb->lwb_nused;
}
+ /*
+ * There must be enough space in the log block to hold reclen.
+ * For WR_COPIED, we need to fit the whole record in one block,
+ * and reclen is the write record header size + the data size.
+ * For WR_NEED_COPY, we can create multiple records, splitting
+ * the data into multiple blocks, so we only need to fit one
+ * word of data per block; in this case reclen is just the header
+ * size (no data).
+ */
+ ASSERT3U(reclen + MIN(dlen, sizeof (uint64_t)), <=, lwb_sp);
+
dnow = MIN(dlen, lwb_sp - reclen);
- lr_buf = lwb->lwb_buf + lwb->lwb_nused;
- memcpy(lr_buf, lrc, reclen);
- lrcb = (lr_t *)lr_buf; /* Like lrc, but inside lwb. */
- lrwb = (lr_write_t *)lrcb; /* Like lrw, but inside lwb. */
+ if (dlen > dnow) {
+ ASSERT3U(lr->lrc_txtype, ==, TX_WRITE);
+ ASSERT3U(itx->itx_wr_state, ==, WR_NEED_COPY);
+ citx = zil_itx_clone(itx);
+ clr = &citx->itx_lr;
+ lr_write_t *clrw = (lr_write_t *)clr;
+ clrw->lr_length = dnow;
+ lrw->lr_offset += dnow;
+ lrw->lr_length -= dnow;
+ zilog->zl_cur_left -= dnow;
+ } else {
+ citx = itx;
+ clr = lr;
+ }
+
+ /*
+ * We're actually making an entry, so update lrc_seq to be the
+ * log record sequence number. Note that this is generally not
+ * equal to the itx sequence number because not all transactions
+ * are synchronous, and sometimes spa_sync() gets there first.
+ */
+ clr->lrc_seq = ++zilog->zl_lr_seq;
+
+ lwb->lwb_nused += reclen + dnow;
+ ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_nmax);
+ ASSERT0(P2PHASE(lwb->lwb_nused, sizeof (uint64_t)));
+
+ zil_lwb_add_txg(lwb, lr->lrc_txg);
+ list_insert_tail(&lwb->lwb_itxs, citx);
+
+ dlen -= dnow;
+ if (dlen > 0)
+ goto cont;
+
+ if (lr->lrc_txtype == TX_WRITE &&
+ lr->lrc_txg > spa_freeze_txg(zilog->zl_spa))
+ txg_wait_synced(zilog->zl_dmu_pool, lr->lrc_txg);
+
+ return (lwb);
+}
+
+/*
+ * Fill the actual transaction data into the lwb, following zil_lwb_assign().
+ * Does not require locking.
+ */
+static void
+zil_lwb_commit(zilog_t *zilog, lwb_t *lwb, itx_t *itx)
+{
+ lr_t *lr, *lrb;
+ lr_write_t *lrw, *lrwb;
+ char *lr_buf;
+ uint64_t dlen, reclen;
- ZIL_STAT_BUMP(zil_itx_count);
+ lr = &itx->itx_lr;
+ lrw = (lr_write_t *)lr;
+
+ if (lr->lrc_txtype == TX_COMMIT)
+ return;
+
+ reclen = lr->lrc_reclen;
+ dlen = zil_itx_data_size(itx);
+ ASSERT3U(reclen + dlen, <=, lwb->lwb_nused - lwb->lwb_nfilled);
+
+ lr_buf = lwb->lwb_buf + lwb->lwb_nfilled;
+ memcpy(lr_buf, lr, reclen);
+ lrb = (lr_t *)lr_buf; /* Like lr, but inside lwb. */
+ lrwb = (lr_write_t *)lrb; /* Like lrw, but inside lwb. */
+
+ ZIL_STAT_BUMP(zilog, zil_itx_count);
/*
* If it's a write, fetch the data or get its blkptr as appropriate.
*/
- if (lrc->lrc_txtype == TX_WRITE) {
- if (txg > spa_freeze_txg(zilog->zl_spa))
- txg_wait_synced(zilog->zl_dmu_pool, txg);
+ if (lr->lrc_txtype == TX_WRITE) {
if (itx->itx_wr_state == WR_COPIED) {
- ZIL_STAT_BUMP(zil_itx_copied_count);
- ZIL_STAT_INCR(zil_itx_copied_bytes, lrw->lr_length);
+ ZIL_STAT_BUMP(zilog, zil_itx_copied_count);
+ ZIL_STAT_INCR(zilog, zil_itx_copied_bytes,
+ lrw->lr_length);
} else {
char *dbuf;
int error;
if (itx->itx_wr_state == WR_NEED_COPY) {
dbuf = lr_buf + reclen;
- lrcb->lrc_reclen += dnow;
- if (lrwb->lr_length > dnow)
- lrwb->lr_length = dnow;
- lrw->lr_offset += dnow;
- lrw->lr_length -= dnow;
- ZIL_STAT_BUMP(zil_itx_needcopy_count);
- ZIL_STAT_INCR(zil_itx_needcopy_bytes, dnow);
+ lrb->lrc_reclen += dlen;
+ ZIL_STAT_BUMP(zilog, zil_itx_needcopy_count);
+ ZIL_STAT_INCR(zilog, zil_itx_needcopy_bytes,
+ dlen);
} else {
ASSERT3S(itx->itx_wr_state, ==, WR_INDIRECT);
dbuf = NULL;
- ZIL_STAT_BUMP(zil_itx_indirect_count);
- ZIL_STAT_INCR(zil_itx_indirect_bytes,
+ ZIL_STAT_BUMP(zilog, zil_itx_indirect_count);
+ ZIL_STAT_INCR(zilog, zil_itx_indirect_bytes,
lrw->lr_length);
+ if (lwb->lwb_child_zio == NULL) {
+ lwb->lwb_child_zio = zio_null(NULL,
+ zilog->zl_spa, NULL, NULL, NULL,
+ ZIO_FLAG_CANFAIL);
+ }
}
/*
- * We pass in the "lwb_write_zio" rather than
- * "lwb_root_zio" so that the "lwb_write_zio"
- * becomes the parent of any zio's created by
- * the "zl_get_data" callback. The vdevs are
- * flushed after the "lwb_write_zio" completes,
- * so we want to make sure that completion
- * callback waits for these additional zio's,
- * such that the vdevs used by those zio's will
- * be included in the lwb's vdev tree, and those
- * vdevs will be properly flushed. If we passed
- * in "lwb_root_zio" here, then these additional
- * vdevs may not be flushed; e.g. if these zio's
- * completed after "lwb_write_zio" completed.
+ * The "lwb_child_zio" we pass in will become a child of
+ * "lwb_write_zio", when one is created, so one will be
+ * a parent of any zio's created by the "zl_get_data".
+ * This way "lwb_write_zio" will first wait for children
+ * block pointers before own writing, and then for their
+ * writing completion before the vdev cache flushing.
*/
error = zilog->zl_get_data(itx->itx_private,
itx->itx_gen, lrwb, dbuf, lwb,
- lwb->lwb_write_zio);
- if (dbuf != NULL && error == 0 && dnow == dlen)
+ lwb->lwb_child_zio);
+ if (dbuf != NULL && error == 0) {
/* Zero any padding bytes in the last block. */
- memset((char *)dbuf + lrwb->lr_length, 0, dpad);
-
- if (error == EIO) {
- txg_wait_synced(zilog->zl_dmu_pool, txg);
- return (lwb);
+ memset((char *)dbuf + lrwb->lr_length, 0,
+ dlen - lrwb->lr_length);
}
- if (error != 0) {
- ASSERT(error == ENOENT || error == EEXIST ||
- error == EALREADY);
- return (lwb);
+
+ /*
+ * Typically, the only return values we should see from
+ * ->zl_get_data() are 0, EIO, ENOENT, EEXIST or
+ * EALREADY. However, it is also possible to see other
+ * error values such as ENOSPC or EINVAL from
+ * dmu_read() -> dnode_hold() -> dnode_hold_impl() or
+ * ENXIO as well as a multitude of others from the
+ * block layer through dmu_buf_hold() -> dbuf_read()
+ * -> zio_wait(), as well as through dmu_read() ->
+ * dnode_hold() -> dnode_hold_impl() -> dbuf_read() ->
+ * zio_wait(). When these errors happen, we can assume
+ * that neither an immediate write nor an indirect
+ * write occurred, so we need to fall back to
+ * txg_wait_synced(). This is unusual, so we print to
+ * dmesg whenever one of these errors occurs.
+ */
+ switch (error) {
+ case 0:
+ break;
+ default:
+ cmn_err(CE_WARN, "zil_lwb_commit() received "
+ "unexpected error %d from ->zl_get_data()"
+ ". Falling back to txg_wait_synced().",
+ error);
+ zfs_fallthrough;
+ case EIO:
+ txg_wait_synced(zilog->zl_dmu_pool,
+ lr->lrc_txg);
+ zfs_fallthrough;
+ case ENOENT:
+ zfs_fallthrough;
+ case EEXIST:
+ zfs_fallthrough;
+ case EALREADY:
+ return;
}
}
}
- /*
- * We're actually making an entry, so update lrc_seq to be the
- * log record sequence number. Note that this is generally not
- * equal to the itx sequence number because not all transactions
- * are synchronous, and sometimes spa_sync() gets there first.
- */
- lrcb->lrc_seq = ++zilog->zl_lr_seq;
- lwb->lwb_nused += reclen + dnow;
-
- zil_lwb_add_txg(lwb, txg);
-
- ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_sz);
- ASSERT0(P2PHASE(lwb->lwb_nused, sizeof (uint64_t)));
-
- dlen -= dnow;
- if (dlen > 0) {
- zilog->zl_cur_used += reclen;
- goto cont;
- }
-
- return (lwb);
+ lwb->lwb_nfilled += reclen + dlen;
+ ASSERT3S(lwb->lwb_nfilled, <=, lwb->lwb_nused);
+ ASSERT0(P2PHASE(lwb->lwb_nfilled, sizeof (uint64_t)));
}
itx_t *
@@ -1913,7 +2345,9 @@ zil_itx_create(uint64_t txtype, size_t olrsize)
size_t itxsize, lrsize;
itx_t *itx;
+ ASSERT3U(olrsize, >=, sizeof (lr_t));
lrsize = P2ROUNDUP_TYPED(olrsize, sizeof (uint64_t), size_t);
+ ASSERT3U(lrsize, >=, olrsize);
itxsize = offsetof(itx_t, itx_lr) + lrsize;
itx = zio_data_buf_alloc(itxsize);
@@ -1929,9 +2363,26 @@ zil_itx_create(uint64_t txtype, size_t olrsize)
return (itx);
}
+static itx_t *
+zil_itx_clone(itx_t *oitx)
+{
+ ASSERT3U(oitx->itx_size, >=, sizeof (itx_t));
+ ASSERT3U(oitx->itx_size, ==,
+ offsetof(itx_t, itx_lr) + oitx->itx_lr.lrc_reclen);
+
+ itx_t *itx = zio_data_buf_alloc(oitx->itx_size);
+ memcpy(itx, oitx, oitx->itx_size);
+ itx->itx_callback = NULL;
+ itx->itx_callback_data = NULL;
+ return (itx);
+}
+
void
zil_itx_destroy(itx_t *itx)
{
+ ASSERT3U(itx->itx_size, >=, sizeof (itx_t));
+ ASSERT3U(itx->itx_lr.lrc_reclen, ==,
+ itx->itx_size - offsetof(itx_t, itx_lr));
IMPLY(itx->itx_lr.lrc_txtype == TX_COMMIT, itx->itx_callback == NULL);
IMPLY(itx->itx_callback != NULL, itx->itx_lr.lrc_txtype != TX_COMMIT);
@@ -1956,11 +2407,11 @@ zil_itxg_clean(void *arg)
itx_async_node_t *ian;
list = &itxs->i_sync_list;
- while ((itx = list_head(list)) != NULL) {
+ while ((itx = list_remove_head(list)) != NULL) {
/*
* In the general case, commit itxs will not be found
* here, as they'll be committed to an lwb via
- * zil_lwb_commit(), and free'd in that function. Having
+ * zil_lwb_assign(), and free'd in that function. Having
* said that, it is still possible for commit itxs to be
* found here, due to the following race:
*
@@ -1979,7 +2430,6 @@ zil_itxg_clean(void *arg)
if (itx->itx_lr.lrc_txtype == TX_COMMIT)
zil_commit_waiter_skip(itx->itx_private);
- list_remove(list, itx);
zil_itx_destroy(itx);
}
@@ -1987,8 +2437,7 @@ zil_itxg_clean(void *arg)
t = &itxs->i_async_tree;
while ((ian = avl_destroy_nodes(t, &cookie)) != NULL) {
list = &ian->ia_list;
- while ((itx = list_head(list)) != NULL) {
- list_remove(list, itx);
+ while ((itx = list_remove_head(list)) != NULL) {
/* commit itxs should never be on the async lists. */
ASSERT3U(itx->itx_lr.lrc_txtype, !=, TX_COMMIT);
zil_itx_destroy(itx);
@@ -2017,7 +2466,7 @@ void
zil_remove_async(zilog_t *zilog, uint64_t oid)
{
uint64_t otxg, txg;
- itx_async_node_t *ian;
+ itx_async_node_t *ian, ian_search;
avl_tree_t *t;
avl_index_t where;
list_t clean_list;
@@ -2044,13 +2493,13 @@ zil_remove_async(zilog_t *zilog, uint64_t oid)
* Locate the object node and append its list.
*/
t = &itxg->itxg_itxs->i_async_tree;
- ian = avl_find(t, &oid, &where);
+ ian_search.ia_foid = oid;
+ ian = avl_find(t, &ian_search, &where);
if (ian != NULL)
list_move_tail(&clean_list, &ian->ia_list);
mutex_exit(&itxg->itxg_lock);
}
- while ((itx = list_head(&clean_list)) != NULL) {
- list_remove(&clean_list, itx);
+ while ((itx = list_remove_head(&clean_list)) != NULL) {
/* commit itxs should never be on the async lists. */
ASSERT3U(itx->itx_lr.lrc_txtype, !=, TX_COMMIT);
zil_itx_destroy(itx);
@@ -2181,10 +2630,10 @@ zil_clean(zilog_t *zilog, uint64_t synced_txg)
* This function will traverse the queue of itxs that need to be
* committed, and move them onto the ZIL's zl_itx_commit_list.
*/
-static void
+static uint64_t
zil_get_commit_list(zilog_t *zilog)
{
- uint64_t otxg, txg;
+ uint64_t otxg, txg, wtxg = 0;
list_t *commit_list = &zilog->zl_itx_commit_list;
ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
@@ -2218,10 +2667,33 @@ zil_get_commit_list(zilog_t *zilog)
*/
ASSERT(zilog_is_dirty_in_txg(zilog, txg) ||
spa_freeze_txg(zilog->zl_spa) != UINT64_MAX);
- list_move_tail(commit_list, &itxg->itxg_itxs->i_sync_list);
+ list_t *sync_list = &itxg->itxg_itxs->i_sync_list;
+ itx_t *itx = NULL;
+ if (unlikely(zilog->zl_suspend > 0)) {
+ /*
+ * ZIL was just suspended, but we lost the race.
+ * Allow all earlier itxs to be committed, but ask
+ * caller to do txg_wait_synced(txg) for any new.
+ */
+ if (!list_is_empty(sync_list))
+ wtxg = MAX(wtxg, txg);
+ } else {
+ itx = list_head(sync_list);
+ list_move_tail(commit_list, sync_list);
+ }
mutex_exit(&itxg->itxg_lock);
+
+ while (itx != NULL) {
+ uint64_t s = zil_itx_full_size(itx);
+ zilog->zl_cur_size += s;
+ zilog->zl_cur_left += s;
+ s = zil_itx_record_size(itx);
+ zilog->zl_cur_max = MAX(zilog->zl_cur_max, s);
+ itx = list_next(commit_list, itx);
+ }
}
+ return (wtxg);
}
/*
@@ -2231,7 +2703,7 @@ void
zil_async_to_sync(zilog_t *zilog, uint64_t foid)
{
uint64_t otxg, txg;
- itx_async_node_t *ian;
+ itx_async_node_t *ian, ian_search;
avl_tree_t *t;
avl_index_t where;
@@ -2261,7 +2733,8 @@ zil_async_to_sync(zilog_t *zilog, uint64_t foid)
*/
t = &itxg->itxg_itxs->i_async_tree;
if (foid != 0) {
- ian = avl_find(t, &foid, &where);
+ ian_search.ia_foid = foid;
+ ian = avl_find(t, &ian_search, &where);
if (ian != NULL) {
list_move_tail(&itxg->itxg_itxs->i_sync_list,
&ian->ia_list);
@@ -2315,7 +2788,6 @@ zil_prune_commit_list(zilog_t *zilog)
zil_commit_waiter_skip(itx->itx_private);
} else {
zil_commit_waiter_link_lwb(itx->itx_private, last_lwb);
- itx->itx_private = NULL;
}
mutex_exit(&zilog->zl_lock);
@@ -2352,7 +2824,27 @@ zil_commit_writer_stall(zilog_t *zilog)
*/
ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
txg_wait_synced(zilog->zl_dmu_pool, 0);
- ASSERT3P(list_tail(&zilog->zl_lwb_list), ==, NULL);
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
+}
+
+static void
+zil_burst_done(zilog_t *zilog)
+{
+ if (!list_is_empty(&zilog->zl_itx_commit_list) ||
+ zilog->zl_cur_size == 0)
+ return;
+
+ if (zilog->zl_parallel)
+ zilog->zl_parallel--;
+
+ uint_t r = (zilog->zl_prev_rotor + 1) & (ZIL_BURSTS - 1);
+ zilog->zl_prev_rotor = r;
+ zilog->zl_prev_opt[r] = zil_lwb_plan(zilog, zilog->zl_cur_size,
+ &zilog->zl_prev_min[r]);
+
+ zilog->zl_cur_size = 0;
+ zilog->zl_cur_max = 0;
+ zilog->zl_cur_left = 0;
}
/*
@@ -2362,12 +2854,12 @@ zil_commit_writer_stall(zilog_t *zilog)
* lwb will be issued to the zio layer to be written to disk.
*/
static void
-zil_process_commit_list(zilog_t *zilog)
+zil_process_commit_list(zilog_t *zilog, zil_commit_waiter_t *zcw, list_t *ilwbs)
{
spa_t *spa = zilog->zl_spa;
list_t nolwb_itxs;
list_t nolwb_waiters;
- lwb_t *lwb;
+ lwb_t *lwb, *plwb;
itx_t *itx;
ASSERT(MUTEX_HELD(&zilog->zl_issuer_lock));
@@ -2376,7 +2868,7 @@ zil_process_commit_list(zilog_t *zilog)
* Return if there's nothing to commit before we dirty the fs by
* calling zil_create().
*/
- if (list_head(&zilog->zl_itx_commit_list) == NULL)
+ if (list_is_empty(&zilog->zl_itx_commit_list))
return;
list_create(&nolwb_itxs, sizeof (itx_t), offsetof(itx_t, itx_node));
@@ -2392,12 +2884,27 @@ zil_process_commit_list(zilog_t *zilog)
* have already been created (zl_lwb_list not empty).
*/
zil_commit_activate_saxattr_feature(zilog);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_ISSUED);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_WRITE_DONE);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_FLUSH_DONE);
+ ASSERT(lwb->lwb_state == LWB_STATE_NEW ||
+ lwb->lwb_state == LWB_STATE_OPENED);
+
+ /*
+ * If the lwb is still opened, it means the workload is really
+ * multi-threaded and we won the chance of write aggregation.
+ * If it is not opened yet, but previous lwb is still not
+ * flushed, it still means the workload is multi-threaded, but
+ * there was too much time between the commits to aggregate, so
+ * we try aggregation next times, but without too much hopes.
+ */
+ if (lwb->lwb_state == LWB_STATE_OPENED) {
+ zilog->zl_parallel = ZIL_BURSTS;
+ } else if ((plwb = list_prev(&zilog->zl_lwb_list, lwb))
+ != NULL && plwb->lwb_state != LWB_STATE_FLUSH_DONE) {
+ zilog->zl_parallel = MAX(zilog->zl_parallel,
+ ZIL_BURSTS / 2);
+ }
}
- while ((itx = list_head(&zilog->zl_itx_commit_list)) != NULL) {
+ while ((itx = list_remove_head(&zilog->zl_itx_commit_list)) != NULL) {
lr_t *lrc = &itx->itx_lr;
uint64_t txg = lrc->lrc_txg;
@@ -2411,8 +2918,6 @@ zil_process_commit_list(zilog_t *zilog)
zilog_t *, zilog, itx_t *, itx);
}
- list_remove(&zilog->zl_itx_commit_list, itx);
-
boolean_t synced = txg <= spa_last_synced_txg(spa);
boolean_t frozen = txg > spa_freeze_txg(spa);
@@ -2462,22 +2967,31 @@ zil_process_commit_list(zilog_t *zilog)
*/
if (frozen || !synced || lrc->lrc_txtype == TX_COMMIT) {
if (lwb != NULL) {
- lwb = zil_lwb_commit(zilog, itx, lwb);
-
- if (lwb == NULL)
+ lwb = zil_lwb_assign(zilog, lwb, itx, ilwbs);
+ if (lwb == NULL) {
list_insert_tail(&nolwb_itxs, itx);
- else
- list_insert_tail(&lwb->lwb_itxs, itx);
+ } else if ((zcw->zcw_lwb != NULL &&
+ zcw->zcw_lwb != lwb) || zcw->zcw_done) {
+ /*
+ * Our lwb is done, leave the rest of
+ * itx list to somebody else who care.
+ */
+ zilog->zl_parallel = ZIL_BURSTS;
+ zilog->zl_cur_left -=
+ zil_itx_full_size(itx);
+ break;
+ }
} else {
if (lrc->lrc_txtype == TX_COMMIT) {
zil_commit_waiter_link_nolwb(
itx->itx_private, &nolwb_waiters);
}
-
list_insert_tail(&nolwb_itxs, itx);
}
+ zilog->zl_cur_left -= zil_itx_full_size(itx);
} else {
ASSERT3S(lrc->lrc_txtype, !=, TX_COMMIT);
+ zilog->zl_cur_left -= zil_itx_full_size(itx);
zil_itx_destroy(itx);
}
}
@@ -2489,6 +3003,8 @@ zil_process_commit_list(zilog_t *zilog)
* the ZIL write pipeline; see the comment within
* zil_commit_writer_stall() for more details.
*/
+ while ((lwb = list_remove_head(ilwbs)) != NULL)
+ zil_lwb_write_issue(zilog, lwb);
zil_commit_writer_stall(zilog);
/*
@@ -2498,54 +3014,45 @@ zil_process_commit_list(zilog_t *zilog)
* normal.
*/
zil_commit_waiter_t *zcw;
- while ((zcw = list_head(&nolwb_waiters)) != NULL) {
+ while ((zcw = list_remove_head(&nolwb_waiters)) != NULL)
zil_commit_waiter_skip(zcw);
- list_remove(&nolwb_waiters, zcw);
- }
/*
* And finally, we have to destroy the itx's that
* couldn't be committed to an lwb; this will also call
* the itx's callback if one exists for the itx.
*/
- while ((itx = list_head(&nolwb_itxs)) != NULL) {
- list_remove(&nolwb_itxs, itx);
+ while ((itx = list_remove_head(&nolwb_itxs)) != NULL)
zil_itx_destroy(itx);
- }
} else {
ASSERT(list_is_empty(&nolwb_waiters));
ASSERT3P(lwb, !=, NULL);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_ISSUED);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_WRITE_DONE);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_FLUSH_DONE);
+ ASSERT(lwb->lwb_state == LWB_STATE_NEW ||
+ lwb->lwb_state == LWB_STATE_OPENED);
/*
* At this point, the ZIL block pointed at by the "lwb"
- * variable is in one of the following states: "closed"
- * or "open".
+ * variable is in "new" or "opened" state.
*
- * If it's "closed", then no itxs have been committed to
- * it, so there's no point in issuing its zio (i.e. it's
- * "empty").
+ * If it's "new", then no itxs have been committed to it, so
+ * there's no point in issuing its zio (i.e. it's "empty").
*
- * If it's "open", then it contains one or more itxs that
+ * If it's "opened", then it contains one or more itxs that
* eventually need to be committed to stable storage. In
* this case we intentionally do not issue the lwb's zio
* to disk yet, and instead rely on one of the following
* two mechanisms for issuing the zio:
*
- * 1. Ideally, there will be more ZIL activity occurring
- * on the system, such that this function will be
- * immediately called again (not necessarily by the same
- * thread) and this lwb's zio will be issued via
- * zil_lwb_commit(). This way, the lwb is guaranteed to
- * be "full" when it is issued to disk, and we'll make
- * use of the lwb's size the best we can.
+ * 1. Ideally, there will be more ZIL activity occurring on
+ * the system, such that this function will be immediately
+ * called again by different thread and this lwb will be
+ * closed by zil_lwb_assign(). This way, the lwb will be
+ * "full" when it is issued to disk, and we'll make use of
+ * the lwb's size the best we can.
*
* 2. If there isn't sufficient ZIL activity occurring on
- * the system, such that this lwb's zio isn't issued via
- * zil_lwb_commit(), zil_commit_waiter() will issue the
- * lwb's zio. If this occurs, the lwb is not guaranteed
+ * the system, zil_commit_waiter() will close it and issue
+ * the zio. If this occurs, the lwb is not guaranteed
* to be "full" by the time its zio is issued, and means
* the size of the lwb was "too large" given the amount
* of ZIL activity occurring on the system at that time.
@@ -2566,6 +3073,16 @@ zil_process_commit_list(zilog_t *zilog)
* possible, without significantly impacting the latency
* of each individual itx.
*/
+ if (lwb->lwb_state == LWB_STATE_OPENED && !zilog->zl_parallel) {
+ zil_burst_done(zilog);
+ list_insert_tail(ilwbs, lwb);
+ lwb = zil_lwb_write_close(zilog, lwb, LWB_STATE_NEW);
+ if (lwb == NULL) {
+ while ((lwb = list_remove_head(ilwbs)) != NULL)
+ zil_lwb_write_issue(zilog, lwb);
+ zil_commit_writer_stall(zilog);
+ }
+ }
}
}
@@ -2583,12 +3100,17 @@ zil_process_commit_list(zilog_t *zilog)
* not issued, we rely on future calls to zil_commit_writer() to issue
* the lwb, or the timeout mechanism found in zil_commit_waiter().
*/
-static void
+static uint64_t
zil_commit_writer(zilog_t *zilog, zil_commit_waiter_t *zcw)
{
+ list_t ilwbs;
+ lwb_t *lwb;
+ uint64_t wtxg = 0;
+
ASSERT(!MUTEX_HELD(&zilog->zl_lock));
ASSERT(spa_writeable(zilog->zl_spa));
+ list_create(&ilwbs, sizeof (lwb_t), offsetof(lwb_t, lwb_issue_node));
mutex_enter(&zilog->zl_issuer_lock);
if (zcw->zcw_lwb != NULL || zcw->zcw_done) {
@@ -2611,14 +3133,18 @@ zil_commit_writer(zilog_t *zilog, zil_commit_waiter_t *zcw)
goto out;
}
- ZIL_STAT_BUMP(zil_commit_writer_count);
+ ZIL_STAT_BUMP(zilog, zil_commit_writer_count);
- zil_get_commit_list(zilog);
+ wtxg = zil_get_commit_list(zilog);
zil_prune_commit_list(zilog);
- zil_process_commit_list(zilog);
+ zil_process_commit_list(zilog, zcw, &ilwbs);
out:
mutex_exit(&zilog->zl_issuer_lock);
+ while ((lwb = list_remove_head(&ilwbs)) != NULL)
+ zil_lwb_write_issue(zilog, lwb);
+ list_destroy(&ilwbs);
+ return (wtxg);
}
static void
@@ -2630,7 +3156,7 @@ zil_commit_waiter_timeout(zilog_t *zilog, zil_commit_waiter_t *zcw)
lwb_t *lwb = zcw->zcw_lwb;
ASSERT3P(lwb, !=, NULL);
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_CLOSED);
+ ASSERT3S(lwb->lwb_state, !=, LWB_STATE_NEW);
/*
* If the lwb has already been issued by another thread, we can
@@ -2639,13 +3165,11 @@ zil_commit_waiter_timeout(zilog_t *zilog, zil_commit_waiter_t *zcw)
* do this prior to acquiring the zl_issuer_lock, to avoid
* acquiring it when it's not necessary to do so.
*/
- if (lwb->lwb_state == LWB_STATE_ISSUED ||
- lwb->lwb_state == LWB_STATE_WRITE_DONE ||
- lwb->lwb_state == LWB_STATE_FLUSH_DONE)
+ if (lwb->lwb_state != LWB_STATE_OPENED)
return;
/*
- * In order to call zil_lwb_write_issue() we must hold the
+ * In order to call zil_lwb_write_close() we must hold the
* zilog's "zl_issuer_lock". We can't simply acquire that lock,
* since we're already holding the commit waiter's "zcw_lock",
* and those two locks are acquired in the opposite order
@@ -2663,8 +3187,10 @@ zil_commit_waiter_timeout(zilog_t *zilog, zil_commit_waiter_t *zcw)
* the waiter is marked "done"), so without this check we could
* wind up with a use-after-free error below.
*/
- if (zcw->zcw_done)
- goto out;
+ if (zcw->zcw_done) {
+ mutex_exit(&zilog->zl_issuer_lock);
+ return;
+ }
ASSERT3P(lwb, ==, zcw->zcw_lwb);
@@ -2674,26 +3200,33 @@ zil_commit_waiter_timeout(zilog_t *zilog, zil_commit_waiter_t *zcw)
* second time while holding the lock.
*
* We don't need to hold the zl_lock since the lwb cannot transition
- * from OPENED to ISSUED while we hold the zl_issuer_lock. The lwb
- * _can_ transition from ISSUED to DONE, but it's OK to race with
+ * from OPENED to CLOSED while we hold the zl_issuer_lock. The lwb
+ * _can_ transition from CLOSED to DONE, but it's OK to race with
* that transition since we treat the lwb the same, whether it's in
- * the ISSUED or DONE states.
+ * the CLOSED, ISSUED or DONE states.
*
* The important thing, is we treat the lwb differently depending on
- * if it's ISSUED or OPENED, and block any other threads that might
- * attempt to issue this lwb. For that reason we hold the
+ * if it's OPENED or CLOSED, and block any other threads that might
+ * attempt to close/issue this lwb. For that reason we hold the
* zl_issuer_lock when checking the lwb_state; we must not call
- * zil_lwb_write_issue() if the lwb had already been issued.
+ * zil_lwb_write_close() if the lwb had already been closed/issued.
*
* See the comment above the lwb_state_t structure definition for
* more details on the lwb states, and locking requirements.
*/
- if (lwb->lwb_state == LWB_STATE_ISSUED ||
- lwb->lwb_state == LWB_STATE_WRITE_DONE ||
- lwb->lwb_state == LWB_STATE_FLUSH_DONE)
- goto out;
+ if (lwb->lwb_state != LWB_STATE_OPENED) {
+ mutex_exit(&zilog->zl_issuer_lock);
+ return;
+ }
- ASSERT3S(lwb->lwb_state, ==, LWB_STATE_OPENED);
+ /*
+ * We do not need zcw_lock once we hold zl_issuer_lock and know lwb
+ * is still open. But we have to drop it to avoid a deadlock in case
+ * callback of zio issued by zil_lwb_write_issue() try to get it,
+ * while zil_lwb_write_issue() is blocked on attempt to issue next
+ * lwb it found in LWB_STATE_READY state.
+ */
+ mutex_exit(&zcw->zcw_lock);
/*
* As described in the comments above zil_commit_waiter() and
@@ -2701,55 +3234,27 @@ zil_commit_waiter_timeout(zilog_t *zilog, zil_commit_waiter_t *zcw)
* since we've reached the commit waiter's timeout and it still
* hasn't been issued.
*/
- lwb_t *nlwb = zil_lwb_write_issue(zilog, lwb);
-
- IMPLY(nlwb != NULL, lwb->lwb_state != LWB_STATE_OPENED);
+ zil_burst_done(zilog);
+ lwb_t *nlwb = zil_lwb_write_close(zilog, lwb, LWB_STATE_NEW);
- /*
- * Since the lwb's zio hadn't been issued by the time this thread
- * reached its timeout, we reset the zilog's "zl_cur_used" field
- * to influence the zil block size selection algorithm.
- *
- * By having to issue the lwb's zio here, it means the size of the
- * lwb was too large, given the incoming throughput of itxs. By
- * setting "zl_cur_used" to zero, we communicate this fact to the
- * block size selection algorithm, so it can take this information
- * into account, and potentially select a smaller size for the
- * next lwb block that is allocated.
- */
- zilog->zl_cur_used = 0;
+ ASSERT3S(lwb->lwb_state, ==, LWB_STATE_CLOSED);
if (nlwb == NULL) {
/*
- * When zil_lwb_write_issue() returns NULL, this
+ * When zil_lwb_write_close() returns NULL, this
* indicates zio_alloc_zil() failed to allocate the
* "next" lwb on-disk. When this occurs, the ZIL write
* pipeline must be stalled; see the comment within the
* zil_commit_writer_stall() function for more details.
- *
- * We must drop the commit waiter's lock prior to
- * calling zil_commit_writer_stall() or else we can wind
- * up with the following deadlock:
- *
- * - This thread is waiting for the txg to sync while
- * holding the waiter's lock; txg_wait_synced() is
- * used within txg_commit_writer_stall().
- *
- * - The txg can't sync because it is waiting for this
- * lwb's zio callback to call dmu_tx_commit().
- *
- * - The lwb's zio callback can't call dmu_tx_commit()
- * because it's blocked trying to acquire the waiter's
- * lock, which occurs prior to calling dmu_tx_commit()
*/
- mutex_exit(&zcw->zcw_lock);
+ zil_lwb_write_issue(zilog, lwb);
zil_commit_writer_stall(zilog);
- mutex_enter(&zcw->zcw_lock);
+ mutex_exit(&zilog->zl_issuer_lock);
+ } else {
+ mutex_exit(&zilog->zl_issuer_lock);
+ zil_lwb_write_issue(zilog, lwb);
}
-
-out:
- mutex_exit(&zilog->zl_issuer_lock);
- ASSERT(MUTEX_HELD(&zcw->zcw_lock));
+ mutex_enter(&zcw->zcw_lock);
}
/*
@@ -2763,7 +3268,7 @@ out:
* waited "long enough" and the lwb is still in the "open" state.
*
* Given a sufficient amount of itxs being generated and written using
- * the ZIL, the lwb's zio will be issued via the zil_lwb_commit()
+ * the ZIL, the lwb's zio will be issued via the zil_lwb_assign()
* function. If this does not occur, this secondary responsibility will
* ensure the lwb is issued even if there is not other synchronous
* activity on the system.
@@ -2814,7 +3319,7 @@ zil_commit_waiter(zilog_t *zilog, zil_commit_waiter_t *zcw)
* where it's "zcw_lwb" field is NULL, and it hasn't yet
* been skipped, so it's "zcw_done" field is still B_FALSE.
*/
- IMPLY(lwb != NULL, lwb->lwb_state != LWB_STATE_CLOSED);
+ IMPLY(lwb != NULL, lwb->lwb_state != LWB_STATE_NEW);
if (lwb != NULL && lwb->lwb_state == LWB_STATE_OPENED) {
ASSERT3B(timedout, ==, B_FALSE);
@@ -2862,6 +3367,8 @@ zil_commit_waiter(zilog_t *zilog, zil_commit_waiter_t *zcw)
*/
IMPLY(lwb != NULL,
+ lwb->lwb_state == LWB_STATE_CLOSED ||
+ lwb->lwb_state == LWB_STATE_READY ||
lwb->lwb_state == LWB_STATE_ISSUED ||
lwb->lwb_state == LWB_STATE_WRITE_DONE ||
lwb->lwb_state == LWB_STATE_FLUSH_DONE);
@@ -2908,7 +3415,14 @@ static void
zil_commit_itx_assign(zilog_t *zilog, zil_commit_waiter_t *zcw)
{
dmu_tx_t *tx = dmu_tx_create(zilog->zl_os);
- VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
+
+ /*
+ * Since we are not going to create any new dirty data, and we
+ * can even help with clearing the existing dirty data, we
+ * should not be subject to the dirty data based delays. We
+ * use TXG_NOTHROTTLE to bypass the delay mechanism.
+ */
+ VERIFY0(dmu_tx_assign(tx, TXG_WAIT | TXG_NOTHROTTLE));
itx_t *itx = zil_itx_create(TX_COMMIT, sizeof (lr_t));
itx->itx_sync = B_TRUE;
@@ -2980,8 +3494,8 @@ zil_commit_itx_assign(zilog_t *zilog, zil_commit_waiter_t *zcw)
* callback of the lwb's zio[*].
*
* * Actually, the waiters are signaled in the zio completion
- * callback of the root zio for the DKIOCFLUSHWRITECACHE commands
- * that are sent to the vdevs upon completion of the lwb zio.
+ * callback of the root zio for the flush commands that are sent to
+ * the vdevs upon completion of the lwb zio.
*
* 2. When the itxs are inserted into the ZIL's queue of uncommitted
* itxs, the order in which they are inserted is preserved[*]; as
@@ -3088,7 +3602,7 @@ zil_commit(zilog_t *zilog, uint64_t foid)
void
zil_commit_impl(zilog_t *zilog, uint64_t foid)
{
- ZIL_STAT_BUMP(zil_commit_count);
+ ZIL_STAT_BUMP(zilog, zil_commit_count);
/*
* Move the "async" itxs for the specified foid to the "sync"
@@ -3119,7 +3633,7 @@ zil_commit_impl(zilog_t *zilog, uint64_t foid)
zil_commit_waiter_t *zcw = zil_alloc_commit_waiter();
zil_commit_itx_assign(zilog, zcw);
- zil_commit_writer(zilog, zcw);
+ uint64_t wtxg = zil_commit_writer(zilog, zcw);
zil_commit_waiter(zilog, zcw);
if (zcw->zcw_zio_error != 0) {
@@ -3134,6 +3648,8 @@ zil_commit_impl(zilog_t *zilog, uint64_t foid)
DTRACE_PROBE2(zil__commit__io__error,
zilog_t *, zilog, zil_commit_waiter_t *, zcw);
txg_wait_synced(zilog->zl_dmu_pool, 0);
+ } else if (wtxg != 0) {
+ txg_wait_synced(zilog->zl_dmu_pool, wtxg);
}
zil_free_commit_waiter(zcw);
@@ -3174,7 +3690,7 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
blkptr_t blk = zh->zh_log;
dsl_dataset_t *ds = dmu_objset_ds(zilog->zl_os);
- ASSERT(list_head(&zilog->zl_lwb_list) == NULL);
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
memset(zh, 0, sizeof (zil_header_t));
memset(zilog->zl_replayed_seq, 0,
@@ -3206,10 +3722,12 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
while ((lwb = list_head(&zilog->zl_lwb_list)) != NULL) {
zh->zh_log = lwb->lwb_blk;
- if (lwb->lwb_buf != NULL || lwb->lwb_max_txg > txg)
+ if (lwb->lwb_state != LWB_STATE_FLUSH_DONE ||
+ lwb->lwb_alloc_txg > txg || lwb->lwb_max_txg > txg)
break;
list_remove(&zilog->zl_lwb_list, lwb);
- zio_free(spa, txg, &lwb->lwb_blk);
+ if (!BP_IS_HOLE(&lwb->lwb_blk))
+ zio_free(spa, txg, &lwb->lwb_blk);
zil_free_lwb(zilog, lwb);
/*
@@ -3218,22 +3736,10 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
* out the zil_header blkptr so that we don't end
* up freeing the same block twice.
*/
- if (list_head(&zilog->zl_lwb_list) == NULL)
+ if (list_is_empty(&zilog->zl_lwb_list))
BP_ZERO(&zh->zh_log);
}
- /*
- * Remove fastwrite on any blocks that have been pre-allocated for
- * the next commit. This prevents fastwrite counter pollution by
- * unused, long-lived LWBs.
- */
- for (; lwb != NULL; lwb = list_next(&zilog->zl_lwb_list, lwb)) {
- if (lwb->lwb_fastwrite && !lwb->lwb_write_zio) {
- metaslab_fastwrite_unmark(zilog->zl_spa, &lwb->lwb_blk);
- lwb->lwb_fastwrite = 0;
- }
- }
-
mutex_exit(&zilog->zl_lock);
}
@@ -3271,13 +3777,16 @@ zil_init(void)
zil_zcw_cache = kmem_cache_create("zil_zcw_cache",
sizeof (zil_commit_waiter_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
- zil_ksp = kstat_create("zfs", 0, "zil", "misc",
+ zil_sums_init(&zil_sums_global);
+ zil_kstats_global = kstat_create("zfs", 0, "zil", "misc",
KSTAT_TYPE_NAMED, sizeof (zil_stats) / sizeof (kstat_named_t),
KSTAT_FLAG_VIRTUAL);
- if (zil_ksp != NULL) {
- zil_ksp->ks_data = &zil_stats;
- kstat_install(zil_ksp);
+ if (zil_kstats_global != NULL) {
+ zil_kstats_global->ks_data = &zil_stats;
+ zil_kstats_global->ks_update = zil_kstats_global_update;
+ zil_kstats_global->ks_private = NULL;
+ kstat_install(zil_kstats_global);
}
}
@@ -3287,10 +3796,12 @@ zil_fini(void)
kmem_cache_destroy(zil_zcw_cache);
kmem_cache_destroy(zil_lwb_cache);
- if (zil_ksp != NULL) {
- kstat_delete(zil_ksp);
- zil_ksp = NULL;
+ if (zil_kstats_global != NULL) {
+ kstat_delete(zil_kstats_global);
+ zil_kstats_global = NULL;
}
+
+ zil_sums_fini(&zil_sums_global);
}
void
@@ -3322,7 +3833,9 @@ zil_alloc(objset_t *os, zil_header_t *zh_phys)
zilog->zl_dirty_max_txg = 0;
zilog->zl_last_lwb_opened = NULL;
zilog->zl_last_lwb_latency = 0;
- zilog->zl_max_block_size = zil_maxblocksize;
+ zilog->zl_max_block_size = MIN(MAX(P2ALIGN_TYPED(zil_maxblocksize,
+ ZIL_MIN_BLKSZ, uint64_t), ZIL_MIN_BLKSZ),
+ spa_maxblocksize(dmu_objset_spa(os)));
mutex_init(&zilog->zl_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&zilog->zl_issuer_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -3342,6 +3855,11 @@ zil_alloc(objset_t *os, zil_header_t *zh_phys)
cv_init(&zilog->zl_cv_suspend, NULL, CV_DEFAULT, NULL);
cv_init(&zilog->zl_lwb_io_cv, NULL, CV_DEFAULT, NULL);
+ for (int i = 0; i < ZIL_BURSTS; i++) {
+ zilog->zl_prev_opt[i] = zilog->zl_max_block_size -
+ sizeof (zil_chain_t);
+ }
+
return (zilog);
}
@@ -3388,7 +3906,7 @@ zil_free(zilog_t *zilog)
* Open an intent log.
*/
zilog_t *
-zil_open(objset_t *os, zil_get_data_t *get_data)
+zil_open(objset_t *os, zil_get_data_t *get_data, zil_sums_t *zil_sums)
{
zilog_t *zilog = dmu_objset_zil(os);
@@ -3397,6 +3915,7 @@ zil_open(objset_t *os, zil_get_data_t *get_data)
ASSERT(list_is_empty(&zilog->zl_lwb_list));
zilog->zl_get_data = get_data;
+ zilog->zl_sums = zil_sums;
return (zilog);
}
@@ -3413,17 +3932,18 @@ zil_close(zilog_t *zilog)
if (!dmu_objset_is_snapshot(zilog->zl_os)) {
zil_commit(zilog, 0);
} else {
- ASSERT3P(list_tail(&zilog->zl_lwb_list), ==, NULL);
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
ASSERT0(zilog->zl_dirty_max_txg);
ASSERT3B(zilog_is_dirty(zilog), ==, B_FALSE);
}
mutex_enter(&zilog->zl_lock);
+ txg = zilog->zl_dirty_max_txg;
lwb = list_tail(&zilog->zl_lwb_list);
- if (lwb == NULL)
- txg = zilog->zl_dirty_max_txg;
- else
- txg = MAX(zilog->zl_dirty_max_txg, lwb->lwb_max_txg);
+ if (lwb != NULL) {
+ txg = MAX(txg, lwb->lwb_alloc_txg);
+ txg = MAX(txg, lwb->lwb_max_txg);
+ }
mutex_exit(&zilog->zl_lock);
/*
@@ -3455,15 +3975,10 @@ zil_close(zilog_t *zilog)
* We should have only one lwb left on the list; remove it now.
*/
mutex_enter(&zilog->zl_lock);
- lwb = list_head(&zilog->zl_lwb_list);
+ lwb = list_remove_head(&zilog->zl_lwb_list);
if (lwb != NULL) {
- ASSERT3P(lwb, ==, list_tail(&zilog->zl_lwb_list));
- ASSERT3S(lwb->lwb_state, !=, LWB_STATE_ISSUED);
-
- if (lwb->lwb_fastwrite)
- metaslab_fastwrite_unmark(zilog->zl_spa, &lwb->lwb_blk);
-
- list_remove(&zilog->zl_lwb_list, lwb);
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
+ ASSERT3S(lwb->lwb_state, ==, LWB_STATE_NEW);
zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
zil_free_lwb(zilog, lwb);
}
@@ -3584,7 +4099,7 @@ zil_suspend(const char *osname, void **cookiep)
/*
* We need to use zil_commit_impl to ensure we wait for all
- * LWB_STATE_OPENED and LWB_STATE_ISSUED lwbs to be committed
+ * LWB_STATE_OPENED, _CLOSED and _READY lwbs to be committed
* to disk before proceeding. If we used zil_commit instead, it
* would just call txg_wait_synced(), because zl_suspend is set.
* txg_wait_synced() doesn't wait for these lwb's to be
@@ -3750,8 +4265,9 @@ zil_incr_blks(zilog_t *zilog, const blkptr_t *bp, void *arg, uint64_t claim_txg)
/*
* If this dataset has a non-empty intent log, replay it and destroy it.
+ * Return B_TRUE if there were any entries to replay.
*/
-void
+boolean_t
zil_replay(objset_t *os, void *arg,
zil_replay_func_t *const replay_func[TX_MAX_TYPE])
{
@@ -3760,8 +4276,7 @@ zil_replay(objset_t *os, void *arg,
zil_replay_arg_t zr;
if ((zh->zh_flags & ZIL_REPLAY_NEEDED) == 0) {
- zil_destroy(zilog, B_TRUE);
- return;
+ return (zil_destroy(zilog, B_TRUE));
}
zr.zr_replay = replay_func;
@@ -3784,6 +4299,8 @@ zil_replay(objset_t *os, void *arg,
zil_destroy(zilog, B_FALSE);
txg_wait_synced(zilog->zl_dmu_pool, zilog->zl_destroy_txg);
zilog->zl_replay = B_FALSE;
+
+ return (B_TRUE);
}
boolean_t
@@ -3838,8 +4355,11 @@ EXPORT_SYMBOL(zil_lwb_add_block);
EXPORT_SYMBOL(zil_bp_tree_add);
EXPORT_SYMBOL(zil_set_sync);
EXPORT_SYMBOL(zil_set_logbias);
+EXPORT_SYMBOL(zil_sums_init);
+EXPORT_SYMBOL(zil_sums_fini);
+EXPORT_SYMBOL(zil_kstat_values_update);
-ZFS_MODULE_PARAM(zfs, zfs_, commit_timeout_pct, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, commit_timeout_pct, UINT, ZMOD_RW,
"ZIL block open timeout percentage");
ZFS_MODULE_PARAM(zfs_zil, zil_, replay_disable, INT, ZMOD_RW,
@@ -3848,8 +4368,11 @@ ZFS_MODULE_PARAM(zfs_zil, zil_, replay_disable, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_zil, zil_, nocacheflush, INT, ZMOD_RW,
"Disable ZIL cache flushes");
-ZFS_MODULE_PARAM(zfs_zil, zil_, slog_bulk, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_zil, zil_, slog_bulk, U64, ZMOD_RW,
"Limit in bytes slog sync writes per commit");
-ZFS_MODULE_PARAM(zfs_zil, zil_, maxblocksize, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_zil, zil_, maxblocksize, UINT, ZMOD_RW,
"Limit in bytes of ZIL log block size");
+
+ZFS_MODULE_PARAM(zfs_zil, zil_, maxcopied, UINT, ZMOD_RW,
+ "Limit in bytes WR_COPIED size");
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 1c9f598b7d13..870343bf4fa3 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -20,10 +20,10 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2022 by Delphix. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
- * Copyright (c) 2019, Klara Inc.
+ * Copyright (c) 2019, 2023, 2024, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright (c) 2021, Datto, Inc.
*/
@@ -41,6 +41,7 @@
#include <sys/zio_checksum.h>
#include <sys/dmu_objset.h>
#include <sys/arc.h>
+#include <sys/brt.h>
#include <sys/ddt.h>
#include <sys/blkptr.h>
#include <sys/zfeature.h>
@@ -62,7 +63,7 @@ const char *const zio_type_name[ZIO_TYPES] = {
* Note: Linux kernel thread name length is limited
* so these names will differ from upstream open zfs.
*/
- "z_null", "z_rd", "z_wr", "z_fr", "z_cl", "z_ioctl", "z_trim"
+ "z_null", "z_rd", "z_wr", "z_fr", "z_cl", "z_flush", "z_trim"
};
int zio_dva_throttle_enabled = B_TRUE;
@@ -83,7 +84,7 @@ static uint64_t zio_buf_cache_frees[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT];
#endif
/* Mark IOs as "slow" if they take longer than 30 seconds */
-static int zio_slow_io_ms = (30 * MILLISEC);
+static uint_t zio_slow_io_ms = (30 * MILLISEC);
#define BP_SPANB(indblkshift, level) \
(((uint64_t)1) << ((level) * ((indblkshift) - SPA_BLKPTRSHIFT)))
@@ -114,9 +115,15 @@ static int zio_slow_io_ms = (30 * MILLISEC);
* fragmented systems, which may have very few free segments of this size,
* and may need to load new metaslabs to satisfy 128K allocations.
*/
-int zfs_sync_pass_deferred_free = 2; /* defer frees starting in this pass */
-static int zfs_sync_pass_dont_compress = 8; /* don't compress s. i. t. p. */
-static int zfs_sync_pass_rewrite = 2; /* rewrite new bps s. i. t. p. */
+
+/* defer frees starting in this pass */
+uint_t zfs_sync_pass_deferred_free = 2;
+
+/* don't compress starting in this pass */
+static uint_t zfs_sync_pass_dont_compress = 8;
+
+/* rewrite new bps starting in this pass */
+static uint_t zfs_sync_pass_rewrite = 2;
/*
* An allocating zio is one that either currently has the DVA allocate
@@ -151,23 +158,22 @@ zio_init(void)
zio_link_cache = kmem_cache_create("zio_link_cache",
sizeof (zio_link_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
- /*
- * For small buffers, we want a cache for each multiple of
- * SPA_MINBLOCKSIZE. For larger buffers, we want a cache
- * for each quarter-power of 2.
- */
for (c = 0; c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; c++) {
size_t size = (c + 1) << SPA_MINBLOCKSHIFT;
- size_t p2 = size;
- size_t align = 0;
- size_t data_cflags, cflags;
-
- data_cflags = KMC_NODEBUG;
- cflags = (zio_exclude_metadata || size > zio_buf_debug_limit) ?
- KMC_NODEBUG : 0;
+ size_t align, cflags, data_cflags;
+ char name[32];
+ /*
+ * Create cache for each half-power of 2 size, starting from
+ * SPA_MINBLOCKSIZE. It should give us memory space efficiency
+ * of ~7/8, sufficient for transient allocations mostly using
+ * these caches.
+ */
+ size_t p2 = size;
while (!ISP2(p2))
p2 &= p2 - 1;
+ if (!IS_P2ALIGNED(size, p2 / 2))
+ continue;
#ifndef _KERNEL
/*
@@ -178,47 +184,37 @@ zio_init(void)
*/
if (arc_watch && !IS_P2ALIGNED(size, PAGESIZE))
continue;
- /*
- * Here's the problem - on 4K native devices in userland on
- * Linux using O_DIRECT, buffers must be 4K aligned or I/O
- * will fail with EINVAL, causing zdb (and others) to coredump.
- * Since userland probably doesn't need optimized buffer caches,
- * we just force 4K alignment on everything.
- */
- align = 8 * SPA_MINBLOCKSIZE;
-#else
- if (size < PAGESIZE) {
- align = SPA_MINBLOCKSIZE;
- } else if (IS_P2ALIGNED(size, p2 >> 2)) {
- align = PAGESIZE;
- }
#endif
- if (align != 0) {
- char name[36];
- if (cflags == data_cflags) {
- /*
- * Resulting kmem caches would be identical.
- * Save memory by creating only one.
- */
- (void) snprintf(name, sizeof (name),
- "zio_buf_comb_%lu", (ulong_t)size);
- zio_buf_cache[c] = kmem_cache_create(name,
- size, align, NULL, NULL, NULL, NULL, NULL,
- cflags);
- zio_data_buf_cache[c] = zio_buf_cache[c];
- continue;
- }
- (void) snprintf(name, sizeof (name), "zio_buf_%lu",
- (ulong_t)size);
- zio_buf_cache[c] = kmem_cache_create(name, size,
- align, NULL, NULL, NULL, NULL, NULL, cflags);
-
- (void) snprintf(name, sizeof (name), "zio_data_buf_%lu",
- (ulong_t)size);
- zio_data_buf_cache[c] = kmem_cache_create(name, size,
- align, NULL, NULL, NULL, NULL, NULL, data_cflags);
+ if (IS_P2ALIGNED(size, PAGESIZE))
+ align = PAGESIZE;
+ else
+ align = 1 << (highbit64(size ^ (size - 1)) - 1);
+
+ cflags = (zio_exclude_metadata || size > zio_buf_debug_limit) ?
+ KMC_NODEBUG : 0;
+ data_cflags = KMC_NODEBUG;
+ if (cflags == data_cflags) {
+ /*
+ * Resulting kmem caches would be identical.
+ * Save memory by creating only one.
+ */
+ (void) snprintf(name, sizeof (name),
+ "zio_buf_comb_%lu", (ulong_t)size);
+ zio_buf_cache[c] = kmem_cache_create(name, size, align,
+ NULL, NULL, NULL, NULL, NULL, cflags);
+ zio_data_buf_cache[c] = zio_buf_cache[c];
+ continue;
}
+ (void) snprintf(name, sizeof (name), "zio_buf_%lu",
+ (ulong_t)size);
+ zio_buf_cache[c] = kmem_cache_create(name, size, align,
+ NULL, NULL, NULL, NULL, NULL, cflags);
+
+ (void) snprintf(name, sizeof (name), "zio_data_buf_%lu",
+ (ulong_t)size);
+ zio_data_buf_cache[c] = kmem_cache_create(name, size, align,
+ NULL, NULL, NULL, NULL, NULL, data_cflags);
}
while (--c != 0) {
@@ -299,6 +295,53 @@ zio_fini(void)
* ==========================================================================
*/
+#ifdef ZFS_DEBUG
+static const ulong_t zio_buf_canary = (ulong_t)0xdeadc0dedead210b;
+#endif
+
+/*
+ * Use empty space after the buffer to detect overflows.
+ *
+ * Since zio_init() creates kmem caches only for certain set of buffer sizes,
+ * allocations of different sizes may have some unused space after the data.
+ * Filling part of that space with a known pattern on allocation and checking
+ * it on free should allow us to detect some buffer overflows.
+ */
+static void
+zio_buf_put_canary(ulong_t *p, size_t size, kmem_cache_t **cache, size_t c)
+{
+#ifdef ZFS_DEBUG
+ size_t off = P2ROUNDUP(size, sizeof (ulong_t));
+ ulong_t *canary = p + off / sizeof (ulong_t);
+ size_t asize = (c + 1) << SPA_MINBLOCKSHIFT;
+ if (c + 1 < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT &&
+ cache[c] == cache[c + 1])
+ asize = (c + 2) << SPA_MINBLOCKSHIFT;
+ for (; off < asize; canary++, off += sizeof (ulong_t))
+ *canary = zio_buf_canary;
+#endif
+}
+
+static void
+zio_buf_check_canary(ulong_t *p, size_t size, kmem_cache_t **cache, size_t c)
+{
+#ifdef ZFS_DEBUG
+ size_t off = P2ROUNDUP(size, sizeof (ulong_t));
+ ulong_t *canary = p + off / sizeof (ulong_t);
+ size_t asize = (c + 1) << SPA_MINBLOCKSHIFT;
+ if (c + 1 < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT &&
+ cache[c] == cache[c + 1])
+ asize = (c + 2) << SPA_MINBLOCKSHIFT;
+ for (; off < asize; canary++, off += sizeof (ulong_t)) {
+ if (unlikely(*canary != zio_buf_canary)) {
+ PANIC("ZIO buffer overflow %p (%zu) + %zu %#lx != %#lx",
+ p, size, (canary - p) * sizeof (ulong_t),
+ *canary, zio_buf_canary);
+ }
+ }
+#endif
+}
+
/*
* Use zio_buf_alloc to allocate ZFS metadata. This data will appear in a
* crashdump if the kernel panics, so use it judiciously. Obviously, it's
@@ -315,7 +358,9 @@ zio_buf_alloc(size_t size)
atomic_add_64(&zio_buf_cache_allocs[c], 1);
#endif
- return (kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE));
+ void *p = kmem_cache_alloc(zio_buf_cache[c], KM_PUSHPAGE);
+ zio_buf_put_canary(p, size, zio_buf_cache, c);
+ return (p);
}
/*
@@ -331,7 +376,9 @@ zio_data_buf_alloc(size_t size)
VERIFY3U(c, <, SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
- return (kmem_cache_alloc(zio_data_buf_cache[c], KM_PUSHPAGE));
+ void *p = kmem_cache_alloc(zio_data_buf_cache[c], KM_PUSHPAGE);
+ zio_buf_put_canary(p, size, zio_data_buf_cache, c);
+ return (p);
}
void
@@ -344,6 +391,7 @@ zio_buf_free(void *buf, size_t size)
atomic_add_64(&zio_buf_cache_frees[c], 1);
#endif
+ zio_buf_check_canary(buf, size, zio_buf_cache, c);
kmem_cache_free(zio_buf_cache[c], buf);
}
@@ -354,6 +402,7 @@ zio_data_buf_free(void *buf, size_t size)
VERIFY3U(c, <, SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
+ zio_buf_check_canary(buf, size, zio_data_buf_cache, c);
kmem_cache_free(zio_data_buf_cache[c], buf);
}
@@ -506,8 +555,9 @@ zio_decrypt(zio_t *zio, abd_t *data, uint64_t size)
/*
* If this is an authenticated block, just check the MAC. It would be
- * nice to separate this out into its own flag, but for the moment
- * enum zio_flag is out of bits.
+ * nice to separate this out into its own flag, but when this was done,
+ * we had run out of bits in what is now zio_flag_t. Future cleanup
+ * could make this a flag bit.
*/
if (BP_IS_AUTHENTICATED(bp)) {
if (ot == DMU_OT_OBJSET) {
@@ -562,7 +612,8 @@ error:
if (ret == ECKSUM) {
zio->io_error = SET_ERROR(EIO);
if ((zio->io_flags & ZIO_FLAG_SPECULATIVE) == 0) {
- spa_log_error(spa, &zio->io_bookmark);
+ spa_log_error(spa, &zio->io_bookmark,
+ BP_GET_LOGICAL_BIRTH(zio->io_bp));
(void) zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
spa, NULL, &zio->io_bookmark, zio, 0);
}
@@ -617,8 +668,6 @@ zio_unique_parent(zio_t *cio)
void
zio_add_child(zio_t *pio, zio_t *cio)
{
- zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_SLEEP);
-
/*
* Logical I/Os can have logical, gang, or vdev children.
* Gang I/Os can have gang or vdev children.
@@ -627,6 +676,12 @@ zio_add_child(zio_t *pio, zio_t *cio)
*/
ASSERT3S(cio->io_child_type, <=, pio->io_child_type);
+ /* Parent should not have READY stage if child doesn't have it. */
+ IMPLY((cio->io_pipeline & ZIO_STAGE_READY) == 0 &&
+ (cio->io_child_type != ZIO_CHILD_VDEV),
+ (pio->io_pipeline & ZIO_STAGE_READY) == 0);
+
+ zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_SLEEP);
zl->zl_parent = pio;
zl->zl_child = cio;
@@ -635,19 +690,53 @@ zio_add_child(zio_t *pio, zio_t *cio)
ASSERT(pio->io_state[ZIO_WAIT_DONE] == 0);
+ uint64_t *countp = pio->io_children[cio->io_child_type];
for (int w = 0; w < ZIO_WAIT_TYPES; w++)
- pio->io_children[cio->io_child_type][w] += !cio->io_state[w];
+ countp[w] += !cio->io_state[w];
list_insert_head(&pio->io_child_list, zl);
list_insert_head(&cio->io_parent_list, zl);
- pio->io_child_count++;
- cio->io_parent_count++;
-
mutex_exit(&cio->io_lock);
mutex_exit(&pio->io_lock);
}
+void
+zio_add_child_first(zio_t *pio, zio_t *cio)
+{
+ /*
+ * Logical I/Os can have logical, gang, or vdev children.
+ * Gang I/Os can have gang or vdev children.
+ * Vdev I/Os can only have vdev children.
+ * The following ASSERT captures all of these constraints.
+ */
+ ASSERT3S(cio->io_child_type, <=, pio->io_child_type);
+
+ /* Parent should not have READY stage if child doesn't have it. */
+ IMPLY((cio->io_pipeline & ZIO_STAGE_READY) == 0 &&
+ (cio->io_child_type != ZIO_CHILD_VDEV),
+ (pio->io_pipeline & ZIO_STAGE_READY) == 0);
+
+ zio_link_t *zl = kmem_cache_alloc(zio_link_cache, KM_SLEEP);
+ zl->zl_parent = pio;
+ zl->zl_child = cio;
+
+ ASSERT(list_is_empty(&cio->io_parent_list));
+ list_insert_head(&cio->io_parent_list, zl);
+
+ mutex_enter(&pio->io_lock);
+
+ ASSERT(pio->io_state[ZIO_WAIT_DONE] == 0);
+
+ uint64_t *countp = pio->io_children[cio->io_child_type];
+ for (int w = 0; w < ZIO_WAIT_TYPES; w++)
+ countp[w] += !cio->io_state[w];
+
+ list_insert_head(&pio->io_child_list, zl);
+
+ mutex_exit(&pio->io_lock);
+}
+
static void
zio_remove_child(zio_t *pio, zio_t *cio, zio_link_t *zl)
{
@@ -660,9 +749,6 @@ zio_remove_child(zio_t *pio, zio_t *cio, zio_link_t *zl)
list_remove(&pio->io_child_list, zl);
list_remove(&cio->io_parent_list, zl);
- pio->io_child_count--;
- cio->io_parent_count--;
-
mutex_exit(&cio->io_lock);
mutex_exit(&pio->io_lock);
kmem_cache_free(zio_link_cache, zl);
@@ -717,7 +803,10 @@ zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait,
/*
* If we can tell the caller to execute this parent next, do
- * so. Otherwise dispatch the parent zio as its own task.
+ * so. We do this if the parent's zio type matches the child's
+ * type, or if it's a zio_null() with no done callback, and so
+ * has no actual work to do. Otherwise dispatch the parent zio
+ * in its own taskq.
*
* Having the caller execute the parent when possible reduces
* locking on the zio taskq's, reduces context switch
@@ -736,7 +825,9 @@ zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait,
* parent-child relationships, as we do with the "mega zio"
* of writes for spa_sync(), and the chain of ZIL blocks.
*/
- if (next_to_executep != NULL && *next_to_executep == NULL) {
+ if (next_to_executep != NULL && *next_to_executep == NULL &&
+ (pio->io_type == zio->io_type ||
+ (pio->io_type == ZIO_TYPE_NULL && !pio->io_done))) {
*next_to_executep = pio;
} else {
zio_taskq_dispatch(pio, type, B_FALSE);
@@ -796,7 +887,7 @@ static zio_t *
zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
abd_t *data, uint64_t lsize, uint64_t psize, zio_done_func_t *done,
void *private, zio_type_t type, zio_priority_t priority,
- enum zio_flag flags, vdev_t *vd, uint64_t offset,
+ zio_flag_t flags, vdev_t *vd, uint64_t offset,
const zbookmark_phys_t *zb, enum zio_stage stage,
enum zio_stage pipeline)
{
@@ -834,12 +925,14 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
zio->io_child_type = ZIO_CHILD_LOGICAL;
if (bp != NULL) {
- zio->io_bp = (blkptr_t *)bp;
- zio->io_bp_copy = *bp;
- zio->io_bp_orig = *bp;
if (type != ZIO_TYPE_WRITE ||
- zio->io_child_type == ZIO_CHILD_DDT)
+ zio->io_child_type == ZIO_CHILD_DDT) {
+ zio->io_bp_copy = *bp;
zio->io_bp = &zio->io_bp_copy; /* so caller can free */
+ } else {
+ zio->io_bp = (blkptr_t *)bp;
+ }
+ zio->io_bp_orig = *bp;
if (zio->io_child_type == ZIO_CHILD_LOGICAL)
zio->io_logical = zio;
if (zio->io_child_type > ZIO_CHILD_GANG && BP_IS_GANG(bp))
@@ -861,8 +954,10 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
zio->io_orig_stage = zio->io_stage = stage;
zio->io_orig_pipeline = zio->io_pipeline = pipeline;
zio->io_pipeline_trace = ZIO_STAGE_OPEN;
+ zio->io_allocator = ZIO_ALLOCATOR_NONE;
- zio->io_state[ZIO_WAIT_READY] = (stage >= ZIO_STAGE_READY);
+ zio->io_state[ZIO_WAIT_READY] = (stage >= ZIO_STAGE_READY) ||
+ (pipeline & ZIO_STAGE_READY) == 0;
zio->io_state[ZIO_WAIT_DONE] = (stage >= ZIO_STAGE_DONE);
if (zb != NULL)
@@ -874,7 +969,7 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
zio->io_logical = pio->io_logical;
if (zio->io_child_type == ZIO_CHILD_GANG)
zio->io_gang_leader = pio->io_gang_leader;
- zio_add_child(pio, zio);
+ zio_add_child_first(pio, zio);
}
taskq_init_ent(&zio->io_tqent);
@@ -882,7 +977,7 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
return (zio);
}
-static void
+void
zio_destroy(zio_t *zio)
{
metaslab_trace_fini(&zio->io_alloc_list);
@@ -893,9 +988,13 @@ zio_destroy(zio_t *zio)
kmem_cache_free(zio_cache, zio);
}
+/*
+ * ZIO intended to be between others. Provides synchronization at READY
+ * and DONE pipeline stages and calls the respective callbacks.
+ */
zio_t *
zio_null(zio_t *pio, spa_t *spa, vdev_t *vd, zio_done_func_t *done,
- void *private, enum zio_flag flags)
+ void *private, zio_flag_t flags)
{
zio_t *zio;
@@ -906,10 +1005,22 @@ zio_null(zio_t *pio, spa_t *spa, vdev_t *vd, zio_done_func_t *done,
return (zio);
}
+/*
+ * ZIO intended to be a root of a tree. Unlike null ZIO does not have a
+ * READY pipeline stage (is ready on creation), so it should not be used
+ * as child of any ZIO that may need waiting for grandchildren READY stage
+ * (any other ZIO type).
+ */
zio_t *
-zio_root(spa_t *spa, zio_done_func_t *done, void *private, enum zio_flag flags)
+zio_root(spa_t *spa, zio_done_func_t *done, void *private, zio_flag_t flags)
{
- return (zio_null(NULL, spa, NULL, done, private, flags));
+ zio_t *zio;
+
+ zio = zio_create(NULL, spa, 0, NULL, NULL, 0, 0, done, private,
+ ZIO_TYPE_NULL, ZIO_PRIORITY_NOW, flags, NULL, 0, NULL,
+ ZIO_STAGE_OPEN, ZIO_ROOT_PIPELINE);
+
+ return (zio);
}
static int
@@ -923,9 +1034,35 @@ zfs_blkptr_verify_log(spa_t *spa, const blkptr_t *bp,
(void) vsnprintf(buf, sizeof (buf), fmt, adx);
va_end(adx);
+ zfs_dbgmsg("bad blkptr at %px: "
+ "DVA[0]=%#llx/%#llx "
+ "DVA[1]=%#llx/%#llx "
+ "DVA[2]=%#llx/%#llx "
+ "prop=%#llx "
+ "pad=%#llx,%#llx "
+ "phys_birth=%#llx "
+ "birth=%#llx "
+ "fill=%#llx "
+ "cksum=%#llx/%#llx/%#llx/%#llx",
+ bp,
+ (long long)bp->blk_dva[0].dva_word[0],
+ (long long)bp->blk_dva[0].dva_word[1],
+ (long long)bp->blk_dva[1].dva_word[0],
+ (long long)bp->blk_dva[1].dva_word[1],
+ (long long)bp->blk_dva[2].dva_word[0],
+ (long long)bp->blk_dva[2].dva_word[1],
+ (long long)bp->blk_prop,
+ (long long)bp->blk_pad[0],
+ (long long)bp->blk_pad[1],
+ (long long)BP_GET_PHYSICAL_BIRTH(bp),
+ (long long)BP_GET_LOGICAL_BIRTH(bp),
+ (long long)bp->blk_fill,
+ (long long)bp->blk_cksum.zc_word[0],
+ (long long)bp->blk_cksum.zc_word[1],
+ (long long)bp->blk_cksum.zc_word[2],
+ (long long)bp->blk_cksum.zc_word[3]);
switch (blk_verify) {
case BLK_VERIFY_HALT:
- dprintf_bp(bp, "blkptr at %p dprintf_bp():", bp);
zfs_panic_recover("%s: %s", spa_name(spa), buf);
break;
case BLK_VERIFY_LOG:
@@ -946,47 +1083,54 @@ zfs_blkptr_verify_log(spa_t *spa, const blkptr_t *bp,
* If everything checks out B_TRUE is returned. The zfs_blkptr_verify
* argument controls the behavior when an invalid field is detected.
*
- * Modes for zfs_blkptr_verify:
- * 1) BLK_VERIFY_ONLY (evaluate the block)
- * 2) BLK_VERIFY_LOG (evaluate the block and log problems)
- * 3) BLK_VERIFY_HALT (call zfs_panic_recover on error)
+ * Values for blk_verify_flag:
+ * BLK_VERIFY_ONLY: evaluate the block
+ * BLK_VERIFY_LOG: evaluate the block and log problems
+ * BLK_VERIFY_HALT: call zfs_panic_recover on error
+ *
+ * Values for blk_config_flag:
+ * BLK_CONFIG_HELD: caller holds SCL_VDEV for writer
+ * BLK_CONFIG_NEEDED: caller holds no config lock, SCL_VDEV will be
+ * obtained for reader
+ * BLK_CONFIG_SKIP: skip checks which require SCL_VDEV, for better
+ * performance
*/
boolean_t
-zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp, boolean_t config_held,
- enum blk_verify_flag blk_verify)
+zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp,
+ enum blk_config_flag blk_config, enum blk_verify_flag blk_verify)
{
int errors = 0;
if (!DMU_OT_IS_VALID(BP_GET_TYPE(bp))) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid TYPE %llu",
+ "blkptr at %px has invalid TYPE %llu",
bp, (longlong_t)BP_GET_TYPE(bp));
}
if (BP_GET_CHECKSUM(bp) >= ZIO_CHECKSUM_FUNCTIONS) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid CHECKSUM %llu",
+ "blkptr at %px has invalid CHECKSUM %llu",
bp, (longlong_t)BP_GET_CHECKSUM(bp));
}
if (BP_GET_COMPRESS(bp) >= ZIO_COMPRESS_FUNCTIONS) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid COMPRESS %llu",
+ "blkptr at %px has invalid COMPRESS %llu",
bp, (longlong_t)BP_GET_COMPRESS(bp));
}
if (BP_GET_LSIZE(bp) > SPA_MAXBLOCKSIZE) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid LSIZE %llu",
+ "blkptr at %px has invalid LSIZE %llu",
bp, (longlong_t)BP_GET_LSIZE(bp));
}
if (BP_GET_PSIZE(bp) > SPA_MAXBLOCKSIZE) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid PSIZE %llu",
+ "blkptr at %px has invalid PSIZE %llu",
bp, (longlong_t)BP_GET_PSIZE(bp));
}
if (BP_IS_EMBEDDED(bp)) {
if (BPE_GET_ETYPE(bp) >= NUM_BP_EMBEDDED_TYPES) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p has invalid ETYPE %llu",
+ "blkptr at %px has invalid ETYPE %llu",
bp, (longlong_t)BPE_GET_ETYPE(bp));
}
}
@@ -998,17 +1142,27 @@ zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp, boolean_t config_held,
if (!spa->spa_trust_config)
return (errors == 0);
- if (!config_held)
- spa_config_enter(spa, SCL_VDEV, bp, RW_READER);
- else
+ switch (blk_config) {
+ case BLK_CONFIG_HELD:
ASSERT(spa_config_held(spa, SCL_VDEV, RW_WRITER));
+ break;
+ case BLK_CONFIG_NEEDED:
+ spa_config_enter(spa, SCL_VDEV, bp, RW_READER);
+ break;
+ case BLK_CONFIG_SKIP:
+ return (errors == 0);
+ default:
+ panic("invalid blk_config %u", blk_config);
+ }
+
/*
* Pool-specific checks.
*
- * Note: it would be nice to verify that the blk_birth and
- * BP_PHYSICAL_BIRTH() are not too large. However, spa_freeze()
- * allows the birth time of log blocks (and dmu_sync()-ed blocks
- * that are in the log) to be arbitrarily large.
+ * Note: it would be nice to verify that the logical birth
+ * and physical birth are not too large. However,
+ * spa_freeze() allows the birth time of log blocks (and
+ * dmu_sync()-ed blocks that are in the log) to be arbitrarily
+ * large.
*/
for (int i = 0; i < BP_GET_NDVAS(bp); i++) {
const dva_t *dva = &bp->blk_dva[i];
@@ -1016,20 +1170,20 @@ zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp, boolean_t config_held,
if (vdevid >= spa->spa_root_vdev->vdev_children) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p DVA %u has invalid VDEV %llu",
+ "blkptr at %px DVA %u has invalid VDEV %llu",
bp, i, (longlong_t)vdevid);
continue;
}
vdev_t *vd = spa->spa_root_vdev->vdev_child[vdevid];
if (vd == NULL) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p DVA %u has invalid VDEV %llu",
+ "blkptr at %px DVA %u has invalid VDEV %llu",
bp, i, (longlong_t)vdevid);
continue;
}
if (vd->vdev_ops == &vdev_hole_ops) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p DVA %u has hole VDEV %llu",
+ "blkptr at %px DVA %u has hole VDEV %llu",
bp, i, (longlong_t)vdevid);
continue;
}
@@ -1047,13 +1201,11 @@ zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp, boolean_t config_held,
asize = vdev_gang_header_asize(vd);
if (offset + asize > vd->vdev_asize) {
errors += zfs_blkptr_verify_log(spa, bp, blk_verify,
- "blkptr at %p DVA %u has invalid OFFSET %llu",
+ "blkptr at %px DVA %u has invalid OFFSET %llu",
bp, i, (longlong_t)offset);
}
}
- if (errors > 0)
- dprintf_bp(bp, "blkptr at %p dprintf_bp():", bp);
- if (!config_held)
+ if (blk_config == BLK_CONFIG_NEEDED)
spa_config_exit(spa, SCL_VDEV, bp);
return (errors == 0);
@@ -1093,11 +1245,11 @@ zfs_dva_valid(spa_t *spa, const dva_t *dva, const blkptr_t *bp)
zio_t *
zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
abd_t *data, uint64_t size, zio_done_func_t *done, void *private,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb)
+ zio_priority_t priority, zio_flag_t flags, const zbookmark_phys_t *zb)
{
zio_t *zio;
- zio = zio_create(pio, spa, BP_PHYSICAL_BIRTH(bp), bp,
+ zio = zio_create(pio, spa, BP_GET_BIRTH(bp), bp,
data, size, size, done, private,
ZIO_TYPE_READ, priority, flags, NULL, 0, zb,
ZIO_STAGE_OPEN, (flags & ZIO_FLAG_DDT_CHILD) ?
@@ -1110,9 +1262,8 @@ zio_t *
zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
abd_t *data, uint64_t lsize, uint64_t psize, const zio_prop_t *zp,
zio_done_func_t *ready, zio_done_func_t *children_ready,
- zio_done_func_t *physdone, zio_done_func_t *done,
- void *private, zio_priority_t priority, enum zio_flag flags,
- const zbookmark_phys_t *zb)
+ zio_done_func_t *done, void *private, zio_priority_t priority,
+ zio_flag_t flags, const zbookmark_phys_t *zb)
{
zio_t *zio;
@@ -1132,7 +1283,6 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
zio->io_ready = ready;
zio->io_children_ready = children_ready;
- zio->io_physdone = physdone;
zio->io_prop = *zp;
/*
@@ -1154,7 +1304,7 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
zio_t *
zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, abd_t *data,
uint64_t size, zio_done_func_t *done, void *private,
- zio_priority_t priority, enum zio_flag flags, zbookmark_phys_t *zb)
+ zio_priority_t priority, zio_flag_t flags, zbookmark_phys_t *zb)
{
zio_t *zio;
@@ -1166,12 +1316,14 @@ zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, abd_t *data,
}
void
-zio_write_override(zio_t *zio, blkptr_t *bp, int copies, boolean_t nopwrite)
+zio_write_override(zio_t *zio, blkptr_t *bp, int copies, boolean_t nopwrite,
+ boolean_t brtwrite)
{
ASSERT(zio->io_type == ZIO_TYPE_WRITE);
ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
ASSERT(zio->io_stage == ZIO_STAGE_OPEN);
ASSERT(zio->io_txg == spa_syncing_txg(zio->io_spa));
+ ASSERT(!brtwrite || !nopwrite);
/*
* We must reset the io_prop to match the values that existed
@@ -1180,6 +1332,7 @@ zio_write_override(zio_t *zio, blkptr_t *bp, int copies, boolean_t nopwrite)
*/
zio->io_prop.zp_dedup = nopwrite ? B_FALSE : zio->io_prop.zp_dedup;
zio->io_prop.zp_nopwrite = nopwrite;
+ zio->io_prop.zp_brtwrite = brtwrite;
zio->io_prop.zp_copies = copies;
zio->io_bp_override = bp;
}
@@ -1188,7 +1341,7 @@ void
zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
{
- (void) zfs_blkptr_verify(spa, bp, B_FALSE, BLK_VERIFY_HALT);
+ (void) zfs_blkptr_verify(spa, bp, BLK_CONFIG_NEEDED, BLK_VERIFY_HALT);
/*
* The check for EMBEDDED is a performance optimization. We
@@ -1197,7 +1350,6 @@ zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
*/
if (BP_IS_EMBEDDED(bp))
return;
- metaslab_check_free(spa, bp);
/*
* Frees that are for the currently-syncing txg, are not going to be
@@ -1213,7 +1365,9 @@ zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
BP_GET_DEDUP(bp) ||
txg != spa->spa_syncing_txg ||
(spa_sync_pass(spa) >= zfs_sync_pass_deferred_free &&
- !spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))) {
+ !spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP)) ||
+ brt_maybe_exists(spa, bp)) {
+ metaslab_check_free(spa, bp);
bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
} else {
VERIFY3P(zio_free_sync(NULL, spa, txg, bp, 0), ==, NULL);
@@ -1227,7 +1381,7 @@ zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
*/
zio_t *
zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
- enum zio_flag flags)
+ zio_flag_t flags)
{
ASSERT(!BP_IS_HOLE(bp));
ASSERT(spa_syncing_txg(spa) == txg);
@@ -1239,11 +1393,13 @@ zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
arc_freed(spa, bp);
dsl_scan_freed(spa, bp);
- if (BP_IS_GANG(bp) || BP_GET_DEDUP(bp)) {
+ if (BP_IS_GANG(bp) ||
+ BP_GET_DEDUP(bp) ||
+ brt_maybe_exists(spa, bp)) {
/*
- * GANG and DEDUP blocks can induce a read (for the gang block
- * header, or the DDT), so issue them asynchronously so that
- * this thread is not tied up.
+ * GANG, DEDUP and BRT blocks can induce a read (for the gang
+ * block header, the DDT or the BRT), so issue them
+ * asynchronously so that this thread is not tied up.
*/
enum zio_stage stage =
ZIO_FREE_PIPELINE | ZIO_STAGE_ISSUE_ASYNC;
@@ -1260,12 +1416,12 @@ zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
zio_t *
zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
- zio_done_func_t *done, void *private, enum zio_flag flags)
+ zio_done_func_t *done, void *private, zio_flag_t flags)
{
zio_t *zio;
- (void) zfs_blkptr_verify(spa, bp, flags & ZIO_FLAG_CONFIG_WRITER,
- BLK_VERIFY_HALT);
+ (void) zfs_blkptr_verify(spa, bp, (flags & ZIO_FLAG_CONFIG_WRITER) ?
+ BLK_CONFIG_HELD : BLK_CONFIG_NEEDED, BLK_VERIFY_HALT);
if (BP_IS_EMBEDDED(bp))
return (zio_null(pio, spa, NULL, NULL, NULL, 0));
@@ -1282,7 +1438,7 @@ zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
* starts allocating blocks -- so that nothing is allocated twice.
* If txg == 0 we just verify that the block is claimable.
*/
- ASSERT3U(spa->spa_uberblock.ub_rootbp.blk_birth, <,
+ ASSERT3U(BP_GET_LOGICAL_BIRTH(&spa->spa_uberblock.ub_rootbp), <,
spa_min_claim_txg(spa));
ASSERT(txg == spa_min_claim_txg(spa) || txg == 0);
ASSERT(!BP_GET_DEDUP(bp) || !spa_writeable(spa)); /* zdb(8) */
@@ -1296,33 +1452,9 @@ zio_claim(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
}
zio_t *
-zio_ioctl(zio_t *pio, spa_t *spa, vdev_t *vd, int cmd,
- zio_done_func_t *done, void *private, enum zio_flag flags)
-{
- zio_t *zio;
- int c;
-
- if (vd->vdev_children == 0) {
- zio = zio_create(pio, spa, 0, NULL, NULL, 0, 0, done, private,
- ZIO_TYPE_IOCTL, ZIO_PRIORITY_NOW, flags, vd, 0, NULL,
- ZIO_STAGE_OPEN, ZIO_IOCTL_PIPELINE);
-
- zio->io_cmd = cmd;
- } else {
- zio = zio_null(pio, spa, NULL, NULL, NULL, flags);
-
- for (c = 0; c < vd->vdev_children; c++)
- zio_nowait(zio_ioctl(zio, spa, vd->vdev_child[c], cmd,
- done, private, flags));
- }
-
- return (zio);
-}
-
-zio_t *
zio_trim(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
zio_done_func_t *done, void *private, zio_priority_t priority,
- enum zio_flag flags, enum trim_flag trim_flags)
+ zio_flag_t flags, enum trim_flag trim_flags)
{
zio_t *zio;
@@ -1342,7 +1474,7 @@ zio_trim(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
zio_t *
zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
abd_t *data, int checksum, zio_done_func_t *done, void *private,
- zio_priority_t priority, enum zio_flag flags, boolean_t labels)
+ zio_priority_t priority, zio_flag_t flags, boolean_t labels)
{
zio_t *zio;
@@ -1363,7 +1495,7 @@ zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
zio_t *
zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
abd_t *data, int checksum, zio_done_func_t *done, void *private,
- zio_priority_t priority, enum zio_flag flags, boolean_t labels)
+ zio_priority_t priority, zio_flag_t flags, boolean_t labels)
{
zio_t *zio;
@@ -1400,7 +1532,7 @@ zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
zio_t *
zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
abd_t *data, uint64_t size, int type, zio_priority_t priority,
- enum zio_flag flags, zio_done_func_t *done, void *private)
+ zio_flag_t flags, zio_done_func_t *done, void *private)
{
enum zio_stage pipeline = ZIO_VDEV_CHILD_PIPELINE;
zio_t *zio;
@@ -1459,22 +1591,17 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
flags &= ~ZIO_FLAG_IO_ALLOCATING;
}
-
zio = zio_create(pio, pio->io_spa, pio->io_txg, bp, data, size, size,
done, private, type, priority, flags, vd, offset, &pio->io_bookmark,
ZIO_STAGE_VDEV_IO_START >> 1, pipeline);
ASSERT3U(zio->io_child_type, ==, ZIO_CHILD_VDEV);
- zio->io_physdone = pio->io_physdone;
- if (vd->vdev_ops->vdev_op_leaf && zio->io_logical != NULL)
- zio->io_logical->io_phys_children++;
-
return (zio);
}
zio_t *
zio_vdev_delegated_io(vdev_t *vd, uint64_t offset, abd_t *data, uint64_t size,
- zio_type_t type, zio_priority_t priority, enum zio_flag flags,
+ zio_type_t type, zio_priority_t priority, zio_flag_t flags,
zio_done_func_t *done, void *private)
{
zio_t *zio;
@@ -1490,12 +1617,29 @@ zio_vdev_delegated_io(vdev_t *vd, uint64_t offset, abd_t *data, uint64_t size,
return (zio);
}
+
+/*
+ * Send a flush command to the given vdev. Unlike most zio creation functions,
+ * the flush zios are issued immediately. You can wait on pio to pause until
+ * the flushes complete.
+ */
void
-zio_flush(zio_t *zio, vdev_t *vd)
+zio_flush(zio_t *pio, vdev_t *vd)
{
- zio_nowait(zio_ioctl(zio, zio->io_spa, vd, DKIOCFLUSHWRITECACHE,
- NULL, NULL,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY));
+ const zio_flag_t flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE |
+ ZIO_FLAG_DONT_RETRY;
+
+ if (vd->vdev_nowritecache)
+ return;
+
+ if (vd->vdev_children == 0) {
+ zio_nowait(zio_create(pio, vd->vdev_spa, 0, NULL, NULL, 0, 0,
+ NULL, NULL, ZIO_TYPE_FLUSH, ZIO_PRIORITY_NOW, flags, vd, 0,
+ NULL, ZIO_STAGE_OPEN, ZIO_FLUSH_PIPELINE));
+ } else {
+ for (uint64_t c = 0; c < vd->vdev_children; c++)
+ zio_flush(pio, vd->vdev_child[c]);
+ }
}
void
@@ -1519,6 +1663,19 @@ zio_shrink(zio_t *zio, uint64_t size)
}
/*
+ * Round provided allocation size up to a value that can be allocated
+ * by at least some vdev(s) in the pool with minimum or no additional
+ * padding and without extra space usage on others
+ */
+static uint64_t
+zio_roundup_alloc_size(spa_t *spa, uint64_t size)
+{
+ if (size > spa->spa_min_alloc)
+ return (roundup(size, spa->spa_gcd_alloc));
+ return (spa->spa_min_alloc);
+}
+
+/*
* ==========================================================================
* Prepare to read and write logical blocks
* ==========================================================================
@@ -1556,15 +1713,8 @@ zio_read_bp_init(zio_t *zio)
abd_return_buf_copy(zio->io_abd, data, psize);
} else {
ASSERT(!BP_IS_EMBEDDED(bp));
- ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
}
- if (!DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) && BP_GET_LEVEL(bp) == 0)
- zio->io_flags |= ZIO_FLAG_DONT_CACHE;
-
- if (BP_GET_TYPE(bp) == DMU_OT_DDT_ZAP)
- zio->io_flags |= ZIO_FLAG_DONT_CACHE;
-
if (BP_GET_DEDUP(bp) && zio->io_child_type == ZIO_CHILD_LOGICAL)
zio->io_pipeline = ZIO_DDT_READ_PIPELINE;
@@ -1583,12 +1733,16 @@ zio_write_bp_init(zio_t *zio)
blkptr_t *bp = zio->io_bp;
zio_prop_t *zp = &zio->io_prop;
- ASSERT(bp->blk_birth != zio->io_txg);
- ASSERT(BP_GET_DEDUP(zio->io_bp_override) == 0);
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) != zio->io_txg);
*bp = *zio->io_bp_override;
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
+ if (zp->zp_brtwrite)
+ return (zio);
+
+ ASSERT(!BP_GET_DEDUP(zio->io_bp_override));
+
if (BP_IS_EMBEDDED(bp))
return (zio);
@@ -1640,7 +1794,7 @@ zio_write_compress(zio_t *zio)
blkptr_t *bp = zio->io_bp;
uint64_t lsize = zio->io_lsize;
uint64_t psize = zio->io_size;
- int pass = 1;
+ uint32_t pass = 1;
/*
* If our children haven't all reached the ready stage,
@@ -1667,7 +1821,7 @@ zio_write_compress(zio_t *zio)
ASSERT(zio->io_child_type != ZIO_CHILD_DDT);
ASSERT(zio->io_bp_override == NULL);
- if (!BP_IS_HOLE(bp) && bp->blk_birth == zio->io_txg) {
+ if (!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) == zio->io_txg) {
/*
* We're rewriting an existing block, which means we're
* working on behalf of spa_sync(). For spa_sync() to
@@ -1687,19 +1841,23 @@ zio_write_compress(zio_t *zio)
compress = ZIO_COMPRESS_OFF;
/* Make sure someone doesn't change their mind on overwrites */
- ASSERT(BP_IS_EMBEDDED(bp) || MIN(zp->zp_copies + BP_IS_GANG(bp),
- spa_max_replication(spa)) == BP_GET_NDVAS(bp));
+ ASSERT(BP_IS_EMBEDDED(bp) || BP_IS_GANG(bp) ||
+ MIN(zp->zp_copies, spa_max_replication(spa))
+ == BP_GET_NDVAS(bp));
}
/* If it's a compressed write that is not raw, compress the buffer. */
if (compress != ZIO_COMPRESS_OFF &&
!(zio->io_flags & ZIO_FLAG_RAW_COMPRESS)) {
- void *cbuf = zio_buf_alloc(lsize);
- psize = zio_compress_data(compress, zio->io_abd, cbuf, lsize,
+ void *cbuf = NULL;
+ psize = zio_compress_data(compress, zio->io_abd, &cbuf, lsize,
zp->zp_complevel);
- if (psize == 0 || psize >= lsize) {
+ if (psize == 0) {
compress = ZIO_COMPRESS_OFF;
- zio_buf_free(cbuf, lsize);
+ } else if (psize >= lsize) {
+ compress = ZIO_COMPRESS_OFF;
+ if (cbuf != NULL)
+ zio_buf_free(cbuf, lsize);
} else if (!zp->zp_dedup && !zp->zp_encrypt &&
psize <= BPE_PAYLOAD_SIZE &&
zp->zp_level == 0 && !DMU_OT_HAS_FILL(zp->zp_type) &&
@@ -1710,7 +1868,7 @@ zio_write_compress(zio_t *zio)
BP_SET_TYPE(bp, zio->io_prop.zp_type);
BP_SET_LEVEL(bp, zio->io_prop.zp_level);
zio_buf_free(cbuf, lsize);
- bp->blk_birth = zio->io_txg;
+ BP_SET_LOGICAL_BIRTH(bp, zio->io_txg);
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
ASSERT(spa_feature_is_active(spa,
SPA_FEATURE_EMBEDDED_DATA));
@@ -1724,9 +1882,8 @@ zio_write_compress(zio_t *zio)
* in that we charge for the padding used to fill out
* the last sector.
*/
- ASSERT3U(spa->spa_min_alloc, >=, SPA_MINBLOCKSHIFT);
- size_t rounded = (size_t)roundup(psize,
- spa->spa_min_alloc);
+ size_t rounded = (size_t)zio_roundup_alloc_size(spa,
+ psize);
if (rounded >= lsize) {
compress = ZIO_COMPRESS_OFF;
zio_buf_free(cbuf, lsize);
@@ -1769,8 +1926,8 @@ zio_write_compress(zio_t *zio)
* take this codepath because it will change the on-disk block
* and decryption will fail.
*/
- size_t rounded = MIN((size_t)roundup(psize,
- spa->spa_min_alloc), lsize);
+ size_t rounded = MIN((size_t)zio_roundup_alloc_size(spa, psize),
+ lsize);
if (rounded != psize) {
abd_t *cdata = abd_alloc_linear(rounded, B_TRUE);
@@ -1792,7 +1949,7 @@ zio_write_compress(zio_t *zio)
* spa_sync() to allocate new blocks, but force rewrites after that.
* There should only be a handful of blocks after pass 1 in any case.
*/
- if (!BP_IS_HOLE(bp) && bp->blk_birth == zio->io_txg &&
+ if (!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) == zio->io_txg &&
BP_GET_PSIZE(bp) == psize &&
pass >= zfs_sync_pass_rewrite) {
VERIFY3U(psize, !=, 0);
@@ -1806,7 +1963,7 @@ zio_write_compress(zio_t *zio)
}
if (psize == 0) {
- if (zio->io_bp_orig.blk_birth != 0 &&
+ if (BP_GET_LOGICAL_BIRTH(&zio->io_bp_orig) != 0 &&
spa_feature_is_active(spa, SPA_FEATURE_HOLE_BIRTH)) {
BP_SET_LSIZE(bp, lsize);
BP_SET_TYPE(bp, zp->zp_type);
@@ -1900,7 +2057,7 @@ zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
*/
ASSERT(taskq_empty_ent(&zio->io_tqent));
spa_taskq_dispatch_ent(spa, t, q, zio_execute, zio, flags,
- &zio->io_tqent);
+ &zio->io_tqent, zio);
}
static boolean_t
@@ -1925,8 +2082,8 @@ zio_taskq_member(zio_t *zio, zio_taskq_type_t q)
static zio_t *
zio_issue_async(zio_t *zio)
{
+ ASSERT((zio->io_type != ZIO_TYPE_WRITE) || ZIO_HAS_ALLOCATOR(zio));
zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
-
return (NULL);
}
@@ -2024,7 +2181,7 @@ zio_deadman_impl(zio_t *pio, int ziodepth)
"delta=%llu queued=%llu io=%llu "
"path=%s "
"last=%llu type=%d "
- "priority=%d flags=0x%x stage=0x%x "
+ "priority=%d flags=0x%llx stage=0x%x "
"pipeline=0x%x pipeline-trace=0x%x "
"objset=%llu object=%llu "
"level=%llu blkid=%llu "
@@ -2034,8 +2191,8 @@ zio_deadman_impl(zio_t *pio, int ziodepth)
(u_longlong_t)delta, pio->io_delta, pio->io_delay,
vd ? vd->vdev_path : "NULL",
vq ? vq->vq_io_complete_ts : 0, pio->io_type,
- pio->io_priority, pio->io_flags, pio->io_stage,
- pio->io_pipeline, pio->io_pipeline_trace,
+ pio->io_priority, (u_longlong_t)pio->io_flags,
+ pio->io_stage, pio->io_pipeline, pio->io_pipeline_trace,
(u_longlong_t)zb->zb_objset, (u_longlong_t)zb->zb_object,
(u_longlong_t)zb->zb_level, (u_longlong_t)zb->zb_blkid,
(u_longlong_t)pio->io_offset, (u_longlong_t)pio->io_size,
@@ -2240,6 +2397,9 @@ zio_wait(zio_t *zio)
ASSERT0(zio->io_queued_timestamp);
zio->io_queued_timestamp = gethrtime();
+ if (zio->io_type == ZIO_TYPE_WRITE) {
+ spa_select_allocator(zio);
+ }
__zio_execute(zio);
mutex_enter(&zio->io_lock);
@@ -2276,7 +2436,7 @@ zio_nowait(zio_t *zio)
ASSERT3P(zio->io_executor, ==, NULL);
if (zio->io_child_type == ZIO_CHILD_LOGICAL &&
- zio_unique_parent(zio) == NULL) {
+ list_is_empty(&zio->io_parent_list)) {
zio_t *pio;
/*
@@ -2292,6 +2452,9 @@ zio_nowait(zio_t *zio)
ASSERT0(zio->io_queued_timestamp);
zio->io_queued_timestamp = gethrtime();
+ if (zio->io_type == ZIO_TYPE_WRITE) {
+ spa_select_allocator(zio);
+ }
__zio_execute(zio);
}
@@ -2305,13 +2468,14 @@ static void
zio_reexecute(void *arg)
{
zio_t *pio = arg;
- zio_t *cio, *cio_next;
+ zio_t *cio, *cio_next, *gio;
ASSERT(pio->io_child_type == ZIO_CHILD_LOGICAL);
ASSERT(pio->io_orig_stage == ZIO_STAGE_OPEN);
ASSERT(pio->io_gang_leader == NULL);
ASSERT(pio->io_gang_tree == NULL);
+ mutex_enter(&pio->io_lock);
pio->io_flags = pio->io_orig_flags;
pio->io_stage = pio->io_orig_stage;
pio->io_pipeline = pio->io_orig_pipeline;
@@ -2319,8 +2483,16 @@ zio_reexecute(void *arg)
pio->io_flags |= ZIO_FLAG_REEXECUTED;
pio->io_pipeline_trace = 0;
pio->io_error = 0;
- for (int w = 0; w < ZIO_WAIT_TYPES; w++)
- pio->io_state[w] = 0;
+ pio->io_state[ZIO_WAIT_READY] = (pio->io_stage >= ZIO_STAGE_READY) ||
+ (pio->io_pipeline & ZIO_STAGE_READY) == 0;
+ pio->io_state[ZIO_WAIT_DONE] = (pio->io_stage >= ZIO_STAGE_DONE);
+ zio_link_t *zl = NULL;
+ while ((gio = zio_walk_parents(pio, &zl)) != NULL) {
+ for (int w = 0; w < ZIO_WAIT_TYPES; w++) {
+ gio->io_children[pio->io_child_type][w] +=
+ !pio->io_state[w];
+ }
+ }
for (int c = 0; c < ZIO_CHILD_TYPES; c++)
pio->io_child_error[c] = 0;
@@ -2334,12 +2506,9 @@ zio_reexecute(void *arg)
* the remainder of pio's io_child_list, from 'cio_next' onward,
* cannot be affected by any side effects of reexecuting 'cio'.
*/
- zio_link_t *zl = NULL;
- mutex_enter(&pio->io_lock);
+ zl = NULL;
for (cio = zio_walk_children(pio, &zl); cio != NULL; cio = cio_next) {
cio_next = zio_walk_children(pio, &zl);
- for (int w = 0; w < ZIO_WAIT_TYPES; w++)
- pio->io_children[cio->io_child_type][w]++;
mutex_exit(&pio->io_lock);
zio_reexecute(cio);
mutex_enter(&pio->io_lock);
@@ -2365,8 +2534,10 @@ zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason)
"failure and the failure mode property for this pool "
"is set to panic.", spa_name(spa));
- cmn_err(CE_WARN, "Pool '%s' has encountered an uncorrectable I/O "
- "failure and has been suspended.\n", spa_name(spa));
+ if (reason != ZIO_SUSPEND_MMP) {
+ cmn_err(CE_WARN, "Pool '%s' has encountered an uncorrectable "
+ "I/O failure and has been suspended.\n", spa_name(spa));
+ }
(void) zfs_ereport_post(FM_EREPORT_ZFS_IO_FAILURE, spa, NULL,
NULL, NULL, 0);
@@ -2652,7 +2823,7 @@ zio_gang_tree_assemble_done(zio_t *zio)
blkptr_t *bp = zio->io_bp;
ASSERT(gio == zio_unique_parent(zio));
- ASSERT(zio->io_child_count == 0);
+ ASSERT(list_is_empty(&zio->io_child_list));
if (zio->io_error)
return;
@@ -2751,6 +2922,12 @@ zio_gang_issue(zio_t *zio)
}
static void
+zio_gang_inherit_allocator(zio_t *pio, zio_t *cio)
+{
+ cio->io_allocator = pio->io_allocator;
+}
+
+static void
zio_write_gang_member_ready(zio_t *zio)
{
zio_t *pio = zio_unique_parent(zio);
@@ -2768,7 +2945,7 @@ zio_write_gang_member_ready(zio_t *zio)
ASSERT3U(zio->io_prop.zp_copies, ==, gio->io_prop.zp_copies);
ASSERT3U(zio->io_prop.zp_copies, <=, BP_GET_NDVAS(zio->io_bp));
ASSERT3U(pio->io_prop.zp_copies, <=, BP_GET_NDVAS(pio->io_bp));
- ASSERT3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
+ VERIFY3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
mutex_enter(&pio->io_lock);
for (int d = 0; d < BP_GET_NDVAS(zio->io_bp); d++) {
@@ -2806,19 +2983,22 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
uint64_t resid = pio->io_size;
uint64_t lsize;
int copies = gio->io_prop.zp_copies;
- int gbh_copies;
zio_prop_t zp;
int error;
boolean_t has_data = !(pio->io_flags & ZIO_FLAG_NODATA);
/*
- * encrypted blocks need DVA[2] free so encrypted gang headers can't
- * have a third copy.
+ * If one copy was requested, store 2 copies of the GBH, so that we
+ * can still traverse all the data (e.g. to free or scrub) even if a
+ * block is damaged. Note that we can't store 3 copies of the GBH in
+ * all cases, e.g. with encryption, which uses DVA[2] for the IV+salt.
*/
- gbh_copies = MIN(copies + 1, spa_max_replication(spa));
- if (gio->io_prop.zp_encrypt && gbh_copies >= SPA_DVAS_PER_BP)
- gbh_copies = SPA_DVAS_PER_BP - 1;
+ int gbh_copies = copies;
+ if (gbh_copies == 1) {
+ gbh_copies = MIN(2, spa_max_replication(spa));
+ }
+ ASSERT(ZIO_HAS_ALLOCATOR(pio));
int flags = METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER;
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
@@ -2882,6 +3062,8 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
zio_write_gang_done, NULL, pio->io_priority,
ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark);
+ zio_gang_inherit_allocator(pio, zio);
+
/*
* Create and nowait the gang children.
*/
@@ -2908,10 +3090,12 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
zio_t *cio = zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
has_data ? abd_get_offset(pio->io_abd, pio->io_size -
resid) : NULL, lsize, lsize, &zp,
- zio_write_gang_member_ready, NULL, NULL,
+ zio_write_gang_member_ready, NULL,
zio_write_gang_done, &gn->gn_child[g], pio->io_priority,
ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark);
+ zio_gang_inherit_allocator(zio, cio);
+
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
ASSERT(has_data);
@@ -2932,11 +3116,6 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
*/
pio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
- /*
- * We didn't allocate this bp, so make sure it doesn't get unmarked.
- */
- pio->io_flags &= ~ZIO_FLAG_FASTWRITE;
-
zio_nowait(zio);
return (pio);
@@ -2967,6 +3146,7 @@ zio_nop_write(zio_t *zio)
blkptr_t *bp_orig = &zio->io_bp_orig;
zio_prop_t *zp = &zio->io_prop;
+ ASSERT(BP_IS_HOLE(bp));
ASSERT(BP_GET_LEVEL(bp) == 0);
ASSERT(!(zio->io_flags & ZIO_FLAG_IO_REWRITE));
ASSERT(zp->zp_nopwrite);
@@ -3000,8 +3180,7 @@ zio_nop_write(zio_t *zio)
ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(bp_orig));
ASSERT3U(BP_GET_LSIZE(bp), ==, BP_GET_LSIZE(bp_orig));
ASSERT(zp->zp_compress != ZIO_COMPRESS_OFF);
- ASSERT(memcmp(&bp->blk_prop, &bp_orig->blk_prop,
- sizeof (uint64_t)) == 0);
+ ASSERT3U(bp->blk_prop, ==, bp_orig->blk_prop);
/*
* If we're overwriting a block that is currently on an
@@ -3009,11 +3188,13 @@ zio_nop_write(zio_t *zio)
* allow a new block to be allocated on a concrete vdev.
*/
spa_config_enter(zio->io_spa, SCL_VDEV, FTAG, RW_READER);
- vdev_t *tvd = vdev_lookup_top(zio->io_spa,
- DVA_GET_VDEV(&bp->blk_dva[0]));
- if (tvd->vdev_ops == &vdev_indirect_ops) {
- spa_config_exit(zio->io_spa, SCL_VDEV, FTAG);
- return (zio);
+ for (int d = 0; d < BP_GET_NDVAS(bp_orig); d++) {
+ vdev_t *tvd = vdev_lookup_top(zio->io_spa,
+ DVA_GET_VDEV(&bp_orig->blk_dva[d]));
+ if (tvd->vdev_ops == &vdev_indirect_ops) {
+ spa_config_exit(zio->io_spa, SCL_VDEV, FTAG);
+ return (zio);
+ }
}
spa_config_exit(zio->io_spa, SCL_VDEV, FTAG);
@@ -3027,6 +3208,35 @@ zio_nop_write(zio_t *zio)
/*
* ==========================================================================
+ * Block Reference Table
+ * ==========================================================================
+ */
+static zio_t *
+zio_brt_free(zio_t *zio)
+{
+ blkptr_t *bp;
+
+ bp = zio->io_bp;
+
+ if (BP_GET_LEVEL(bp) > 0 ||
+ BP_IS_METADATA(bp) ||
+ !brt_maybe_exists(zio->io_spa, bp)) {
+ return (zio);
+ }
+
+ if (!brt_entry_decref(zio->io_spa, bp)) {
+ /*
+ * This isn't the last reference, so we cannot free
+ * the data yet.
+ */
+ zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
+ }
+
+ return (zio);
+}
+
+/*
+ * ==========================================================================
* Dedup
* ==========================================================================
*/
@@ -3332,14 +3542,14 @@ zio_ddt_write(zio_t *zio)
else
ddt_phys_addref(ddp);
} else if (zio->io_bp_override) {
- ASSERT(bp->blk_birth == txg);
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) == txg);
ASSERT(BP_EQUAL(bp, zio->io_bp_override));
ddt_phys_fill(ddp, bp);
ddt_phys_addref(ddp);
} else {
cio = zio_write(zio, spa, txg, bp, zio->io_orig_abd,
zio->io_orig_size, zio->io_orig_size, zp,
- zio_ddt_child_write_ready, NULL, NULL,
+ zio_ddt_child_write_ready, NULL,
zio_ddt_child_write_done, dde, zio->io_priority,
ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
@@ -3354,7 +3564,7 @@ zio_ddt_write(zio_t *zio)
return (zio);
}
-ddt_entry_t *freedde; /* for debugging */
+static ddt_entry_t *freedde; /* for debugging */
static zio_t *
zio_ddt_free(zio_t *zio)
@@ -3398,6 +3608,7 @@ zio_io_to_allocate(spa_t *spa, int allocator)
return (NULL);
ASSERT(IO_IS_ALLOCATING(zio));
+ ASSERT(ZIO_HAS_ALLOCATOR(zio));
/*
* Try to place a reservation for this zio. If we're unable to
@@ -3434,21 +3645,12 @@ zio_dva_throttle(zio_t *zio)
}
ASSERT(zio->io_type == ZIO_TYPE_WRITE);
+ ASSERT(ZIO_HAS_ALLOCATOR(zio));
ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
ASSERT3U(zio->io_queued_timestamp, >, 0);
ASSERT(zio->io_stage == ZIO_STAGE_DVA_THROTTLE);
- zbookmark_phys_t *bm = &zio->io_bookmark;
- /*
- * We want to try to use as many allocators as possible to help improve
- * performance, but we also want logically adjacent IOs to be physically
- * adjacent to improve sequential read performance. We chunk each object
- * into 2^20 block regions, and then hash based on the objset, object,
- * level, and region to accomplish both of these goals.
- */
- int allocator = (uint_t)cityhash4(bm->zb_objset, bm->zb_object,
- bm->zb_level, bm->zb_blkid >> 20) % spa->spa_alloc_count;
- zio->io_allocator = allocator;
+ int allocator = zio->io_allocator;
zio->io_metaslab_class = mc;
mutex_enter(&spa->spa_allocs[allocator].spaa_lock);
avl_add(&spa->spa_allocs[allocator].spaa_tree, zio);
@@ -3493,7 +3695,6 @@ zio_dva_allocate(zio_t *zio)
ASSERT3U(zio->io_prop.zp_copies, <=, spa_max_replication(spa));
ASSERT3U(zio->io_size, ==, BP_GET_PSIZE(bp));
- flags |= (zio->io_flags & ZIO_FLAG_FASTWRITE) ? METASLAB_FASTWRITE : 0;
if (zio->io_flags & ZIO_FLAG_NODATA)
flags |= METASLAB_DONT_THROTTLE;
if (zio->io_flags & ZIO_FLAG_GANG_CHILD)
@@ -3523,6 +3724,7 @@ zio_dva_allocate(zio_t *zio)
* sync write performance. If a log allocation fails, we will fall
* back to spa_sync() which is abysmal for performance.
*/
+ ASSERT(ZIO_HAS_ALLOCATOR(zio));
error = metaslab_alloc(spa, mc, zio->io_size, bp,
zio->io_prop.zp_copies, zio->io_txg, NULL, flags,
&zio->io_alloc_list, zio, zio->io_allocator);
@@ -3611,11 +3813,13 @@ zio_dva_claim(zio_t *zio)
static void
zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp)
{
- ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp));
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) == zio->io_txg || BP_IS_HOLE(bp));
ASSERT(zio->io_bp_override == NULL);
- if (!BP_IS_HOLE(bp))
- metaslab_free(zio->io_spa, bp, bp->blk_birth, B_TRUE);
+ if (!BP_IS_HOLE(bp)) {
+ metaslab_free(zio->io_spa, bp, BP_GET_LOGICAL_BIRTH(bp),
+ B_TRUE);
+ }
if (gn != NULL) {
for (int g = 0; g < SPA_GBH_NBLKPTRS; g++) {
@@ -3653,7 +3857,7 @@ zio_alloc_zil(spa_t *spa, objset_t *os, uint64_t txg, blkptr_t *new_bp,
* of, so we just hash the objset ID to pick the allocator to get
* some parallelism.
*/
- int flags = METASLAB_FASTWRITE | METASLAB_ZIL;
+ int flags = METASLAB_ZIL;
int allocator = (uint_t)cityhash4(0, 0, 0,
os->os_dsl_dataset->ds_object) % spa->spa_alloc_count;
error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1,
@@ -3857,8 +4061,15 @@ zio_vdev_io_start(zio_t *zio)
zio->io_type == ZIO_TYPE_WRITE ||
zio->io_type == ZIO_TYPE_TRIM)) {
- if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio))
- return (zio);
+ if (zio_handle_device_injection(vd, zio, ENOSYS) != 0) {
+ /*
+ * "no-op" injections return success, but do no actual
+ * work. Just skip the remaining vdev stages.
+ */
+ zio_vdev_io_bypass(zio);
+ zio_interrupt(zio);
+ return (NULL);
+ }
if ((zio = vdev_queue_io(zio)) == NULL)
return (NULL);
@@ -3887,17 +4098,17 @@ zio_vdev_io_done(zio_t *zio)
}
ASSERT(zio->io_type == ZIO_TYPE_READ ||
- zio->io_type == ZIO_TYPE_WRITE || zio->io_type == ZIO_TYPE_TRIM);
+ zio->io_type == ZIO_TYPE_WRITE ||
+ zio->io_type == ZIO_TYPE_FLUSH ||
+ zio->io_type == ZIO_TYPE_TRIM);
if (zio->io_delay)
zio->io_delay = gethrtime() - zio->io_delay;
if (vd != NULL && vd->vdev_ops->vdev_op_leaf &&
vd->vdev_ops != &vdev_draid_spare_ops) {
- vdev_queue_io_done(zio);
-
- if (zio->io_type == ZIO_TYPE_WRITE)
- vdev_cache_write(zio);
+ if (zio->io_type != ZIO_TYPE_FLUSH)
+ vdev_queue_io_done(zio);
if (zio_injection_enabled && zio->io_error == 0)
zio->io_error = zio_handle_device_injections(vd, zio,
@@ -3906,7 +4117,8 @@ zio_vdev_io_done(zio_t *zio)
if (zio_injection_enabled && zio->io_error == 0)
zio->io_error = zio_handle_label_injection(zio, EIO);
- if (zio->io_error && zio->io_type != ZIO_TYPE_TRIM) {
+ if (zio->io_error && zio->io_type != ZIO_TYPE_FLUSH &&
+ zio->io_type != ZIO_TYPE_TRIM) {
if (!vdev_accessible(vd, zio)) {
zio->io_error = SET_ERROR(ENXIO);
} else {
@@ -3917,7 +4129,7 @@ zio_vdev_io_done(zio_t *zio)
ops->vdev_op_io_done(zio);
- if (unexpected_error)
+ if (unexpected_error && vd->vdev_remove_wanted == B_FALSE)
VERIFY(vdev_probe(vd, zio) == NULL);
return (zio);
@@ -4008,8 +4220,7 @@ zio_vdev_io_assess(zio_t *zio)
ASSERT(!(zio->io_flags & ZIO_FLAG_DONT_QUEUE)); /* not a leaf */
ASSERT(!(zio->io_flags & ZIO_FLAG_IO_BYPASS)); /* not a leaf */
zio->io_error = 0;
- zio->io_flags |= ZIO_FLAG_IO_RETRY |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE;
+ zio->io_flags |= ZIO_FLAG_IO_RETRY | ZIO_FLAG_DONT_AGGREGATE;
zio->io_stage = ZIO_STAGE_VDEV_IO_START >> 1;
zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE,
zio_requeue_io_start_cut_in_line);
@@ -4042,20 +4253,12 @@ zio_vdev_io_assess(zio_t *zio)
* boolean flag so that we don't bother with it in the future.
*/
if ((zio->io_error == ENOTSUP || zio->io_error == ENOTTY) &&
- zio->io_type == ZIO_TYPE_IOCTL &&
- zio->io_cmd == DKIOCFLUSHWRITECACHE && vd != NULL)
+ zio->io_type == ZIO_TYPE_FLUSH && vd != NULL)
vd->vdev_nowritecache = B_TRUE;
if (zio->io_error)
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
- if (vd != NULL && vd->vdev_ops->vdev_op_leaf &&
- zio->io_physdone != NULL) {
- ASSERT(!(zio->io_flags & ZIO_FLAG_DELEGATED));
- ASSERT(zio->io_child_type == ZIO_CHILD_VDEV);
- zio->io_physdone(zio->io_logical);
- }
-
return (zio);
}
@@ -4304,12 +4507,12 @@ zio_checksum_verify(zio_t *zio)
zio->io_error = error;
if (error == ECKSUM &&
!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
- (void) zfs_ereport_start_checksum(zio->io_spa,
- zio->io_vd, &zio->io_bookmark, zio,
- zio->io_offset, zio->io_size, &info);
mutex_enter(&zio->io_vd->vdev_stat_lock);
zio->io_vd->vdev_stat.vs_checksum_errors++;
mutex_exit(&zio->io_vd->vdev_stat_lock);
+ (void) zfs_ereport_start_checksum(zio->io_spa,
+ zio->io_vd, &zio->io_bookmark, zio,
+ zio->io_offset, zio->io_size, &info);
}
}
@@ -4363,22 +4566,24 @@ zio_ready(zio_t *zio)
zio_t *pio, *pio_next;
zio_link_t *zl = NULL;
- if (zio_wait_for_children(zio, ZIO_CHILD_GANG_BIT | ZIO_CHILD_DDT_BIT,
- ZIO_WAIT_READY)) {
+ if (zio_wait_for_children(zio, ZIO_CHILD_LOGICAL_BIT |
+ ZIO_CHILD_GANG_BIT | ZIO_CHILD_DDT_BIT, ZIO_WAIT_READY)) {
return (NULL);
}
if (zio->io_ready) {
ASSERT(IO_IS_ALLOCATING(zio));
- ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp) ||
- (zio->io_flags & ZIO_FLAG_NOPWRITE));
+ ASSERT(BP_GET_LOGICAL_BIRTH(bp) == zio->io_txg ||
+ BP_IS_HOLE(bp) || (zio->io_flags & ZIO_FLAG_NOPWRITE));
ASSERT(zio->io_children[ZIO_CHILD_GANG][ZIO_WAIT_READY] == 0);
zio->io_ready(zio);
}
+#ifdef ZFS_DEBUG
if (bp != NULL && bp != &zio->io_bp_copy)
zio->io_bp_copy = *bp;
+#endif
if (zio->io_error != 0) {
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
@@ -4387,6 +4592,7 @@ zio_ready(zio_t *zio)
ASSERT(IO_IS_ALLOCATING(zio));
ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
ASSERT(zio->io_metaslab_class != NULL);
+ ASSERT(ZIO_HAS_ALLOCATOR(zio));
/*
* We were unable to allocate anything, unreserve and
@@ -4417,7 +4623,7 @@ zio_ready(zio_t *zio)
}
if (zio->io_flags & ZIO_FLAG_NODATA) {
- if (BP_IS_GANG(bp)) {
+ if (bp != NULL && BP_IS_GANG(bp)) {
zio->io_flags &= ~ZIO_FLAG_NODATA;
} else {
ASSERT((uintptr_t)zio->io_abd < SPA_MAXBLOCKSIZE);
@@ -4473,6 +4679,7 @@ zio_dva_throttle_done(zio_t *zio)
}
ASSERT(IO_IS_ALLOCATING(pio));
+ ASSERT(ZIO_HAS_ALLOCATOR(pio));
ASSERT3P(zio, !=, zio->io_logical);
ASSERT(zio->io_logical != NULL);
ASSERT(!(zio->io_flags & ZIO_FLAG_IO_REPAIR));
@@ -4535,6 +4742,7 @@ zio_done(zio_t *zio)
ASSERT(zio->io_type == ZIO_TYPE_WRITE);
ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
ASSERT(zio->io_bp != NULL);
+ ASSERT(ZIO_HAS_ALLOCATOR(zio));
metaslab_group_alloc_verify(zio->io_spa, zio->io_bp, zio,
zio->io_allocator);
@@ -4661,7 +4869,8 @@ zio_done(zio_t *zio)
* For logical I/O requests, tell the SPA to log the
* error and generate a logical data ereport.
*/
- spa_log_error(zio->io_spa, &zio->io_bookmark);
+ spa_log_error(zio->io_spa, &zio->io_bookmark,
+ BP_GET_LOGICAL_BIRTH(zio->io_bp));
(void) zfs_ereport_post(FM_EREPORT_ZFS_DATA,
zio->io_spa, NULL, &zio->io_bookmark, zio, 0);
}
@@ -4799,12 +5008,12 @@ zio_done(zio_t *zio)
ASSERT(taskq_empty_ent(&zio->io_tqent));
spa_taskq_dispatch_ent(zio->io_spa,
ZIO_TYPE_CLAIM, ZIO_TASKQ_ISSUE,
- zio_reexecute, zio, 0, &zio->io_tqent);
+ zio_reexecute, zio, 0, &zio->io_tqent, NULL);
}
return (NULL);
}
- ASSERT(zio->io_child_count == 0);
+ ASSERT(list_is_empty(&zio->io_child_list));
ASSERT(zio->io_reexecute == 0);
ASSERT(zio->io_error == 0 || (zio->io_flags & ZIO_FLAG_CANFAIL));
@@ -4819,12 +5028,6 @@ zio_done(zio_t *zio)
zfs_ereport_free_checksum(zcr);
}
- if (zio->io_flags & ZIO_FLAG_FASTWRITE && zio->io_bp &&
- !BP_IS_HOLE(zio->io_bp) && !BP_IS_EMBEDDED(zio->io_bp) &&
- !(zio->io_flags & ZIO_FLAG_NOPWRITE)) {
- metaslab_fastwrite_unmark(zio->io_spa, zio->io_bp);
- }
-
/*
* It is the responsibility of the done callback to ensure that this
* particular zio is no longer discoverable for adoption, and as
@@ -4877,6 +5080,7 @@ static zio_pipe_stage_t *zio_pipeline[] = {
zio_encrypt,
zio_checksum_generate,
zio_nop_write,
+ zio_brt_free,
zio_ddt_read_start,
zio_ddt_read_done,
zio_ddt_write,
@@ -4997,7 +5201,7 @@ zbookmark_subtree_completed(const dnode_phys_t *dnp,
{
zbookmark_phys_t mod_zb = *subtree_root;
mod_zb.zb_blkid++;
- ASSERT(last_block->zb_level == 0);
+ ASSERT0(last_block->zb_level);
/* The objset_phys_t isn't before anything. */
if (dnp == NULL)
@@ -5023,6 +5227,22 @@ zbookmark_subtree_completed(const dnode_phys_t *dnp,
last_block) <= 0);
}
+/*
+ * This function is similar to zbookmark_subtree_completed(), but returns true
+ * if subtree_root is equal or ahead of last_block, i.e. still to be done.
+ */
+boolean_t
+zbookmark_subtree_tbd(const dnode_phys_t *dnp,
+ const zbookmark_phys_t *subtree_root, const zbookmark_phys_t *last_block)
+{
+ ASSERT0(last_block->zb_level);
+ if (dnp == NULL)
+ return (B_FALSE);
+ return (zbookmark_compare(dnp->dn_datablkszsec, dnp->dn_indblkshift,
+ 1ULL << (DNODE_BLOCK_SHIFT - SPA_MINBLOCKSHIFT), 0, subtree_root,
+ last_block) >= 0);
+}
+
EXPORT_SYMBOL(zio_type_name);
EXPORT_SYMBOL(zio_buf_alloc);
EXPORT_SYMBOL(zio_data_buf_alloc);
@@ -5035,13 +5255,13 @@ ZFS_MODULE_PARAM(zfs_zio, zio_, slow_io_ms, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_zio, zio_, requeue_io_start_cut_in_line, INT, ZMOD_RW,
"Prioritize requeued I/O");
-ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_deferred_free, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_deferred_free, UINT, ZMOD_RW,
"Defer frees starting in this pass");
-ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_dont_compress, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_dont_compress, UINT, ZMOD_RW,
"Don't compress starting in this pass");
-ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_rewrite, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zfs_, sync_pass_rewrite, UINT, ZMOD_RW,
"Rewrite new bps starting in this pass");
ZFS_MODULE_PARAM(zfs_zio, zio_, dva_throttle_enabled, INT, ZMOD_RW,
diff --git a/module/zfs/zio_checksum.c b/module/zfs/zio_checksum.c
index c7368ac26a09..ce6772a40c8b 100644
--- a/module/zfs/zio_checksum.c
+++ b/module/zfs/zio_checksum.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -160,15 +160,15 @@ abd_fletcher_4_byteswap(abd_t *abd, uint64_t size,
abd_fletcher_4_impl(abd, size, &acd);
}
-const zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
+zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
{{NULL, NULL}, NULL, NULL, 0, "inherit"},
{{NULL, NULL}, NULL, NULL, 0, "on"},
{{abd_checksum_off, abd_checksum_off},
NULL, NULL, 0, "off"},
- {{abd_checksum_SHA256, abd_checksum_SHA256},
+ {{abd_checksum_sha256, abd_checksum_sha256},
NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_EMBEDDED,
"label"},
- {{abd_checksum_SHA256, abd_checksum_SHA256},
+ {{abd_checksum_sha256, abd_checksum_sha256},
NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_EMBEDDED,
"gang_header"},
{{abd_fletcher_2_native, abd_fletcher_2_byteswap},
@@ -177,14 +177,14 @@ const zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
NULL, NULL, 0, "fletcher2"},
{{abd_fletcher_4_native, abd_fletcher_4_byteswap},
NULL, NULL, ZCHECKSUM_FLAG_METADATA, "fletcher4"},
- {{abd_checksum_SHA256, abd_checksum_SHA256},
+ {{abd_checksum_sha256, abd_checksum_sha256},
NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP |
ZCHECKSUM_FLAG_NOPWRITE, "sha256"},
{{abd_fletcher_4_native, abd_fletcher_4_byteswap},
NULL, NULL, ZCHECKSUM_FLAG_EMBEDDED, "zilog2"},
{{abd_checksum_off, abd_checksum_off},
NULL, NULL, 0, "noparity"},
- {{abd_checksum_SHA512_native, abd_checksum_SHA512_byteswap},
+ {{abd_checksum_sha512_native, abd_checksum_sha512_byteswap},
NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP |
ZCHECKSUM_FLAG_NOPWRITE, "sha512"},
{{abd_checksum_skein_native, abd_checksum_skein_byteswap},
@@ -272,7 +272,7 @@ static void
zio_checksum_gang_verifier(zio_cksum_t *zcp, const blkptr_t *bp)
{
const dva_t *dva = BP_IDENTITY(bp);
- uint64_t txg = BP_PHYSICAL_BIRTH(bp);
+ uint64_t txg = BP_GET_BIRTH(bp);
ASSERT(BP_IS_GANG(bp));
@@ -363,11 +363,14 @@ zio_checksum_compute(zio_t *zio, enum zio_checksum checksum,
zil_chain_t zilc;
abd_copy_to_buf(&zilc, abd, sizeof (zil_chain_t));
- size = P2ROUNDUP_TYPED(zilc.zc_nused, ZIL_MIN_BLKSZ,
- uint64_t);
+ uint64_t nused = P2ROUNDUP_TYPED(zilc.zc_nused,
+ ZIL_MIN_BLKSZ, uint64_t);
+ ASSERT3U(size, >=, nused);
+ size = nused;
eck = zilc.zc_eck;
eck_offset = offsetof(zil_chain_t, zc_eck);
} else {
+ ASSERT3U(size, >=, sizeof (zio_eck_t));
eck_offset = size - sizeof (zio_eck_t);
abd_copy_to_buf_off(&eck, abd, eck_offset,
sizeof (zio_eck_t));
@@ -423,6 +426,9 @@ zio_checksum_error_impl(spa_t *spa, const blkptr_t *bp,
zio_checksum_template_init(checksum, spa);
+ IMPLY(bp == NULL, ci->ci_flags & ZCHECKSUM_FLAG_EMBEDDED);
+ IMPLY(bp == NULL, checksum == ZIO_CHECKSUM_LABEL);
+
if (ci->ci_flags & ZCHECKSUM_FLAG_EMBEDDED) {
zio_cksum_t verifier;
size_t eck_offset;
@@ -445,12 +451,13 @@ zio_checksum_error_impl(spa_t *spa, const blkptr_t *bp,
return (SET_ERROR(ECKSUM));
}
- if (nused > size) {
+ nused = P2ROUNDUP_TYPED(nused, ZIL_MIN_BLKSZ, uint64_t);
+ if (size < nused)
return (SET_ERROR(ECKSUM));
- }
-
- size = P2ROUNDUP_TYPED(nused, ZIL_MIN_BLKSZ, uint64_t);
+ size = nused;
} else {
+ if (size < sizeof (zio_eck_t))
+ return (SET_ERROR(ECKSUM));
eck_offset = size - sizeof (zio_eck_t);
abd_copy_to_buf_off(&eck, abd, eck_offset,
sizeof (zio_eck_t));
@@ -512,8 +519,6 @@ zio_checksum_error_impl(spa_t *spa, const blkptr_t *bp,
}
if (info != NULL) {
- info->zbc_expected = expected_cksum;
- info->zbc_actual = actual_cksum;
info->zbc_checksum_name = ci->ci_name;
info->zbc_byteswapped = byteswap;
info->zbc_injected = 0;
diff --git a/module/zfs/zio_compress.c b/module/zfs/zio_compress.c
index 717395dcf456..c8a10db7483b 100644
--- a/module/zfs/zio_compress.c
+++ b/module/zfs/zio_compress.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -44,12 +44,12 @@
* If nonzero, every 1/X decompression attempts will fail, simulating
* an undetected memory error.
*/
-unsigned long zio_decompress_fail_fraction = 0;
+static unsigned long zio_decompress_fail_fraction = 0;
/*
* Compression vectors.
*/
-const zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = {
+zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = {
{"inherit", 0, NULL, NULL, NULL},
{"on", 0, NULL, NULL, NULL},
{"uncompressed", 0, NULL, NULL, NULL},
@@ -125,7 +125,7 @@ zio_compress_zeroed_cb(void *data, size_t len, void *private)
}
size_t
-zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len,
+zio_compress_data(enum zio_compress c, abd_t *src, void **dst, size_t s_len,
uint8_t level)
{
size_t c_len, d_len;
@@ -163,9 +163,12 @@ zio_compress_data(enum zio_compress c, abd_t *src, void *dst, size_t s_len,
ASSERT3U(complevel, !=, ZIO_COMPLEVEL_INHERIT);
}
+ if (*dst == NULL)
+ *dst = zio_buf_alloc(s_len);
+
/* No compression algorithms can read from ABDs directly */
void *tmp = abd_borrow_buf_copy(src, s_len);
- c_len = ci->ci_compress(tmp, dst, s_len, d_len, complevel);
+ c_len = ci->ci_compress(tmp, *dst, s_len, d_len, complevel);
abd_return_buf(src, tmp, s_len);
if (c_len > d_len)
diff --git a/module/zfs/zio_inject.c b/module/zfs/zio_inject.c
index f10abaf17209..012a0e3c6c17 100644
--- a/module/zfs/zio_inject.c
+++ b/module/zfs/zio_inject.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
+ * Copyright (c) 2024, Klara Inc.
*/
/*
@@ -59,6 +60,7 @@ uint32_t zio_injection_enabled = 0;
typedef struct inject_handler {
int zi_id;
spa_t *zi_spa;
+ char *zi_spa_name; /* ZINJECT_DELAY_IMPORT only */
zinject_record_t zi_record;
uint64_t *zi_lanes;
int zi_next_lane;
@@ -364,10 +366,10 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
int ret = 0;
/*
- * We skip over faults in the labels unless it's during
- * device open (i.e. zio == NULL).
+ * We skip over faults in the labels unless it's during device open
+ * (i.e. zio == NULL) or a device flush (offset is meaningless)
*/
- if (zio != NULL) {
+ if (zio != NULL && zio->io_type != ZIO_TYPE_FLUSH) {
uint64_t offset = zio->io_offset;
if (offset < VDEV_LABEL_START_SIZE ||
@@ -605,6 +607,12 @@ zio_handle_io_delay(zio_t *zio)
if (vd->vdev_guid != handler->zi_record.zi_guid)
continue;
+ /* also match on I/O type (e.g., -T read) */
+ if (handler->zi_record.zi_iotype != ZIO_TYPES &&
+ handler->zi_record.zi_iotype != zio->io_type) {
+ continue;
+ }
+
/*
* Defensive; should never happen as the array allocation
* occurs prior to inserting this handler on the list.
@@ -699,6 +707,63 @@ zio_handle_io_delay(zio_t *zio)
return (min_target);
}
+static void
+zio_handle_pool_delay(spa_t *spa, hrtime_t elapsed, zinject_type_t command)
+{
+ inject_handler_t *handler;
+ hrtime_t delay = 0;
+ int id = 0;
+
+ rw_enter(&inject_lock, RW_READER);
+
+ for (handler = list_head(&inject_handlers);
+ handler != NULL && handler->zi_record.zi_cmd == command;
+ handler = list_next(&inject_handlers, handler)) {
+ ASSERT3P(handler->zi_spa_name, !=, NULL);
+ if (strcmp(spa_name(spa), handler->zi_spa_name) == 0) {
+ uint64_t pause =
+ SEC2NSEC(handler->zi_record.zi_duration);
+ if (pause > elapsed) {
+ delay = pause - elapsed;
+ }
+ id = handler->zi_id;
+ break;
+ }
+ }
+
+ rw_exit(&inject_lock);
+
+ if (delay) {
+ if (command == ZINJECT_DELAY_IMPORT) {
+ spa_import_progress_set_notes(spa, "injecting %llu "
+ "sec delay", (u_longlong_t)NSEC2SEC(delay));
+ }
+ zfs_sleep_until(gethrtime() + delay);
+ }
+ if (id) {
+ /* all done with this one-shot handler */
+ zio_clear_fault(id);
+ }
+}
+
+/*
+ * For testing, inject a delay during an import
+ */
+void
+zio_handle_import_delay(spa_t *spa, hrtime_t elapsed)
+{
+ zio_handle_pool_delay(spa, elapsed, ZINJECT_DELAY_IMPORT);
+}
+
+/*
+ * For testing, inject a delay during an export
+ */
+void
+zio_handle_export_delay(spa_t *spa, hrtime_t elapsed)
+{
+ zio_handle_pool_delay(spa, elapsed, ZINJECT_DELAY_EXPORT);
+}
+
static int
zio_calculate_range(const char *pool, zinject_record_t *record)
{
@@ -756,6 +821,28 @@ zio_calculate_range(const char *pool, zinject_record_t *record)
return (0);
}
+static boolean_t
+zio_pool_handler_exists(const char *name, zinject_type_t command)
+{
+ boolean_t exists = B_FALSE;
+
+ rw_enter(&inject_lock, RW_READER);
+ for (inject_handler_t *handler = list_head(&inject_handlers);
+ handler != NULL; handler = list_next(&inject_handlers, handler)) {
+ if (command != handler->zi_record.zi_cmd)
+ continue;
+
+ const char *pool = (handler->zi_spa_name != NULL) ?
+ handler->zi_spa_name : spa_name(handler->zi_spa);
+ if (strcmp(name, pool) == 0) {
+ exists = B_TRUE;
+ break;
+ }
+ }
+ rw_exit(&inject_lock);
+
+ return (exists);
+}
/*
* Create a new handler for the given record. We add it to the list, adding
* a reference to the spa_t in the process. We increment zio_injection_enabled,
@@ -806,16 +893,42 @@ zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record)
if (!(flags & ZINJECT_NULL)) {
/*
- * spa_inject_ref() will add an injection reference, which will
- * prevent the pool from being removed from the namespace while
- * still allowing it to be unloaded.
+ * Pool delays for import or export don't take an
+ * injection reference on the spa. Instead they
+ * rely on matching by name.
*/
- if ((spa = spa_inject_addref(name)) == NULL)
- return (SET_ERROR(ENOENT));
+ if (record->zi_cmd == ZINJECT_DELAY_IMPORT ||
+ record->zi_cmd == ZINJECT_DELAY_EXPORT) {
+ if (record->zi_duration <= 0)
+ return (SET_ERROR(EINVAL));
+ /*
+ * Only one import | export delay handler per pool.
+ */
+ if (zio_pool_handler_exists(name, record->zi_cmd))
+ return (SET_ERROR(EEXIST));
+
+ mutex_enter(&spa_namespace_lock);
+ boolean_t has_spa = spa_lookup(name) != NULL;
+ mutex_exit(&spa_namespace_lock);
+
+ if (record->zi_cmd == ZINJECT_DELAY_IMPORT && has_spa)
+ return (SET_ERROR(EEXIST));
+ if (record->zi_cmd == ZINJECT_DELAY_EXPORT && !has_spa)
+ return (SET_ERROR(ENOENT));
+ spa = NULL;
+ } else {
+ /*
+ * spa_inject_ref() will add an injection reference,
+ * which will prevent the pool from being removed
+ * from the namespace while still allowing it to be
+ * unloaded.
+ */
+ if ((spa = spa_inject_addref(name)) == NULL)
+ return (SET_ERROR(ENOENT));
+ }
handler = kmem_alloc(sizeof (inject_handler_t), KM_SLEEP);
-
- handler->zi_spa = spa;
+ handler->zi_spa = spa; /* note: can be NULL */
handler->zi_record = *record;
if (handler->zi_record.zi_cmd == ZINJECT_DELAY_IO) {
@@ -828,6 +941,11 @@ zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record)
handler->zi_next_lane = 0;
}
+ if (handler->zi_spa == NULL)
+ handler->zi_spa_name = spa_strdup(name);
+ else
+ handler->zi_spa_name = NULL;
+
rw_enter(&inject_lock, RW_WRITER);
/*
@@ -887,7 +1005,11 @@ zio_inject_list_next(int *id, char *name, size_t buflen,
if (handler) {
*record = handler->zi_record;
*id = handler->zi_id;
- (void) strncpy(name, spa_name(handler->zi_spa), buflen);
+ ASSERT(handler->zi_spa || handler->zi_spa_name);
+ if (handler->zi_spa != NULL)
+ (void) strlcpy(name, spa_name(handler->zi_spa), buflen);
+ else
+ (void) strlcpy(name, handler->zi_spa_name, buflen);
ret = 0;
} else {
ret = SET_ERROR(ENOENT);
@@ -937,7 +1059,11 @@ zio_clear_fault(int id)
ASSERT3P(handler->zi_lanes, ==, NULL);
}
- spa_inject_delref(handler->zi_spa);
+ if (handler->zi_spa_name != NULL)
+ spa_strfree(handler->zi_spa_name);
+
+ if (handler->zi_spa != NULL)
+ spa_inject_delref(handler->zi_spa);
kmem_free(handler, sizeof (inject_handler_t));
atomic_dec_32(&zio_injection_enabled);
diff --git a/module/zfs/zle.c b/module/zfs/zle.c
index 0decebb13ca7..1483a65af803 100644
--- a/module/zfs/zle.c
+++ b/module/zfs/zle.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/module/zfs/zrlock.c b/module/zfs/zrlock.c
index a4def6053622..0d50cc4712ca 100644
--- a/module/zfs/zrlock.c
+++ b/module/zfs/zrlock.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -106,16 +106,16 @@ zrl_add_impl(zrlock_t *zrl, const char *zc)
void
zrl_remove(zrlock_t *zrl)
{
- uint32_t n;
-
#ifdef ZFS_DEBUG
if (zrl->zr_owner == curthread) {
zrl->zr_owner = NULL;
zrl->zr_caller = NULL;
}
+ int32_t n = atomic_dec_32_nv((uint32_t *)&zrl->zr_refcount);
+ ASSERT3S(n, >=, 0);
+#else
+ atomic_dec_32((uint32_t *)&zrl->zr_refcount);
#endif
- n = atomic_dec_32_nv((uint32_t *)&zrl->zr_refcount);
- ASSERT3S((int32_t)n, >=, 0);
}
int
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index ac7c3a0c3232..5b6a3f5cb410 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -111,13 +111,10 @@ typedef struct {
uint64_t
zvol_name_hash(const char *name)
{
- int i;
uint64_t crc = -1ULL;
- const uint8_t *p = (const uint8_t *)name;
ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY);
- for (i = 0; i < MAXNAMELEN - 1 && *p; i++, p++) {
+ for (const uint8_t *p = (const uint8_t *)name; *p != 0; p++)
crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ (*p)) & 0xFF];
- }
return (crc);
}
@@ -138,8 +135,7 @@ zvol_find_by_name_hash(const char *name, uint64_t hash, int mode)
hlist_for_each(p, ZVOL_HT_HEAD(hash)) {
zv = hlist_entry(p, zvol_state_t, zv_hlink);
mutex_enter(&zv->zv_state_lock);
- if (zv->zv_hash == hash &&
- strncmp(zv->zv_name, name, MAXNAMELEN) == 0) {
+ if (zv->zv_hash == hash && strcmp(zv->zv_name, name) == 0) {
/*
* this is the right zvol, take the locks in the
* right order
@@ -154,8 +150,7 @@ zvol_find_by_name_hash(const char *name, uint64_t hash, int mode)
* to hold zvol_state_lock
*/
ASSERT(zv->zv_hash == hash &&
- strncmp(zv->zv_name, name, MAXNAMELEN)
- == 0);
+ strcmp(zv->zv_name, name) == 0);
}
rw_exit(&zvol_state_lock);
return (zv);
@@ -370,6 +365,40 @@ out:
}
/*
+ * Update volthreading.
+ */
+int
+zvol_set_volthreading(const char *name, boolean_t value)
+{
+ zvol_state_t *zv = zvol_find_by_name(name, RW_NONE);
+ if (zv == NULL)
+ return (ENOENT);
+ zv->zv_threading = value;
+ mutex_exit(&zv->zv_state_lock);
+ return (0);
+}
+
+/*
+ * Update zvol ro property.
+ */
+int
+zvol_set_ro(const char *name, boolean_t value)
+{
+ zvol_state_t *zv = zvol_find_by_name(name, RW_NONE);
+ if (zv == NULL)
+ return (-1);
+ if (value) {
+ zvol_os_set_disk_ro(zv, 1);
+ zv->zv_flags |= ZVOL_RDONLY;
+ } else {
+ zvol_os_set_disk_ro(zv, 0);
+ zv->zv_flags &= ~ZVOL_RDONLY;
+ }
+ mutex_exit(&zv->zv_state_lock);
+ return (0);
+}
+
+/*
* Sanity check volume block size.
*/
int
@@ -417,6 +446,8 @@ zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
lr_truncate_t *lr = arg2;
uint64_t offset, length;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -429,7 +460,7 @@ zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
if (error != 0) {
dmu_tx_abort(tx);
} else {
- zil_replaying(zv->zv_zilog, tx);
+ (void) zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset,
length);
@@ -453,6 +484,8 @@ zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_tx_t *tx;
int error;
+ ASSERT3U(lr->lr_common.lrc_reclen, >=, sizeof (*lr));
+
if (byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
@@ -475,7 +508,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);
+ (void) zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
}
@@ -514,6 +547,9 @@ zil_replay_func_t *const zvol_replay_vector[TX_MAX_TYPE] = {
zvol_replay_err, /* TX_MKDIR_ACL_ATTR */
zvol_replay_err, /* TX_WRITE2 */
zvol_replay_err, /* TX_SETSAXATTR */
+ zvol_replay_err, /* TX_RENAME_EXCHANGE */
+ zvol_replay_err, /* TX_RENAME_WHITEOUT */
+ zvol_replay_err, /* TX_CLONE_RANGE */
};
/*
@@ -526,7 +562,7 @@ static const ssize_t zvol_immediate_write_sz = 32768;
void
zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
- uint64_t size, int sync)
+ uint64_t size, boolean_t commit)
{
uint32_t blocksize = zv->zv_volblocksize;
zilog_t *zilog = zv->zv_zilog;
@@ -541,7 +577,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
else if (!spa_has_slogs(zilog->zl_spa) &&
size >= blocksize && blocksize > zvol_immediate_write_sz)
write_state = WR_INDIRECT;
- else if (sync)
+ else if (commit)
write_state = WR_COPIED;
else
write_state = WR_NEED_COPY;
@@ -576,7 +612,6 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
BP_ZERO(&lr->lr_blkptr);
itx->itx_private = zv;
- itx->itx_sync = sync;
(void) zil_itx_assign(zilog, itx, tx);
@@ -593,8 +628,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
* Log a DKIOCFREE/free-long-range to the ZIL with TX_TRUNCATE.
*/
void
-zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len,
- boolean_t sync)
+zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len)
{
itx_t *itx;
lr_truncate_t *lr;
@@ -609,7 +643,6 @@ zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len,
lr->lr_offset = off;
lr->lr_length = len;
- itx->itx_sync = sync;
zil_itx_assign(zilog, itx, tx);
}
@@ -641,10 +674,9 @@ zvol_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
int error;
ASSERT3P(lwb, !=, NULL);
- ASSERT3P(zio, !=, NULL);
ASSERT3U(size, !=, 0);
- zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
+ zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
zgd->zgd_lwb = lwb;
/*
@@ -660,6 +692,7 @@ zvol_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
error = dmu_read_by_dnode(zv->zv_dn, offset, size, buf,
DMU_READ_NO_PREFETCH);
} else { /* indirect write */
+ ASSERT3P(zio, !=, NULL);
/*
* Have to lock the whole block to ensure when it's written out
* and its checksum is being calculated that no one can change
@@ -670,8 +703,8 @@ zvol_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
offset = P2ALIGN_TYPED(offset, size, uint64_t);
zgd->zgd_lr = zfs_rangelock_enter(&zv->zv_rangelock, offset,
size, RL_READER);
- error = dmu_buf_hold_by_dnode(zv->zv_dn, offset, zgd, &db,
- DMU_READ_NO_PREFETCH);
+ error = dmu_buf_hold_noread_by_dnode(zv->zv_dn, offset, zgd,
+ &db);
if (error == 0) {
blkptr_t *bp = &lr->lr_blkptr;
@@ -924,7 +957,7 @@ zvol_prefetch_minors_impl(void *arg)
job->error = dmu_objset_own(dsname, DMU_OST_ZVOL, B_TRUE, B_TRUE,
FTAG, &os);
if (job->error == 0) {
- dmu_prefetch(os, ZVOL_OBJ, 0, 0, 0, ZIO_PRIORITY_SYNC_READ);
+ dmu_prefetch_dnode(os, ZVOL_OBJ, ZIO_PRIORITY_SYNC_READ);
dmu_objset_disown(os, B_TRUE, FTAG);
}
}
@@ -1026,8 +1059,7 @@ zvol_add_clones(const char *dsname, list_t *minors_list)
out:
if (dd != NULL)
dsl_dir_rele(dd, FTAG);
- if (dp != NULL)
- dsl_pool_rele(dp, FTAG);
+ dsl_pool_rele(dp, FTAG);
}
/*
@@ -1075,7 +1107,7 @@ zvol_create_minors_cb(const char *dsname, void *arg)
* traverse snapshots only, do not traverse children,
* and skip the 'dsname'
*/
- error = dmu_objset_find(dsname,
+ (void) dmu_objset_find(dsname,
zvol_create_snap_minor_cb, (void *)job,
DS_FIND_SNAPSHOTS);
}
@@ -1147,8 +1179,7 @@ zvol_create_minors_recursive(const char *name)
* Prefetch is completed, we can do zvol_os_create_minor
* sequentially.
*/
- while ((job = list_head(&minors_list)) != NULL) {
- list_remove(&minors_list, job);
+ while ((job = list_remove_head(&minors_list)) != NULL) {
if (!job->error)
(void) zvol_os_create_minor(job->name);
kmem_strfree(job->name);
@@ -1255,10 +1286,8 @@ zvol_remove_minors_impl(const char *name)
rw_exit(&zvol_state_lock);
/* Drop zvol_state_lock before calling zvol_free() */
- while ((zv = list_head(&free_list)) != NULL) {
- list_remove(&free_list, zv);
+ while ((zv = list_remove_head(&free_list)) != NULL)
zvol_os_free(zv);
- }
}
/* Remove minor for this specific volume only */
@@ -1442,9 +1471,9 @@ zvol_task_alloc(zvol_async_op_t op, const char *name1, const char *name2,
task->op = op;
task->value = value;
- strlcpy(task->name1, name1, MAXNAMELEN);
+ strlcpy(task->name1, name1, sizeof (task->name1));
if (name2 != NULL)
- strlcpy(task->name2, name2, MAXNAMELEN);
+ strlcpy(task->name2, name2, sizeof (task->name2));
return (task);
}
@@ -1488,7 +1517,7 @@ typedef struct zvol_set_prop_int_arg {
const char *zsda_name;
uint64_t zsda_value;
zprop_source_t zsda_source;
- dmu_tx_t *zsda_tx;
+ zfs_prop_t zsda_prop;
} zvol_set_prop_int_arg_t;
/*
@@ -1496,7 +1525,7 @@ typedef struct zvol_set_prop_int_arg {
* conditions are imposed.
*/
static int
-zvol_set_snapdev_check(void *arg, dmu_tx_t *tx)
+zvol_set_common_check(void *arg, dmu_tx_t *tx)
{
zvol_set_prop_int_arg_t *zsda = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
@@ -1513,103 +1542,33 @@ zvol_set_snapdev_check(void *arg, dmu_tx_t *tx)
}
static int
-zvol_set_snapdev_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
+zvol_set_common_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
{
- (void) arg;
- char dsname[MAXNAMELEN];
+ zvol_set_prop_int_arg_t *zsda = arg;
+ char dsname[ZFS_MAX_DATASET_NAME_LEN];
zvol_task_t *task;
- uint64_t snapdev;
+ uint64_t prop;
+ const char *prop_name = zfs_prop_to_name(zsda->zsda_prop);
dsl_dataset_name(ds, dsname);
- if (dsl_prop_get_int_ds(ds, "snapdev", &snapdev) != 0)
- return (0);
- task = zvol_task_alloc(ZVOL_ASYNC_SET_SNAPDEV, dsname, NULL, snapdev);
- if (task == NULL)
- return (0);
- (void) taskq_dispatch(dp->dp_spa->spa_zvol_taskq, zvol_task_cb,
- task, TQ_SLEEP);
- return (0);
-}
-
-/*
- * Traverse all child datasets and apply snapdev appropriately.
- * We call dsl_prop_set_sync_impl() here to set the value only on the toplevel
- * dataset and read the effective "snapdev" on every child in the callback
- * function: this is because the value is not guaranteed to be the same in the
- * whole dataset hierarchy.
- */
-static void
-zvol_set_snapdev_sync(void *arg, dmu_tx_t *tx)
-{
- zvol_set_prop_int_arg_t *zsda = arg;
- dsl_pool_t *dp = dmu_tx_pool(tx);
- dsl_dir_t *dd;
- dsl_dataset_t *ds;
- int error;
-
- VERIFY0(dsl_dir_hold(dp, zsda->zsda_name, FTAG, &dd, NULL));
- zsda->zsda_tx = tx;
+ if (dsl_prop_get_int_ds(ds, prop_name, &prop) != 0)
+ return (0);
- error = dsl_dataset_hold(dp, zsda->zsda_name, FTAG, &ds);
- if (error == 0) {
- dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_SNAPDEV),
- zsda->zsda_source, sizeof (zsda->zsda_value), 1,
- &zsda->zsda_value, zsda->zsda_tx);
- dsl_dataset_rele(ds, FTAG);
+ switch (zsda->zsda_prop) {
+ case ZFS_PROP_VOLMODE:
+ task = zvol_task_alloc(ZVOL_ASYNC_SET_VOLMODE, dsname,
+ NULL, prop);
+ break;
+ case ZFS_PROP_SNAPDEV:
+ task = zvol_task_alloc(ZVOL_ASYNC_SET_SNAPDEV, dsname,
+ NULL, prop);
+ break;
+ default:
+ task = NULL;
+ break;
}
- dmu_objset_find_dp(dp, dd->dd_object, zvol_set_snapdev_sync_cb,
- zsda, DS_FIND_CHILDREN);
-
- dsl_dir_rele(dd, FTAG);
-}
-
-int
-zvol_set_snapdev(const char *ddname, zprop_source_t source, uint64_t snapdev)
-{
- zvol_set_prop_int_arg_t zsda;
-
- zsda.zsda_name = ddname;
- zsda.zsda_source = source;
- zsda.zsda_value = snapdev;
-
- return (dsl_sync_task(ddname, zvol_set_snapdev_check,
- zvol_set_snapdev_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE));
-}
-
-/*
- * Sanity check the dataset for safe use by the sync task. No additional
- * conditions are imposed.
- */
-static int
-zvol_set_volmode_check(void *arg, dmu_tx_t *tx)
-{
- zvol_set_prop_int_arg_t *zsda = arg;
- dsl_pool_t *dp = dmu_tx_pool(tx);
- dsl_dir_t *dd;
- int error;
- error = dsl_dir_hold(dp, zsda->zsda_name, FTAG, &dd, NULL);
- if (error != 0)
- return (error);
-
- dsl_dir_rele(dd, FTAG);
-
- return (error);
-}
-
-static int
-zvol_set_volmode_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
-{
- (void) arg;
- char dsname[MAXNAMELEN];
- zvol_task_t *task;
- uint64_t volmode;
-
- dsl_dataset_name(ds, dsname);
- if (dsl_prop_get_int_ds(ds, "volmode", &volmode) != 0)
- return (0);
- task = zvol_task_alloc(ZVOL_ASYNC_SET_VOLMODE, dsname, NULL, volmode);
if (task == NULL)
return (0);
@@ -1619,14 +1578,14 @@ zvol_set_volmode_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
}
/*
- * Traverse all child datasets and apply volmode appropriately.
+ * Traverse all child datasets and apply the property appropriately.
* We call dsl_prop_set_sync_impl() here to set the value only on the toplevel
- * dataset and read the effective "volmode" on every child in the callback
+ * dataset and read the effective "property" on every child in the callback
* function: this is because the value is not guaranteed to be the same in the
* whole dataset hierarchy.
*/
static void
-zvol_set_volmode_sync(void *arg, dmu_tx_t *tx)
+zvol_set_common_sync(void *arg, dmu_tx_t *tx)
{
zvol_set_prop_int_arg_t *zsda = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
@@ -1635,33 +1594,34 @@ zvol_set_volmode_sync(void *arg, dmu_tx_t *tx)
int error;
VERIFY0(dsl_dir_hold(dp, zsda->zsda_name, FTAG, &dd, NULL));
- zsda->zsda_tx = tx;
error = dsl_dataset_hold(dp, zsda->zsda_name, FTAG, &ds);
if (error == 0) {
- dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_VOLMODE),
+ dsl_prop_set_sync_impl(ds, zfs_prop_to_name(zsda->zsda_prop),
zsda->zsda_source, sizeof (zsda->zsda_value), 1,
- &zsda->zsda_value, zsda->zsda_tx);
+ &zsda->zsda_value, tx);
dsl_dataset_rele(ds, FTAG);
}
- dmu_objset_find_dp(dp, dd->dd_object, zvol_set_volmode_sync_cb,
+ dmu_objset_find_dp(dp, dd->dd_object, zvol_set_common_sync_cb,
zsda, DS_FIND_CHILDREN);
dsl_dir_rele(dd, FTAG);
}
int
-zvol_set_volmode(const char *ddname, zprop_source_t source, uint64_t volmode)
+zvol_set_common(const char *ddname, zfs_prop_t prop, zprop_source_t source,
+ uint64_t val)
{
zvol_set_prop_int_arg_t zsda;
zsda.zsda_name = ddname;
zsda.zsda_source = source;
- zsda.zsda_value = volmode;
+ zsda.zsda_value = val;
+ zsda.zsda_prop = prop;
- return (dsl_sync_task(ddname, zvol_set_volmode_check,
- zvol_set_volmode_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE));
+ return (dsl_sync_task(ddname, zvol_set_common_check,
+ zvol_set_common_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE));
}
void
diff --git a/module/zstd/include/zstd_compat_wrapper.h b/module/zstd/include/zstd_compat_wrapper.h
index 2c4baad27d4e..4e6561f31a68 100644
--- a/module/zstd/include/zstd_compat_wrapper.h
+++ b/module/zstd/include/zstd_compat_wrapper.h
@@ -73,11 +73,9 @@
#define FSE_buildDTable_raw zfs_FSE_buildDTable_raw
#define FSE_buildDTable_rle zfs_FSE_buildDTable_rle
#define FSE_buildDTable zfs_FSE_buildDTable
-#define FSE_createDTable zfs_FSE_createDTable
#define FSE_decompress_usingDTable zfs_FSE_decompress_usingDTable
#define FSE_decompress_wksp zfs_FSE_decompress_wksp
#define FSE_decompress zfs_FSE_decompress
-#define FSE_freeDTable zfs_FSE_freeDTable
/* lib/common/pool.o: */
#define POOL_add zfs_POOL_add
diff --git a/module/zstd/lib/common/fse_decompress.c b/module/zstd/lib/common/fse_decompress.c
index bcc2223ccc65..6b3205c63cc8 100644
--- a/module/zstd/lib/common/fse_decompress.c
+++ b/module/zstd/lib/common/fse_decompress.c
@@ -56,17 +56,6 @@
/* Function templates */
-FSE_DTable* FSE_createDTable (unsigned tableLog)
-{
- if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
- return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
-}
-
-void FSE_freeDTable (FSE_DTable* dt)
-{
- free(dt);
-}
-
size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
{
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
diff --git a/module/zstd/lib/compress/zstd_compress_superblock.c b/module/zstd/lib/compress/zstd_compress_superblock.c
index ffa4bb67597f..77d05d394c39 100644
--- a/module/zstd/lib/compress/zstd_compress_superblock.c
+++ b/module/zstd/lib/compress/zstd_compress_superblock.c
@@ -603,7 +603,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
const BYTE* codeTable, unsigned maxCode,
size_t nbSeq, const FSE_CTable* fseCTable,
const U32* additionalBits,
- short const* defaultNorm, U32 defaultNormLog,
+ short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
void* workspace, size_t wkspSize)
{
unsigned* const countWksp = (unsigned*)workspace;
@@ -615,7 +615,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
if (type == set_basic) {
- cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);
+ /* We selected this encoding type, so it must be valid. */
+ assert(max <= defaultMax);
+ cSymbolTypeSizeEstimateInBits = max <= defaultMax
+ ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
+ : ERROR(GENERIC);
} else if (type == set_rle) {
cSymbolTypeSizeEstimateInBits = 0;
} else if (type == set_compressed || type == set_repeat) {
@@ -643,15 +647,15 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
size_t cSeqSizeEstimate = 0;
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
nbSeq, fseTables->offcodeCTable, NULL,
- OF_defaultNorm, OF_defaultNormLog,
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
workspace, wkspSize);
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
nbSeq, fseTables->litlengthCTable, LL_bits,
- LL_defaultNorm, LL_defaultNormLog,
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
workspace, wkspSize);
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
nbSeq, fseTables->matchlengthCTable, ML_bits,
- ML_defaultNorm, ML_defaultNormLog,
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
workspace, wkspSize);
if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
return cSeqSizeEstimate + sequencesSectionHeaderSize;
@@ -809,7 +813,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
if (sp < send) {
seqDef const* seq;
repcodes_t rep;
- memcpy(&rep, prevCBlock->rep, sizeof(rep));
+ memcpy(&rep, prevCBlock->rep, sizeof(rep));
for (seq = sstart; seq < sp; ++seq) {
rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
}
diff --git a/module/zstd/lib/compress/zstd_double_fast.c b/module/zstd/lib/compress/zstd_double_fast.c
index 27eed66cfedd..4a95c01a090d 100644
--- a/module/zstd/lib/compress/zstd_double_fast.c
+++ b/module/zstd/lib/compress/zstd_double_fast.c
@@ -409,7 +409,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
- & (repIndex > dictStartIndex))
+ & (offset_1 < current+1 - dictStartIndex)) /* note: we are searching at current+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
@@ -477,7 +477,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
U32 const repIndex2 = current2 - offset_2;
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
- & (repIndex2 > dictStartIndex))
+ & (offset_2 < current2 - dictStartIndex))
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
diff --git a/module/zstd/lib/compress/zstd_fast.c b/module/zstd/lib/compress/zstd_fast.c
index 85a3a7a91e49..17894b85472f 100644
--- a/module/zstd/lib/compress/zstd_fast.c
+++ b/module/zstd/lib/compress/zstd_fast.c
@@ -416,9 +416,9 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
const BYTE* const repMatch = repBase + repIndex;
hashTable[h] = current; /* update hash table */
DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current);
- assert(offset_1 <= current +1); /* check repIndex */
- if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex))
+ if ( ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */
+ & (offset_1 < current+1 - dictStartIndex) ) /* note: we are searching at current+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
@@ -453,7 +453,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
U32 const current2 = (U32)(ip-base);
U32 const repIndex2 = current2 - offset_2;
const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */
+ if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 < current - dictStartIndex)) /* intentional overflow */
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
diff --git a/module/zstd/lib/compress/zstd_lazy.c b/module/zstd/lib/compress/zstd_lazy.c
index 4cf5c88b5325..22d80597ec62 100644
--- a/module/zstd/lib/compress/zstd_lazy.c
+++ b/module/zstd/lib/compress/zstd_lazy.c
@@ -975,7 +975,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const U32 repIndex = (U32)(current+1 - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
+ & (offset_1 < current+1 - windowLow) ) /* note: we are searching at current+1 */
if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1006,7 +1007,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_1 < current - windowLow) ) /* equivalent to `current > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1037,7 +1039,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const U32 repIndex = (U32)(current - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_1 < current - windowLow) ) /* equivalent to `current > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1083,7 +1086,8 @@ _storeSequence:
const U32 repIndex = repCurrent - offset_2;
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_2 < repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
diff --git a/module/zstd/lib/decompress/zstd_decompress_block.c b/module/zstd/lib/decompress/zstd_decompress_block.c
index ad3b3d8dbd0a..6f09e61b70cc 100644
--- a/module/zstd/lib/decompress/zstd_decompress_block.c
+++ b/module/zstd/lib/decompress/zstd_decompress_block.c
@@ -554,7 +554,6 @@ typedef struct {
size_t litLength;
size_t matchLength;
size_t offset;
- const BYTE* match;
} seq_t;
typedef struct {
@@ -568,9 +567,6 @@ typedef struct {
ZSTD_fseState stateOffb;
ZSTD_fseState stateML;
size_t prevOffset[ZSTD_REP_NUM];
- const BYTE* prefixStart;
- const BYTE* dictEnd;
- size_t pos;
} seqState_t;
/*! ZSTD_overlapCopy8() :
@@ -832,10 +828,9 @@ ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD
: 0)
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
-typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e;
FORCE_INLINE_TEMPLATE seq_t
-ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch)
+ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
{
seq_t seq;
ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
@@ -910,14 +905,6 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
- if (prefetch == ZSTD_p_prefetch) {
- size_t const pos = seqState->pos + seq.litLength;
- const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
- seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
- * No consequence though : no memory access will occur, offset is only used for prefetching */
- seqState->pos = pos + seq.matchLength;
- }
-
/* ANS state update
* gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
* clang-9.2.0 does 7% worse with ZSTD_updateFseState().
@@ -1072,7 +1059,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
__asm__(".p2align 4");
#endif
for ( ; ; ) {
- seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch);
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
assert(!ZSTD_isError(oneSeqSize));
@@ -1124,6 +1111,24 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_prefetchMatch(size_t prefixPos, seq_t const sequence,
+ const BYTE* const prefixStart, const BYTE* const dictEnd)
+{
+ prefixPos += sequence.litLength;
+ { const BYTE* const matchBase = (sequence.offset > prefixPos) ? dictEnd : prefixStart;
+ const BYTE* const match = matchBase + prefixPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
+ * No consequence though : no memory access will occur, offset is only used for prefetching */
+ PREFETCH_L1(match); PREFETCH_L1(match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ }
+ return prefixPos + sequence.matchLength;
+}
+
+/* This decoding function employs prefetching
+ * to reduce latency impact of cache misses.
+ * It's generally employed when block contains a significant portion of long-distance matches
+ * or when coupled with a "cold" dictionary */
FORCE_INLINE_TEMPLATE size_t
ZSTD_decompressSequencesLong_body(
ZSTD_DCtx* dctx,
@@ -1153,11 +1158,10 @@ ZSTD_decompressSequencesLong_body(
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
seqState_t seqState;
int seqNb;
+ size_t prefixPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */
+
dctx->fseEntropy = 1;
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
- seqState.prefixStart = prefixStart;
- seqState.pos = (size_t)(op-prefixStart);
- seqState.dictEnd = dictEnd;
assert(dst != NULL);
assert(iend >= ip);
RETURN_ERROR_IF(
@@ -1169,21 +1173,23 @@ ZSTD_decompressSequencesLong_body(
/* prepare in advance */
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
- sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
- PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ prefixPos = ZSTD_prefetchMatch(prefixPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb] = sequence;
}
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
/* decode and decompress */
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
assert(!ZSTD_isError(oneSeqSize));
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
#endif
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+
+ prefixPos = ZSTD_prefetchMatch(prefixPos, sequence, prefixStart, dictEnd);
sequences[seqNb & STORED_SEQS_MASK] = sequence;
op += oneSeqSize;
}
diff --git a/module/zstd/zfs_zstd.c b/module/zstd/zfs_zstd.c
index 41351898981a..ed0271a8d683 100644
--- a/module/zstd/zfs_zstd.c
+++ b/module/zstd/zfs_zstd.c
@@ -50,7 +50,7 @@
#include "lib/zstd.h"
#include "lib/common/zstd_errors.h"
-static int zstd_earlyabort_pass = 1;
+static uint_t zstd_earlyabort_pass = 1;
static int zstd_cutoff_level = ZIO_ZSTD_LEVEL_3;
static unsigned int zstd_abort_size = (128 * 1024);
@@ -784,9 +784,9 @@ create_fallback_mem(struct zstd_fallback_mem *mem, size_t size)
static void __init
zstd_mempool_init(void)
{
- zstd_mempool_cctx = (struct zstd_pool *)
+ zstd_mempool_cctx =
kmem_zalloc(ZSTD_POOL_MAX * sizeof (struct zstd_pool), KM_SLEEP);
- zstd_mempool_dctx = (struct zstd_pool *)
+ zstd_mempool_dctx =
kmem_zalloc(ZSTD_POOL_MAX * sizeof (struct zstd_pool), KM_SLEEP);
for (int i = 0; i < ZSTD_POOL_MAX; i++) {
@@ -897,7 +897,7 @@ module_init(zstd_init);
module_exit(zstd_fini);
#endif
-ZFS_MODULE_PARAM(zfs, zstd_, earlyabort_pass, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs, zstd_, earlyabort_pass, UINT, ZMOD_RW,
"Enable early abort attempts when using zstd");
ZFS_MODULE_PARAM(zfs, zstd_, abort_size, UINT, ZMOD_RW,
"Minimal size of block to attempt early abort");
diff --git a/rpm/generic/zfs-dkms.spec.in b/rpm/generic/zfs-dkms.spec.in
index f23347380d05..cd85dd28cf56 100644
--- a/rpm/generic/zfs-dkms.spec.in
+++ b/rpm/generic/zfs-dkms.spec.in
@@ -1,6 +1,6 @@
%{?!packager: %define packager Brian Behlendorf <behlendorf1@llnl.gov>}
-%if ! 0%{?rhel}%{?fedora}%{?mageia}%{?suse_version}
+%if ! 0%{?rhel}%{?fedora}%{?mageia}%{?suse_version}%{?openEuler}
%define not_rpm 1
%endif
@@ -24,19 +24,20 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch: noarch
Requires: dkms >= 2.2.0.3
+Requires(pre): dkms >= 2.2.0.3
Requires(post): dkms >= 2.2.0.3
Requires(preun): dkms >= 2.2.0.3
Requires: gcc, make, perl, diffutils
Requires(post): gcc, make, perl, diffutils
-%if 0%{?rhel}%{?fedora}%{?mageia}%{?suse_version}
+%if 0%{?rhel}%{?fedora}%{?mageia}%{?suse_version}%{?openEuler}
Requires: kernel-devel >= @ZFS_META_KVER_MIN@, kernel-devel <= @ZFS_META_KVER_MAX@.999
Requires(post): kernel-devel >= @ZFS_META_KVER_MIN@, kernel-devel <= @ZFS_META_KVER_MAX@.999
-Obsoletes: spl-dkms
+Obsoletes: spl-dkms <= %{version}
%endif
Provides: %{module}-kmod = %{version}
AutoReqProv: no
-%if (0%{?fedora}%{?suse_version}) || (0%{?rhel} && 0%{?rhel} < 9)
+%if (0%{?fedora}%{?suse_version}%{?openEuler}) || (0%{?rhel} && 0%{?rhel} < 9)
# We don't directly use it, but if this isn't installed, rpmbuild as root can
# crash+corrupt rpmdb
# See issue #12071
@@ -68,9 +69,93 @@ fi
%defattr(-,root,root)
/usr/src/%{module}-%{version}
+%pre
+echo "Running pre installation script: $0. Parameters: $*"
+# We don't want any other versions lingering around in dkms.
+# Tests with 'dnf' showed that in case of reinstall, or upgrade
+# the preun scriptlet removed the version we are trying to install.
+# Because of this, find all zfs dkms sources in /var/lib/dkms and
+# remove them, if we find a matching version in dkms.
+
+dkms_root=/var/lib/dkms
+if [ -d ${dkms_root}/%{module} ]; then
+ cd ${dkms_root}/%{module}
+ for x in [[:digit:]]*; do
+ [ -d "$x" ] || continue
+ otherver="$x"
+ opath="${dkms_root}/%{module}/${otherver}"
+ if [ "$otherver" != %{version} ]; then
+ # This is a workaround for a broken 'dkms status', we caused in a previous version.
+ # One day it might be not needed anymore, but it does not hurt to keep it.
+ if dkms status -m %{module} -v "$otherver" 2>&1 | grep "${opath}/source/dkms.conf does not exist"
+ then
+ echo "ERROR: dkms status is broken!" >&2
+ if [ -L "${opath}/source" -a ! -d "${opath}/source" ]
+ then
+ echo "Trying to fix it by removing the symlink: ${opath}/source" >&2
+ echo "You should manually remove ${opath}" >&2
+ rm -f "${opath}/source" || echo "Removal failed!" >&2
+ fi
+ fi
+ if [ `dkms status -m %{module} -v "$otherver" | grep -c %{module}` -gt 0 ]; then
+ echo "Removing old %{module} dkms modules version $otherver from all kernels."
+ dkms remove -m %{module} -v "$otherver" --all ||:
+ fi
+ fi
+ done
+ cd ${dkms_root}
+fi
+
+# Uninstall this version of zfs dkms modules before installation of the package.
+if [ `dkms status -m %{module} -v %{version} | grep -c %{module}` -gt 0 ]; then
+ echo "Removing %{module} dkms modules version %{version} from all kernels."
+ dkms remove -m %{module} -v %{version} --all ||:
+fi
+
+%post
+echo "Running post installation script: $0. Parameters: $*"
+# Add the module to dkms, as reccommended in the dkms man page.
+# This is generally rpm specfic.
+# But this also may help, if we have a broken 'dkms status'.
+# Because, if the sources are available and only the symlink pointing
+# to them is missing, this will resolve the situation
+echo "Adding %{module} dkms modules version %{version} to dkms."
+dkms add -m %{module} -v %{version} %{!?not_rpm:--rpm_safe_upgrade} ||:
+
+# After installing the package, dkms install this zfs version for the current kernel.
+# Force the overwriting of old modules to avoid diff warnings in dkms status.
+# Or in case of a downgrade to overwrite newer versions.
+# Or if some other backed up versions have been restored before.
+echo "Installing %{module} dkms modules version %{version} for the current kernel."
+dkms install --force -m %{module} -v %{version} ||:
+
%preun
-dkms remove -m %{module} -v %{version} --all
+dkms_root="/var/lib/dkms/%{module}/%{version}"
+echo "Running pre uninstall script: $0. Parameters: $*"
+# In case of upgrade we do nothing. See above comment in pre hook.
+if [ "$1" = "1" -o "$1" = "upgrade" ] ; then
+ echo "This is an upgrade. Skipping pre uninstall action."
+ exit 0
+fi
+
+# Check if we uninstall the package. In that case remove the dkms modules.
+# '0' is the value for the first parameter for rpm packages.
+# 'remove' or 'purge' are the possible names for deb packages.
+if [ "$1" = "0" -o "$1" = "remove" -o "$1" = "purge" ] ; then
+ if [ `dkms status -m %{module} -v %{version} | grep -c %{module}` -gt 0 ]; then
+ echo "Removing %{module} dkms modules version %{version} from all kernels."
+ dkms remove -m %{module} -v %{version} --all %{!?not_rpm:--rpm_safe_upgrade} && exit 0
+ fi
+ # If removing the modules failed, it might be because of the broken 'dkms status'.
+ if dkms status -m %{module} -v %{version} 2>&1 | grep "${dkms_root}/source/dkms.conf does not exist"
+ then
+ echo "ERROR: dkms status is broken!" >&2
+ echo "You should manually remove ${dkms_root}" >&2
+ echo "WARNING: installed modules in /lib/modules/`uname -r`/extra could not be removed automatically!" >&2
+ fi
+else
+ echo "Script parameter $1 did not match any removal condition."
+fi
-%posttrans
-/usr/lib/dkms/common.postinst %{module} %{version}
+exit 0
diff --git a/rpm/generic/zfs-kmod.spec.in b/rpm/generic/zfs-kmod.spec.in
index ae0795427868..4cc075585d4b 100644
--- a/rpm/generic/zfs-kmod.spec.in
+++ b/rpm/generic/zfs-kmod.spec.in
@@ -1,7 +1,7 @@
%define module @PACKAGE@
%if !%{defined ksrc}
-%if 0%{?rhel}%{?fedora}
+%if 0%{?rhel}%{?fedora}%{?openEuler}
%define ksrc ${kernel_version##*___}
%else
%define ksrc "$( \
@@ -16,7 +16,7 @@
%endif
%if !%{defined kobj}
-%if 0%{?rhel}%{?fedora}
+%if 0%{?rhel}%{?fedora}%{?openEuler}
%define kobj ${kernel_version##*___}
%else
%define kobj "$( \
@@ -52,12 +52,12 @@ URL: https://github.com/openzfs/zfs
Source0: %{module}-%{version}.tar.gz
Source10: kmodtool
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -u -n)
-%if 0%{?rhel}%{?fedora}
+%if 0%{?rhel}%{?fedora}%{?openEuler}
BuildRequires: gcc, make
BuildRequires: elfutils-libelf-devel
%endif
-%if (0%{?fedora}%{?suse_version}) || (0%{?rhel} && 0%{?rhel} < 9)
+%if (0%{?fedora}%{?suse_version}%{?openEuler}) || (0%{?rhel} && 0%{?rhel} < 9)
# We don't directly use it, but if this isn't installed, rpmbuild as root can
# crash+corrupt rpmdb
# See issue #12071
@@ -79,10 +79,11 @@ BuildRequires: %{_bindir}/kmodtool
# Building local packages attempt to to use the installed kernel.
%{?rhel:BuildRequires: kernel-devel}
%{?fedora:BuildRequires: kernel-devel}
+%{?openEuler:BuildRequires: kernel-devel}
%{?suse_version:BuildRequires: kernel-source}
%if !%{defined kernels} && !%{defined build_src_rpm}
- %if 0%{?rhel}%{?fedora}%{?suse_version}
+ %if 0%{?rhel}%{?fedora}%{?suse_version}%{?openEuler}
%define kernels %(ls -1 /usr/src/kernels)
%else
%define kernels %(ls -1 /lib/modules)
@@ -149,6 +150,30 @@ for kernel_version in %{?kernel_versions}; do
done
+# Module signing (modsign)
+#
+# This must be run _after_ find-debuginfo.sh runs, otherwise that will strip
+# the signature off of the modules.
+# (Based on Fedora's kernel.spec workaround)
+%define __modsign_install_post \
+ sign_pem="%{ksrc}/certs/signing_key.pem"; \
+ sign_x509="%{ksrc}/certs/signing_key.x509"; \
+ if [ -f "${sign_x509}" ]\
+ then \
+ echo "Signing kernel modules ..."; \
+ for kmod in $(find ${RPM_BUILD_ROOT}%{kmodinstdir_prefix}/*/extra/ -name \*.ko); do \
+ %{ksrc}/scripts/sign-file sha256 ${sign_pem} ${sign_x509} ${kmod}; \
+ done \
+ fi \
+%{nil}
+
+# hack to ensure signing happens after find-debuginfo.sh runs
+%define __spec_install_post \
+ %{?__debug_package:%{__debug_install_post}}\
+ %{__arch_install_post}\
+ %{__os_install_post}\
+ %{__modsign_install_post}
+
%install
rm -rf ${RPM_BUILD_ROOT}
diff --git a/rpm/generic/zfs.spec.in b/rpm/generic/zfs.spec.in
index 493e93c1f3e6..2e89abd0edfd 100644
--- a/rpm/generic/zfs.spec.in
+++ b/rpm/generic/zfs.spec.in
@@ -3,7 +3,7 @@
# Set the default udev directory based on distribution.
%if %{undefined _udevdir}
-%if 0%{?fedora}%{?rhel}%{?centos}
+%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}%{?openEuler}
%global _udevdir %{_prefix}/lib/udev
%else
%global _udevdir /lib/udev
@@ -12,16 +12,25 @@
# Set the default udevrule directory based on distribution.
%if %{undefined _udevruledir}
-%if 0%{?fedora}%{?rhel}%{?centos}
+%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}%{?openEuler}
%global _udevruledir %{_prefix}/lib/udev/rules.d
%else
%global _udevruledir /lib/udev/rules.d
%endif
%endif
+# Set the default _bashcompletiondir directory based on distribution.
+%if %{undefined _bashcompletiondir}
+%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}%{?openEuler}
+%global _bashcompletiondir /etc/bash_completion.d
+%else
+%global _bashcompletiondir /usr/share/bash-completion
+%endif
+%endif
+
# Set the default dracut directory based on distribution.
%if %{undefined _dracutdir}
-%if 0%{?fedora}%{?rhel}%{?centos}
+%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}%{?openEuler}
%global _dracutdir %{_prefix}/lib/dracut
%else
%global _dracutdir %{_prefix}/share/dracut
@@ -66,7 +75,7 @@
%endif
# Distros below support systemd
-%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}
+%if 0%{?rhel}%{?fedora}%{?centos}%{?suse_version}%{?openEuler}
%define _systemd 1
%endif
@@ -78,7 +87,7 @@
%define __python %{__use_python}
%define __python_pkg_version %{__use_python_pkg_version}
%endif
-%define __python_sitelib %(%{__python} -Esc "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
+%define __python_sitelib %(%{__python} -Esc "from distutils.sysconfig import get_python_lib; print(get_python_lib())" 2>/dev/null || %{__python} -Esc "import sysconfig; print(sysconfig.get_path('purelib'))")
Name: @PACKAGE@
Version: @VERSION@
@@ -96,13 +105,13 @@ Requires: libuutil3%{?_isa} = %{version}-%{release}
Requires: libzfs5%{?_isa} = %{version}-%{release}
Requires: %{name}-kmod = %{version}
Provides: %{name}-kmod-common = %{version}-%{release}
-Obsoletes: spl
+Obsoletes: spl <= %{version}
# zfs-fuse provides the same commands and man pages that OpenZFS does.
# Renaming those on either side would conflict with all available documentation.
Conflicts: zfs-fuse
-%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}
+%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}%{?openEuler}
BuildRequires: gcc, make
BuildRequires: zlib-devel
BuildRequires: libuuid-devel
@@ -110,11 +119,11 @@ BuildRequires: libblkid-devel
BuildRequires: libudev-devel
BuildRequires: libattr-devel
BuildRequires: openssl-devel
-%if 0%{?fedora} || 0%{?rhel} >= 8 || 0%{?centos} >= 8
+%if 0%{?fedora}%{?suse_version}%{?openEuler} || 0%{?rhel} >= 8 || 0%{?centos} >= 8
BuildRequires: libtirpc-devel
%endif
-%if (0%{?fedora}%{?suse_version}) || (0%{?rhel} && 0%{?rhel} < 9)
+%if (0%{?fedora}%{?suse_version}%{?openEuler}) || (0%{?rhel} && 0%{?rhel} < 9)
# We don't directly use it, but if this isn't installed, rpmbuild as root can
# crash+corrupt rpmdb
# See issue #12071
@@ -144,8 +153,8 @@ This package contains the core ZFS command line utilities.
%package -n libzpool5
Summary: Native ZFS pool library for Linux
Group: System Environment/Kernel
-Obsoletes: libzpool2
-Obsoletes: libzpool4
+Obsoletes: libzpool2 <= %{version}
+Obsoletes: libzpool4 <= %{version}
%description -n libzpool5
This package contains the zpool library, which provides support
@@ -161,7 +170,7 @@ for managing zpools
%package -n libnvpair3
Summary: Solaris name-value library for Linux
Group: System Environment/Kernel
-Obsoletes: libnvpair1
+Obsoletes: libnvpair1 <= %{version}
%description -n libnvpair3
This package contains routines for packing and unpacking name-value
@@ -179,7 +188,7 @@ to write self describing data structures on disk.
%package -n libuutil3
Summary: Solaris userland utility library for Linux
Group: System Environment/Kernel
-Obsoletes: libuutil1
+Obsoletes: libuutil1 <= %{version}
%description -n libuutil3
This library provides a variety of compatibility functions for OpenZFS:
@@ -205,8 +214,8 @@ This library provides a variety of compatibility functions for OpenZFS:
%package -n libzfs5
Summary: Native ZFS filesystem library for Linux
Group: System Environment/Kernel
-Obsoletes: libzfs2
-Obsoletes: libzfs4
+Obsoletes: libzfs2 <= %{version}
+Obsoletes: libzfs4 <= %{version}
%description -n libzfs5
This package provides support for managing ZFS filesystems
@@ -228,9 +237,9 @@ Requires: libuutil3%{?_isa} = %{version}-%{release}
Provides: libzpool5-devel = %{version}-%{release}
Provides: libnvpair3-devel = %{version}-%{release}
Provides: libuutil3-devel = %{version}-%{release}
-Obsoletes: zfs-devel
-Obsoletes: libzfs2-devel
-Obsoletes: libzfs4-devel
+Obsoletes: zfs-devel <= %{version}
+Obsoletes: libzfs2-devel <= %{version}
+Obsoletes: libzfs4-devel <= %{version}
%description -n libzfs5-devel
This package contains the header files needed for building additional
@@ -251,7 +260,7 @@ Requires: sudo
Requires: sysstat
Requires: libaio
Requires: python%{__python_pkg_version}
-%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}
+%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}%{?openEuler}
BuildRequires: libaio-devel
%endif
AutoReqProv: no
@@ -292,7 +301,7 @@ Requires: python36-cffi
Requires: python%{__python_pkg_version}-cffi
%endif
-%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}
+%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}%{?openEuler}
%if 0%{?centos} == 7
BuildRequires: python36-packaging
BuildRequires: python36-devel
@@ -328,7 +337,7 @@ image which is ZFS aware.
%package -n pam_zfs_key
Summary: PAM module for encrypted ZFS datasets
-%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}
+%if 0%{?rhel}%{?centos}%{?fedora}%{?suse_version}%{?openEuler}
BuildRequires: pam-devel
%endif
@@ -409,7 +418,8 @@ make install DESTDIR=%{?buildroot}
find %{?buildroot}%{_libdir} -name '*.la' -exec rm -f {} \;
%if 0%{!?__brp_mangle_shebangs:1}
find %{?buildroot}%{_bindir} \
- \( -name arc_summary -or -name arcstat -or -name dbufstat \) \
+ \( -name arc_summary -or -name arcstat -or -name dbufstat \
+ -or -name zilstat \) \
-exec %{__sed} -i 's|^#!.*|#!%{__python}|' {} \;
find %{?buildroot}%{_datadir} \
\( -name test-runner.py -or -name zts-report.py \) \
@@ -487,6 +497,7 @@ systemctl --system daemon-reload >/dev/null || true
%{_bindir}/arc_summary
%{_bindir}/arcstat
%{_bindir}/dbufstat
+%{_bindir}/zilstat
# Man pages
%{_mandir}/man1/*
%{_mandir}/man4/*
@@ -520,7 +531,7 @@ systemctl --system daemon-reload >/dev/null || true
%config(noreplace) %{_sysconfdir}/%{name}/vdev_id.conf.*.example
%attr(440, root, root) %config(noreplace) %{_sysconfdir}/sudoers.d/*
-%config(noreplace) %{_sysconfdir}/bash_completion.d/zfs
+%config(noreplace) %{_bashcompletiondir}/zfs
%files -n libzpool5
%{_libdir}/libzpool.so.*
diff --git a/rpm/redhat/zfs-kmod.spec.in b/rpm/redhat/zfs-kmod.spec.in
index f59551c0b43a..876c198c64de 100644
--- a/rpm/redhat/zfs-kmod.spec.in
+++ b/rpm/redhat/zfs-kmod.spec.in
@@ -17,7 +17,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
# by generating a preamble text file which kmodtool can append to the spec file.
%(/bin/echo -e "\
Requires: @PACKAGE@ = %{version}\n\
-Conflicts: @PACKAGE@-dkms)
+Conflicts: @PACKAGE@-dkms" > %{_sourcedir}/kmod-preamble)
# LDFLAGS are not sanitized by arch/*/Makefile for these architectures.
%ifarch ppc ppc64 ppc64le aarch64
@@ -72,6 +72,30 @@ fi
%{?kernel_llvm}
make %{?_smp_mflags}
+# Module signing (modsign)
+#
+# This must be run _after_ find-debuginfo.sh runs, otherwise that will strip
+# the signature off of the modules.
+# (Based on Fedora's kernel.spec workaround)
+%define __modsign_install_post \
+ sign_pem="%{ksrc}/certs/signing_key.pem"; \
+ sign_x509="%{ksrc}/certs/signing_key.x509"; \
+ if [ -f "${sign_x509}" ]\
+ then \
+ echo "Signing kernel modules ..."; \
+ for kmod in $(find %{buildroot}/lib/modules/%{kverrel}/extra/ -name \*.ko); do \
+ %{ksrc}/scripts/sign-file sha256 ${sign_pem} ${sign_x509} ${kmod}; \
+ done \
+ fi \
+%{nil}
+
+# hack to ensure signing happens after find-debuginfo.sh runs
+%define __spec_install_post \
+ %{?__debug_package:%{__debug_install_post}}\
+ %{__arch_install_post}\
+ %{__os_install_post}\
+ %{__modsign_install_post}
+
%install
make install \
DESTDIR=${RPM_BUILD_ROOT} \
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 79719e621b69..b43bf97dbdf4 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -1,11 +1,4 @@
scriptsdir = $(datadir)/$(PACKAGE)
-dist_scripts_SCRIPTS = \
- %D%/zfs-helpers.sh \
- %D%/zfs-tests.sh \
- %D%/zfs.sh \
- %D%/zimport.sh \
- %D%/zloop.sh
-
dist_noinst_SCRIPTS = \
%D%/commitcheck.sh \
%D%/common.sh.in \
@@ -18,9 +11,25 @@ dist_noinst_SCRIPTS = \
%D%/paxcheck.sh \
%D%/zfs-tests-color.sh
+scripts_scripts = \
+ %D%/zfs-helpers.sh \
+ %D%/zfs-tests.sh \
+ %D%/zfs.sh \
+ %D%/zimport.sh \
+ %D%/zloop.sh
+
+if CONFIG_USER
+dist_scripts_SCRIPTS = $(scripts_scripts)
+dist_zfsexec_SCRIPTS = \
+ %D%/zfs_prepare_disk
+else
+dist_noinst_SCRIPTS += $(scripts_scripts)
+endif
+
dist_noinst_DATA += \
%D%/cstyle.pl \
%D%/enum-extract.pl \
+ %D%/update_authors.pl \
%D%/zfs2zol-patch.sed \
%D%/zol2zfs-patch.sed
diff --git a/scripts/common.sh.in b/scripts/common.sh.in
index 8268315b3361..33669457f415 100644
--- a/scripts/common.sh.in
+++ b/scripts/common.sh.in
@@ -8,15 +8,15 @@ export ZTS_DIR=
export SCRIPT_DIR=
# General commands
-export ZDB=${ZDB:-$SBIN_DIR/zdb}
-export ZFS=${ZFS:-$SBIN_DIR/zfs}
-export ZPOOL=${ZPOOL:-$SBIN_DIR/zpool}
-export ZTEST=${ZTEST:-$SBIN_DIR/ztest}
-export ZFS_SH=${ZFS_SH:-$SCRIPT_DIR/zfs.sh}
+export ZDB="${ZDB:-$SBIN_DIR/zdb}"
+export ZFS="${ZFS:-$SBIN_DIR/zfs}"
+export ZPOOL="${ZPOOL:-$SBIN_DIR/zpool}"
+export ZTEST="${ZTEST:-$SBIN_DIR/ztest}"
+export ZFS_SH="${ZFS_SH:-$SCRIPT_DIR/zfs.sh}"
# Test Suite
-export RUNFILE_DIR=${RUNFILE_DIR:-$ZTS_DIR/runfiles}
-export TEST_RUNNER=${TEST_RUNNER:-$ZTS_DIR/test-runner/bin/test-runner.py}
-export ZTS_REPORT=${ZTS_REPORT:-$ZTS_DIR/test-runner/bin/zts-report.py}
-export STF_TOOLS=${STF_TOOLS:-$ZTS_DIR/test-runner}
-export STF_SUITE=${STF_SUITE:-$ZTS_DIR/zfs-tests}
+export RUNFILE_DIR="${RUNFILE_DIR:-$ZTS_DIR/runfiles}"
+export TEST_RUNNER="${TEST_RUNNER:-$ZTS_DIR/test-runner/bin/test-runner.py}"
+export ZTS_REPORT="${ZTS_REPORT:-$ZTS_DIR/test-runner/bin/zts-report.py}"
+export STF_TOOLS="${STF_TOOLS:-$ZTS_DIR/test-runner}"
+export STF_SUITE="${STF_SUITE:-$ZTS_DIR/zfs-tests}"
diff --git a/scripts/cstyle.pl b/scripts/cstyle.pl
index 4846ea570ff3..d47fd3362408 100755
--- a/scripts/cstyle.pl
+++ b/scripts/cstyle.pl
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -498,9 +498,6 @@ line: while (<$filehandle>) {
if (/\S\*\/[^)]|\S\*\/$/ && !/$lint_re/) {
err("missing blank before close comment");
}
- if (/\/\/\S/) { # C++ comments
- err("missing blank after start comment");
- }
# check for unterminated single line comments, but allow them when
# they are used to comment out the argument list of a function
# declaration.
@@ -534,7 +531,15 @@ line: while (<$filehandle>) {
# multiple comments on the same line.
#
s/\/\*.*?\*\///g;
- s/\/\/.*$//; # C++ comments
+ s/\/\/(?:\s.*)?$//; # Valid C++ comments
+
+ # After stripping correctly spaced comments, check for (and strip) comments
+ # without a blank. By checking this after clearing out C++ comments that
+ # correctly have a blank, we guarantee URIs in a C++ comment will not cause
+ # an error.
+ if (s!//.*$!!) { # C++ comments
+ err("missing blank after start comment");
+ }
# delete any trailing whitespace; we have already checked for that.
s/\s*$//;
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 = <<EOT;
usage: config-enum enum [file ...]
diff --git a/scripts/kmodtool b/scripts/kmodtool
index a79ad0c7a0f3..0d6af2c7f1d1 100755
--- a/scripts/kmodtool
+++ b/scripts/kmodtool
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# shellcheck disable=SC2086
+# shellcheck disable=SC2086,SC2295
# kmodtool - Helper script for building kernel module RPMs
# Copyright (c) 2003-2012 Ville Skyttä <ville.skytta@iki.fi>,
@@ -125,10 +125,10 @@ EOF
print_rpmtemplate_per_kmodpkg ()
{
- if [ "${1}" = "--custom" ]; then
+ if [[ "${1}" = "--custom" ]]; then
shift
local customkernel=true
- elif [ "${1}" = "--redhat" ]; then
+ elif [[ "${1}" = "--redhat" ]]; then
# this is needed for akmods
shift
local redhatkernel=true
@@ -139,7 +139,7 @@ print_rpmtemplate_per_kmodpkg ()
# Detect depmod install location
local depmod_path=/sbin/depmod
- if [ ! -f "${depmod_path}" ]; then
+ if [[ ! -f "${depmod_path}" ]]; then
depmod_path=/usr/sbin/depmod
fi
@@ -163,24 +163,24 @@ Requires(postun): kmod
EOF
# second part
- if [ -z "${customkernel}" ]; then
+ if [[ -z "${customkernel}" ]]; then
cat <<EOF
Requires: kernel-uname-r = ${kernel_uname_r}
BuildRequires: kernel-devel-uname-r = ${kernel_uname_r}
%{?KmodsRequires:Requires: %{KmodsRequires}-uname-r = ${kernel_uname_r}}
%{?KmodsRequires:BuildRequires: %{KmodsRequires}-uname-r = ${kernel_uname_r}}
%post -n kmod-${kmodname}-${kernel_uname_r}
-if [ -f "/boot/System.map-${kernel_uname_r}" ]; then
+if [[ -f "/boot/System.map-${kernel_uname_r}" ]]; then
${prefix}${depmod_path} -aeF /boot/System.map-${kernel_uname_r} ${kernel_uname_r} > /dev/null || :
-elif [ -f "/lib/modules/${kernel_uname_r}/System.map" ]; then
+elif [[ -f "/lib/modules/${kernel_uname_r}/System.map" ]]; then
${prefix}${depmod_path} -aeF /lib/modules/${kernel_uname_r}/System.map ${kernel_uname_r} > /dev/null || :
else
${prefix}${depmod_path} -ae ${kernel_uname_r} &> /dev/null || :
fi
%postun -n kmod-${kmodname}-${kernel_uname_r}
-if [ -f "/boot/System.map-${kernel_uname_r}" ]; then
+if [[ -f "/boot/System.map-${kernel_uname_r}" ]]; then
${prefix}${depmod_path} -aF /boot/System.map-${kernel_uname_r} ${kernel_uname_r} &> /dev/null || :
-elif [ -f "/lib/modules/${kernel_uname_r}/System.map" ]; then
+elif [[ -f "/lib/modules/${kernel_uname_r}/System.map" ]]; then
${prefix}${depmod_path} -aF /lib/modules/${kernel_uname_r}/System.map ${kernel_uname_r} &> /dev/null || :
else
${prefix}${depmod_path} -a ${kernel_uname_r} &> /dev/null || :
@@ -213,10 +213,10 @@ EOF
print_rpmtemplate_kmoddevelpkg ()
{
- if [ "${1}" = "--custom" ]; then
+ if [[ "${1}" = "--custom" ]]; then
shift
local customkernel=true
- elif [ "${1}" = "--redhat" ]; then
+ elif [[ "${1}" = "--redhat" ]]; then
shift
local redhatkernel=true
fi
@@ -230,7 +230,7 @@ Group: System Environment/Kernel
Provides: ${kmodname}-devel-kmod = %{?epoch:%{epoch}:}%{version}-%{release}
EOF
- if [ -z "${customkernel}" ] && [ -z "${redhatkernel}" ]; then
+ if [[ -z "${customkernel}" ]] && [[ -z "${redhatkernel}" ]]; then
echo "Requires: kmod-${kmodname}-devel-${kernel_uname_r} >= %{?epoch:%{epoch}:}%{version}-%{release}"
fi
@@ -256,10 +256,10 @@ EOF
print_rpmtemplate_per_kmoddevelpkg ()
{
- if [ "${1}" = "--custom" ]; then
+ if [[ "${1}" = "--custom" ]]; then
shift
local customkernel=true
- elif [ "${1}" = "--redhat" ]; then
+ elif [[ "${1}" = "--redhat" ]]; then
# this is needed for akmods
shift
local redhatkernel=true
@@ -279,7 +279,7 @@ Provides: kmod-${kmodname}-devel-uname-r = ${kernel_uname_r}
EOF
# second part
- if [ -z "${customkernel}" ]; then
+ if [[ -z "${customkernel}" ]]; then
cat <<EOF
Requires: kernel-devel-uname-r = ${kernel_uname_r}
BuildRequires: kernel-devel-uname-r = ${kernel_uname_r}
@@ -333,36 +333,36 @@ print_customrpmtemplate ()
{
for kernel in ${1}
do
- if [ -e "${buildroot}/usr/src/kernels/${kernel}" ] ; then
- # this looks like a Fedora/RH kernel -- print a normal template (which includes the proper BR) and be happy :)
- kernel_versions="${kernel_versions}${kernel}___${buildroot}%{_usrsrc}/kernels/${kernel} "
+ if [[ -e "${prefix}/lib/modules/${kernel}/build/Makefile" ]]; then
+ # likely a user-build-kernel with available buildfiles
+ # fixme: we should check if uname from Makefile is the same as ${kernel}
- # parse kernel versions string and print template
- local kernel_verrelarch=${kernel%%${kernels_known_variants}}
- print_rpmtemplate_per_kmodpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
+ kernel_versions="${kernel_versions}${kernel}___${prefix}/lib/modules/${kernel}/build/ "
+ print_rpmtemplate_per_kmodpkg --custom "${kernel}"
# create development package
- if [ -n "${devel}" ]; then
+ if [[ -n "${devel}" ]]; then
# create devel package including common headers
- print_rpmtemplate_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
+ print_rpmtemplate_kmoddevelpkg --custom "${kernel}"
# create devel package
- print_rpmtemplate_per_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
+ print_rpmtemplate_per_kmoddevelpkg --custom "${kernel}"
fi
- elif [ -e "${prefix}/lib/modules/${kernel}/build/Makefile" ]; then
- # likely a user-build-kernel with available buildfiles
- # fixme: we should check if uname from Makefile is the same as ${kernel}
+ elif [[ -e "${buildroot}/usr/src/kernels/${kernel}" ]]; then
+ # this looks like a Fedora/RH kernel -- print a normal template (which includes the proper BR) and be happy :)
+ kernel_versions="${kernel_versions}${kernel}___${buildroot}%{_usrsrc}/kernels/${kernel} "
- kernel_versions="${kernel_versions}${kernel}___${prefix}/lib/modules/${kernel}/build/ "
- print_rpmtemplate_per_kmodpkg --custom "${kernel}"
+ # parse kernel versions string and print template
+ local kernel_verrelarch=${kernel%%${kernels_known_variants}}
+ print_rpmtemplate_per_kmodpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
# create development package
- if [ -n "${devel}" ]; then
+ if [[ -n "${devel}" ]]; then
# create devel package including common headers
- print_rpmtemplate_kmoddevelpkg --custom "${kernel}"
+ print_rpmtemplate_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
# create devel package
- print_rpmtemplate_per_kmoddevelpkg --custom "${kernel}"
+ print_rpmtemplate_per_kmoddevelpkg --redhat ${kernel} ${kernel##${kernel_verrelarch}}
fi
else
error_out 2 "Don't know how to handle ${kernel} -- ${prefix}/lib/modules/${kernel}/build/Makefile not found"
@@ -396,7 +396,7 @@ print_rpmtemplate ()
# create package
print_rpmtemplate_per_kmodpkg "${kernel}" "${kernel##${kernel_verrelarch}}"
- if [ -n "${devel}" ]; then
+ if [[ -n "${devel}" ]]; then
# create devel package including common headers
print_rpmtemplate_kmoddevelpkg "${kernel}" "${kernel##${kernel_verrelarch}}"
@@ -423,13 +423,13 @@ myprog_help ()
echo " --buildroot <dir> -- Build root (place to look for build files)"
}
-while [ -n "${1}" ] ; do
+while [[ -n "${1}" ]] ; do
case "${1}" in
--filterfile)
shift
- if [ -z "${1}" ] ; then
+ if [[ -z "${1}" ]] ; then
error_out 2 "Please provide path to a filter-file together with --filterfile" >&2
- elif [ ! -e "${1}" ]; then
+ elif [[ ! -e "${1}" ]]; then
error_out 2 "Filterfile ${1} not found" >&2
fi
filterfile="${1}"
@@ -437,7 +437,7 @@ while [ -n "${1}" ] ; do
;;
--kmodname)
shift
- if [ -z "${1}" ] ; then
+ if [[ -z "${1}" ]] ; then
error_out 2 "Please provide the name of the kmod together with --kmodname" >&2
fi
# strip pending -kmod
@@ -450,7 +450,7 @@ while [ -n "${1}" ] ; do
;;
--prefix)
shift
- if [ -z "${1}" ] ; then
+ if [[ -z "${1}" ]] ; then
error_out 2 "Please provide a prefix with --prefix" >&2
fi
prefix="${1}"
@@ -458,7 +458,7 @@ while [ -n "${1}" ] ; do
;;
--repo)
shift
- if [ -z "${1}" ] ; then
+ if [[ -z "${1}" ]] ; then
error_out 2 "Please provide the name of the repo together with --repo" >&2
fi
repo=${1}
@@ -466,7 +466,7 @@ while [ -n "${1}" ] ; do
;;
--for-kernels)
shift
- if [ -z "${1}" ] ; then
+ if [[ -z "${1}" ]] ; then
error_out 2 "Please provide the name of the kmod together with --kmodname" >&2
fi
for_kernels="${1}"
@@ -514,28 +514,28 @@ while [ -n "${1}" ] ; do
esac
done
-if [ -e ./kmodtool-kernel-variants ]; then
+if [[ -e ./kmodtool-kernel-variants ]]; then
kernels_known_variants="$(cat ./kmodtool-kernel-variants)"
-elif [ -e /usr/share/kmodtool/kernel-variants ] ; then
+elif [[ -e /usr/share/kmodtool/kernel-variants ]] ; then
kernels_known_variants="$(cat /usr/share/kmodtool/kernel-variants)"
else
kernels_known_variants="@(smp?(-debug)|PAE?(-debug)|debug|kdump|xen|kirkwood|highbank|imx|omap|tegra)"
fi
# general sanity checks
-if [ -z "${target}" ]; then
+if [[ -z "${target}" ]]; then
error_out 2 "please pass target arch with --target"
-elif [ -z "${kmodname}" ]; then
+elif [[ -z "${kmodname}" ]]; then
error_out 2 "please pass kmodname with --kmodname"
-elif [ -z "${kernels_known_variants}" ] ; then
+elif [[ -z "${kernels_known_variants}" ]] ; then
error_out 2 "could not determine known variants"
fi
# go
-if [ -n "${for_kernels}" ]; then
+if [[ -n "${for_kernels}" ]]; then
# this is easy:
print_customrpmtemplate "${for_kernels}"
-elif [ "${build_kernels}" = "akmod" ]; then
+elif [[ "${build_kernels}" = "akmod" ]]; then
# do only a akmod package
print_akmodtemplate
print_akmodmeta
@@ -543,7 +543,7 @@ else
# seems we are on out own to decide for which kernels to build
# we need more sanity checks in this case
- if [ -z "${repo}" ]; then
+ if [[ -z "${repo}" ]]; then
error_out 2 "please provide repo name with --repo"
elif ! command -v "buildsys-build-${repo}-kerneldevpkgs" > /dev/null 2>&1; then
error_out 2 "buildsys-build-${repo}-kerneldevpkgs not found"
@@ -553,14 +553,14 @@ else
cmdoptions="--target ${target}"
# filterfile to filter list of kernels?
- if [ -n "${filterfile}" ] ; then
+ if [[ -n "${filterfile}" ]] ; then
cmdoptions="${cmdoptions} --filterfile ${filterfile}"
fi
kernel_versions_to_build_for=$(buildsys-build-${repo}-kerneldevpkgs "--${build_kernels}" ${cmdoptions}) ||
error_out 2 "buildsys-build-${repo}-kerneldevpkgs failed: ${kernel_versions_to_build_for}"
- if [ "${build_kernels}" = "current" ] && [ -z "${noakmod}" ]; then
+ if [[ "${build_kernels}" = "current" ]] && [[ -z "${noakmod}" ]]; then
print_akmodtemplate
fi
diff --git a/scripts/mancheck.sh b/scripts/mancheck.sh
index 347b2e086470..364ad1b76286 100755
--- a/scripts/mancheck.sh
+++ b/scripts/mancheck.sh
@@ -27,7 +27,7 @@ fi
IFS="
"
-files="$(find "$@" -type f -name '*[1-9]*')" || exit 1
+files="$(find "$@" -type f -name '*[1-9]*' -not -name '.*')" || exit 1
add_excl="$(awk '
/^.\\" lint-ok:/ {
diff --git a/scripts/update_authors.pl b/scripts/update_authors.pl
new file mode 100755
index 000000000000..8dd49b5fb38d
--- /dev/null
+++ b/scripts/update_authors.pl
@@ -0,0 +1,322 @@
+#!/usr/bin/env perl
+
+# SPDX-License-Identifier: MIT
+#
+# Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+
+# This program will update the AUTHORS file to include commit authors that are
+# in the git history but are not yet credited.
+#
+# The CONTRIBUTORS section of the AUTHORS file attempts to be a list of
+# individual contributors to OpenZFS, with one name, address and line per
+# person. This is good for readability, but does not really leave room for the
+# that names and emails on commits from the same individual can be different,
+# for all kinds of reasons, not limited to:
+#
+# - a person might change organisations, and so their email address changes
+#
+# - a person might be paid to work on OpenZFS for their employer, and then hack
+# on personal projects in the evening, so commits legitimately come from
+# different addresses
+#
+# - names change for all kinds of reasons
+#
+# To try and account for this, this program will try to find all the possible
+# names and emails for a single contributor, and then select the "best" one to
+# add to the AUTHORS file.
+#
+# The CONTRIBUTORS section of the AUTHORS file is considered the source of
+# truth. Once an individual committer is listed in there, that line will not be
+# removed regardless of what is discovered in the commit history. However, it
+# can't just be _anything_. The name or email still has to match something seen
+# in the commit history, so that we're able to undertand that its the same
+# contributor.
+#
+# The bulk of the work is in running `git log` to fetch commit author names and
+# emails. For each value, we generate a "slug" to use as an internal id for
+# that value, which is mostly just the lowercase of the value with whitespace
+# and punctuation removed. Two values with subtle differences can produce the
+# same slug, so at this point we also try to keep the "best" pre-slug value as
+# the display version. We use this slug to update two maps, one of email->name,
+# the other of name->email.
+#
+# Once collected, we then walk all the emails we've seen and get all the names
+# associated with every instance. Then for each of those names, we get all the
+# emails associated, and so on until we've seen all the connected names and
+# emails. This collection is every possible name and email for an individual
+# contributor.
+#
+# Finaly, we consider these groups, and select the "best" name and email for
+# the contributor, and add them to the author tables if they aren't there
+# already. Once we've done everyone, we write out a new AUTHORS file, and
+# that's the whole job.
+#
+# This is imperfect! Its necessary for the user to examine the diff and make
+# sure its sensible. If it hasn't hooked up right, it may necessary to adjust
+# the input data (via .mailmap) or improve the heuristics in this program. It
+# took a long time to get into good shape when first written (355 new names
+# added to AUTHORS!) but hopefully in the future we'll be running this
+# regularly so it doesn't fall so far behind.
+
+
+use 5.010;
+use warnings;
+use strict;
+
+# Storage for the "best looking" version of name or email, keyed on slug.
+my %display_name;
+my %display_email;
+
+# First, we load the existing AUTHORS file. We save everything before
+# CONTRIBUTORS: line as-is so we can write it back out to the new file. Then
+# we extract name,email pairs from the remainder and store them in a pair of
+# hashtables, keyed on slug.
+my %authors_name;
+my %authors_email;
+
+my @authors_header;
+
+for my $line (do { local (@ARGV) = ('AUTHORS'); <> }) {
+ chomp $line;
+ state $in_header = 1;
+ if ($in_header) {
+ push @authors_header, $line;
+ $in_header = 0 if $line =~ m/^CONTRIBUTORS:/;
+ } else {
+ my ($name, $email) = $line =~ m/^\s+(.+)(?= <) <([^>]+)/;
+ next unless $name;
+
+ my $semail = email_slug($email);
+ my $sname = name_slug($name);
+
+ $authors_name{$semail} = $sname;
+ $authors_email{$sname} = $semail;
+
+ # The name/email in AUTHORS is already the "best looking"
+ # version, by definition.
+ $display_name{$sname} = $name;
+ $display_email{$semail} = $email;
+ }
+}
+
+# Next, we load all the commit authors. and form name<->email mappings, keyed
+# on slug. Note that this format is getting the .mailmap-converted form. This
+# lets us control the input to some extent by making changes there.
+my %git_names;
+my %git_emails;
+
+for my $line (reverse qx(git log --pretty=tformat:'%aN:::%aE')) {
+ chomp $line;
+ my ($name, $email) = $line =~ m/^(.*):::(.*)/;
+ next unless $name && $email;
+
+ my $semail = email_slug($email);
+ my $sname = name_slug($name);
+
+ $git_names{$semail}{$sname} = 1;
+ $git_emails{$sname}{$semail} = 1;
+
+ # Update the "best looking" display value, but only if we don't already
+ # have something from the AUTHORS file. If we do, we must not change it.
+ if (!$authors_name{email_slug($email)}) {
+ update_display_email($email);
+ }
+
+ if (!$authors_email{name_slug($name)}) {
+ update_display_name($name);
+ }
+}
+
+# Now collect unique committers by all names+emails we've ever seen for them.
+# We start with emails and resolve all possible names, then we resolve the
+# emails for those names, and round and round until there's nothing left.
+my @committers;
+for my $start_email (sort keys %git_names) {
+ # it might have been deleted already through a cross-reference
+ next unless $git_names{$start_email};
+
+ my %emails;
+ my %names;
+
+ my @check_emails = ($start_email);
+ my @check_names;
+ while (@check_emails || @check_names) {
+ while (my $email = shift @check_emails) {
+ next if $emails{$email}++;
+ push @check_names,
+ sort keys %{delete $git_names{$email}};
+ }
+ while (my $name = shift @check_names) {
+ next if $names{$name}++;
+ push @check_emails,
+ sort keys %{delete $git_emails{$name}};
+ }
+ }
+
+ # A "committer" is the collection of connected names and emails.
+ push @committers, [[sort keys %emails], [sort keys %names]];
+}
+
+# Now we have our committers, we can work out what to add to AUTHORS.
+for my $committer (@committers) {
+ my ($emails, $names) = @$committer;
+
+ # If this commiter is already in AUTHORS, we must not touch.
+ next if grep { $authors_name{$_} } @$emails;
+ next if grep { $authors_email{$_} } @$names;
+
+ # Decide on the "best" name and email to use
+ my $email = best_email(@$emails);
+ my $name = best_name(@$names);
+
+ $authors_email{$name} = $email;
+ $authors_name{$email} = $name;
+}
+
+# Now output the new AUTHORS file
+open my $fh, '>', 'AUTHORS' or die "E: couldn't open AUTHORS for write: $!\n";
+#my $fh = \*STDOUT;
+say $fh join("\n", @authors_header, "");
+for my $name (sort keys %authors_email) {
+ my $cname = $display_name{$name};
+ my $cemail = $display_email{email_slug($authors_email{$name})};
+ say $fh " $cname <$cemail>";
+}
+
+exit 0;
+
+# "Slugs" are used at the hashtable key for names and emails. They are used to
+# making two variants of a value be the "same" for matching. Mostly this is
+# to make upper and lower-case versions of a name or email compare the same,
+# but we do a little bit of munging to handle some common cases.
+#
+# Note that these are only used for matching internally; for display, the
+# slug will be used to look up the display form.
+sub name_slug {
+ my ($name) = @_;
+
+ # Remove spaces and dots, to handle differences in initials.
+ $name =~ s/[\s\.]//g;
+
+ return lc $name;
+}
+sub email_slug {
+ my ($email) = @_;
+
+ # Remove everything up to and including the first space, and the last
+ # space and everything after it.
+ $email =~ s/^(.*\s+)|(\s+.*)$//g;
+
+ # Remove the leading userid+ on Github noreply addresses. They're
+ # optional and we want to treat them as the same thing.
+ $email =~ s/^[^\+]*\+//g if $email =~ m/\.noreply\.github\.com$/;
+
+ return lc $email;
+}
+
+sub update_display_name {
+ my ($name) = @_;
+ my $sname = name_slug($name);
+
+ # For names, "more specific" means "has more non-lower-case characters"
+ # (in ASCII), guessing that if a person has gone to some effort to
+ # specialise their name in a later commit, they presumably care more
+ # about it. If this is wrong, its probably better to add a .mailmap
+ # entry.
+
+ my $cname = $display_name{$sname};
+ if (!$cname ||
+ ($name =~ tr/a-z //) < ($cname =~ tr/a-z //)) {
+ $display_name{$sname} = $name;
+ }
+}
+sub update_display_email {
+ my ($email) = @_;
+ my $semail = email_slug($email);
+
+ # Like names, we prefer uppercase when possible. We also remove any
+ # leading "plus address" for Github noreply addresses.
+ $email =~ s/^[^\+]*\+//g if $email =~ m/\.noreply\.github\.com$/;
+
+ my $cemail = $display_email{$semail};
+ if (!$cemail ||
+ ($email =~ tr/a-z //) < ($cemail =~ tr/a-z //)) {
+ $display_email{$semail} = $email;
+ }
+}
+
+sub best_name {
+ my @names = sort {
+ my $cmp;
+ my ($aa) = $display_name{$a};
+ my ($bb) = $display_name{$b};
+
+ # The "best" name is very subjective, and a simple sort
+ # produced good-enough results, so I didn't try harder. Use of
+ # accented characters, punctuation and caps are probably an
+ # indicator of "better", but possibly we should also take into
+ # account the most recent name we saw, in case the committer
+ # has changed their name or nickname or similar.
+ #
+ # Really, .mailmap is the place to control this.
+
+ return ($aa cmp $bb);
+ } @_;
+
+ return shift @names;
+}
+sub best_email {
+ state $internal_re = qr/\.(?:internal|local|\(none\))$/;
+ state $noreply_re = qr/\.noreply\.github\.com$/;
+ state $freemail_re = qr/\@(?:gmail|hotmail)\.com$/;
+
+ my @emails = sort {
+ my $cmp;
+
+ # prefer address with a single @ over those without
+ $cmp = (($b =~ tr/@//) == 1) <=> (($a =~ tr/@//) == 1);
+ return $cmp unless $cmp == 0;
+
+ # prefer any address over internal/local addresses
+ $cmp = (($a =~ $internal_re) <=> ($b =~ $internal_re));
+ return $cmp unless $cmp == 0;
+
+ # prefer any address over github noreply aliases
+ $cmp = (($a =~ $noreply_re) <=> ($b =~ $noreply_re));
+ return $cmp unless $cmp == 0;
+
+ # prefer any address over freemail providers
+ $cmp = (($a =~ $freemail_re) <=> ($b =~ $freemail_re));
+ return $cmp unless $cmp == 0;
+
+ # alphabetical by domain
+ my ($alocal, $adom) = split /\@/, $a;
+ my ($blocal, $bdom) = split /\@/, $b;
+ $cmp = ($adom cmp $bdom);
+ return $cmp unless $cmp == 0;
+
+ # alphabetical by local part
+ return ($alocal cmp $blocal);
+ } @_;
+
+ return shift @emails;
+}
diff --git a/scripts/zfs-tests.sh b/scripts/zfs-tests.sh
index cad65d04869f..c25903ea1bee 100755
--- a/scripts/zfs-tests.sh
+++ b/scripts/zfs-tests.sh
@@ -9,7 +9,7 @@
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -32,6 +32,7 @@ SCRIPT_COMMON=${SCRIPT_COMMON:-${0%/*}/common.sh}
PROG=zfs-tests.sh
VERBOSE="no"
QUIET=""
+DEBUG=""
CLEANUP="yes"
CLEANUPALL="no"
KMSG=""
@@ -313,6 +314,7 @@ OPTIONS:
-h Show this message
-v Verbose zfs-tests.sh output
-q Quiet test-runner output
+ -D Debug; show all test output immediately (noisy)
-x Remove all testpools, dm, lo, and files (unsafe)
-k Disable cleanup after test failure
-K Log test names to /dev/kmsg
@@ -326,7 +328,8 @@ OPTIONS:
-d DIR Use world-writable DIR for files and loopback devices
-s SIZE Use vdevs of SIZE (default: 4G)
-r RUNFILES Run tests in RUNFILES (default: ${DEFAULT_RUNFILES})
- -t PATH Run single test at PATH relative to test suite
+ -t PATH|NAME Run single test at PATH relative to test suite,
+ or search for test by NAME
-T TAGS Comma separated list of tags (default: 'functional')
-u USER Run single test as USER (default: root)
@@ -340,6 +343,9 @@ $0 -r linux-fast
# Run a single test
$0 -t tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
+# Run a single test by name
+$0 -t zfs_bookmark_cliargs
+
# Cleanup a previous run of the test suite prior to testing, run the
# default ($(echo "${DEFAULT_RUNFILES}" | sed 's/\.run//')) suite of tests and perform no cleanup on exit.
$0 -x
@@ -347,7 +353,7 @@ $0 -x
EOF
}
-while getopts 'hvqxkKfScRmn:d:s:r:?t:T:u:I:' OPTION; do
+while getopts 'hvqxkKfScRmn:d:Ds:r:?t:T:u:I:' OPTION; do
case $OPTION in
h)
usage
@@ -393,6 +399,9 @@ while getopts 'hvqxkKfScRmn:d:s:r:?t:T:u:I:' OPTION; do
d)
FILEDIR="$OPTARG"
;;
+ D)
+ DEBUG="yes"
+ ;;
I)
ITERATIONS="$OPTARG"
if [ "$ITERATIONS" -le 0 ]; then
@@ -450,8 +459,15 @@ post_user = root
post =
outputdir = /var/tmp/test_results
EOF
- SINGLETESTDIR="${SINGLETEST%/*}"
+ if [ "$SINGLETEST" = "${SINGLETEST%/*}" ] ; then
+ NEWSINGLETEST=$(find "$STF_SUITE" -name "$SINGLETEST*" -print -quit)
+ if [ -z "$NEWSINGLETEST" ] ; then
+ fail "couldn't find test matching '$SINGLETEST'"
+ fi
+ SINGLETEST=$NEWSINGLETEST
+ fi
+ SINGLETESTDIR="${SINGLETEST%/*}"
SETUPDIR="$SINGLETESTDIR"
[ "${SETUPDIR#/}" = "$SETUPDIR" ] && SETUPDIR="$STF_SUITE/$SINGLETESTDIR"
[ -x "$SETUPDIR/setup.ksh" ] && SETUPSCRIPT="setup" || SETUPSCRIPT=
@@ -680,6 +696,7 @@ REPORT_FILE=$(mktemp_file zts-report)
#
msg "${TEST_RUNNER}" \
"${QUIET:+-q}" \
+ "${DEBUG:+-D}" \
"${KMEMLEAK:+-m}" \
"${KMSG:+-K}" \
"-c \"${RUNFILES}\"" \
@@ -689,6 +706,7 @@ msg "${TEST_RUNNER}" \
{ PATH=$STF_PATH \
${TEST_RUNNER} \
${QUIET:+-q} \
+ ${DEBUG:+-D} \
${KMEMLEAK:+-m} \
${KMSG:+-K} \
-c "${RUNFILES}" \
@@ -715,6 +733,7 @@ if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then
{ PATH=$STF_PATH \
${TEST_RUNNER} \
${QUIET:+-q} \
+ ${DEBUG:+-D} \
${KMEMLEAK:+-m} \
-c "${RUNFILES}" \
-T "${TAGS}" \
diff --git a/scripts/zfs_prepare_disk b/scripts/zfs_prepare_disk
new file mode 100755
index 000000000000..02aa9f8a7728
--- /dev/null
+++ b/scripts/zfs_prepare_disk
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# This is an optional helper script that is automatically called by libzfs
+# before a disk is about to be added into the pool. It can be modified by
+# the user to run whatever commands are necessary to prepare a disk for
+# inclusion into the pool. For example, users can add lines to this
+# script to do things like update the drive's firmware or check the drive's
+# health. The script is optional and can be removed if it is not needed.
+#
+# See the zfs_prepare_disk(8) man page for details.
+#
+# Example:
+#
+# echo "Prepare disk $VDEV_PATH ($VDEV_UPATH) for $VDEV_PREPARE in $POOL_NAME"
+#
+
+exit 0
diff --git a/scripts/zimport.sh b/scripts/zimport.sh
index 595de494e50b..2549a483b148 100755
--- a/scripts/zimport.sh
+++ b/scripts/zimport.sh
@@ -54,7 +54,7 @@
BASE_DIR=$(dirname "$0")
SCRIPT_COMMON=common.sh
-if [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then
+if [[ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]]; then
. "${BASE_DIR}/${SCRIPT_COMMON}"
else
echo "Missing helper script ${SCRIPT_COMMON}" && exit 1
@@ -188,7 +188,7 @@ populate "$SRC_DIR" 10 100
SRC_DIR="$TEST_DIR/src"
SRC_DIR_ZFS="$SRC_DIR/zfs"
-if [ "$COLOR" = "no" ]; then
+if [[ "$COLOR" = "no" ]]; then
COLOR_GREEN=""
COLOR_BROWN=""
COLOR_RED=""
@@ -230,7 +230,7 @@ src_set_vars() {
ZFS_DIR="$SRC_DIR_ZFS/$ZFS_TAG"
ZFS_URL="$REPO/zfs/tarball/$ZFS_TAG"
- if [ "$TAG" = "installed" ]; then
+ if [[ "$TAG" = "installed" ]]; then
ZPOOL_CMD=$(command -v zpool)
ZFS_CMD=$(command -v zfs)
ZFS_SH="/usr/share/zfs/zfs.sh"
@@ -273,7 +273,7 @@ pool_create() {
pool_set_vars "$1"
src_set_vars "$1"
- if [ "$POOL_TAG" != "installed" ]; then
+ if [[ "$POOL_TAG" != "installed" ]]; then
cd "$POOL_DIR_SRC" || fail "Failed 'cd $POOL_DIR_SRC'"
fi
@@ -319,7 +319,7 @@ pool_create() {
# If the zfs-images directory doesn't exist fetch a copy from Github then
# cache it in the $TEST_DIR and update $IMAGES_DIR.
-if [ ! -d "$IMAGES_DIR" ]; then
+if [[ ! -d "$IMAGES_DIR" ]]; then
IMAGES_DIR="$TEST_DIR/zfs-images"
mkdir -p "$IMAGES_DIR"
curl -sL "$IMAGES_TAR" | \
@@ -331,7 +331,7 @@ fi
# list of available images for the reserved keyword 'all'.
for TAG in $POOL_TAGS; do
- if [ "$TAG" = "all" ]; then
+ if [[ "$TAG" = "all" ]]; then
ALL_TAGS=$(echo "$IMAGES_DIR"/*.tar.bz2 | \
sed "s|$IMAGES_DIR/||g;s|.tar.bz2||g")
NEW_TAGS="$NEW_TAGS $ALL_TAGS"
@@ -341,7 +341,7 @@ for TAG in $POOL_TAGS; do
done
POOL_TAGS="$NEW_TAGS"
-if [ "$VERBOSE" = "yes" ]; then
+if [[ "$VERBOSE" = "yes" ]]; then
echo "---------------------------- Options ----------------------------"
echo "VERBOSE=$VERBOSE"
echo "KEEP=$KEEP"
@@ -353,11 +353,11 @@ if [ "$VERBOSE" = "yes" ]; then
echo
fi
-if [ ! -d "$TEST_DIR" ]; then
+if [[ ! -d "$TEST_DIR" ]]; then
mkdir -p "$TEST_DIR"
fi
-if [ ! -d "$SRC_DIR" ]; then
+if [[ ! -d "$SRC_DIR" ]]; then
mkdir -p "$SRC_DIR"
fi
@@ -367,9 +367,9 @@ printf "%-16s" " "
for TAG in $SRC_TAGS; do
src_set_vars "$TAG"
- if [ "$TAG" = "installed" ]; then
+ if [[ "$TAG" = "installed" ]]; then
ZFS_VERSION=$(modinfo zfs | awk '/version:/ { print $2; exit }')
- if [ -n "$ZFS_VERSION" ]; then
+ if [[ -n "$ZFS_VERSION" ]]; then
printf "%-16s" "$ZFS_VERSION"
else
fail "ZFS is not installed"
@@ -388,21 +388,21 @@ printf "%-16s" "Clone ZFS"
for TAG in $SRC_TAGS; do
src_set_vars "$TAG"
- if [ -d "$ZFS_DIR" ]; then
+ if [[ -d "$ZFS_DIR" ]]; then
skip_nonewline
- elif [ "$ZFS_TAG" = "installed" ]; then
+ elif [[ "$ZFS_TAG" = "installed" ]]; then
skip_nonewline
else
cd "$SRC_DIR" || fail "Failed 'cd $SRC_DIR'"
- if [ ! -d "$SRC_DIR_ZFS" ]; then
+ if [[ ! -d "$SRC_DIR_ZFS" ]]; then
mkdir -p "$SRC_DIR_ZFS"
fi
git archive --format=tar --prefix="$ZFS_TAG/ $ZFS_TAG" \
-o "$SRC_DIR_ZFS/$ZFS_TAG.tar" &>/dev/null || \
rm "$SRC_DIR_ZFS/$ZFS_TAG.tar"
- if [ -s "$SRC_DIR_ZFS/$ZFS_TAG.tar" ]; then
+ if [[ -s "$SRC_DIR_ZFS/$ZFS_TAG.tar" ]]; then
tar -xf "$SRC_DIR_ZFS/$ZFS_TAG.tar" -C "$SRC_DIR_ZFS"
rm "$SRC_DIR_ZFS/$ZFS_TAG.tar"
echo -n -e "${COLOR_GREEN}Local${COLOR_RESET}\t\t"
@@ -422,9 +422,9 @@ printf "%-16s" "Build ZFS"
for TAG in $SRC_TAGS; do
src_set_vars "$TAG"
- if [ -f "$ZFS_DIR/module/zfs/zfs.ko" ]; then
+ if [[ -f "$ZFS_DIR/module/zfs/zfs.ko" ]]; then
skip_nonewline
- elif [ "$ZFS_TAG" = "installed" ]; then
+ elif [[ "$ZFS_TAG" = "installed" ]]; then
skip_nonewline
else
cd "$ZFS_DIR" || fail "Failed 'cd $ZFS_DIR'"
@@ -454,15 +454,15 @@ for TAG in $POOL_TAGS; do
mkdir -p "$POOL_DIR_PRISTINE"
# Use the existing compressed image if available.
- if [ -f "$POOL_BZIP" ]; then
+ if [[ -f "$POOL_BZIP" ]]; then
tar -xjf "$POOL_BZIP" -C "$POOL_DIR_PRISTINE" \
--strip-components=1 || \
fail "Failed 'tar -xjf $POOL_BZIP"
# Use the installed version to create the pool.
- elif [ "$TAG" = "installed" ]; then
+ elif [[ "$TAG" = "installed" ]]; then
pool_create "$TAG"
# A source build is available to create the pool.
- elif [ -d "$POOL_DIR_SRC" ]; then
+ elif [[ -d "$POOL_DIR_SRC" ]]; then
pool_create "$TAG"
else
SKIP=1
@@ -471,13 +471,13 @@ for TAG in $POOL_TAGS; do
# Verify 'zpool import' works for all listed source versions.
for SRC_TAG in $SRC_TAGS; do
- if [ "$SKIP" -eq 1 ]; then
+ if [[ "$SKIP" -eq 1 ]]; then
skip_nonewline
continue
fi
src_set_vars "$SRC_TAG"
- if [ "$SRC_TAG" != "installed" ]; then
+ if [[ "$SRC_TAG" != "installed" ]]; then
cd "$ZFS_DIR" || fail "Failed 'cd $ZFS_DIR'"
fi
$ZFS_SH zfs="spa_config_path=$POOL_DIR_COPY"
@@ -505,7 +505,7 @@ for TAG in $POOL_TAGS; do
printf "\n"
done
-if [ "$KEEP" = "no" ]; then
+if [[ "$KEEP" = "no" ]]; then
rm -Rf "$TEST_DIR"
fi
diff --git a/scripts/zloop.sh b/scripts/zloop.sh
index ade2c84c55b7..7cda23743382 100755
--- a/scripts/zloop.sh
+++ b/scripts/zloop.sh
@@ -23,7 +23,7 @@
BASE_DIR=${0%/*}
SCRIPT_COMMON=common.sh
-if [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then
+if [[ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]]; then
. "${BASE_DIR}/${SCRIPT_COMMON}"
else
echo "Missing helper script ${SCRIPT_COMMON}" && exit 1
@@ -252,38 +252,57 @@ while (( timeout == 0 )) || (( curtime <= (starttime + timeout) )); do
or_die rm -rf "$workdir"
or_die mkdir "$workdir"
- # switch between three types of configs
- # 1/3 basic, 1/3 raidz mix, and 1/3 draid mix
- choice=$((RANDOM % 3))
-
# ashift range 9 - 15
align=$(((RANDOM % 2) * 3 + 9))
+ # choose parity value
+ parity=$(((RANDOM % 3) + 1))
+
+ draid_data=0
+ draid_spares=0
+
# randomly use special classes
class="special=random"
- if [[ $choice -eq 0 ]]; then
- # basic mirror only
- parity=1
+ # choose between four types of configs
+ # (basic, raidz mix, raidz expansion, and draid mix)
+ case $((RANDOM % 4)) in
+
+ # basic mirror configuration
+ 0) parity=1
mirrors=2
- draid_data=0
- draid_spares=0
raid_children=0
vdevs=2
raid_type="raidz"
- elif [[ $choice -eq 1 ]]; then
- # fully randomized mirror/raidz (sans dRAID)
- parity=$(((RANDOM % 3) + 1))
- mirrors=$(((RANDOM % 3) * 1))
- draid_data=0
- draid_spares=0
+ ;;
+
+ # fully randomized mirror/raidz (sans dRAID)
+ 1) mirrors=$(((RANDOM % 3) * 1))
raid_children=$((((RANDOM % 9) + parity + 1) * (RANDOM % 2)))
vdevs=$(((RANDOM % 3) + 3))
raid_type="raidz"
- else
- # fully randomized dRAID (sans mirror/raidz)
- parity=$(((RANDOM % 3) + 1))
- mirrors=0
+ ;;
+
+ # randomized raidz expansion (one top-level raidz vdev)
+ 2) mirrors=0
+ vdevs=1
+ # derive initial raidz disk count based on parity choice
+ # P1: 3 - 7 disks
+ # P2: 5 - 9 disks
+ # P3: 7 - 11 disks
+ raid_children=$(((RANDOM % 5) + (parity * 2) + 1))
+
+ # 1/3 of the time use a dedicated '-X' raidz expansion test
+ if [[ $((RANDOM % 3)) -eq 0 ]]; then
+ zopt="$zopt -X -t 16"
+ raid_type="raidz"
+ else
+ raid_type="eraidz"
+ fi
+ ;;
+
+ # fully randomized dRAID (sans mirror/raidz)
+ 3) mirrors=0
draid_data=$(((RANDOM % 8) + 3))
draid_spares=$(((RANDOM % 2) + parity))
stripe=$((draid_data + parity))
@@ -291,7 +310,11 @@ while (( timeout == 0 )) || (( curtime <= (starttime + timeout) )); do
raid_children=$(((((RANDOM % 4) + 1) * stripe) + extra))
vdevs=$((RANDOM % 3))
raid_type="draid"
- fi
+ ;;
+ *)
+ # avoid shellcheck SC2249
+ ;;
+ esac
zopt="$zopt -K $raid_type"
zopt="$zopt -m $mirrors"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2e633041ab59..12e9c9f9daf2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,6 +16,7 @@ dist_scripts_test_runner_include_DATA = \
scripts_runfilesdir = $(datadir)/$(PACKAGE)/runfiles
dist_scripts_runfiles_DATA = \
+ %D%/runfiles/bclone.run \
%D%/runfiles/common.run \
%D%/runfiles/freebsd.run \
%D%/runfiles/linux.run \
diff --git a/tests/runfiles/bclone.run b/tests/runfiles/bclone.run
new file mode 100644
index 000000000000..3d0f545d9226
--- /dev/null
+++ b/tests/runfiles/bclone.run
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+# This run file contains all of the common functional tests. When
+# adding a new test consider also adding it to the sanity.run file
+# if the new test runs to completion in only a few seconds.
+#
+# Approximate run time: 5 hours
+#
+
+[DEFAULT]
+pre = setup
+quiet = False
+pre_user = root
+user = root
+timeout = 28800
+post_user = root
+post = cleanup
+failsafe_user = root
+failsafe = callbacks/zfs_failsafe
+outputdir = /var/tmp/test_results
+tags = ['bclone']
+
+[tests/functional/bclone]
+tests = ['bclone_crossfs_corner_cases',
+ 'bclone_crossfs_data',
+ 'bclone_crossfs_embedded',
+ 'bclone_crossfs_hole',
+ 'bclone_diffprops_all',
+ 'bclone_diffprops_checksum',
+ 'bclone_diffprops_compress',
+ 'bclone_diffprops_copies',
+ 'bclone_diffprops_recordsize',
+ 'bclone_prop_sync',
+ 'bclone_samefs_corner_cases',
+ 'bclone_samefs_data',
+ 'bclone_samefs_embedded',
+ 'bclone_samefs_hole']
+tags = ['bclone']
diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
index a4ec27a368ac..5e7fdf359a75 100644
--- a/tests/runfiles/common.run
+++ b/tests/runfiles/common.run
@@ -37,7 +37,7 @@ tests = ['alloc_class_001_pos', 'alloc_class_002_neg', 'alloc_class_003_pos',
'alloc_class_004_pos', 'alloc_class_005_pos', 'alloc_class_006_pos',
'alloc_class_007_pos', 'alloc_class_008_pos', 'alloc_class_009_pos',
'alloc_class_010_pos', 'alloc_class_011_neg', 'alloc_class_012_pos',
- 'alloc_class_013_pos']
+ 'alloc_class_013_pos', 'alloc_class_014_neg', 'alloc_class_015_pos']
tags = ['functional', 'alloc_class']
[tests/functional/append]
@@ -53,6 +53,37 @@ tags = ['functional', 'arc']
tests = ['atime_001_pos', 'atime_002_neg', 'root_atime_off', 'root_atime_on']
tags = ['functional', 'atime']
+[tests/functional/bclone]
+tests = ['bclone_crossfs_corner_cases_limited',
+ 'bclone_crossfs_data',
+ 'bclone_crossfs_embedded',
+ 'bclone_crossfs_hole',
+ 'bclone_diffprops_all',
+ 'bclone_diffprops_checksum',
+ 'bclone_diffprops_compress',
+ 'bclone_diffprops_copies',
+ 'bclone_diffprops_recordsize',
+ 'bclone_prop_sync',
+ 'bclone_samefs_corner_cases_limited',
+ 'bclone_samefs_data',
+ 'bclone_samefs_embedded',
+ 'bclone_samefs_hole']
+tags = ['functional', 'bclone']
+timeout = 7200
+
+[tests/functional/block_cloning]
+tests = ['block_cloning_clone_mmap_cached',
+ 'block_cloning_copyfilerange',
+ 'block_cloning_copyfilerange_partial',
+ 'block_cloning_copyfilerange_fallback',
+ 'block_cloning_disabled_copyfilerange',
+ 'block_cloning_copyfilerange_cross_dataset',
+ 'block_cloning_cross_enc_dataset',
+ 'block_cloning_copyfilerange_fallback_same_txg',
+ 'block_cloning_replay', 'block_cloning_replay_encrypted',
+ 'block_cloning_lwb_buffer_overflow', 'block_cloning_clone_mmap_write']
+tags = ['functional', 'block_cloning']
+
[tests/functional/bootfs]
tests = ['bootfs_001_pos', 'bootfs_002_neg', 'bootfs_003_pos',
'bootfs_004_neg', 'bootfs_005_neg', 'bootfs_006_pos', 'bootfs_007_pos',
@@ -106,7 +137,7 @@ tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
'tst.list_user_props', 'tst.parse_args_neg','tst.promote_conflict',
'tst.promote_multiple', 'tst.promote_simple', 'tst.rollback_mult',
'tst.rollback_one', 'tst.set_props', 'tst.snapshot_destroy', 'tst.snapshot_neg',
- 'tst.snapshot_recursive', 'tst.snapshot_simple',
+ 'tst.snapshot_recursive', 'tst.snapshot_rename', 'tst.snapshot_simple',
'tst.bookmark.create', 'tst.bookmark.copy',
'tst.terminate_by_signal'
]
@@ -122,16 +153,23 @@ tests = [ 'clean_mirror_001_pos', 'clean_mirror_002_pos',
'clean_mirror_003_pos', 'clean_mirror_004_pos']
tags = ['functional', 'clean_mirror']
+[tests/functional/cli_root/zinject]
+tests = ['zinject_args']
+pre =
+post =
+tags = ['functional', 'cli_root', 'zinject']
+
[tests/functional/cli_root/zdb]
tests = ['zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos', 'zdb_005_pos',
'zdb_006_pos', 'zdb_args_neg', 'zdb_args_pos',
'zdb_block_size_histogram', 'zdb_checksum', 'zdb_decompress',
- 'zdb_display_block', 'zdb_label_checksum', 'zdb_object_range_neg',
- 'zdb_object_range_pos', 'zdb_objset_id', 'zdb_decompress_zstd',
- 'zdb_recover', 'zdb_recover_2']
+ 'zdb_display_block', 'zdb_encrypted', 'zdb_label_checksum',
+ 'zdb_object_range_neg', 'zdb_object_range_pos', 'zdb_objset_id',
+ 'zdb_decompress_zstd', 'zdb_recover', 'zdb_recover_2', 'zdb_backup']
pre =
post =
tags = ['functional', 'cli_root', 'zdb']
+timeout = 1200
[tests/functional/cli_root/zfs]
tests = ['zfs_001_neg', 'zfs_002_pos']
@@ -151,7 +189,8 @@ tags = ['functional', 'cli_root', 'zfs_change-key']
tests = ['zfs_clone_001_neg', 'zfs_clone_002_pos', 'zfs_clone_003_pos',
'zfs_clone_004_pos', 'zfs_clone_005_pos', 'zfs_clone_006_pos',
'zfs_clone_007_pos', 'zfs_clone_008_neg', 'zfs_clone_009_neg',
- 'zfs_clone_010_pos', 'zfs_clone_encrypted', 'zfs_clone_deeply_nested']
+ 'zfs_clone_010_pos', 'zfs_clone_encrypted', 'zfs_clone_deeply_nested',
+ 'zfs_clone_rm_nested']
tags = ['functional', 'cli_root', 'zfs_clone']
[tests/functional/cli_root/zfs_copies]
@@ -213,7 +252,7 @@ tests = ['zfs_mount_001_pos', 'zfs_mount_002_pos', 'zfs_mount_003_pos',
'zfs_mount_009_neg', 'zfs_mount_010_neg', 'zfs_mount_011_neg',
'zfs_mount_012_pos', 'zfs_mount_all_001_pos', 'zfs_mount_encrypted',
'zfs_mount_remount', 'zfs_mount_all_fail', 'zfs_mount_all_mountpoints',
- 'zfs_mount_test_race']
+ 'zfs_mount_test_race', 'zfs_mount_recursive']
tags = ['functional', 'cli_root', 'zfs_mount']
[tests/functional/cli_root/zfs_program]
@@ -241,7 +280,8 @@ tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
'zfs_receive_from_encrypted', 'zfs_receive_to_encrypted',
'zfs_receive_raw', 'zfs_receive_raw_incremental', 'zfs_receive_-e',
'zfs_receive_raw_-d', 'zfs_receive_from_zstd', 'zfs_receive_new_props',
- 'zfs_receive_-wR-encrypted-mix']
+ 'zfs_receive_-wR-encrypted-mix', 'zfs_receive_corrective',
+ 'zfs_receive_compressed_corrective', 'zfs_receive_large_block_corrective']
tags = ['functional', 'cli_root', 'zfs_receive']
[tests/functional/cli_root/zfs_rename]
@@ -265,8 +305,8 @@ tags = ['functional', 'cli_root', 'zfs_rollback']
[tests/functional/cli_root/zfs_send]
tests = ['zfs_send_001_pos', 'zfs_send_002_pos', 'zfs_send_003_pos',
'zfs_send_004_neg', 'zfs_send_005_pos', 'zfs_send_006_pos',
- 'zfs_send_007_pos', 'zfs_send_encrypted', 'zfs_send_raw',
- 'zfs_send_sparse', 'zfs_send-b', 'zfs_send_skip_missing']
+ 'zfs_send_007_pos', 'zfs_send_encrypted', 'zfs_send_encrypted_unloaded',
+ 'zfs_send_raw', 'zfs_send_sparse', 'zfs_send-b', 'zfs_send_skip_missing']
tags = ['functional', 'cli_root', 'zfs_send']
[tests/functional/cli_root/zfs_set]
@@ -279,13 +319,14 @@ tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
'user_property_004_pos', 'version_001_neg', 'zfs_set_001_neg',
'zfs_set_002_neg', 'zfs_set_003_neg', 'property_alias_001_pos',
'mountpoint_003_pos', 'ro_props_001_pos', 'zfs_set_keylocation',
- 'zfs_set_feature_activation']
+ 'zfs_set_feature_activation', 'zfs_set_nomount']
tags = ['functional', 'cli_root', 'zfs_set']
[tests/functional/cli_root/zfs_share]
tests = ['zfs_share_001_pos', 'zfs_share_002_pos', 'zfs_share_003_pos',
'zfs_share_004_pos', 'zfs_share_006_pos', 'zfs_share_008_neg',
- 'zfs_share_010_neg', 'zfs_share_011_pos', 'zfs_share_concurrent_shares']
+ 'zfs_share_010_neg', 'zfs_share_011_pos', 'zfs_share_concurrent_shares',
+ 'zfs_share_after_mount']
tags = ['functional', 'cli_root', 'zfs_share']
[tests/functional/cli_root/zfs_snapshot]
@@ -309,7 +350,7 @@ tags = ['functional', 'cli_root', 'zfs_unmount']
[tests/functional/cli_root/zfs_unshare]
tests = ['zfs_unshare_001_pos', 'zfs_unshare_002_pos', 'zfs_unshare_003_pos',
'zfs_unshare_004_neg', 'zfs_unshare_005_neg', 'zfs_unshare_006_pos',
- 'zfs_unshare_007_pos', 'zfs_unshare_008_pos']
+ 'zfs_unshare_007_pos']
tags = ['functional', 'cli_root', 'zfs_unshare']
[tests/functional/cli_root/zfs_upgrade]
@@ -323,7 +364,8 @@ tests = ['zfs_wait_deleteq', 'zfs_wait_getsubopt']
tags = ['functional', 'cli_root', 'zfs_wait']
[tests/functional/cli_root/zhack]
-tests = ['zhack_label_checksum']
+tests = ['zhack_label_repair_001', 'zhack_label_repair_002',
+ 'zhack_label_repair_003', 'zhack_label_repair_004']
pre =
post =
tags = ['functional', 'cli_root', 'zhack']
@@ -336,7 +378,8 @@ tags = ['functional', 'cli_root', 'zpool']
tests = ['zpool_add_001_pos', 'zpool_add_002_pos', 'zpool_add_003_pos',
'zpool_add_004_pos', 'zpool_add_006_pos', 'zpool_add_007_neg',
'zpool_add_008_neg', 'zpool_add_009_neg', 'zpool_add_010_pos',
- 'add-o_ashift', 'add_prop_ashift', 'zpool_add_dryrun_output']
+ 'add-o_ashift', 'add_prop_ashift', 'zpool_add_dryrun_output',
+ 'zpool_add--allow-ashift-mismatch']
tags = ['functional', 'cli_root', 'zpool_add']
[tests/functional/cli_root/zpool_attach]
@@ -392,7 +435,7 @@ tags = ['functional', 'cli_root', 'zpool_export']
[tests/functional/cli_root/zpool_get]
tests = ['zpool_get_001_pos', 'zpool_get_002_pos', 'zpool_get_003_pos',
- 'zpool_get_004_neg', 'zpool_get_005_pos']
+ 'zpool_get_004_neg', 'zpool_get_005_pos', 'vdev_get_001_pos']
tags = ['functional', 'cli_root', 'zpool_get']
[tests/functional/cli_root/zpool_history]
@@ -419,10 +462,12 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos',
'import_cachefile_mirror_detached',
'import_cachefile_paths_changed',
'import_cachefile_shared_device',
- 'import_devices_missing',
+ 'import_devices_missing', 'import_log_missing',
'import_paths_changed',
'import_rewind_config_changed',
- 'import_rewind_device_replaced']
+ 'import_rewind_device_replaced',
+ 'zpool_import_status', 'zpool_import_parallel_pos',
+ 'zpool_import_parallel_neg', 'zpool_import_parallel_admin']
tags = ['functional', 'cli_root', 'zpool_import']
timeout = 1200
@@ -443,6 +488,7 @@ tests = ['zpool_initialize_attach_detach_add_remove',
'zpool_initialize_start_and_cancel_neg',
'zpool_initialize_start_and_cancel_pos',
'zpool_initialize_suspend_resume',
+ 'zpool_initialize_uninit',
'zpool_initialize_unsupported_vdevs',
'zpool_initialize_verify_checksums',
'zpool_initialize_verify_initialized']
@@ -468,19 +514,23 @@ tests = ['zpool_replace_001_neg', 'replace-o_ashift', 'replace_prop_ashift']
tags = ['functional', 'cli_root', 'zpool_replace']
[tests/functional/cli_root/zpool_resilver]
-tests = ['zpool_resilver_bad_args', 'zpool_resilver_restart']
+tests = ['zpool_resilver_bad_args', 'zpool_resilver_restart',
+ 'zpool_resilver_concurrent']
tags = ['functional', 'cli_root', 'zpool_resilver']
[tests/functional/cli_root/zpool_scrub]
tests = ['zpool_scrub_001_neg', 'zpool_scrub_002_pos', 'zpool_scrub_003_pos',
'zpool_scrub_004_pos', 'zpool_scrub_005_pos',
'zpool_scrub_encrypted_unloaded', 'zpool_scrub_print_repairing',
- 'zpool_scrub_offline_device', 'zpool_scrub_multiple_copies']
+ 'zpool_scrub_offline_device', 'zpool_scrub_multiple_copies',
+ 'zpool_error_scrub_001_pos', 'zpool_error_scrub_002_pos',
+ 'zpool_error_scrub_003_pos', 'zpool_error_scrub_004_pos']
tags = ['functional', 'cli_root', 'zpool_scrub']
[tests/functional/cli_root/zpool_set]
tests = ['zpool_set_001_pos', 'zpool_set_002_neg', 'zpool_set_003_neg',
- 'zpool_set_ashift', 'zpool_set_features']
+ 'zpool_set_ashift', 'zpool_set_features', 'vdev_set_001_pos',
+ 'user_property_001_pos', 'user_property_002_neg']
tags = ['functional', 'cli_root', 'zpool_set']
[tests/functional/cli_root/zpool_split]
@@ -493,6 +543,8 @@ tags = ['functional', 'cli_root', 'zpool_split']
[tests/functional/cli_root/zpool_status]
tests = ['zpool_status_001_pos', 'zpool_status_002_pos',
'zpool_status_003_pos', 'zpool_status_004_pos',
+ 'zpool_status_005_pos', 'zpool_status_006_pos',
+ 'zpool_status_007_pos', 'zpool_status_008_pos',
'zpool_status_features_001_pos']
tags = ['functional', 'cli_root', 'zpool_status']
@@ -550,7 +602,8 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg',
'zpool_offline_001_neg', 'zpool_online_001_neg', 'zpool_remove_001_neg',
'zpool_replace_001_neg', 'zpool_scrub_001_neg', 'zpool_set_001_neg',
'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'arcstat_001_pos',
- 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege']
+ 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege',
+ 'zilstat_001_pos']
user =
tags = ['functional', 'cli_user', 'misc']
@@ -587,9 +640,13 @@ tests = ['compress_001_pos', 'compress_002_pos', 'compress_003_pos',
tags = ['functional', 'compression']
[tests/functional/cp_files]
-tests = ['cp_files_001_pos']
+tests = ['cp_files_001_pos', 'cp_files_002_pos', 'cp_stress']
tags = ['functional', 'cp_files']
+[tests/functional/zap_shrink]
+tests = ['zap_shrink_001_pos']
+tags = ['functional', 'zap_shrink']
+
[tests/functional/crtime]
tests = ['crtime_001_pos' ]
tags = ['functional', 'crtime']
@@ -685,7 +742,8 @@ tests = ['migration_001_pos', 'migration_002_pos', 'migration_003_pos',
tags = ['functional', 'migration']
[tests/functional/mmap]
-tests = ['mmap_write_001_pos', 'mmap_read_001_pos', 'mmap_seek_001_pos', 'mmap_sync_001_pos']
+tests = ['mmap_mixed', 'mmap_read_001_pos', 'mmap_seek_001_pos',
+ 'mmap_sync_001_pos', 'mmap_write_001_pos']
tags = ['functional', 'mmap']
[tests/functional/mount]
@@ -702,7 +760,7 @@ tags = ['functional', 'nestedfs']
[tests/functional/no_space]
tests = ['enospc_001_pos', 'enospc_002_pos', 'enospc_003_pos',
- 'enospc_df', 'enospc_rm']
+ 'enospc_df', 'enospc_ganging', 'enospc_rm']
tags = ['functional', 'no_space']
[tests/functional/nopwrite]
@@ -758,8 +816,12 @@ tests = ['redacted_compressed', 'redacted_contents', 'redacted_deleted',
tags = ['functional', 'redacted_send']
[tests/functional/raidz]
-tests = ['raidz_001_neg', 'raidz_002_pos', 'raidz_003_pos', 'raidz_004_pos']
+tests = ['raidz_001_neg', 'raidz_002_pos', 'raidz_expand_001_pos',
+ 'raidz_expand_002_pos', 'raidz_expand_003_neg', 'raidz_expand_003_pos',
+ 'raidz_expand_004_pos', 'raidz_expand_005_pos', 'raidz_expand_006_neg',
+ 'raidz_expand_007_neg']
tags = ['functional', 'raidz']
+timeout = 1200
[tests/functional/redundancy]
tests = ['redundancy_draid', 'redundancy_draid1', 'redundancy_draid2',
@@ -790,13 +852,13 @@ tests = ['removal_all_vdev', 'removal_cancel', 'removal_check_space',
'removal_nopwrite', 'removal_remap_deadlists',
'removal_resume_export', 'removal_sanity', 'removal_with_add',
'removal_with_create_fs', 'removal_with_dedup',
- 'removal_with_errors', 'removal_with_export',
+ 'removal_with_errors', 'removal_with_export', 'removal_with_indirect',
'removal_with_ganging', 'removal_with_faulted',
'removal_with_remove', 'removal_with_scrub', 'removal_with_send',
'removal_with_send_recv', 'removal_with_snapshot',
'removal_with_write', 'removal_with_zdb', 'remove_expanded',
'remove_mirror', 'remove_mirror_sanity', 'remove_raidz',
- 'remove_indirect', 'remove_attach_mirror']
+ 'remove_indirect', 'remove_attach_mirror', 'removal_reservation']
tags = ['functional', 'removal']
[tests/functional/rename_dirs]
@@ -834,18 +896,20 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos',
'rsend_014_pos', 'rsend_016_neg', 'rsend_019_pos', 'rsend_020_pos',
'rsend_021_pos', 'rsend_022_pos', 'rsend_024_pos', 'rsend_025_pos',
'rsend_026_neg', 'rsend_027_pos', 'rsend_028_neg', 'rsend_029_neg',
- 'send-c_verify_ratio', 'send-c_verify_contents', 'send-c_props',
- 'send-c_incremental', 'send-c_volume', 'send-c_zstreamdump',
+ 'rsend_030_pos', 'rsend_031_pos', 'send-c_verify_ratio',
+ 'send-c_verify_contents', 'send-c_props', 'send-c_incremental',
+ 'send-c_volume', 'send-c_zstream_recompress', 'send-c_zstreamdump',
'send-c_lz4_disabled', 'send-c_recv_lz4_disabled',
'send-c_mixed_compression', 'send-c_stream_size_estimate',
'send-c_embedded_blocks', 'send-c_resume', 'send-cpL_varied_recsize',
- 'send-c_recv_dedup', 'send-L_toggle', 'send_encrypted_hierarchy',
+ 'send-c_recv_dedup', 'send-L_toggle', 'send_encrypted_incremental',
+ 'send_encrypted_freeobjects', 'send_encrypted_hierarchy',
'send_encrypted_props', 'send_encrypted_truncated_files',
- 'send_freeobjects', 'send_realloc_files',
- 'send_realloc_encrypted_files', 'send_spill_block', 'send_holds',
- 'send_hole_birth', 'send_mixed_raw', 'send-wR_encrypted_zvol',
- 'send_partial_dataset', 'send_invalid', 'send_doall',
- 'send_raw_spill_block', 'send_raw_ashift']
+ 'send_freeobjects', 'send_realloc_files', 'send_realloc_encrypted_files',
+ 'send_spill_block', 'send_holds', 'send_hole_birth', 'send_mixed_raw',
+ 'send-wR_encrypted_zvol', 'send_partial_dataset', 'send_invalid',
+ 'send_doall', 'send_raw_spill_block', 'send_raw_ashift',
+ 'send_raw_large_blocks']
tags = ['functional', 'rsend']
[tests/functional/scrub_mirror]
@@ -868,7 +932,7 @@ tests = ['clone_001_pos', 'rollback_001_pos', 'rollback_002_pos',
'snapshot_006_pos', 'snapshot_007_pos', 'snapshot_008_pos',
'snapshot_009_pos', 'snapshot_010_pos', 'snapshot_011_pos',
'snapshot_012_pos', 'snapshot_013_pos', 'snapshot_014_pos',
- 'snapshot_017_pos']
+ 'snapshot_017_pos', 'snapshot_018_pos']
tags = ['functional', 'snapshot']
[tests/functional/snapused]
@@ -909,9 +973,15 @@ tests = [
'userquota_007_pos', 'userquota_008_pos', 'userquota_009_pos',
'userquota_010_pos', 'userquota_011_pos', 'userquota_012_neg',
'userspace_001_pos', 'userspace_002_pos', 'userspace_encrypted',
- 'userspace_send_encrypted']
+ 'userspace_send_encrypted', 'userspace_encrypted_13709']
tags = ['functional', 'userquota']
+[tests/functional/vdev_disk:Linux]
+pre =
+post =
+tests = ['page_alignment']
+tags = ['functional', 'vdev_disk']
+
[tests/functional/vdev_zaps]
tests = ['vdev_zaps_001_pos', 'vdev_zaps_002_pos', 'vdev_zaps_003_pos',
'vdev_zaps_004_pos', 'vdev_zaps_005_pos', 'vdev_zaps_006_pos',
diff --git a/tests/runfiles/freebsd.run b/tests/runfiles/freebsd.run
index c7ca1d769fc3..13696d645850 100644
--- a/tests/runfiles/freebsd.run
+++ b/tests/runfiles/freebsd.run
@@ -25,3 +25,8 @@ tags = ['functional']
[tests/functional/cli_root/zfs_jail:FreeBSD]
tests = ['zfs_jail_001_pos']
tags = ['functional', 'cli_root', 'zfs_jail']
+
+[tests/functional/pam:FreeBSD]
+tests = ['pam_basic', 'pam_change_unmounted', 'pam_nounmount', 'pam_recursive',
+ 'pam_short_password']
+tags = ['functional', 'pam']
diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
index 9b32e73afb1e..92ce09ec6fcb 100644
--- a/tests/runfiles/linux.run
+++ b/tests/runfiles/linux.run
@@ -34,6 +34,12 @@ tags = ['functional', 'acl', 'posix-sa']
tests = ['atime_003_pos', 'root_relatime_on']
tags = ['functional', 'atime']
+[tests/functional/block_cloning:Linux]
+tests = ['block_cloning_ficlone', 'block_cloning_ficlonerange',
+ 'block_cloning_ficlonerange_partial', 'block_cloning_disabled_ficlone',
+ 'block_cloning_disabled_ficlonerange']
+tags = ['functional', 'block_cloning']
+
[tests/functional/chattr:Linux]
tests = ['chattr_001_pos', 'chattr_002_neg']
tags = ['functional', 'chattr']
@@ -52,6 +58,10 @@ tests = ['zfs_share_005_pos', 'zfs_share_007_neg', 'zfs_share_009_neg',
'zfs_share_012_pos', 'zfs_share_013_pos']
tags = ['functional', 'cli_root', 'zfs_share']
+[tests/functional/cli_root/zfs_unshare:Linux]
+tests = ['zfs_unshare_008_pos']
+tags = ['functional', 'cli_root', 'zfs_unshare']
+
[tests/functional/cli_root/zfs_sysfs:Linux]
tests = ['zfeature_set_unsupported', 'zfs_get_unsupported',
'zfs_set_unsupported', 'zfs_sysfs_live', 'zpool_get_unsupported',
@@ -67,6 +77,13 @@ tests = ['zpool_expand_001_pos', 'zpool_expand_002_pos',
'zpool_expand_003_neg', 'zpool_expand_004_pos', 'zpool_expand_005_pos']
tags = ['functional', 'cli_root', 'zpool_expand']
+[tests/functional/cli_root/zpool_import:Linux]
+tests = ['zpool_import_hostid_changed',
+ 'zpool_import_hostid_changed_unclean_export',
+ 'zpool_import_hostid_changed_cachefile',
+ 'zpool_import_hostid_changed_cachefile_unclean_export']
+tags = ['functional', 'cli_root', 'zpool_import']
+
[tests/functional/cli_root/zpool_reopen:Linux]
tests = ['zpool_reopen_001_pos', 'zpool_reopen_002_pos',
'zpool_reopen_003_pos', 'zpool_reopen_004_pos', 'zpool_reopen_005_pos',
@@ -86,19 +103,25 @@ tests = ['devices_001_pos', 'devices_002_neg', 'devices_003_pos']
tags = ['functional', 'devices']
[tests/functional/events:Linux]
-tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill']
+tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill',
+ 'zed_cksum_reported', 'zed_cksum_config', 'zed_io_config',
+ 'zed_slow_io', 'zed_slow_io_many_vdevs']
tags = ['functional', 'events']
+[tests/functional/fadvise:Linux]
+tests = ['fadvise_sequential']
+tags = ['functional', 'fadvise']
+
[tests/functional/fallocate:Linux]
tests = ['fallocate_prealloc', 'fallocate_zero-range']
tags = ['functional', 'fallocate']
[tests/functional/fault:Linux]
tests = ['auto_offline_001_pos', 'auto_online_001_pos', 'auto_online_002_pos',
- 'auto_replace_001_pos', 'auto_spare_001_pos', 'auto_spare_002_pos',
- 'auto_spare_multiple', 'auto_spare_ashift', 'auto_spare_shared',
- 'decrypt_fault', 'decompress_fault', 'scrub_after_resilver',
- 'zpool_status_-s']
+ 'auto_replace_001_pos', 'auto_replace_002_pos', 'auto_spare_001_pos',
+ 'auto_spare_002_pos', 'auto_spare_multiple', 'auto_spare_ashift',
+ 'auto_spare_shared', 'decrypt_fault', 'decompress_fault',
+ 'scrub_after_resilver', 'zpool_status_-s']
tags = ['functional', 'fault']
[tests/functional/features/large_dnode:Linux]
@@ -116,14 +139,14 @@ post =
tags = ['functional', 'largest_pool']
[tests/functional/mmap:Linux]
-tests = ['mmap_libaio_001_pos']
+tests = ['mmap_libaio_001_pos', 'mmap_sync_001_pos']
tags = ['functional', 'mmap']
[tests/functional/mmp:Linux]
tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval',
'mmp_active_import', 'mmp_inactive_import', 'mmp_exported_import',
'mmp_write_uberblocks', 'mmp_reset_interval', 'multihost_history',
- 'mmp_on_zdb', 'mmp_write_distribution', 'mmp_hostid']
+ 'mmp_on_zdb', 'mmp_write_distribution', 'mmp_hostid', 'mmp_write_slow_disk']
tags = ['functional', 'mmp']
[tests/functional/mount:Linux]
@@ -131,7 +154,8 @@ tests = ['umount_unlinked_drain']
tags = ['functional', 'mount']
[tests/functional/pam:Linux]
-tests = ['pam_basic', 'pam_nounmount', 'pam_short_password']
+tests = ['pam_basic', 'pam_change_unmounted', 'pam_nounmount', 'pam_recursive',
+ 'pam_short_password']
tags = ['functional', 'pam']
[tests/functional/procfs:Linux]
@@ -153,6 +177,10 @@ tags = ['functional', 'projectquota']
tests = ['read_dos_attrs_001', 'write_dos_attrs_001']
tags = ['functional', 'dos_attributes']
+[tests/functional/renameat2:Linux]
+tests = ['renameat2_noreplace', 'renameat2_exchange', 'renameat2_whiteout']
+tags = ['functional', 'renameat2']
+
[tests/functional/rsend:Linux]
tests = ['send_realloc_dnode_size', 'send_encrypted_files']
tags = ['functional', 'rsend']
@@ -190,3 +218,7 @@ tags = ['functional', 'userquota']
tests = ['zvol_misc_fua']
tags = ['functional', 'zvol', 'zvol_misc']
+[tests/functional/idmap_mount:Linux]
+tests = ['idmap_mount_001', 'idmap_mount_002', 'idmap_mount_003',
+ 'idmap_mount_004', 'idmap_mount_005']
+tags = ['functional', 'idmap_mount']
diff --git a/tests/runfiles/sanity.run b/tests/runfiles/sanity.run
index f5dcfa5be4b7..d6a791e3375d 100644
--- a/tests/runfiles/sanity.run
+++ b/tests/runfiles/sanity.run
@@ -155,7 +155,8 @@ tests = ['zfs_mount_001_pos', 'zfs_mount_002_pos', 'zfs_mount_003_pos',
'zfs_mount_004_pos', 'zfs_mount_005_pos', 'zfs_mount_007_pos',
'zfs_mount_009_neg', 'zfs_mount_010_neg', 'zfs_mount_011_neg',
'zfs_mount_012_pos', 'zfs_mount_encrypted', 'zfs_mount_remount',
- 'zfs_mount_all_fail', 'zfs_mount_all_mountpoints', 'zfs_mount_test_race']
+ 'zfs_mount_all_fail', 'zfs_mount_all_mountpoints',
+ 'zfs_mount_test_race', 'zfs_mount_recursive']
tags = ['functional', 'cli_root', 'zfs_mount']
[tests/functional/cli_root/zfs_program]
@@ -212,7 +213,7 @@ tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
'user_property_001_pos', 'user_property_003_neg', 'readonly_001_pos',
'user_property_004_pos', 'version_001_neg',
'zfs_set_003_neg', 'property_alias_001_pos',
- 'zfs_set_keylocation', 'zfs_set_feature_activation']
+ 'zfs_set_keylocation', 'zfs_set_feature_activation', 'zfs_set_nomount']
tags = ['functional', 'cli_root', 'zfs_set']
[tests/functional/cli_root/zfs_snapshot]
@@ -396,7 +397,8 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg',
'zpool_history_001_neg', 'zpool_offline_001_neg', 'zpool_online_001_neg',
'zpool_remove_001_neg', 'zpool_scrub_001_neg', 'zpool_set_001_neg',
'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'arcstat_001_pos',
- 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege']
+ 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege',
+ 'zilstat_001_pos']
user =
tags = ['functional', 'cli_user', 'misc']
@@ -549,6 +551,7 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos',
'rsend_014_pos', 'rsend_016_neg', 'send-c_verify_contents',
'send-c_volume', 'send-c_zstreamdump', 'send-c_recv_dedup',
'send-L_toggle', 'send_encrypted_hierarchy', 'send_encrypted_props',
+ 'send_encrypted_freeobjects',
'send_encrypted_truncated_files', 'send_freeobjects', 'send_holds',
'send_mixed_raw', 'send-wR_encrypted_zvol', 'send_partial_dataset',
'send_invalid']
@@ -568,7 +571,8 @@ tests = ['clone_001_pos', 'rollback_001_pos', 'rollback_002_pos',
'snapshot_004_pos', 'snapshot_005_pos', 'snapshot_006_pos',
'snapshot_007_pos', 'snapshot_008_pos', 'snapshot_009_pos',
'snapshot_010_pos', 'snapshot_011_pos', 'snapshot_012_pos',
- 'snapshot_013_pos', 'snapshot_014_pos', 'snapshot_017_pos']
+ 'snapshot_013_pos', 'snapshot_014_pos', 'snapshot_017_pos',
+ 'snapshot_018_pos']
tags = ['functional', 'snapshot']
[tests/functional/snapused]
@@ -596,6 +600,12 @@ tags = ['functional', 'truncate']
tests = ['upgrade_userobj_001_pos', 'upgrade_readonly_pool']
tags = ['functional', 'upgrade']
+[tests/functional/vdev_disk:Linux]
+pre =
+post =
+tests = ['page_alignment']
+tags = ['functional', 'vdev_disk']
+
[tests/functional/vdev_zaps]
tests = ['vdev_zaps_001_pos', 'vdev_zaps_003_pos', 'vdev_zaps_004_pos',
'vdev_zaps_005_pos', 'vdev_zaps_006_pos']
@@ -622,3 +632,9 @@ tags = ['functional', 'zvol', 'zvol_swap']
[tests/functional/zpool_influxdb]
tests = ['zpool_influxdb']
tags = ['functional', 'zpool_influxdb']
+
+[tests/functional/pyzfs]
+tests = ['pyzfs_unittest']
+pre =
+post =
+tags = ['functional', 'pyzfs']
diff --git a/tests/test-runner/bin/test-runner.py.in b/tests/test-runner/bin/test-runner.py.in
index cb453b266f3c..65247f4f06fc 100755
--- a/tests/test-runner/bin/test-runner.py.in
+++ b/tests/test-runner/bin/test-runner.py.in
@@ -47,25 +47,25 @@ LOG_OUT = 'LOG_OUT'
LOG_ERR = 'LOG_ERR'
LOG_FILE_OBJ = None
+try:
+ from time import monotonic as monotonic_time
+except ImportError:
+ class timespec(ctypes.Structure):
+ _fields_ = [
+ ('tv_sec', ctypes.c_long),
+ ('tv_nsec', ctypes.c_long)
+ ]
-class timespec(ctypes.Structure):
- _fields_ = [
- ('tv_sec', ctypes.c_long),
- ('tv_nsec', ctypes.c_long)
- ]
-
-
-librt = ctypes.CDLL('librt.so.1', use_errno=True)
-clock_gettime = librt.clock_gettime
-clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
-
+ librt = ctypes.CDLL('librt.so.1', use_errno=True)
+ clock_gettime = librt.clock_gettime
+ clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
-def monotonic_time():
- t = timespec()
- if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
- errno_ = ctypes.get_errno()
- raise OSError(errno_, os.strerror(errno_))
- return t.tv_sec + t.tv_nsec * 1e-9
+ def monotonic_time():
+ t = timespec()
+ if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
+ errno_ = ctypes.get_errno()
+ raise OSError(errno_, os.strerror(errno_))
+ return t.tv_sec + t.tv_nsec * 1e-9
class Result(object):
@@ -113,8 +113,9 @@ class Output(object):
This class is a slightly modified version of the 'Stream' class found
here: http://goo.gl/aSGfv
"""
- def __init__(self, stream):
+ def __init__(self, stream, debug=False):
self.stream = stream
+ self.debug = debug
self._buf = b''
self.lines = []
@@ -140,6 +141,8 @@ class Output(object):
buf = os.read(fd, 4096)
if not buf:
return None
+ if self.debug:
+ os.write(sys.stderr.fileno(), buf)
if b'\n' not in buf:
self._buf += buf
return []
@@ -181,7 +184,7 @@ Timeout: %d
User: %s
''' % (self.pathname, self.identifier, self.outputdir, self.timeout, self.user)
- def kill_cmd(self, proc, keyboard_interrupt=False):
+ def kill_cmd(self, proc, options, kmemleak, keyboard_interrupt=False):
"""
Kill a running command due to timeout, or ^C from the keyboard. If
sudo is required, this user was verified previously.
@@ -211,7 +214,7 @@ User: %s
if int(self.timeout) > runtime:
self.killed = False
self.reran = False
- self.run(False)
+ self.run(options, dryrun=False, kmemleak=kmemleak)
self.reran = True
def update_cmd_privs(self, cmd, user):
@@ -238,14 +241,14 @@ User: %s
ret = '%s -E -u %s %s' % (SUDO, user, cmd)
return ret.split(' ')
- def collect_output(self, proc):
+ def collect_output(self, proc, debug=False):
"""
Read from stdout/stderr as data becomes available, until the
process is no longer running. Return the lines from the stdout and
stderr Output objects.
"""
- out = Output(proc.stdout)
- err = Output(proc.stderr)
+ out = Output(proc.stdout, debug)
+ err = Output(proc.stderr, debug)
res = []
while proc.returncode is None:
proc.poll()
@@ -257,15 +260,19 @@ User: %s
return out.lines, err.lines
- def run(self, dryrun, kmemleak, kmsg):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
This is the main function that runs each individual test.
Determine whether or not the command requires sudo, and modify it
if needed. Run the command, and update the result object.
"""
+ if dryrun is None:
+ dryrun = options.dryrun
if dryrun is True:
print(self)
return
+ if kmemleak is None:
+ kmemleak = options.kmemleak
privcmd = self.update_cmd_privs(self.pathname, self.user)
try:
@@ -280,7 +287,7 @@ User: %s
Log each test we run to /dev/kmsg (on Linux), so if there's a kernel
warning we'll be able to match it up to a particular test.
"""
- if kmsg is True and exists("/dev/kmsg"):
+ if options.kmsg is True and exists("/dev/kmsg"):
try:
kp = Popen([SUDO, "sh", "-c",
f"echo ZTS run {self.pathname} > /dev/kmsg"])
@@ -297,12 +304,17 @@ User: %s
proc = Popen(privcmd, stdout=PIPE, stderr=PIPE)
# Allow a special timeout value of 0 to mean infinity
if int(self.timeout) == 0:
- self.timeout = sys.maxsize
- t = Timer(int(self.timeout), self.kill_cmd, [proc])
+ self.timeout = sys.maxsize / (10 ** 9)
+ t = Timer(
+ int(self.timeout), self.kill_cmd, [proc, options, kmemleak]
+ )
try:
t.start()
- self.result.stdout, self.result.stderr = self.collect_output(proc)
+
+ out, err = self.collect_output(proc, options.debug)
+ self.result.stdout = out
+ self.result.stderr = err
if kmemleak:
cmd = f'{SUDO} sh -c "echo scan > {KMEMLEAK_FILE}"'
@@ -310,7 +322,7 @@ User: %s
cmd = f'{SUDO} cat {KMEMLEAK_FILE}'
self.result.kmemleak = check_output(cmd, shell=True)
except KeyboardInterrupt:
- self.kill_cmd(proc, True)
+ self.kill_cmd(proc, options, kmemleak, True)
fail('\nRun terminated at user request.')
finally:
t.cancel()
@@ -450,7 +462,7 @@ Tags: %s
return True
- def run(self, options):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
Create Cmd instances for the pre/post/failsafe scripts. If the pre
script doesn't pass, skip this Test. Run the post script regardless.
@@ -472,14 +484,14 @@ Tags: %s
cont = True
if len(pretest.pathname):
- pretest.run(options.dryrun, False, options.kmsg)
+ pretest.run(options, kmemleak=False)
cont = pretest.result.result == 'PASS'
pretest.log(options)
if cont:
- test.run(options.dryrun, options.kmemleak, options.kmsg)
+ test.run(options, kmemleak=kmemleak)
if test.result.result == 'KILLED' and len(failsafe.pathname):
- failsafe.run(options.dryrun, False, options.kmsg)
+ failsafe.run(options, kmemleak=False)
failsafe.log(options, suppress_console=True)
else:
test.skip()
@@ -487,7 +499,7 @@ Tags: %s
test.log(options)
if len(posttest.pathname):
- posttest.run(options.dryrun, False, options.kmsg)
+ posttest.run(options, kmemleak=False)
posttest.log(options)
@@ -571,7 +583,7 @@ Tags: %s
return len(self.tests) != 0
- def run(self, options):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
Create Cmd instances for the pre/post/failsafe scripts. If the pre
script doesn't pass, skip all the tests in this TestGroup. Run the
@@ -590,7 +602,7 @@ Tags: %s
cont = True
if len(pretest.pathname):
- pretest.run(options.dryrun, False, options.kmsg)
+ pretest.run(options, dryrun=dryrun, kmemleak=False)
cont = pretest.result.result == 'PASS'
pretest.log(options)
@@ -603,9 +615,9 @@ Tags: %s
failsafe = Cmd(self.failsafe, outputdir=odir, timeout=self.timeout,
user=self.failsafe_user, identifier=self.identifier)
if cont:
- test.run(options.dryrun, options.kmemleak, options.kmsg)
+ test.run(options, dryrun=dryrun, kmemleak=kmemleak)
if test.result.result == 'KILLED' and len(failsafe.pathname):
- failsafe.run(options.dryrun, False, options.kmsg)
+ failsafe.run(options, dryrun=dryrun, kmemleak=False)
failsafe.log(options, suppress_console=True)
else:
test.skip()
@@ -613,12 +625,12 @@ Tags: %s
test.log(options)
if len(posttest.pathname):
- posttest.run(options.dryrun, False, options.kmsg)
+ posttest.run(options, dryrun=dryrun, kmemleak=False)
posttest.log(options)
class TestRun(object):
- props = ['quiet', 'outputdir']
+ props = ['quiet', 'outputdir', 'debug']
def __init__(self, options):
self.tests = {}
@@ -638,7 +650,8 @@ class TestRun(object):
('post_user', ''),
('failsafe', ''),
('failsafe_user', ''),
- ('tags', [])
+ ('tags', []),
+ ('debug', False)
]
def __str__(self):
@@ -1061,6 +1074,8 @@ def parse_args():
help='Specify tests to run via config files.')
parser.add_option('-d', action='store_true', default=False, dest='dryrun',
help='Dry run. Print tests, but take no other action.')
+ parser.add_option('-D', action='store_true', default=False, dest='debug',
+ help='Write all test output to stdout as it arrives.')
parser.add_option('-l', action='callback', callback=options_cb,
default=None, dest='logfile', metavar='logfile',
type='string',
diff --git a/tests/test-runner/bin/zts-report.py.in b/tests/test-runner/bin/zts-report.py.in
index bf7cf22b61fc..ecc50f487152 100755
--- a/tests/test-runner/bin/zts-report.py.in
+++ b/tests/test-runner/bin/zts-report.py.in
@@ -62,12 +62,9 @@ known_reason = 'Known issue'
exec_reason = 'Test user execute permissions required for utilities'
#
-# Some tests require a minimum python version of 3.6 and will be skipped when
-# the default system version is too old. There may also be tests which require
-# additional python modules be installed, for example python3-cffi is required
-# by the pyzfs tests.
+# Some tests require that the kernel supports renameat2 syscall.
#
-python_deps_reason = 'Python modules missing: python3-cffi'
+renameat2_reason = 'Kernel renameat2 support required'
#
# Some tests require the O_TMPFILE flag which was first introduced in the
@@ -132,6 +129,20 @@ na_reason = "Not applicable"
#
ci_reason = 'CI runner doesn\'t have all requirements'
+#
+# Idmapped mount is only supported in kernel version >= 5.12
+#
+idmap_reason = 'Idmapped mount needs kernel 5.12+'
+
+#
+# copy_file_range() is not supported by all kernels
+#
+cfr_reason = 'Kernel copy_file_range support required'
+
+if sys.platform.startswith('freebsd'):
+ cfr_cross_reason = 'copy_file_range(2) cross-filesystem needs FreeBSD 14+'
+else:
+ cfr_cross_reason = 'copy_file_range(2) cross-filesystem needs kernel 5.3+'
#
# These tests are known to fail, thus we use this list to prevent these
@@ -151,6 +162,7 @@ known = {
['FAIL', rewind_reason],
'cli_user/misc/zfs_share_001_neg': ['SKIP', na_reason],
'cli_user/misc/zfs_unshare_001_neg': ['SKIP', na_reason],
+ 'pool_checkpoint/checkpoint_discard_busy': ['SKIP', 12053],
'privilege/setup': ['SKIP', na_reason],
'refreserv/refreserv_004_pos': ['FAIL', known_reason],
'rootpool/setup': ['SKIP', na_reason],
@@ -162,13 +174,17 @@ if sys.platform.startswith('freebsd'):
known.update({
'cli_root/zfs_receive/receive-o-x_props_override':
['FAIL', known_reason],
+ 'cli_root/zpool_resilver/zpool_resilver_concurrent':
+ ['SKIP', na_reason],
'cli_root/zpool_wait/zpool_wait_trim_basic': ['SKIP', trim_reason],
'cli_root/zpool_wait/zpool_wait_trim_cancel': ['SKIP', trim_reason],
'cli_root/zpool_wait/zpool_wait_trim_flag': ['SKIP', trim_reason],
'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason],
+ 'cp_files/cp_files_002_pos': ['SKIP', na_reason],
'link_count/link_count_001': ['SKIP', na_reason],
'casenorm/mixed_create_failure': ['FAIL', 13215],
'mmap/mmap_sync_001_pos': ['SKIP', na_reason],
+ 'rsend/send_raw_ashift': ['SKIP', 14961],
})
elif sys.platform.startswith('linux'):
known.update({
@@ -193,6 +209,7 @@ elif sys.platform.startswith('linux'):
# reasons listed above can be used.
#
maybe = {
+ 'append/threadsappend_001_pos': ['FAIL', 6136],
'chattr/setup': ['SKIP', exec_reason],
'crtime/crtime_001_pos': ['SKIP', statx_reason],
'cli_root/zdb/zdb_006_pos': ['FAIL', known_reason],
@@ -202,6 +219,7 @@ maybe = {
'cli_root/zfs_get/zfs_get_009_pos': ['SKIP', 5479],
'cli_root/zfs_rollback/zfs_rollback_001_pos': ['FAIL', known_reason],
'cli_root/zfs_rollback/zfs_rollback_002_pos': ['FAIL', known_reason],
+ 'cli_root/zfs_share/zfs_share_concurrent_shares': ['FAIL', known_reason],
'cli_root/zfs_snapshot/zfs_snapshot_002_neg': ['FAIL', known_reason],
'cli_root/zfs_unshare/zfs_unshare_006_pos': ['SKIP', na_reason],
'cli_root/zpool_add/zpool_add_004_pos': ['FAIL', known_reason],
@@ -223,10 +241,11 @@ maybe = {
'io/mmap': ['SKIP', fio_reason],
'largest_pool/largest_pool_001_pos': ['FAIL', known_reason],
'mmp/mmp_on_uberblocks': ['FAIL', known_reason],
- 'pyzfs/pyzfs_unittest': ['SKIP', python_deps_reason],
+ 'pam/setup': ['SKIP', "pamtester might be not available"],
'pool_checkpoint/checkpoint_discard_busy': ['FAIL', 11946],
'projectquota/setup': ['SKIP', exec_reason],
'removal/removal_condense_export': ['FAIL', known_reason],
+ 'renameat2/setup': ['SKIP', renameat2_reason],
'reservation/reservation_008_pos': ['FAIL', 7741],
'reservation/reservation_018_pos': ['FAIL', 5642],
'snapshot/clone_001_pos': ['FAIL', known_reason],
@@ -234,45 +253,110 @@ maybe = {
'snapshot/snapshot_010_pos': ['FAIL', 7961],
'snapused/snapused_004_pos': ['FAIL', 5513],
'tmpfile/setup': ['SKIP', tmpfile_reason],
- 'append/threadsappend_001_pos': ['FAIL', 6136],
'trim/setup': ['SKIP', trim_reason],
'upgrade/upgrade_projectquota_001_pos': ['SKIP', project_id_reason],
'user_namespace/setup': ['SKIP', user_ns_reason],
'userquota/setup': ['SKIP', exec_reason],
+ 'vdev_zaps/vdev_zaps_004_pos': ['FAIL', known_reason],
'zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos': ['FAIL', 5848],
- 'pam/setup': ['SKIP', "pamtester might be not available"],
}
if sys.platform.startswith('freebsd'):
maybe.update({
'cli_root/zfs_copies/zfs_copies_002_pos': ['FAIL', known_reason],
'cli_root/zfs_inherit/zfs_inherit_001_neg': ['FAIL', known_reason],
- 'cli_root/zfs_share/zfs_share_concurrent_shares':
- ['FAIL', known_reason],
'cli_root/zpool_import/zpool_import_012_pos': ['FAIL', known_reason],
'delegate/zfs_allow_003_pos': ['FAIL', known_reason],
'inheritance/inherit_001_pos': ['FAIL', 11829],
- 'resilver/resilver_restart_001': ['FAIL', known_reason],
'pool_checkpoint/checkpoint_big_rewind': ['FAIL', 12622],
'pool_checkpoint/checkpoint_indirect': ['FAIL', 12623],
+ 'resilver/resilver_restart_001': ['FAIL', known_reason],
+ 'snapshot/snapshot_002_pos': ['FAIL', '14831'],
+ 'bclone/bclone_crossfs_corner_cases': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_corner_cases_limited':
+ ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_data': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_embedded': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_hole': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_all': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_checksum': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_compress': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_copies': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_recordsize': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_prop_sync': ['SKIP', cfr_cross_reason],
+ 'block_cloning/block_cloning_cross_enc_dataset':
+ ['SKIP', cfr_cross_reason],
+ 'block_cloning/block_cloning_copyfilerange_cross_dataset':
+ ['SKIP', cfr_cross_reason]
})
elif sys.platform.startswith('linux'):
maybe.update({
+ 'bclone/bclone_crossfs_corner_cases': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_corner_cases_limited':
+ ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_data': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_embedded': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_crossfs_hole': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_all': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_checksum': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_compress': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_copies': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_diffprops_recordsize': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_prop_sync': ['SKIP', cfr_cross_reason],
+ 'bclone/bclone_samefs_corner_cases': ['SKIP', cfr_reason],
+ 'bclone/bclone_samefs_corner_cases_limited': ['SKIP', cfr_reason],
+ 'bclone/bclone_samefs_data': ['SKIP', cfr_reason],
+ 'bclone/bclone_samefs_embedded': ['SKIP', cfr_reason],
+ 'bclone/bclone_samefs_hole': ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_clone_mmap_cached': ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_clone_mmap_write':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_copyfilerange':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_copyfilerange_cross_dataset':
+ ['SKIP', cfr_cross_reason],
+ 'block_cloning/block_cloning_copyfilerange_fallback':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_copyfilerange_fallback_same_txg':
+ ['SKIP', cfr_cross_reason],
+ 'block_cloning/block_cloning_copyfilerange_partial':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_cross_enc_dataset':
+ ['SKIP', cfr_cross_reason],
+ 'block_cloning/block_cloning_disabled_copyfilerange':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_lwb_buffer_overflow':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_replay':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_replay_encrypted':
+ ['SKIP', cfr_reason],
'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason],
'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason],
- 'fault/auto_spare_shared': ['FAIL', 11889],
+ 'cp_files/cp_files_002_pos': ['SKIP', cfr_reason],
+ 'fault/auto_online_002_pos': ['FAIL', 11889],
+ 'fault/auto_replace_001_pos': ['FAIL', 14851],
+ 'fault/auto_spare_002_pos': ['FAIL', 11889],
'fault/auto_spare_multiple': ['FAIL', 11889],
+ 'fault/auto_spare_shared': ['FAIL', 11889],
+ 'fault/decompress_fault': ['FAIL', 11889],
+ 'idmap_mount/idmap_mount_001': ['SKIP', idmap_reason],
+ 'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason],
+ 'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason],
+ 'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason],
+ 'idmap_mount/idmap_mount_005': ['SKIP', idmap_reason],
'io/io_uring': ['SKIP', 'io_uring support required'],
'limits/filesystem_limit': ['SKIP', known_reason],
'limits/snapshot_limit': ['SKIP', known_reason],
'mmp/mmp_active_import': ['FAIL', known_reason],
'mmp/mmp_exported_import': ['FAIL', known_reason],
'mmp/mmp_inactive_import': ['FAIL', known_reason],
+ 'zvol/zvol_misc/zvol_misc_fua': ['SKIP', 14872],
'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', 12621],
+ 'zvol/zvol_misc/zvol_misc_trim': ['SKIP', 14872],
'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason],
})
-
# Not all Github actions runners have scsi_debug module, so we may skip
# some tests which use it.
if os.environ.get('CI') == 'true':
@@ -293,6 +377,7 @@ if os.environ.get('CI') == 'true':
'fault/auto_online_001_pos': ['SKIP', ci_reason],
'fault/auto_online_002_pos': ['SKIP', ci_reason],
'fault/auto_replace_001_pos': ['SKIP', ci_reason],
+ 'fault/auto_replace_002_pos': ['SKIP', ci_reason],
'fault/auto_spare_ashift': ['SKIP', ci_reason],
'fault/auto_spare_shared': ['SKIP', ci_reason],
'procfs/pool_state': ['SKIP', ci_reason],
@@ -310,7 +395,7 @@ def process_results(pathname):
print('Error opening file:', e)
sys.exit(1)
- prefix = '/zfs-tests/tests/functional/'
+ prefix = '/zfs-tests/tests/(?:functional|perf/regression)/'
pattern = \
r'^Test(?:\s+\(\S+\))?:' + \
rf'\s*\S*{prefix}(\S+)' + \
diff --git a/tests/test-runner/include/logapi.shlib b/tests/test-runner/include/logapi.shlib
index 094e8cb21a33..8a9ca3e87caf 100644
--- a/tests/test-runner/include/logapi.shlib
+++ b/tests/test-runner/include/logapi.shlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/Makefile.am b/tests/zfs-tests/Makefile.am
index f8166352489e..40a361d582a2 100644
--- a/tests/zfs-tests/Makefile.am
+++ b/tests/zfs-tests/Makefile.am
@@ -13,6 +13,12 @@ scripts_zfs_tests_functional_hkdf_PROGRAMS = %D%/tests/functional/hkdf/hkdf_test
%C%_tests_functional_hkdf_hkdf_test_LDADD = \
libzpool.la
+scripts_zfs_tests_functional_vdev_diskdir = $(datadir)/$(PACKAGE)/zfs-tests/tests/functional/vdev_disk
+scripts_zfs_tests_functional_vdev_disk_PROGRAMS = %D%/tests/functional/vdev_disk/page_alignment
+
+scripts_zfs_tests_functional_cp_filesdir = $(datadir)/$(PACKAGE)/zfs-tests/tests/functional/cp_files
+scripts_zfs_tests_functional_cp_files_PROGRAMS = %D%/tests/functional/cp_files/seekflood
+
if BUILD_LINUX
scripts_zfs_tests_functional_tmpfiledir = $(datadir)/$(PACKAGE)/zfs-tests/tests/functional/tmpfile
scripts_zfs_tests_functional_tmpfile_PROGRAMS = \
diff --git a/tests/zfs-tests/callbacks/zfs_dbgmsg.ksh b/tests/zfs-tests/callbacks/zfs_dbgmsg.ksh
index be001ad9daf7..114bc5a0cce7 100755
--- a/tests/zfs-tests/callbacks/zfs_dbgmsg.ksh
+++ b/tests/zfs-tests/callbacks/zfs_dbgmsg.ksh
@@ -24,6 +24,9 @@ echo "================================================================="
sudo tail -n $lines /proc/spl/kstat/zfs/dbgmsg
+# reset dbgmsg
+sudo bash -c "echo > /proc/spl/kstat/zfs/dbgmsg"
+
echo "================================================================="
echo " End of zfs_dbgmsg log"
echo "================================================================="
diff --git a/tests/zfs-tests/callbacks/zfs_dmesg.ksh b/tests/zfs-tests/callbacks/zfs_dmesg.ksh
index 3d8191de57a0..9fee4b044958 100755
--- a/tests/zfs-tests/callbacks/zfs_dmesg.ksh
+++ b/tests/zfs-tests/callbacks/zfs_dmesg.ksh
@@ -23,7 +23,8 @@ echo "================================================================="
echo " Tailing last $lines lines of dmesg log"
echo "================================================================="
-sudo dmesg | tail -n $lines
+# report and reset afterwards
+sudo dmesg -c | tail -n $lines
echo "================================================================="
echo " End of dmesg log"
diff --git a/tests/zfs-tests/callbacks/zfs_mmp.ksh b/tests/zfs-tests/callbacks/zfs_mmp.ksh
index 402e0b03f618..d57061438c54 100755
--- a/tests/zfs-tests/callbacks/zfs_mmp.ksh
+++ b/tests/zfs-tests/callbacks/zfs_mmp.ksh
@@ -30,6 +30,7 @@ for f in /proc/spl/kstat/zfs/*/multihost; do
echo "================================================================="
sudo tail -n $lines $f
+ sudo bash -c "echo > $f"
done
echo "================================================================="
diff --git a/tests/zfs-tests/cmd/.gitignore b/tests/zfs-tests/cmd/.gitignore
index 20d1382532bd..0ed0a69eb013 100644
--- a/tests/zfs-tests/cmd/.gitignore
+++ b/tests/zfs-tests/cmd/.gitignore
@@ -1,9 +1,13 @@
/badsend
/btree_test
/chg_usr_exec
+/clonefile
+/clone_mmap_cached
+/clone_mmap_write
/devname2devid
/dir_rd_update
/draid
+/file_fadvise
/file_append
/file_check
/file_trunc
@@ -26,6 +30,7 @@
/randwritecomp
/read_dos_attributes
/readmmap
+/renameat2
/rename_dir
/rm_lnkcnt_zero_file
/send_doall
@@ -46,3 +51,4 @@
/edonr_test
/skein_test
/sha2_test
+/idmap_util
diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am
index 3c8faf5afbbb..23848a82ffbd 100644
--- a/tests/zfs-tests/cmd/Makefile.am
+++ b/tests/zfs-tests/cmd/Makefile.am
@@ -2,6 +2,9 @@ scripts_zfs_tests_bindir = $(datadir)/$(PACKAGE)/zfs-tests/bin
scripts_zfs_tests_bin_PROGRAMS = %D%/chg_usr_exec
+scripts_zfs_tests_bin_PROGRAMS += %D%/clonefile
+scripts_zfs_tests_bin_PROGRAMS += %D%/clone_mmap_cached
+scripts_zfs_tests_bin_PROGRAMS += %D%/clone_mmap_write
scripts_zfs_tests_bin_PROGRAMS += %D%/cp_files
scripts_zfs_tests_bin_PROGRAMS += %D%/ctime
scripts_zfs_tests_bin_PROGRAMS += %D%/dir_rd_update
@@ -112,20 +115,24 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/edonr_test %D%/skein_test \
%C%_edonr_test_LDADD = $(%C%_skein_test_LDADD)
%C%_blake3_test_LDADD = $(%C%_skein_test_LDADD)
-
if BUILD_LINUX
scripts_zfs_tests_bin_PROGRAMS += %D%/getversion
scripts_zfs_tests_bin_PROGRAMS += %D%/user_ns_exec
+scripts_zfs_tests_bin_PROGRAMS += %D%/renameat2
scripts_zfs_tests_bin_PROGRAMS += %D%/xattrtest
scripts_zfs_tests_bin_PROGRAMS += %D%/zed_fd_spill-zedlet
+scripts_zfs_tests_bin_PROGRAMS += %D%/idmap_util
+%C%_idmap_util_LDADD = libspl.la
dist_noinst_DATA += %D%/linux_dos_attributes/dos_attributes.h
scripts_zfs_tests_bin_PROGRAMS += %D%/read_dos_attributes %D%/write_dos_attributes
%C%_read_dos_attributes_SOURCES = %D%/linux_dos_attributes/read_dos_attributes.c
%C%_write_dos_attributes_SOURCES = %D%/linux_dos_attributes/write_dos_attributes.c
-
scripts_zfs_tests_bin_PROGRAMS += %D%/randfree_file
%C%_randfree_file_SOURCES = %D%/file/randfree_file.c
+
+scripts_zfs_tests_bin_PROGRAMS += %D%/file_fadvise
+%C%_file_fadvise_SOURCES = %D%/file/file_fadvise.c
endif
diff --git a/tests/zfs-tests/cmd/badsend.c b/tests/zfs-tests/cmd/badsend.c
index af17bc7255b4..7a54532fb28d 100644
--- a/tests/zfs-tests/cmd/badsend.c
+++ b/tests/zfs-tests/cmd/badsend.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -76,6 +76,10 @@ main(int argc, char const * const argv[])
tosnap = p + 1;
fsname = strndup(tofull, p - tofull);
+ if (fsname == NULL) {
+ perror("strndup");
+ exit(EXIT_FAILURE);
+ }
if (strncmp(fsname, fromfull, p - tofull) != 0)
usage(argv[0]);
diff --git a/tests/zfs-tests/cmd/btree_test.c b/tests/zfs-tests/cmd/btree_test.c
index aaad4e47e464..fda9229915ce 100644
--- a/tests/zfs-tests/cmd/btree_test.c
+++ b/tests/zfs-tests/cmd/btree_test.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/avl.h>
#include <sys/btree.h>
#include <sys/time.h>
@@ -22,11 +23,11 @@
#define BUFSIZE 256
-int seed = 0;
-int stress_timeout = 180;
-int contents_frequency = 100;
-int tree_limit = 64 * 1024;
-boolean_t stress_only = B_FALSE;
+static int seed = 0;
+static int stress_timeout = 180;
+static int contents_frequency = 100;
+static int tree_limit = 64 * 1024;
+static boolean_t stress_only = B_FALSE;
static void
usage(int exit_value)
@@ -164,7 +165,7 @@ find_without_index(zfs_btree_t *bt, char *why)
zfs_btree_add(bt, &i);
if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, NULL)) == NULL ||
*p != i) {
- snprintf(why, BUFSIZE, "Unexpectedly found %llu\n",
+ (void) snprintf(why, BUFSIZE, "Unexpectedly found %llu\n",
p == NULL ? 0 : *p);
return (1);
}
@@ -172,7 +173,7 @@ find_without_index(zfs_btree_t *bt, char *why)
i++;
if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, NULL)) != NULL) {
- snprintf(why, BUFSIZE, "Found bad value: %llu\n", *p);
+ (void) snprintf(why, BUFSIZE, "Found bad value: %llu\n", *p);
return (1);
}
@@ -189,10 +190,10 @@ insert_find_remove(zfs_btree_t *bt, char *why)
/* Insert 'i' into the tree, and attempt to find it again. */
zfs_btree_add(bt, &i);
if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, &bt_idx)) == NULL) {
- snprintf(why, BUFSIZE, "Didn't find value in tree\n");
+ (void) snprintf(why, BUFSIZE, "Didn't find value in tree\n");
return (1);
} else if (*p != i) {
- snprintf(why, BUFSIZE, "Found (%llu) in tree\n", *p);
+ (void) snprintf(why, BUFSIZE, "Found (%llu) in tree\n", *p);
return (1);
}
ASSERT3S(zfs_btree_numnodes(bt), ==, 1);
@@ -201,7 +202,8 @@ insert_find_remove(zfs_btree_t *bt, char *why)
/* Remove 'i' from the tree, and verify it is not found. */
zfs_btree_remove(bt, &i);
if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) {
- snprintf(why, BUFSIZE, "Found removed value (%llu)\n", *p);
+ (void) snprintf(why, BUFSIZE,
+ "Found removed value (%llu)\n", *p);
return (1);
}
ASSERT3S(zfs_btree_numnodes(bt), ==, 0);
@@ -218,7 +220,6 @@ insert_find_remove(zfs_btree_t *bt, char *why)
static int
drain_tree(zfs_btree_t *bt, char *why)
{
- uint64_t *p;
avl_tree_t avl;
int i = 0;
int_node_t *node;
@@ -230,19 +231,22 @@ drain_tree(zfs_btree_t *bt, char *why)
/* Fill both trees with the same data */
for (i = 0; i < 64 * 1024; i++) {
- void *ret;
-
u_longlong_t randval = random();
- node = malloc(sizeof (int_node_t));
- if ((p = (uint64_t *)zfs_btree_find(bt, &randval, &bt_idx)) !=
- NULL) {
+ if (zfs_btree_find(bt, &randval, &bt_idx) != NULL) {
continue;
}
zfs_btree_add_idx(bt, &randval, &bt_idx);
+ node = malloc(sizeof (int_node_t));
+ if (node == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
node->data = randval;
- if ((ret = avl_find(&avl, node, &avl_idx)) != NULL) {
- snprintf(why, BUFSIZE, "Found in avl: %llu\n", randval);
+ if (avl_find(&avl, node, &avl_idx) != NULL) {
+ (void) snprintf(why, BUFSIZE,
+ "Found in avl: %llu\n", randval);
return (1);
}
avl_insert(&avl, node, avl_idx);
@@ -314,6 +318,10 @@ stress_tree(zfs_btree_t *bt, char *why)
uint64_t randval = random() % tree_limit;
node = malloc(sizeof (*node));
+ if (node == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
node->data = randval;
max = randval > max ? randval : max;
@@ -360,9 +368,7 @@ stress_tree(zfs_btree_t *bt, char *why)
if (stress_only) {
zfs_btree_index_t *idx = NULL;
- uint64_t *rv;
-
- while ((rv = zfs_btree_destroy_nodes(bt, &idx)) != NULL)
+ while (zfs_btree_destroy_nodes(bt, &idx) != NULL)
;
zfs_btree_verify(bt);
}
@@ -377,15 +383,15 @@ stress_tree(zfs_btree_t *bt, char *why)
static int
insert_duplicate(zfs_btree_t *bt)
{
- uint64_t *p, i = 23456;
+ uint64_t i = 23456;
zfs_btree_index_t bt_idx = {0};
- if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) {
+ if (zfs_btree_find(bt, &i, &bt_idx) != NULL) {
fprintf(stderr, "Found value in empty tree.\n");
return (0);
}
zfs_btree_add_idx(bt, &i, &bt_idx);
- if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) == NULL) {
+ if (zfs_btree_find(bt, &i, &bt_idx) == NULL) {
fprintf(stderr, "Did not find expected value.\n");
return (0);
}
@@ -403,10 +409,10 @@ insert_duplicate(zfs_btree_t *bt)
static int
remove_missing(zfs_btree_t *bt)
{
- uint64_t *p, i = 23456;
+ uint64_t i = 23456;
zfs_btree_index_t bt_idx = {0};
- if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) {
+ if (zfs_btree_find(bt, &i, &bt_idx) != NULL) {
fprintf(stderr, "Found value in empty tree.\n");
return (0);
}
@@ -422,7 +428,8 @@ do_negative_test(zfs_btree_t *bt, char *test_name)
{
int rval = 0;
struct rlimit rlim = {0};
- setrlimit(RLIMIT_CORE, &rlim);
+
+ (void) setrlimit(RLIMIT_CORE, &rlim);
if (strcmp(test_name, "insert_duplicate") == 0) {
rval = insert_duplicate(bt);
@@ -486,10 +493,6 @@ main(int argc, char *argv[])
break;
}
}
- argc -= optind;
- argv += optind;
- optind = 1;
-
if (seed == 0) {
(void) gettimeofday(&tp, NULL);
@@ -498,7 +501,7 @@ main(int argc, char *argv[])
srandom(seed);
zfs_btree_init();
- zfs_btree_create(&bt, zfs_btree_compare, sizeof (uint64_t));
+ zfs_btree_create(&bt, zfs_btree_compare, NULL, sizeof (uint64_t));
/*
* This runs the named negative test. None of them should
@@ -523,7 +526,6 @@ main(int argc, char *argv[])
btree_test_t *test = &test_table[0];
while (test->name) {
int retval;
- uint64_t *rv;
char why[BUFSIZE] = {0};
zfs_btree_index_t *idx = NULL;
@@ -541,7 +543,7 @@ main(int argc, char *argv[])
}
/* Remove all the elements and re-verify the tree */
- while ((rv = zfs_btree_destroy_nodes(&bt, &idx)) != NULL)
+ while (zfs_btree_destroy_nodes(&bt, &idx) != NULL)
;
zfs_btree_verify(&bt);
diff --git a/tests/zfs-tests/cmd/checksum/blake3_test.c b/tests/zfs-tests/cmd/checksum/blake3_test.c
index 55d268f5f8b7..aebe0363cc6e 100644
--- a/tests/zfs-tests/cmd/checksum/blake3_test.c
+++ b/tests/zfs-tests/cmd/checksum/blake3_test.c
@@ -7,7 +7,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -31,6 +31,8 @@
#include <sys/time.h>
#include <sys/blake3.h>
+#include <sys/zfs_impl.h>
+
/*
* set it to a define for debugging
*/
@@ -485,10 +487,14 @@ main(int argc, char *argv[])
uint8_t buffer[102400];
uint64_t cpu_mhz = 0;
int id, i, j;
+ const zfs_impl_t *blake3 = zfs_impl_get_ops("blake3");
if (argc == 2)
cpu_mhz = atoi(argv[1]);
+ if (!blake3)
+ return (1);
+
/* fill test message */
for (i = 0, j = 0; i < sizeof (buffer); i++, j++) {
if (j == 251)
@@ -497,9 +503,9 @@ main(int argc, char *argv[])
}
(void) printf("Running algorithm correctness tests:\n");
- for (id = 0; id < blake3_get_impl_count(); id++) {
- blake3_set_impl_id(id);
- const char *name = blake3_get_impl_name();
+ for (id = 0; id < blake3->getcnt(); id++) {
+ blake3->setid(id);
+ const char *name = blake3->getname();
dprintf("Result for BLAKE3-%s:\n", name);
for (i = 0; TestArray[i].hash; i++) {
blake3_test_t *cur = &TestArray[i];
@@ -565,9 +571,9 @@ main(int argc, char *argv[])
} while (0)
printf("Running performance tests (hashing 1024 MiB of data):\n");
- for (id = 0; id < blake3_get_impl_count(); id++) {
- blake3_set_impl_id(id);
- const char *name = blake3_get_impl_name();
+ for (id = 0; id < blake3->getcnt(); id++) {
+ blake3->setid(id);
+ const char *name = blake3->getname();
BLAKE3_PERF_TEST(name, 256);
}
diff --git a/tests/zfs-tests/cmd/checksum/edonr_test.c b/tests/zfs-tests/cmd/checksum/edonr_test.c
index 3a0a48533c53..1204f4c9d017 100644
--- a/tests/zfs-tests/cmd/checksum/edonr_test.c
+++ b/tests/zfs-tests/cmd/checksum/edonr_test.c
@@ -40,77 +40,11 @@
* Test messages from:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
*/
-const char *test_msg0 = "abc";
-const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
- "lmnomnopnopq";
-const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
- "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+static const char *test_msg0 = "abc";
+static const char *test_msg1 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh"
+ "ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
-/*
- * Test digests computed by hand. There's no formal standard or spec for edonr.
- */
-const uint8_t edonr_224_test_digests[][28] = {
- {
- /* for test_msg0 */
- 0x56, 0x63, 0xc4, 0x93, 0x95, 0x20, 0xfa, 0xf6,
- 0x12, 0x31, 0x65, 0xa4, 0x66, 0xf2, 0x56, 0x01,
- 0x95, 0x2e, 0xa9, 0xe4, 0x24, 0xdd, 0xc9, 0x6b,
- 0xef, 0xd0, 0x40, 0x94
- },
- {
- /* for test_msg1 */
- 0xd0, 0x13, 0xe4, 0x87, 0x4d, 0x06, 0x8d, 0xca,
- 0x4e, 0x14, 0xb9, 0x37, 0x2f, 0xce, 0x12, 0x20,
- 0x60, 0xf8, 0x5c, 0x0a, 0xfd, 0x7a, 0x7d, 0x97,
- 0x88, 0x2b, 0x05, 0x75
- }
- /* no test vector for test_msg2 */
-};
-
-const uint8_t edonr_256_test_digests[][32] = {
- {
- /* for test_msg0 */
- 0x54, 0xd7, 0x8b, 0x13, 0xc7, 0x4e, 0xda, 0x5a,
- 0xed, 0xc2, 0x71, 0xcc, 0x88, 0x1f, 0xb2, 0x2f,
- 0x83, 0x99, 0xaf, 0xd3, 0x04, 0x0b, 0x6a, 0x39,
- 0x2d, 0x73, 0x94, 0x05, 0x50, 0x8d, 0xd8, 0x51
- },
- {
- /* for test_msg1 */
- 0x49, 0x2d, 0x0b, 0x19, 0xab, 0x1e, 0xde, 0x3a,
- 0xea, 0x9b, 0xf2, 0x39, 0x3a, 0xb1, 0x21, 0xde,
- 0x21, 0xf6, 0x80, 0x1f, 0xad, 0xbe, 0x8b, 0x07,
- 0xc7, 0xfb, 0xe6, 0x99, 0x0e, 0x4d, 0x73, 0x63
- }
- /* no test vectorfor test_msg2 */
-};
-
-const uint8_t edonr_384_test_digests[][48] = {
- {
- /* for test_msg0 */
- 0x0e, 0x7c, 0xd7, 0x85, 0x78, 0x77, 0xe0, 0x89,
- 0x5b, 0x1c, 0xdf, 0x49, 0xf4, 0x1d, 0x20, 0x9c,
- 0x72, 0x7d, 0x2e, 0x57, 0x9b, 0x9b, 0x9a, 0xdc,
- 0x60, 0x27, 0x97, 0x82, 0xb9, 0x90, 0x72, 0xec,
- 0x7e, 0xce, 0xd3, 0x16, 0x5f, 0x47, 0x75, 0x48,
- 0xfa, 0x60, 0x72, 0x7e, 0x01, 0xc7, 0x7c, 0xc6
- },
- {
- /* no test vector for test_msg1 */
- 0
- },
- {
- /* for test_msg2 */
- 0xe2, 0x34, 0xa1, 0x02, 0x83, 0x76, 0xae, 0xe6,
- 0x82, 0xd9, 0x38, 0x32, 0x0e, 0x00, 0x78, 0xd2,
- 0x34, 0xdb, 0xb9, 0xbd, 0xf0, 0x08, 0xa8, 0x0f,
- 0x63, 0x1c, 0x3d, 0x4a, 0xfd, 0x0a, 0xe9, 0x59,
- 0xdc, 0xd4, 0xce, 0xcd, 0x8d, 0x67, 0x6c, 0xea,
- 0xbb, 0x1a, 0x32, 0xed, 0x5c, 0x6b, 0xf1, 0x7f
- }
-};
-
-const uint8_t edonr_512_test_digests[][64] = {
+static const uint8_t edonr_512_test_digests[][64] = {
{
/* for test_msg0 */
0x1b, 0x14, 0xdb, 0x15, 0x5f, 0x1d, 0x40, 0x65,
@@ -127,7 +61,7 @@ const uint8_t edonr_512_test_digests[][64] = {
0
},
{
- /* for test_msg2 */
+ /* for test_msg1 */
0x53, 0x51, 0x07, 0x0d, 0xc5, 0x1c, 0x3b, 0x2b,
0xac, 0xa5, 0xa6, 0x0d, 0x02, 0x52, 0xcc, 0xb4,
0xe4, 0x92, 0x1a, 0x96, 0xfe, 0x5a, 0x69, 0xe7,
@@ -152,7 +86,7 @@ main(int argc, char *argv[])
do { \
EdonRState ctx; \
uint8_t digest[mode / 8]; \
- EdonRInit(&ctx, mode); \
+ EdonRInit(&ctx); \
EdonRUpdate(&ctx, (const uint8_t *) _m, strlen(_m) * 8);\
EdonRFinal(&ctx, digest); \
(void) printf("Edon-R-%-6sMessage: " #_m \
@@ -176,7 +110,7 @@ main(int argc, char *argv[])
struct timeval start, end; \
memset(block, 0, sizeof (block)); \
(void) gettimeofday(&start, NULL); \
- EdonRInit(&ctx, mode); \
+ EdonRInit(&ctx); \
for (i = 0; i < 8192; i++) \
EdonRUpdate(&ctx, block, sizeof (block) * 8); \
EdonRFinal(&ctx, digest); \
@@ -192,20 +126,13 @@ main(int argc, char *argv[])
} while (0)
(void) printf("Running algorithm correctness tests:\n");
- EDONR_ALGO_TEST(test_msg0, 224, edonr_224_test_digests[0]);
- EDONR_ALGO_TEST(test_msg1, 224, edonr_224_test_digests[1]);
- EDONR_ALGO_TEST(test_msg0, 256, edonr_256_test_digests[0]);
- EDONR_ALGO_TEST(test_msg1, 256, edonr_256_test_digests[1]);
- EDONR_ALGO_TEST(test_msg0, 384, edonr_384_test_digests[0]);
- EDONR_ALGO_TEST(test_msg2, 384, edonr_384_test_digests[2]);
EDONR_ALGO_TEST(test_msg0, 512, edonr_512_test_digests[0]);
- EDONR_ALGO_TEST(test_msg2, 512, edonr_512_test_digests[2]);
+ EDONR_ALGO_TEST(test_msg1, 512, edonr_512_test_digests[2]);
if (failed)
return (1);
(void) printf("Running performance tests (hashing 1024 MiB of "
"data):\n");
- EDONR_PERF_TEST(256);
EDONR_PERF_TEST(512);
return (0);
diff --git a/tests/zfs-tests/cmd/checksum/sha2_test.c b/tests/zfs-tests/cmd/checksum/sha2_test.c
index bb355311091e..efcf812d7749 100644
--- a/tests/zfs-tests/cmd/checksum/sha2_test.c
+++ b/tests/zfs-tests/cmd/checksum/sha2_test.c
@@ -33,28 +33,28 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+
#include <sys/time.h>
-#define _SHA2_IMPL
#include <sys/sha2.h>
#include <sys/stdtypes.h>
-
+#include <sys/zfs_impl.h>
/*
* Test messages from:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
*/
-const char *test_msg0 = "abc";
-const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
- "lmnomnopnopq";
-const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
- "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+static const char *test_msg0 = "abc";
+static const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklm"
+ "nlmnomnopnopq";
+static const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh"
+ "ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
/*
* Test digests from:
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
*/
-const uint8_t sha256_test_digests[][32] = {
+static const uint8_t sha256_test_digests[][32] = {
{
/* for test_msg0 */
0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
@@ -72,7 +72,7 @@ const uint8_t sha256_test_digests[][32] = {
/* no test vector for test_msg2 */
};
-const uint8_t sha384_test_digests[][48] = {
+static const uint8_t sha384_test_digests[][48] = {
{
/* for test_msg0 */
0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
@@ -97,7 +97,7 @@ const uint8_t sha384_test_digests[][48] = {
}
};
-const uint8_t sha512_test_digests[][64] = {
+static const uint8_t sha512_test_digests[][64] = {
{
/* for test_msg0 */
0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
@@ -126,7 +126,7 @@ const uint8_t sha512_test_digests[][64] = {
}
};
-const uint8_t sha512_224_test_digests[][28] = {
+static const uint8_t sha512_224_test_digests[][28] = {
{
/* for test_msg0 */
0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54,
@@ -147,7 +147,7 @@ const uint8_t sha512_224_test_digests[][28] = {
}
};
-const uint8_t sha512_256_test_digests[][32] = {
+static const uint8_t sha512_256_test_digests[][32] = {
{
/* for test_msg0 */
0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
@@ -174,9 +174,19 @@ main(int argc, char *argv[])
boolean_t failed = B_FALSE;
uint64_t cpu_mhz = 0;
+ const zfs_impl_t *sha256 = zfs_impl_get_ops("sha256");
+ const zfs_impl_t *sha512 = zfs_impl_get_ops("sha512");
+ uint32_t id;
+
if (argc == 2)
cpu_mhz = atoi(argv[1]);
+ if (!sha256)
+ return (1);
+
+ if (!sha512)
+ return (1);
+
#define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \
do { \
SHA2_CTX ctx; \
@@ -194,7 +204,7 @@ main(int argc, char *argv[])
} \
} while (0)
-#define SHA2_PERF_TEST(mode, diglen) \
+#define SHA2_PERF_TEST(mode, diglen, name) \
do { \
SHA2_CTX ctx; \
uint8_t digest[diglen / 8]; \
@@ -216,8 +226,8 @@ main(int argc, char *argv[])
cpb = (cpu_mhz * 1e6 * ((double)delta / \
1000000)) / (8192 * 128 * 1024); \
} \
- (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \
- (u_longlong_t)delta, cpb); \
+ (void) printf("sha%s-%-9s%7llu us (%.02f CPB)\n", #mode,\
+ name, (u_longlong_t)delta, cpb); \
} while (0)
(void) printf("Running algorithm correctness tests:\n");
@@ -237,8 +247,18 @@ main(int argc, char *argv[])
(void) printf("Running performance tests (hashing 1024 MiB of "
"data):\n");
- SHA2_PERF_TEST(256, 256);
- SHA2_PERF_TEST(512, 512);
+
+ for (id = 0; id < sha256->getcnt(); id++) {
+ sha256->setid(id);
+ const char *name = sha256->getname();
+ SHA2_PERF_TEST(256, 256, name);
+ }
+
+ for (id = 0; id < sha512->getcnt(); id++) {
+ sha512->setid(id);
+ const char *name = sha512->getname();
+ SHA2_PERF_TEST(512, 512, name);
+ }
return (0);
}
diff --git a/tests/zfs-tests/cmd/checksum/skein_test.c b/tests/zfs-tests/cmd/checksum/skein_test.c
index 13611c860c42..20eb36d3e883 100644
--- a/tests/zfs-tests/cmd/checksum/skein_test.c
+++ b/tests/zfs-tests/cmd/checksum/skein_test.c
@@ -44,18 +44,18 @@
/*
* Test messages from the Skein spec, Appendix C.
*/
-const uint8_t test_msg0[] = {
+static const uint8_t test_msg0[] = {
0xFF
};
-const uint8_t test_msg1[] = {
+static const uint8_t test_msg1[] = {
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0
};
-const uint8_t test_msg2[] = {
+static const uint8_t test_msg2[] = {
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
@@ -66,7 +66,7 @@ const uint8_t test_msg2[] = {
0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0
};
-const uint8_t test_msg3[] = {
+static const uint8_t test_msg3[] = {
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
@@ -85,7 +85,7 @@ const uint8_t test_msg3[] = {
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
};
-const uint8_t test_msg4[] = {
+static const uint8_t test_msg4[] = {
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
@@ -123,7 +123,7 @@ const uint8_t test_msg4[] = {
/*
* Test digests from the Skein spec, Appendix C.
*/
-const uint8_t skein_256_test_digests[][32] = {
+static const uint8_t skein_256_test_digests[][32] = {
{
/* for test_msg0 */
0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50,
@@ -148,7 +148,7 @@ const uint8_t skein_256_test_digests[][32] = {
/* no test digests for test_msg3 and test_msg4 */
};
-const uint8_t skein_512_test_digests[][64] = {
+static const uint8_t skein_512_test_digests[][64] = {
{
/* for test_msg0 */
0x71, 0xB7, 0xBC, 0xE6, 0xFE, 0x64, 0x52, 0x22,
@@ -189,7 +189,7 @@ const uint8_t skein_512_test_digests[][64] = {
/* no test digests for test_msg4 */
};
-const uint8_t skein_1024_test_digests[][128] = {
+static const uint8_t skein_1024_test_digests[][128] = {
{
/* for test_msg0 */
0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24,
diff --git a/tests/zfs-tests/cmd/chg_usr_exec.c b/tests/zfs-tests/cmd/chg_usr_exec.c
index 1fa9e88a6fde..911c907b38ac 100644
--- a/tests/zfs-tests/cmd/chg_usr_exec.c
+++ b/tests/zfs-tests/cmd/chg_usr_exec.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/clone_mmap_cached.c b/tests/zfs-tests/cmd/clone_mmap_cached.c
new file mode 100644
index 000000000000..c1cdf796cfb4
--- /dev/null
+++ b/tests/zfs-tests/cmd/clone_mmap_cached.c
@@ -0,0 +1,146 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2024 by Pawel Jakub Dawidek
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __FreeBSD__
+#define loff_t off_t
+#endif
+
+ssize_t
+copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
+ __attribute__((weak));
+
+static void *
+mmap_file(int fd, size_t size)
+{
+ void *p;
+
+ p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED) {
+ (void) fprintf(stderr, "mmap failed: %s\n", strerror(errno));
+ exit(2);
+ }
+
+ return (p);
+}
+
+static void
+usage(const char *progname)
+{
+
+ /*
+ * -i cache input before copy_file_range(2).
+ * -o cache input before copy_file_range(2).
+ */
+ (void) fprintf(stderr, "usage: %s [-io] <input> <output>\n", progname);
+ exit(3);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int dfd, sfd;
+ size_t dsize, ssize;
+ void *dmem, *smem, *ptr;
+ off_t doff, soff;
+ struct stat sb;
+ bool cache_input, cache_output;
+ const char *progname;
+ int c;
+
+ progname = argv[0];
+ cache_input = cache_output = false;
+
+ while ((c = getopt(argc, argv, "io")) != -1) {
+ switch (c) {
+ case 'i':
+ cache_input = true;
+ break;
+ case 'o':
+ cache_output = true;
+ break;
+ default:
+ usage(progname);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2) {
+ usage(progname);
+ }
+
+ sfd = open(argv[0], O_RDONLY);
+ if (fstat(sfd, &sb) == -1) {
+ (void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
+ exit(2);
+ }
+ ssize = sb.st_size;
+ smem = mmap_file(sfd, ssize);
+
+ dfd = open(argv[1], O_RDWR);
+ if (fstat(dfd, &sb) == -1) {
+ (void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
+ exit(2);
+ }
+ dsize = sb.st_size;
+ dmem = mmap_file(dfd, dsize);
+
+ /*
+ * Hopefully it won't be compiled out.
+ */
+ if (cache_input) {
+ ptr = malloc(ssize);
+ assert(ptr != NULL);
+ memcpy(ptr, smem, ssize);
+ free(ptr);
+ }
+ if (cache_output) {
+ ptr = malloc(ssize);
+ assert(ptr != NULL);
+ memcpy(ptr, dmem, dsize);
+ free(ptr);
+ }
+
+ soff = doff = 0;
+ if (copy_file_range(sfd, &soff, dfd, &doff, ssize, 0) < 0) {
+ (void) fprintf(stderr, "copy_file_range failed: %s\n",
+ strerror(errno));
+ exit(2);
+ }
+
+ exit(memcmp(smem, dmem, ssize) == 0 ? 0 : 1);
+}
diff --git a/tests/zfs-tests/cmd/clone_mmap_write.c b/tests/zfs-tests/cmd/clone_mmap_write.c
new file mode 100644
index 000000000000..6a5cd8721c57
--- /dev/null
+++ b/tests/zfs-tests/cmd/clone_mmap_write.c
@@ -0,0 +1,123 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * This program clones the file, mmap it, and writes from the map into
+ * file. This scenario triggers a panic on Linux in dbuf_redirty(),
+ * which is fixed under PR#15656. On FreeBSD, the same test causes data
+ * corruption, which is fixed by PR#15665.
+ *
+ * It would be good to test for this scenario in ZTS. This program and
+ * issue was initially produced by @robn.
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#ifdef __FreeBSD__
+#define loff_t off_t
+#endif
+
+ssize_t
+copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
+ __attribute__((weak));
+
+static int
+open_file(const char *source)
+{
+ int fd;
+ if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {
+ (void) fprintf(stderr, "Error opening %s\n", source);
+ exit(1);
+ }
+ sync();
+ return (fd);
+}
+
+static int
+clone_file(int sfd, long long size, const char *dest)
+{
+ int dfd;
+
+ if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
+ (void) fprintf(stderr, "Error opening %s\n", dest);
+ exit(1);
+ }
+
+ if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {
+ (void) fprintf(stderr, "copy_file_range failed\n");
+ exit(1);
+ }
+
+ return (dfd);
+}
+
+static void *
+map_file(int fd, long long size)
+{
+ void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED) {
+ (void) fprintf(stderr, "mmap failed\n");
+ exit(1);
+ }
+
+ return (p);
+}
+
+static void
+map_write(void *p, int fd)
+{
+ if (pwrite(fd, p, 1024*128, 0) < 0) {
+ (void) fprintf(stderr, "write failed\n");
+ exit(1);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int sfd, dfd;
+ void *p;
+ struct stat sb;
+ if (argc != 3) {
+ (void) printf("usage: %s <input source file> "
+ "<clone destination file>\n", argv[0]);
+ exit(1);
+ }
+ sfd = open_file(argv[1]);
+ if (fstat(sfd, &sb) == -1) {
+ (void) fprintf(stderr, "fstat failed\n");
+ exit(1);
+ }
+ dfd = clone_file(sfd, sb.st_size, argv[2]);
+ p = map_file(dfd, sb.st_size);
+ map_write(p, dfd);
+ return (0);
+}
diff --git a/tests/zfs-tests/cmd/clonefile.c b/tests/zfs-tests/cmd/clonefile.c
new file mode 100644
index 000000000000..bc30bb7798e9
--- /dev/null
+++ b/tests/zfs-tests/cmd/clonefile.c
@@ -0,0 +1,373 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This program is to test the availability and behaviour of copy_file_range,
+ * FICLONE, FICLONERANGE and FIDEDUPERANGE in the Linux kernel. It should
+ * compile and run even if these features aren't exposed through the libc.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef __NR_copy_file_range
+#if defined(__x86_64__)
+#define __NR_copy_file_range (326)
+#elif defined(__i386__)
+#define __NR_copy_file_range (377)
+#elif defined(__s390__)
+#define __NR_copy_file_range (375)
+#elif defined(__arm__)
+#define __NR_copy_file_range (391)
+#elif defined(__aarch64__)
+#define __NR_copy_file_range (285)
+#elif defined(__powerpc__)
+#define __NR_copy_file_range (379)
+#else
+#error "no definition of __NR_copy_file_range for this platform"
+#endif
+#endif /* __NR_copy_file_range */
+
+#ifdef __FreeBSD__
+#define loff_t off_t
+#endif
+
+ssize_t
+copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
+ __attribute__((weak));
+
+static inline ssize_t
+cf_copy_file_range(int sfd, loff_t *soff, int dfd, loff_t *doff,
+ size_t len, unsigned int flags)
+{
+ if (copy_file_range)
+ return (copy_file_range(sfd, soff, dfd, doff, len, flags));
+ return (
+ syscall(__NR_copy_file_range, sfd, soff, dfd, doff, len, flags));
+}
+
+/* Define missing FICLONE */
+#ifdef FICLONE
+#define CF_FICLONE FICLONE
+#else
+#define CF_FICLONE _IOW(0x94, 9, int)
+#endif
+
+/* Define missing FICLONERANGE and support structs */
+#ifdef FICLONERANGE
+#define CF_FICLONERANGE FICLONERANGE
+typedef struct file_clone_range cf_file_clone_range_t;
+#else
+typedef struct {
+ int64_t src_fd;
+ uint64_t src_offset;
+ uint64_t src_length;
+ uint64_t dest_offset;
+} cf_file_clone_range_t;
+#define CF_FICLONERANGE _IOW(0x94, 13, cf_file_clone_range_t)
+#endif
+
+/* Define missing FIDEDUPERANGE and support structs */
+#ifdef FIDEDUPERANGE
+#define CF_FIDEDUPERANGE FIDEDUPERANGE
+#define CF_FILE_DEDUPE_RANGE_SAME FILE_DEDUPE_RANGE_SAME
+#define CF_FILE_DEDUPE_RANGE_DIFFERS FILE_DEDUPE_RANGE_DIFFERS
+typedef struct file_dedupe_range_info cf_file_dedupe_range_info_t;
+typedef struct file_dedupe_range cf_file_dedupe_range_t;
+#else
+typedef struct {
+ int64_t dest_fd;
+ uint64_t dest_offset;
+ uint64_t bytes_deduped;
+ int32_t status;
+ uint32_t reserved;
+} cf_file_dedupe_range_info_t;
+typedef struct {
+ uint64_t src_offset;
+ uint64_t src_length;
+ uint16_t dest_count;
+ uint16_t reserved1;
+ uint32_t reserved2;
+ cf_file_dedupe_range_info_t info[0];
+} cf_file_dedupe_range_t;
+#define CF_FIDEDUPERANGE _IOWR(0x94, 54, cf_file_dedupe_range_t)
+#define CF_FILE_DEDUPE_RANGE_SAME (0)
+#define CF_FILE_DEDUPE_RANGE_DIFFERS (1)
+#endif
+
+typedef enum {
+ CF_MODE_NONE,
+ CF_MODE_CLONE,
+ CF_MODE_CLONERANGE,
+ CF_MODE_COPYFILERANGE,
+ CF_MODE_DEDUPERANGE,
+} cf_mode_t;
+
+static int
+usage(void)
+{
+ printf(
+ "usage:\n"
+ " FICLONE:\n"
+ " clonefile -c <src> <dst>\n"
+ " FICLONERANGE:\n"
+ " clonefile -r <src> <dst> <soff> <doff> <len>\n"
+ " copy_file_range:\n"
+ " clonefile -f <src> <dst> [<soff> <doff> <len | \"all\">]\n"
+ " FIDEDUPERANGE:\n"
+ " clonefile -d <src> <dst> <soff> <doff> <len>\n");
+ return (1);
+}
+
+int do_clone(int sfd, int dfd);
+int do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len);
+int do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len);
+int do_deduperange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len);
+
+int quiet = 0;
+
+int
+main(int argc, char **argv)
+{
+ cf_mode_t mode = CF_MODE_NONE;
+
+ int c;
+ while ((c = getopt(argc, argv, "crfdq")) != -1) {
+ switch (c) {
+ case 'c':
+ mode = CF_MODE_CLONE;
+ break;
+ case 'r':
+ mode = CF_MODE_CLONERANGE;
+ break;
+ case 'f':
+ mode = CF_MODE_COPYFILERANGE;
+ break;
+ case 'd':
+ mode = CF_MODE_DEDUPERANGE;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ }
+ }
+
+ switch (mode) {
+ case CF_MODE_NONE:
+ return (usage());
+ case CF_MODE_CLONE:
+ if ((argc-optind) != 2)
+ return (usage());
+ break;
+ case CF_MODE_CLONERANGE:
+ case CF_MODE_DEDUPERANGE:
+ if ((argc-optind) != 5)
+ return (usage());
+ break;
+ case CF_MODE_COPYFILERANGE:
+ if ((argc-optind) != 2 && (argc-optind) != 5)
+ return (usage());
+ break;
+ default:
+ abort();
+ }
+
+ loff_t soff = 0, doff = 0;
+ size_t len = SSIZE_MAX;
+ if ((argc-optind) == 5) {
+ soff = strtoull(argv[optind+2], NULL, 10);
+ if (soff == ULLONG_MAX) {
+ fprintf(stderr, "invalid source offset");
+ return (1);
+ }
+ doff = strtoull(argv[optind+3], NULL, 10);
+ if (doff == ULLONG_MAX) {
+ fprintf(stderr, "invalid dest offset");
+ return (1);
+ }
+ if (mode == CF_MODE_COPYFILERANGE &&
+ strcmp(argv[optind+4], "all") == 0) {
+ len = SSIZE_MAX;
+ } else {
+ len = strtoull(argv[optind+4], NULL, 10);
+ if (len == ULLONG_MAX) {
+ fprintf(stderr, "invalid length");
+ return (1);
+ }
+ }
+ }
+
+ int sfd = open(argv[optind], O_RDONLY);
+ if (sfd < 0) {
+ fprintf(stderr, "open: %s: %s\n",
+ argv[optind], strerror(errno));
+ return (1);
+ }
+
+ int dfd = open(argv[optind+1], O_WRONLY|O_CREAT,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (dfd < 0) {
+ fprintf(stderr, "open: %s: %s\n",
+ argv[optind+1], strerror(errno));
+ close(sfd);
+ return (1);
+ }
+
+ int err;
+ switch (mode) {
+ case CF_MODE_CLONE:
+ err = do_clone(sfd, dfd);
+ break;
+ case CF_MODE_CLONERANGE:
+ err = do_clonerange(sfd, dfd, soff, doff, len);
+ break;
+ case CF_MODE_COPYFILERANGE:
+ err = do_copyfilerange(sfd, dfd, soff, doff, len);
+ break;
+ case CF_MODE_DEDUPERANGE:
+ err = do_deduperange(sfd, dfd, soff, doff, len);
+ break;
+ default:
+ abort();
+ }
+
+ if (!quiet) {
+ off_t spos = lseek(sfd, 0, SEEK_CUR);
+ off_t slen = lseek(sfd, 0, SEEK_END);
+ off_t dpos = lseek(dfd, 0, SEEK_CUR);
+ off_t dlen = lseek(dfd, 0, SEEK_END);
+
+ fprintf(stderr, "file offsets: src=%lu/%lu; dst=%lu/%lu\n",
+ spos, slen, dpos, dlen);
+ }
+
+ close(dfd);
+ close(sfd);
+
+ return (err == 0 ? 0 : 1);
+}
+
+int
+do_clone(int sfd, int dfd)
+{
+ if (!quiet)
+ fprintf(stderr, "using FICLONE\n");
+ int err = ioctl(dfd, CF_FICLONE, sfd);
+ if (err < 0) {
+ fprintf(stderr, "ioctl(FICLONE): %s\n", strerror(errno));
+ return (err);
+ }
+ return (0);
+}
+
+int
+do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len)
+{
+ if (!quiet)
+ fprintf(stderr, "using FICLONERANGE\n");
+ cf_file_clone_range_t fcr = {
+ .src_fd = sfd,
+ .src_offset = soff,
+ .src_length = len,
+ .dest_offset = doff,
+ };
+ int err = ioctl(dfd, CF_FICLONERANGE, &fcr);
+ if (err < 0) {
+ fprintf(stderr, "ioctl(FICLONERANGE): %s\n", strerror(errno));
+ return (err);
+ }
+ return (0);
+}
+
+int
+do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len)
+{
+ if (!quiet)
+ fprintf(stderr, "using copy_file_range\n");
+ ssize_t copied = cf_copy_file_range(sfd, &soff, dfd, &doff, len, 0);
+ if (copied < 0) {
+ fprintf(stderr, "copy_file_range: %s\n", strerror(errno));
+ return (1);
+ }
+ if (len == SSIZE_MAX) {
+ struct stat sb;
+
+ if (fstat(sfd, &sb) < 0) {
+ fprintf(stderr, "fstat(sfd): %s\n", strerror(errno));
+ return (1);
+ }
+ len = sb.st_size;
+ }
+ if (copied != len) {
+ fprintf(stderr, "copy_file_range: copied less than requested: "
+ "requested=%lu; copied=%lu\n", len, copied);
+ return (1);
+ }
+ return (0);
+}
+
+int
+do_deduperange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len)
+{
+ if (!quiet)
+ fprintf(stderr, "using FIDEDUPERANGE\n");
+
+ char buf[sizeof (cf_file_dedupe_range_t)+
+ sizeof (cf_file_dedupe_range_info_t)] = {0};
+ cf_file_dedupe_range_t *fdr = (cf_file_dedupe_range_t *)&buf[0];
+ cf_file_dedupe_range_info_t *fdri =
+ (cf_file_dedupe_range_info_t *)
+ &buf[sizeof (cf_file_dedupe_range_t)];
+
+ fdr->src_offset = soff;
+ fdr->src_length = len;
+ fdr->dest_count = 1;
+
+ fdri->dest_fd = dfd;
+ fdri->dest_offset = doff;
+
+ int err = ioctl(sfd, CF_FIDEDUPERANGE, fdr);
+ if (err != 0)
+ fprintf(stderr, "ioctl(FIDEDUPERANGE): %s\n", strerror(errno));
+
+ if (fdri->status < 0) {
+ fprintf(stderr, "dedup failed: %s\n", strerror(-fdri->status));
+ err = -1;
+ } else if (fdri->status == CF_FILE_DEDUPE_RANGE_DIFFERS) {
+ fprintf(stderr, "dedup failed: range differs\n");
+ err = -1;
+ }
+
+ return (err);
+}
diff --git a/tests/zfs-tests/cmd/ctime.c b/tests/zfs-tests/cmd/ctime.c
index 6d9cf9608969..5ff1cea8a869 100644
--- a/tests/zfs-tests/cmd/ctime.c
+++ b/tests/zfs-tests/cmd/ctime.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -327,7 +327,6 @@ main(void)
if (access(tfile, F_OK) == 0) {
(void) unlink(tfile);
}
- ret = 0;
if ((fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)) == -1) {
(void) fprintf(stderr, "open(%s) failed: %d\n", tfile, errno);
return (1);
@@ -363,12 +362,20 @@ main(void)
return (1);
}
- if (t1 == t2) {
- (void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
+
+ /*
+ * Ideally, time change would be exactly two seconds, but allow
+ * a little slack in case of scheduling delays or similar.
+ */
+ long delta = (long)t2 - (long)t1;
+ if (delta < 2 || delta > 4) {
+ (void) fprintf(stderr,
+ "%s: BAD time change: t1(%ld), t2(%ld)\n",
timetest_table[i].name, (long)t1, (long)t2);
return (1);
} else {
- (void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
+ (void) fprintf(stderr,
+ "%s: good time change: t1(%ld), t2(%ld)\n",
timetest_table[i].name, (long)t1, (long)t2);
}
}
diff --git a/tests/zfs-tests/cmd/devname2devid.c b/tests/zfs-tests/cmd/devname2devid.c
index 91e59c589fd5..0f3655be7143 100644
--- a/tests/zfs-tests/cmd/devname2devid.c
+++ b/tests/zfs-tests/cmd/devname2devid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/dir_rd_update.c b/tests/zfs-tests/cmd/dir_rd_update.c
index 0f460fbecdc2..c0d283105a92 100644
--- a/tests/zfs-tests/cmd/dir_rd_update.c
+++ b/tests/zfs-tests/cmd/dir_rd_update.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -63,13 +63,12 @@ main(int argc, char **argv)
}
cp1 = argv[1];
- if (strlen(cp1) >= (sizeof (dirpath) - strlen("TMP_DIR"))) {
+ if (strlen(cp1) >= (sizeof (dirpath) - strlen("/TMP_DIR"))) {
(void) printf("The string length of mount point is "
"too large\n");
exit(-1);
}
- (void) strcpy(&dirpath[0], (const char *)cp1);
- (void) strcat(&dirpath[strlen(dirpath)], "TMP_DIR");
+ (void) snprintf(dirpath, sizeof (dirpath), "%s/TMP_DIR", cp1);
ret = mkdir(dirpath, 0777);
if (ret != 0) {
diff --git a/tests/zfs-tests/cmd/dosmode_readonly_write.c b/tests/zfs-tests/cmd/dosmode_readonly_write.c
index 0441d1c7b472..b45602d80651 100644
--- a/tests/zfs-tests/cmd/dosmode_readonly_write.c
+++ b/tests/zfs-tests/cmd/dosmode_readonly_write.c
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 iXsystems, Inc.
*
diff --git a/tests/zfs-tests/cmd/draid.c b/tests/zfs-tests/cmd/draid.c
index d1183b4388a3..fdcec7bc6958 100644
--- a/tests/zfs-tests/cmd/draid.c
+++ b/tests/zfs-tests/cmd/draid.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -93,8 +93,8 @@ read_map(const char *filename, nvlist_t **allcfgs)
rc = gzread(fp, buf + bytes, block_size);
if ((rc < 0) || (rc == 0 && !gzeof(fp))) {
free(buf);
- (void) gzclose(fp);
(void) gzerror(fp, &error);
+ (void) gzclose(fp);
return (error);
} else {
bytes += rc;
@@ -139,7 +139,7 @@ read_map_key(const char *filename, const char *key, nvlist_t **cfg)
if (error != 0)
return (error);
- nvlist_lookup_nvlist(allcfgs, key, &foundcfg);
+ (void) nvlist_lookup_nvlist(allcfgs, key, &foundcfg);
if (foundcfg != NULL) {
nvlist_dup(foundcfg, cfg, KM_SLEEP);
error = 0;
@@ -375,7 +375,7 @@ dump_map_nv(const char *key, nvlist_t *cfg, int verbose)
map.dm_checksum = fnvlist_lookup_uint64(cfg, MAP_CHECKSUM);
map.dm_children = fnvlist_lookup_uint64(cfg, MAP_CHILDREN);
map.dm_nperms = fnvlist_lookup_uint64(cfg, MAP_NPERMS);
- nvlist_lookup_uint8_array(cfg, MAP_PERMS, &map.dm_perms, &c);
+ map.dm_perms = fnvlist_lookup_uint8_array(cfg, MAP_PERMS, &c);
dump_map(&map, key, (double)worst_ratio / 1000.0,
avg_ratio / 1000.0, verbose);
@@ -505,6 +505,8 @@ eval_resilver(draid_map_t *map, uint64_t groupwidth, uint64_t nspares,
int *ios = calloc(map->dm_children, sizeof (uint64_t));
+ ASSERT3P(ios, !=, NULL);
+
/* Resilver all rows */
for (int i = 0; i < map->dm_nperms; i++) {
uint8_t *row = &map->dm_perms[i * map->dm_children];
@@ -720,8 +722,11 @@ eval_maps(uint64_t children, int passes, uint64_t *map_seed,
*/
error = alloc_new_map(children, MAP_ROWS_DEFAULT,
vdev_draid_rand(map_seed), &map);
- if (error)
+ if (error) {
+ if (best_map != NULL)
+ free_map(best_map);
return (error);
+ }
/*
* Consider maps with a lower worst_ratio to be of higher
@@ -767,7 +772,7 @@ static int
draid_generate(int argc, char *argv[])
{
char filename[MAXPATHLEN] = {0};
- uint64_t map_seed;
+ uint64_t map_seed[2];
int c, fd, error, verbose = 0, passes = 1, continuous = 0;
int min_children = VDEV_DRAID_MIN_CHILDREN;
int max_children = VDEV_DRAID_MAX_CHILDREN;
@@ -825,7 +830,7 @@ draid_generate(int argc, char *argv[])
}
if (argc > optind)
- strncpy(filename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(filename, argv[optind], sizeof (filename));
else {
(void) fprintf(stderr, "A FILE must be specified.\n");
return (1);
@@ -844,11 +849,12 @@ restart:
ssize_t bytes_read = 0;
while (bytes_read < bytes) {
- ssize_t rc = read(fd, ((char *)&map_seed) + bytes_read,
+ ssize_t rc = read(fd, ((char *)map_seed) + bytes_read,
bytes - bytes_read);
if (rc < 0) {
printf("Unable to read /dev/urandom: %s\n:",
strerror(errno));
+ close(fd);
return (1);
}
bytes_read += rc;
@@ -872,7 +878,7 @@ restart:
double worst_ratio = 1000.0;
double avg_ratio = 1000.0;
- error = eval_maps(children, passes, &map_seed, &map,
+ error = eval_maps(children, passes, map_seed, &map,
&worst_ratio, &avg_ratio);
if (error) {
printf("Error eval_maps(): %s\n", strerror(error));
@@ -956,9 +962,9 @@ draid_verify(int argc, char *argv[])
return (ENOMEM);
if (realpath(argv[optind], abspath) != NULL)
- strncpy(filename, abspath, MAXPATHLEN - 1);
+ strlcpy(filename, abspath, sizeof (filename));
else
- strncpy(filename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(filename, argv[optind], sizeof (filename));
free(abspath);
} else {
@@ -1165,7 +1171,7 @@ draid_dump(int argc, char *argv[])
}
if (argc > optind)
- strncpy(filename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(filename, argv[optind], sizeof (filename));
else {
(void) fprintf(stderr, "A FILE must be specified.\n");
return (1);
@@ -1202,7 +1208,7 @@ draid_table(int argc, char *argv[])
int error;
if (argc > optind)
- strncpy(filename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(filename, argv[optind], sizeof (filename));
else {
(void) fprintf(stderr, "A FILE must be specified.\n");
return (1);
@@ -1261,7 +1267,7 @@ draid_merge_impl(nvlist_t *allcfgs, const char *srcfilename, int *mergedp)
uint64_t nv_worst_ratio;
uint64_t allcfg_worst_ratio;
nvlist_t *cfg, *allcfg;
- char *key;
+ const char *key;
switch (nvpair_type(elem)) {
case DATA_TYPE_NVLIST:
@@ -1279,12 +1285,11 @@ draid_merge_impl(nvlist_t *allcfgs, const char *srcfilename, int *mergedp)
if (nv_worst_ratio < allcfg_worst_ratio) {
fnvlist_remove(allcfgs, key);
- error = nvlist_add_nvlist(allcfgs,
- key, cfg);
+ fnvlist_add_nvlist(allcfgs, key, cfg);
merged++;
}
} else if (error == ENOENT) {
- error = nvlist_add_nvlist(allcfgs, key, cfg);
+ fnvlist_add_nvlist(allcfgs, key, cfg);
merged++;
} else {
return (error);
@@ -1336,7 +1341,7 @@ draid_merge(int argc, char *argv[])
return (1);
}
- strncpy(filename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(filename, argv[optind], sizeof (filename));
optind++;
error = read_map(filename, &allcfgs);
@@ -1351,7 +1356,7 @@ draid_merge(int argc, char *argv[])
char srcfilename[MAXPATHLEN] = {0};
int merged = 0;
- strncpy(srcfilename, argv[optind], MAXPATHLEN - 1);
+ strlcpy(srcfilename, argv[optind], sizeof (srcfilename));
error = draid_merge_impl(allcfgs, srcfilename, &merged);
if (error) {
diff --git a/tests/zfs-tests/cmd/ereports.c b/tests/zfs-tests/cmd/ereports.c
index 392f5952d27a..42168997c0a8 100644
--- a/tests/zfs-tests/cmd/ereports.c
+++ b/tests/zfs-tests/cmd/ereports.c
@@ -62,7 +62,7 @@ static const char *const criteria_name[] = {
static void
print_ereport_line(nvlist_t *nvl)
{
- char *class;
+ const char *class;
int last = CRITERIA_NAMES_COUNT - 1;
/*
@@ -81,7 +81,7 @@ print_ereport_line(nvlist_t *nvl)
nvpair_t *nvp;
uint32_t i32 = 0;
uint64_t i64 = 0;
- char *str = NULL;
+ const char *str = NULL;
if (nvlist_lookup_nvpair(nvl, criteria_name[i], &nvp) != 0) {
/* print a proxy for optional criteria */
diff --git a/tests/zfs-tests/cmd/file/file_append.c b/tests/zfs-tests/cmd/file/file_append.c
index 32433e4fa2f6..3c2e196121e1 100644
--- a/tests/zfs-tests/cmd/file/file_append.c
+++ b/tests/zfs-tests/cmd/file/file_append.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/file/file_check.c b/tests/zfs-tests/cmd/file/file_check.c
index c93b56f45bba..1976beffaf28 100644
--- a/tests/zfs-tests/cmd/file/file_check.c
+++ b/tests/zfs-tests/cmd/file/file_check.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/file/file_common.h b/tests/zfs-tests/cmd/file/file_common.h
index f0c0e32b5f4e..2aedf2905aef 100644
--- a/tests/zfs-tests/cmd/file/file_common.h
+++ b/tests/zfs-tests/cmd/file/file_common.h
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/file/file_fadvise.c b/tests/zfs-tests/cmd/file/file_fadvise.c
new file mode 100644
index 000000000000..d64e2dea3696
--- /dev/null
+++ b/tests/zfs-tests/cmd/file/file_fadvise.c
@@ -0,0 +1,101 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2022 by Information2 Software, Inc. All rights reserved.
+ */
+
+#include "file_common.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+/*
+ * Call fadvise to prefetch data
+ */
+static const char *execname = "file_fadvise";
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr,
+ "usage: %s -f filename -a advise \n", execname);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *filename = NULL;
+ int advise = 0;
+ int fd, ch;
+ int err = 0;
+
+ while ((ch = getopt(argc, argv, "a:f:")) != EOF) {
+ switch (ch) {
+ case 'a':
+ advise = atoll(optarg);
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case '?':
+ (void) printf("unknown arg %c\n", optopt);
+ usage();
+ break;
+ }
+ }
+
+ if (!filename) {
+ (void) printf("Filename not specified (-f <file>)\n");
+ err++;
+ }
+
+ if (advise < POSIX_FADV_NORMAL || advise > POSIX_FADV_NOREUSE) {
+ (void) printf("advise is invalid\n");
+ err++;
+ }
+
+ if (err) {
+ usage(); /* no return */
+ return (1);
+ }
+
+ if ((fd = open(filename, O_RDWR, 0666)) < 0) {
+ perror("open");
+ return (1);
+ }
+
+ if (posix_fadvise(fd, 0, 0, advise) != 0) {
+ perror("posix_fadvise");
+ close(fd);
+ return (1);
+ }
+
+ close(fd);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/cmd/file/file_trunc.c b/tests/zfs-tests/cmd/file/file_trunc.c
index 69096752efa2..9e3bba24afdf 100644
--- a/tests/zfs-tests/cmd/file/file_trunc.c
+++ b/tests/zfs-tests/cmd/file/file_trunc.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -53,7 +53,7 @@ static long fsize = FSIZE;
static size_t bsize = BSIZE;
static int count = 0;
static int rflag = 0;
-static int seed = 0;
+static uint_t seed = 0;
static int vflag = 0;
static int errflag = 0;
static off_t offset = 0;
@@ -105,7 +105,7 @@ parse_options(int argc, char *argv[])
extern int optind, optopt;
count = fsize / bsize;
- seed = time(NULL);
+ seed = (uint_t)time(NULL);
while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
switch (c) {
case 'b':
diff --git a/tests/zfs-tests/cmd/file/file_write.c b/tests/zfs-tests/cmd/file/file_write.c
index 8791c151f66f..ce1fa5d9bc02 100644
--- a/tests/zfs-tests/cmd/file/file_write.c
+++ b/tests/zfs-tests/cmd/file/file_write.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/file/largest_file.c b/tests/zfs-tests/cmd/file/largest_file.c
index 5acb5f1db87d..d7252556b3cf 100644
--- a/tests/zfs-tests/cmd/file/largest_file.c
+++ b/tests/zfs-tests/cmd/file/largest_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -78,6 +78,8 @@ main(int argc, char **argv)
return (errno);
testfile = strdup(argv[1]);
+ if (testfile == NULL)
+ return (errno);
fd = open(testfile, O_CREAT | O_RDWR, mode);
if (fd < 0) {
diff --git a/tests/zfs-tests/cmd/file/randfree_file.c b/tests/zfs-tests/cmd/file/randfree_file.c
index e00780cd2e81..1bb897881830 100644
--- a/tests/zfs-tests/cmd/file/randfree_file.c
+++ b/tests/zfs-tests/cmd/file/randfree_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/file/randwritecomp.c b/tests/zfs-tests/cmd/file/randwritecomp.c
index cc70d1212f84..2d5c0ec8643c 100644
--- a/tests/zfs-tests/cmd/file/randwritecomp.c
+++ b/tests/zfs-tests/cmd/file/randwritecomp.c
@@ -152,6 +152,11 @@ main(int argc, char *argv[])
n = strtoull(argv[0], NULL, 0);
fd = open(filename, O_RDWR|O_CREAT, 0666);
+ if (fd == -1) {
+ (void) fprintf(stderr, "open(%s) failed: %s\n", filename,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
err = fstat(fd, &ss);
if (err != 0) {
(void) fprintf(stderr,
diff --git a/tests/zfs-tests/cmd/get_diff.c b/tests/zfs-tests/cmd/get_diff.c
index 3f8fe787f7b9..61467f25014c 100644
--- a/tests/zfs-tests/cmd/get_diff.c
+++ b/tests/zfs-tests/cmd/get_diff.c
@@ -96,7 +96,7 @@ main(int argc, char *argv[])
off += bytes;
}
- if (diff_len != 0 && diff_len != 0) {
+ if (diff_len != 0) {
(void) fprintf(stdout, "%lld,%lld\n", (long long)diff_off,
(long long)diff_len);
}
diff --git a/tests/zfs-tests/cmd/idmap_util.c b/tests/zfs-tests/cmd/idmap_util.c
new file mode 100644
index 000000000000..49483cbaa421
--- /dev/null
+++ b/tests/zfs-tests/cmd/idmap_util.c
@@ -0,0 +1,808 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <linux/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sched.h>
+#include <syscall.h>
+#include <sys/socket.h>
+
+#include <sys/list.h>
+
+#ifndef UINT_MAX
+#define UINT_MAX 4294967295U
+#endif
+
+#ifndef __NR_Linux
+#if defined __alpha__
+#define __NR_Linux 110
+#elif defined _MIPS_SIM
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define __NR_Linux 4000
+#endif
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+#define __NR_Linux 6000
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+#define __NR_Linux 5000
+#endif
+#elif defined __ia64__
+#define __NR_Linux 1024
+#else
+#define __NR_Linux 0
+#endif
+#endif
+
+#ifndef __NR_mount_setattr
+#define __NR_mount_setattr (442 + __NR_Linux)
+#endif
+
+#ifndef __NR_open_tree
+#define __NR_open_tree (428 + __NR_Linux)
+#endif
+
+#ifndef __NR_move_mount
+#define __NR_move_mount (429 + __NR_Linux)
+#endif
+
+#ifndef MNT_DETACH
+#define MNT_DETACH 2
+#endif
+
+#ifndef MOVE_MOUNT_F_EMPTY_PATH
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004
+#endif
+
+#ifndef MOUNT_ATTR_IDMAP
+#define MOUNT_ATTR_IDMAP 0x00100000
+#endif
+
+#ifndef OPEN_TREE_CLONE
+#define OPEN_TREE_CLONE 1
+#endif
+
+#ifndef OPEN_TREE_CLOEXEC
+#define OPEN_TREE_CLOEXEC O_CLOEXEC
+#endif
+
+#ifndef AT_RECURSIVE
+#define AT_RECURSIVE 0x8000
+#endif
+
+typedef struct {
+ __u64 attr_set;
+ __u64 attr_clr;
+ __u64 propagation;
+ __u64 userns_fd;
+} mount_attr_t;
+
+static inline int
+sys_mount_setattr(int dfd, const char *path, unsigned int flags,
+ mount_attr_t *attr, size_t size)
+{
+ return (syscall(__NR_mount_setattr, dfd, path, flags, attr, size));
+}
+
+static inline int
+sys_open_tree(int dfd, const char *filename, unsigned int flags)
+{
+ return (syscall(__NR_open_tree, dfd, filename, flags));
+}
+
+static inline int sys_move_mount(int from_dfd, const char *from_pathname,
+ int to_dfd, const char *to_pathname, unsigned int flags)
+{
+ return (syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd,
+ to_pathname, flags));
+}
+
+typedef enum idmap_type_t {
+ TYPE_UID,
+ TYPE_GID,
+ TYPE_BOTH
+} idmap_type_t;
+
+struct idmap_entry {
+ __u32 first;
+ __u32 lower_first;
+ __u32 count;
+ idmap_type_t type;
+ list_node_t node;
+};
+
+static void
+log_msg(const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
+
+#define log_errno(msg, args...) \
+ do { \
+ log_msg("%s:%d:%s: [%m] " msg, __FILE__, __LINE__,\
+ __FUNCTION__, ##args); \
+ } while (0)
+
+/*
+ * Parse the idmapping in the following format
+ * and add to the list:
+ *
+ * u:nsid_first:hostid_first:count
+ * g:nsid_first:hostid_first:count
+ * b:nsid_first:hostid_first:count
+ *
+ * The delimiter can be : or space character.
+ *
+ * Return:
+ * 0 if success
+ * ENOMEM if out of memory
+ * EINVAL if wrong arg or input
+ */
+static int
+parse_idmap_entry(list_t *head, char *input)
+{
+ char *token, *savedptr = NULL;
+ struct idmap_entry *entry;
+ unsigned long ul;
+ char *delimiter = (char *)": ";
+ char c;
+
+ if (!input || !head)
+ return (EINVAL);
+ entry = malloc(sizeof (*entry));
+ if (!entry)
+ return (ENOMEM);
+
+ token = strtok_r(input, delimiter, &savedptr);
+ if (token)
+ c = token[0];
+ if (!token || (c != 'b' && c != 'u' && c != 'g'))
+ goto errout;
+ entry->type = (c == 'b') ? TYPE_BOTH :
+ ((c == 'u') ? TYPE_UID : TYPE_GID);
+
+ token = strtok_r(NULL, delimiter, &savedptr);
+ if (!token)
+ goto errout;
+ ul = strtoul(token, NULL, 10);
+ if (ul > UINT_MAX || errno != 0)
+ goto errout;
+ entry->first = (__u32)ul;
+
+ token = strtok_r(NULL, delimiter, &savedptr);
+ if (!token)
+ goto errout;
+ ul = strtoul(token, NULL, 10);
+ if (ul > UINT_MAX || errno != 0)
+ goto errout;
+ entry->lower_first = (__u32)ul;
+
+ token = strtok_r(NULL, delimiter, &savedptr);
+ if (!token)
+ goto errout;
+ ul = strtoul(token, NULL, 10);
+ if (ul > UINT_MAX || errno != 0)
+ goto errout;
+ entry->count = (__u32)ul;
+
+ list_insert_tail(head, entry);
+
+ return (0);
+
+errout:
+ free(entry);
+ return (EINVAL);
+}
+
+/*
+ * Release all the entries in the list
+ */
+static void
+free_idmap(list_t *head)
+{
+ struct idmap_entry *entry;
+
+ while ((entry = list_remove_head(head)) != NULL)
+ free(entry);
+ /* list_destroy() to be done by the caller */
+}
+
+/*
+ * Write all bytes in the buffer to fd
+ */
+static ssize_t
+write_buf(int fd, const char *buf, size_t buf_size)
+{
+ ssize_t written, total_written = 0;
+ size_t remaining = buf_size;
+ char *position = (char *)buf;
+
+ for (;;) {
+ written = write(fd, position, remaining);
+ if (written < 0 && errno == EINTR)
+ continue;
+ if (written < 0) {
+ log_errno("write");
+ return (written);
+ }
+ total_written += written;
+ if (total_written == buf_size)
+ break;
+ remaining -= written;
+ position += written;
+ }
+
+ return (total_written);
+}
+
+/*
+ * Read data from file into buffer
+ */
+static ssize_t
+read_buf(int fd, char *buf, size_t buf_size)
+{
+ int ret;
+ for (;;) {
+ ret = read(fd, buf, buf_size);
+ if (ret < 0 && errno == EINTR)
+ continue;
+ break;
+ }
+ if (ret < 0)
+ log_errno("read");
+ return (ret);
+}
+
+/*
+ * Write idmap of the given type in the buffer to the
+ * process' uid_map or gid_map proc file.
+ *
+ * Return:
+ * 0 if success
+ * errno if there's any error
+ */
+static int
+write_idmap(pid_t pid, char *buf, size_t buf_size, idmap_type_t type)
+{
+ char path[PATH_MAX];
+ int fd = -EBADF;
+ int ret;
+
+ (void) snprintf(path, sizeof (path), "/proc/%d/%cid_map",
+ pid, type == TYPE_UID ? 'u' : 'g');
+ fd = open(path, O_WRONLY | O_CLOEXEC);
+ if (fd < 0) {
+ ret = errno;
+ log_errno("open(%s)", path);
+ goto out;
+ }
+ ret = write_buf(fd, buf, buf_size);
+ if (ret < 0)
+ ret = errno;
+ else
+ ret = 0;
+out:
+ if (fd >= 0)
+ close(fd);
+ return (ret);
+}
+
+/*
+ * Write idmap info in the list to the process
+ * user namespace, i.e. its /proc/<pid>/uid_map
+ * and /proc/<pid>/gid_map file.
+ *
+ * Return:
+ * 0 if success
+ * errno if it fails
+ */
+static int
+write_pid_idmaps(pid_t pid, list_t *head)
+{
+ char *buf_uids, *buf_gids;
+ char *curr_bufu, *curr_bufg;
+ /* max 4k to be allowed for each map */
+ int size_buf_uids = 4096, size_buf_gids = 4096;
+ struct idmap_entry *entry;
+ int uid_filled, gid_filled;
+ int ret = 0;
+ int has_uids = 0, has_gids = 0;
+ size_t buf_size;
+
+ buf_uids = malloc(size_buf_uids);
+ if (!buf_uids)
+ return (ENOMEM);
+ buf_gids = malloc(size_buf_gids);
+ if (!buf_gids) {
+ free(buf_uids);
+ return (ENOMEM);
+ }
+ curr_bufu = buf_uids;
+ curr_bufg = buf_gids;
+
+ for (entry = list_head(head); entry; entry = list_next(head, entry)) {
+ if (entry->type == TYPE_UID || entry->type == TYPE_BOTH) {
+ uid_filled = snprintf(curr_bufu, size_buf_uids,
+ "%u %u %u\n", entry->first, entry->lower_first,
+ entry->count);
+ if (uid_filled <= 0 || uid_filled >= size_buf_uids) {
+ ret = E2BIG;
+ goto out;
+ }
+ curr_bufu += uid_filled;
+ size_buf_uids -= uid_filled;
+ has_uids = 1;
+ }
+ if (entry->type == TYPE_GID || entry->type == TYPE_BOTH) {
+ gid_filled = snprintf(curr_bufg, size_buf_gids,
+ "%u %u %u\n", entry->first, entry->lower_first,
+ entry->count);
+ if (gid_filled <= 0 || gid_filled >= size_buf_gids) {
+ ret = E2BIG;
+ goto out;
+ }
+ curr_bufg += gid_filled;
+ size_buf_gids -= gid_filled;
+ has_gids = 1;
+ }
+ }
+ if (has_uids) {
+ buf_size = curr_bufu - buf_uids;
+ ret = write_idmap(pid, buf_uids, buf_size, TYPE_UID);
+ if (ret)
+ goto out;
+ }
+ if (has_gids) {
+ buf_size = curr_bufg - buf_gids;
+ ret = write_idmap(pid, buf_gids, buf_size, TYPE_GID);
+ }
+
+out:
+ free(buf_uids);
+ free(buf_gids);
+ return (ret);
+}
+
+/*
+ * Wait for the child process to exit
+ * and reap it.
+ *
+ * Return:
+ * process exit code if available
+ */
+static int
+wait_for_pid(pid_t pid)
+{
+ int status;
+ int ret;
+
+ for (;;) {
+ ret = waitpid(pid, &status, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ return (EXIT_FAILURE);
+ }
+ break;
+ }
+ if (!WIFEXITED(status))
+ return (EXIT_FAILURE);
+ return (WEXITSTATUS(status));
+}
+
+/*
+ * Get the file descriptor of the process user namespace
+ * given its pid.
+ *
+ * Return:
+ * fd if success
+ * -1 if it fails
+ */
+static int
+userns_fd_from_pid(pid_t pid)
+{
+ int fd;
+ char path[PATH_MAX];
+
+ (void) snprintf(path, sizeof (path), "/proc/%d/ns/user", pid);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ log_errno("open(%s)", path);
+ return (fd);
+}
+
+/*
+ * Get the user namespace file descriptor given a list
+ * of idmap info.
+ *
+ * Return:
+ * fd if success
+ * -errno if it fails
+ */
+static int
+userns_fd_from_idmap(list_t *head)
+{
+ pid_t pid;
+ int ret, fd;
+ int fds[2];
+ char c;
+ int saved_errno = 0;
+
+ /* socketpair for bidirectional communication */
+ ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
+ if (ret) {
+ log_errno("socketpair");
+ return (-errno);
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ log_errno("fork");
+ fd = -errno;
+ goto out;
+ }
+
+ if (pid == 0) {
+ /* child process */
+ ret = unshare(CLONE_NEWUSER);
+ if (ret == 0) {
+ /* notify the parent of success */
+ ret = write_buf(fds[1], "1", 1);
+ if (ret < 0)
+ saved_errno = errno;
+ else {
+ /*
+ * Until the parent has written to idmap,
+ * we cannot exit, otherwise the defunct
+ * process is owned by the real root, writing
+ * to its idmap ends up with EPERM in the
+ * context of a user ns
+ */
+ ret = read_buf(fds[1], &c, 1);
+ if (ret < 0)
+ saved_errno = errno;
+ }
+ } else {
+ saved_errno = errno;
+ log_errno("unshare");
+ ret = write_buf(fds[1], "0", 1);
+ if (ret < 0)
+ saved_errno = errno;
+ }
+ exit(saved_errno);
+ }
+
+ /* parent process */
+ ret = read_buf(fds[0], &c, 1);
+ if (ret == 1 && c == '1') {
+ ret = write_pid_idmaps(pid, head);
+ if (!ret) {
+ fd = userns_fd_from_pid(pid);
+ if (fd < 0)
+ fd = -errno;
+ } else {
+ fd = -ret;
+ }
+ /* Let child know it can exit */
+ (void) write_buf(fds[0], "1", 1);
+ } else {
+ fd = -EBADF;
+ }
+ (void) wait_for_pid(pid);
+out:
+ close(fds[0]);
+ close(fds[1]);
+ return (fd);
+}
+
+/*
+ * Check if the operating system supports idmapped mount on the
+ * given path or not.
+ *
+ * Return:
+ * true if supported
+ * false if not supported
+ */
+static bool
+is_idmap_supported(char *path)
+{
+ list_t head;
+ int ret;
+ int tree_fd = -EBADF, path_fd = -EBADF;
+ mount_attr_t attr = {
+ .attr_set = MOUNT_ATTR_IDMAP,
+ .userns_fd = -EBADF,
+ };
+
+ /* strtok_r() won't be happy with a const string */
+ /* To check if idmapped mount can be done in a user ns, map 0 to 0 */
+ char *input = strdup("b:0:0:1");
+
+ if (!input) {
+ errno = ENOMEM;
+ log_errno("strdup");
+ return (false);
+ }
+
+ list_create(&head, sizeof (struct idmap_entry),
+ offsetof(struct idmap_entry, node));
+ ret = parse_idmap_entry(&head, input);
+ if (ret) {
+ errno = ret;
+ log_errno("parse_idmap_entry(%s)", input);
+ goto out1;
+ }
+ ret = userns_fd_from_idmap(&head);
+ if (ret < 0)
+ goto out1;
+ attr.userns_fd = ret;
+ ret = openat(-EBADF, path, O_DIRECTORY | O_CLOEXEC);
+ if (ret < 0) {
+ log_errno("openat(%s)", path);
+ goto out;
+ }
+ path_fd = ret;
+ ret = sys_open_tree(path_fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT |
+ AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
+ if (ret < 0) {
+ log_errno("sys_open_tree");
+ goto out;
+ }
+ tree_fd = ret;
+ ret = sys_mount_setattr(tree_fd, "", AT_EMPTY_PATH, &attr,
+ sizeof (attr));
+ if (ret < 0) {
+ log_errno("sys_mount_setattr");
+ }
+out:
+ close(attr.userns_fd);
+out1:
+ free_idmap(&head);
+ list_destroy(&head);
+ if (tree_fd >= 0)
+ close(tree_fd);
+ if (path_fd >= 0)
+ close(path_fd);
+ free(input);
+ return (ret == 0);
+}
+
+/*
+ * Check if the given path is a mount point or not.
+ *
+ * Return:
+ * true if it is
+ * false otherwise
+ */
+static bool
+is_mountpoint(char *path)
+{
+ char *parent;
+ struct stat st_me, st_parent;
+ bool ret;
+
+ parent = malloc(strlen(path)+4);
+ if (!parent) {
+ errno = ENOMEM;
+ log_errno("malloc");
+ return (false);
+ }
+ strcat(strcpy(parent, path), "/..");
+ if (lstat(path, &st_me) != 0 ||
+ lstat(parent, &st_parent) != 0)
+ ret = false;
+ else
+ if (st_me.st_dev != st_parent.st_dev ||
+ st_me.st_ino == st_parent.st_ino)
+ ret = true;
+ else
+ ret = false;
+ free(parent);
+ return (ret);
+}
+
+/*
+ * Remount the source on the new target folder with the given
+ * list of idmap info. If target is NULL, the source will be
+ * unmounted and then remounted if it is a mountpoint, otherwise
+ * no unmount is done, the source is simply idmap remounted.
+ *
+ * Return:
+ * 0 if success
+ * -errno otherwise
+ */
+static int
+do_idmap_mount(list_t *idmap, char *source, char *target, int flags)
+{
+ int ret;
+ int tree_fd = -EBADF, source_fd = -EBADF;
+ mount_attr_t attr = {
+ .attr_set = MOUNT_ATTR_IDMAP,
+ .userns_fd = -EBADF,
+ };
+
+ ret = userns_fd_from_idmap(idmap);
+ if (ret < 0)
+ goto out1;
+ attr.userns_fd = ret;
+ ret = openat(-EBADF, source, O_DIRECTORY | O_CLOEXEC);
+ if (ret < 0) {
+ ret = -errno;
+ log_errno("openat(%s)", source);
+ goto out;
+ }
+ source_fd = ret;
+ ret = sys_open_tree(source_fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT |
+ AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE | flags);
+ if (ret < 0) {
+ ret = -errno;
+ log_errno("sys_open_tree");
+ goto out;
+ }
+ tree_fd = ret;
+ ret = sys_mount_setattr(tree_fd, "", AT_EMPTY_PATH | flags, &attr,
+ sizeof (attr));
+ if (ret < 0) {
+ ret = -errno;
+ log_errno("sys_mount_setattr");
+ goto out;
+ }
+ if (target == NULL && is_mountpoint(source)) {
+ ret = umount2(source, MNT_DETACH);
+ if (ret < 0) {
+ ret = -errno;
+ log_errno("umount2(%s)", source);
+ goto out;
+ }
+ }
+ ret = sys_move_mount(tree_fd, "", -EBADF, target == NULL ?
+ source : target, MOVE_MOUNT_F_EMPTY_PATH);
+ if (ret < 0) {
+ ret = -errno;
+ log_errno("sys_move_mount(%s)", target == NULL ?
+ source : target);
+ }
+out:
+ close(attr.userns_fd);
+out1:
+ if (tree_fd >= 0)
+ close(tree_fd);
+ if (source_fd >= 0)
+ close(source_fd);
+ return (ret);
+}
+
+static void
+print_usage(char *argv[])
+{
+ fprintf(stderr, "Usage: %s [-r] [-c] [-m <idmap1>] [-m <idmap2>]" \
+ " ... [<source>] [<target>]\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -r Recursively do idmapped mount.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -c Checks if idmapped mount is supported " \
+ "on the <source> by the operating system or not.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -m <idmap> to specify the idmap info, " \
+ "in the following format:\n");
+ fprintf(stderr, " <id_type>:<nsid_first>:<hostid_first>:<count>\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " <id_type> can be either of 'b', 'u', and 'g'.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "The <source> folder will be mounted at <target> " \
+ "with the provided idmap information.\nIf no <target> is " \
+ "specified, and <source> is a mount point, " \
+ "then <source> will be unmounted and then remounted.\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+ list_t idmap_head;
+ int check_supported = 0;
+ int ret = EXIT_SUCCESS;
+ char *source = NULL, *target = NULL;
+ int flags = 0;
+
+ list_create(&idmap_head, sizeof (struct idmap_entry),
+ offsetof(struct idmap_entry, node));
+
+ while ((opt = getopt(argc, argv, "rcm:")) != -1) {
+ switch (opt) {
+ case 'r':
+ flags |= AT_RECURSIVE;
+ break;
+ case 'c':
+ check_supported = 1;
+ break;
+ case 'm':
+ ret = parse_idmap_entry(&idmap_head, optarg);
+ if (ret) {
+ errno = ret;
+ log_errno("parse_idmap_entry(%s)", optarg);
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+ break;
+ default:
+ print_usage(argv);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (check_supported == 0 && list_is_empty(&idmap_head)) {
+ print_usage(argv);
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Expected to have <source>, <target>.\n");
+ print_usage(argv);
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+
+ source = argv[optind];
+ if (optind < (argc - 1)) {
+ target = argv[optind + 1];
+ }
+
+ if (check_supported) {
+ free_idmap(&idmap_head);
+ list_destroy(&idmap_head);
+ if (is_idmap_supported(source)) {
+ printf("idmapped mount is supported on [%s].\n",
+ source);
+ return (EXIT_SUCCESS);
+ } else {
+ printf("idmapped mount is NOT supported.\n");
+ return (EXIT_FAILURE);
+ }
+ }
+
+ ret = do_idmap_mount(&idmap_head, source, target, flags);
+ if (ret)
+ ret = EXIT_FAILURE;
+out:
+ free_idmap(&idmap_head);
+ list_destroy(&idmap_head);
+
+ exit(ret);
+}
diff --git a/tests/zfs-tests/cmd/libzfs_input_check.c b/tests/zfs-tests/cmd/libzfs_input_check.c
index e84a00273cf8..c661718a296c 100644
--- a/tests/zfs-tests/cmd/libzfs_input_check.c
+++ b/tests/zfs-tests/cmd/libzfs_input_check.c
@@ -27,6 +27,7 @@
#include <sys/vdev_impl.h>
#include <sys/zfs_ioctl.h>
#include <sys/zfs_bootenv.h>
+#include <sys/fs/zfs.h>
/*
* Test the nvpair inputs for the non-legacy zfs ioctl commands.
@@ -528,7 +529,11 @@ test_recv_new(const char *dataset, int fd)
ssize_t count;
int cleanup_fd = open(ZFS_DEV, O_RDWR);
-
+ if (cleanup_fd == -1) {
+ (void) fprintf(stderr, "open(%s) failed: %s\n", ZFS_DEV,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
(void) snprintf(snapshot, sizeof (snapshot), "%s@replicant", dataset);
count = pread(fd, &drr, sizeof (drr), 0);
@@ -545,6 +550,7 @@ test_recv_new(const char *dataset, int fd)
fnvlist_add_string(props, "org.openzfs:launch", "September 17th, 2013");
fnvlist_add_nvlist(optional, "localprops", props);
fnvlist_add_boolean(optional, "force");
+ fnvlist_add_boolean(optional, "heal");
fnvlist_add_int32(optional, "cleanup_fd", cleanup_fd);
/*
@@ -558,7 +564,7 @@ test_recv_new(const char *dataset, int fd)
fnvlist_add_uint64(optional, "action_handle", *action_handle);
#endif
IOC_INPUT_TEST(ZFS_IOC_RECV_NEW, dataset, required, optional,
- ZFS_ERR_STREAM_TRUNCATED);
+ ENOTSUP);
nvlist_free(props);
nvlist_free(optional);
@@ -683,6 +689,17 @@ test_vdev_trim(const char *pool)
nvlist_free(required);
}
+/* Test with invalid values */
+static void
+test_scrub(const char *pool)
+{
+ nvlist_t *required = fnvlist_alloc();
+ fnvlist_add_uint64(required, "scan_type", POOL_SCAN_FUNCS + 1);
+ fnvlist_add_uint64(required, "scan_command", POOL_SCRUB_FLAGS_END + 1);
+ IOC_INPUT_TEST(ZFS_IOC_POOL_SCRUB, pool, required, NULL, EINVAL);
+ nvlist_free(required);
+}
+
static int
zfs_destroy(const char *dataset)
{
@@ -863,6 +880,8 @@ zfs_ioc_input_tests(const char *pool)
test_set_bootenv(pool);
test_get_bootenv(pool);
+ test_scrub(pool);
+
/*
* cleanup
*/
@@ -1017,6 +1036,7 @@ validate_ioc_values(void)
CHECK(ZFS_IOC_BASE + 82 == ZFS_IOC_GET_BOOKMARK_PROPS);
CHECK(ZFS_IOC_BASE + 83 == ZFS_IOC_WAIT);
CHECK(ZFS_IOC_BASE + 84 == ZFS_IOC_WAIT_FS);
+ CHECK(ZFS_IOC_BASE + 87 == ZFS_IOC_POOL_SCRUB);
CHECK(ZFS_IOC_PLATFORM_BASE + 1 == ZFS_IOC_EVENTS_NEXT);
CHECK(ZFS_IOC_PLATFORM_BASE + 2 == ZFS_IOC_EVENTS_CLEAR);
CHECK(ZFS_IOC_PLATFORM_BASE + 3 == ZFS_IOC_EVENTS_SEEK);
diff --git a/tests/zfs-tests/cmd/mkbusy.c b/tests/zfs-tests/cmd/mkbusy.c
index cc4a6cfcb98c..78860381d880 100644
--- a/tests/zfs-tests/cmd/mkbusy.c
+++ b/tests/zfs-tests/cmd/mkbusy.c
@@ -148,14 +148,10 @@ main(int argc, char *argv[])
}
if (!isdir) {
- int fd;
-
- if ((fd = open(fpath, O_CREAT | O_RDWR, 0600)) < 0)
+ if (open(fpath, O_CREAT | O_RDWR, 0600) < 0)
fail("open");
} else {
- DIR *dp;
-
- if ((dp = opendir(fpath)) == NULL)
+ if (opendir(fpath) == NULL)
fail("opendir");
}
free(fpath);
diff --git a/tests/zfs-tests/cmd/mkfile.c b/tests/zfs-tests/cmd/mkfile.c
index ede05a1220af..3b61deed6bf5 100644
--- a/tests/zfs-tests/cmd/mkfile.c
+++ b/tests/zfs-tests/cmd/mkfile.c
@@ -7,7 +7,7 @@
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -276,5 +276,9 @@ main(int argc, char **argv)
argv++;
argc--;
}
+
+ if (buf)
+ free(buf);
+
return (errors);
}
diff --git a/tests/zfs-tests/cmd/mktree.c b/tests/zfs-tests/cmd/mktree.c
index 8ee86e5a01f0..8ab38ee83aa8 100644
--- a/tests/zfs-tests/cmd/mktree.c
+++ b/tests/zfs-tests/cmd/mktree.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/mmap_exec.c b/tests/zfs-tests/cmd/mmap_exec.c
index db90adbdca10..462f985398b6 100644
--- a/tests/zfs-tests/cmd/mmap_exec.c
+++ b/tests/zfs-tests/cmd/mmap_exec.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/mmap_libaio.c b/tests/zfs-tests/cmd/mmap_libaio.c
index a02f46d91b30..5ee1f600a737 100644
--- a/tests/zfs-tests/cmd/mmap_libaio.c
+++ b/tests/zfs-tests/cmd/mmap_libaio.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -33,7 +33,7 @@
#include <libaio.h>
#include <err.h>
-io_context_t io_ctx;
+static io_context_t io_ctx;
static void
do_sync_io(struct iocb *iocb)
diff --git a/tests/zfs-tests/cmd/mmap_seek.c b/tests/zfs-tests/cmd/mmap_seek.c
index bb36527aafee..7be92d109565 100644
--- a/tests/zfs-tests/cmd/mmap_seek.c
+++ b/tests/zfs-tests/cmd/mmap_seek.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/mmap_sync.c b/tests/zfs-tests/cmd/mmap_sync.c
index 0e4bba37d7be..226e71be2f57 100644
--- a/tests/zfs-tests/cmd/mmap_sync.c
+++ b/tests/zfs-tests/cmd/mmap_sync.c
@@ -32,7 +32,7 @@
static void
cleanup(char *file)
{
- remove(file);
+ (void) remove(file);
}
int
@@ -59,7 +59,7 @@ main(int argc, char *argv[])
return (1);
}
- int run_time_mins = 5;
+ int run_time_mins = 1;
if (argc >= 2) {
run_time_mins = atoi(argv[1]);
}
@@ -73,8 +73,7 @@ main(int argc, char *argv[])
filepath[0] = '\0';
char *file = &filepath[0];
- strcat(file, testdir);
- strcat(file, "/msync_file");
+ (void) snprintf(file, 512, "%s/msync_file", testdir);
const int LEN = 8;
cleanup(file);
@@ -125,7 +124,8 @@ main(int argc, char *argv[])
elapsed += ((t2.tv_usec - t1.tv_usec) / 1000.0);
if (elapsed > max_msync_time_ms) {
fprintf(stderr, "slow msync: %f ms\n", elapsed);
- munmap(ptr, LEN);
+ if (munmap(ptr, LEN) != 0)
+ perror("munmap");
cleanup(file);
return (1);
}
diff --git a/tests/zfs-tests/cmd/mmapwrite.c b/tests/zfs-tests/cmd/mmapwrite.c
index 1f344534d53e..20a50085a227 100644
--- a/tests/zfs-tests/cmd/mmapwrite.c
+++ b/tests/zfs-tests/cmd/mmapwrite.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -52,6 +52,7 @@
*/
#define NORMAL_WRITE_TH_NUM 2
+#define MAX_WRITE_BYTES 262144000
static void *
normal_writer(void *filename)
@@ -66,15 +67,26 @@ normal_writer(void *filename)
err(1, "failed to open %s", file_path);
}
- char buf;
- while (1) {
+ char buf = 'z';
+ off_t bytes_written = 0;
+
+ while (bytes_written < MAX_WRITE_BYTES) {
write_num = write(fd, &buf, 1);
if (write_num == 0) {
err(1, "write failed!");
break;
}
- lseek(fd, page_size, SEEK_CUR);
+ if ((bytes_written = lseek(fd, page_size, SEEK_CUR)) == -1) {
+ err(1, "lseek failed on %s: %s", file_path,
+ strerror(errno));
+ break;
+ }
}
+
+ if (close(fd) != 0)
+ err(1, "failed to close file");
+
+ return (NULL);
}
static void *
@@ -84,29 +96,21 @@ map_writer(void *filename)
int ret = 0;
char *buf = NULL;
int page_size = getpagesize();
- int op_errno = 0;
char *file_path = filename;
while (1) {
- ret = access(file_path, F_OK);
- if (ret) {
- op_errno = errno;
- if (op_errno == ENOENT) {
+ fd = open(file_path, O_RDWR);
+ if (fd == -1) {
+ if (errno == ENOENT) {
fd = open(file_path, O_RDWR | O_CREAT, 0777);
if (fd == -1) {
err(1, "open file failed");
}
-
ret = ftruncate(fd, page_size);
if (ret == -1) {
err(1, "truncate file failed");
}
} else {
- err(1, "access file failed!");
- }
- } else {
- fd = open(file_path, O_RDWR, 0777);
- if (fd == -1) {
err(1, "open file failed");
}
}
diff --git a/tests/zfs-tests/cmd/nvlist_to_lua.c b/tests/zfs-tests/cmd/nvlist_to_lua.c
index b65b3fd269d9..57a8f51e1cc0 100644
--- a/tests/zfs-tests/cmd/nvlist_to_lua.c
+++ b/tests/zfs-tests/cmd/nvlist_to_lua.c
@@ -39,7 +39,7 @@ nvlist_equal(nvlist_t *nvla, nvlist_t *nvlb)
*/
for (nvpair_t *pair = nvlist_next_nvpair(nvla, NULL);
pair != NULL; pair = nvlist_next_nvpair(nvla, pair)) {
- char *key = nvpair_name(pair);
+ const char *key = nvpair_name(pair);
if (!nvlist_exists(nvlb, key))
return (B_FALSE);
@@ -129,6 +129,11 @@ run_tests(void)
/* Note: maximum nvlist key length is 32KB */
int len = 1024 * 31;
char *bigstring = malloc(len);
+ if (bigstring == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
for (int i = 0; i < len; i++)
bigstring[i] = 'a' + i % 26;
bigstring[len - 1] = '\0';
diff --git a/tests/zfs-tests/cmd/readmmap.c b/tests/zfs-tests/cmd/readmmap.c
index f119e114d71e..a5c8079d0e46 100644
--- a/tests/zfs-tests/cmd/readmmap.c
+++ b/tests/zfs-tests/cmd/readmmap.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -44,6 +44,7 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
+#include <sys/types.h>
#include <time.h>
int
@@ -55,7 +56,7 @@ main(int argc, char **argv)
char *buf = NULL;
char *map = NULL;
int fd = -1, bytes, retval = 0;
- unsigned seed;
+ uint_t seed;
if (argc < 2 || optind == argc) {
(void) fprintf(stderr,
@@ -92,7 +93,7 @@ main(int argc, char **argv)
retval = 1;
goto end;
}
- seed = time(NULL);
+ seed = (uint_t)time(NULL);
srandom(seed);
idx = random() % size;
diff --git a/tests/zfs-tests/cmd/rename_dir.c b/tests/zfs-tests/cmd/rename_dir.c
index 3c3f45146e16..568cbfe720b9 100644
--- a/tests/zfs-tests/cmd/rename_dir.c
+++ b/tests/zfs-tests/cmd/rename_dir.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/renameat2.c b/tests/zfs-tests/cmd/renameat2.c
new file mode 100644
index 000000000000..ddd10ffc3ac7
--- /dev/null
+++ b/tests/zfs-tests/cmd/renameat2.c
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: CDDL-1.0 OR MPL-2.0 */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
+ * Copyright (C) 2019 SUSE LLC
+ */
+
+/*
+ * mv(1) doesn't currently support RENAME_{EXCHANGE,WHITEOUT} so this is a very
+ * simple renameat2(2) wrapper for the OpenZFS self-tests.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+#ifndef SYS_renameat2
+#ifdef __NR_renameat2
+#define SYS_renameat2 __NR_renameat2
+#elif defined(__x86_64__)
+#define SYS_renameat2 316
+#elif defined(__i386__)
+#define SYS_renameat2 353
+#elif defined(__arm__) || defined(__aarch64__)
+#define SYS_renameat2 382
+#else
+#error "SYS_renameat2 not known for this architecture."
+#endif
+#endif
+
+#ifndef RENAME_NOREPLACE
+#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
+#endif
+#ifndef RENAME_EXCHANGE
+#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
+#endif
+#ifndef RENAME_WHITEOUT
+#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
+#endif
+
+/* glibc doesn't provide renameat2 wrapper, let's use our own */
+static int
+sys_renameat2(int olddirfd, const char *oldpath,
+ int newdirfd, const char *newpath, unsigned int flags)
+{
+ int ret = syscall(SYS_renameat2, olddirfd, oldpath, newdirfd, newpath,
+ flags);
+ return ((ret < 0) ? -errno : ret);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: renameat2 [-Cnwx] src dst\n");
+ exit(1);
+}
+
+static void
+check(void)
+{
+ int err = sys_renameat2(AT_FDCWD, ".", AT_FDCWD, ".", RENAME_EXCHANGE);
+ exit(err == -ENOSYS);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *src, *dst;
+ int ch, err;
+ unsigned int flags = 0;
+
+ while ((ch = getopt(argc, argv, "Cnwx")) >= 0) {
+ switch (ch) {
+ case 'C':
+ check();
+ break;
+ case 'n':
+ flags |= RENAME_NOREPLACE;
+ break;
+ case 'w':
+ flags |= RENAME_WHITEOUT;
+ break;
+ case 'x':
+ flags |= RENAME_EXCHANGE;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+ src = argv[0];
+ dst = argv[1];
+
+ err = sys_renameat2(AT_FDCWD, src, AT_FDCWD, dst, flags);
+ if (err < 0)
+ fprintf(stderr, "renameat2: %s", strerror(-err));
+ return (err != 0);
+}
diff --git a/tests/zfs-tests/cmd/rm_lnkcnt_zero_file.c b/tests/zfs-tests/cmd/rm_lnkcnt_zero_file.c
index 9aeabb08e02f..0bf3b54cc090 100644
--- a/tests/zfs-tests/cmd/rm_lnkcnt_zero_file.c
+++ b/tests/zfs-tests/cmd/rm_lnkcnt_zero_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/send_doall.c b/tests/zfs-tests/cmd/send_doall.c
index 6f47df047478..e0ab6c41812c 100644
--- a/tests/zfs-tests/cmd/send_doall.c
+++ b/tests/zfs-tests/cmd/send_doall.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/stride_dd.c b/tests/zfs-tests/cmd/stride_dd.c
index 732ac9f47268..a20b26131650 100644
--- a/tests/zfs-tests/cmd/stride_dd.c
+++ b/tests/zfs-tests/cmd/stride_dd.c
@@ -25,8 +25,8 @@ static int bsize = 0;
static int count = 0;
static char *ifile = NULL;
static char *ofile = NULL;
-static int stride = 0;
-static int seek = 0;
+static off_t stride = 0;
+static off_t seek = 0;
static const char *execname = "stride_dd";
static void usage(void);
diff --git a/tests/zfs-tests/cmd/suid_write_to_file.c b/tests/zfs-tests/cmd/suid_write_to_file.c
index f3febb903b59..1a8157aa564f 100644
--- a/tests/zfs-tests/cmd/suid_write_to_file.c
+++ b/tests/zfs-tests/cmd/suid_write_to_file.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/threadsappend.c b/tests/zfs-tests/cmd/threadsappend.c
index 25710a3c12ef..b0ccd0ff6c42 100644
--- a/tests/zfs-tests/cmd/threadsappend.c
+++ b/tests/zfs-tests/cmd/threadsappend.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/user_ns_exec.c b/tests/zfs-tests/cmd/user_ns_exec.c
index cd46738bd0bd..d781301473a9 100644
--- a/tests/zfs-tests/cmd/user_ns_exec.c
+++ b/tests/zfs-tests/cmd/user_ns_exec.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -97,7 +97,6 @@ set_idmap(pid_t pid, const char *file)
mapfd = open(path, O_WRONLY);
if (mapfd < 0) {
- result = errno;
perror("open");
return (errno);
}
diff --git a/tests/zfs-tests/cmd/xattrtest.c b/tests/zfs-tests/cmd/xattrtest.c
index 4f82facb0682..4e72e9182b60 100644
--- a/tests/zfs-tests/cmd/xattrtest.c
+++ b/tests/zfs-tests/cmd/xattrtest.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/cmd/zed_fd_spill-zedlet.c b/tests/zfs-tests/cmd/zed_fd_spill-zedlet.c
index c072f906d23e..b248579abb7c 100644
--- a/tests/zfs-tests/cmd/zed_fd_spill-zedlet.c
+++ b/tests/zfs-tests/cmd/zed_fd_spill-zedlet.c
@@ -13,6 +13,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
@@ -28,7 +29,19 @@ int main(void) {
char buf[64];
sprintf(buf, "/tmp/zts-zed_fd_spill-logdir/%d", getppid());
- dup2(creat(buf, 0644), STDOUT_FILENO);
+ int fd = creat(buf, 0644);
+ if (fd == -1) {
+ (void) fprintf(stderr, "creat(%s) failed: %s\n", buf,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ close(fd);
+ (void) fprintf(stderr, "dup2(%s, STDOUT_FILENO) failed: %s\n",
+ buf, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
snprintf(buf, sizeof (buf), "/proc/%d/fd", getppid());
execlp("ls", "ls", buf, NULL);
diff --git a/tests/zfs-tests/cmd/zfs_diff-socket.c b/tests/zfs-tests/cmd/zfs_diff-socket.c
index be4bf31dde9f..3ebc95799fe3 100644
--- a/tests/zfs-tests/cmd/zfs_diff-socket.c
+++ b/tests/zfs-tests/cmd/zfs_diff-socket.c
@@ -37,8 +37,7 @@ main(int argc, char *argv[])
}
path = argv[1];
size = sizeof (sock.sun_path);
- strncpy(sock.sun_path, (char *)path, size - 1);
- sock.sun_path[size - 1] = '\0';
+ (void) snprintf(sock.sun_path, size, "%s", path);
sock.sun_family = AF_UNIX;
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
diff --git a/tests/zfs-tests/include/blkdev.shlib b/tests/zfs-tests/include/blkdev.shlib
index 6b83b10d604d..51eff3023e73 100644
--- a/tests/zfs-tests/include/blkdev.shlib
+++ b/tests/zfs-tests/include/blkdev.shlib
@@ -289,7 +289,7 @@ function get_persistent_disk_name #device
if is_linux; then
if is_real_device $device; then
udevadm info -q all -n $DEV_DSKDIR/$device \
- | awk '/disk\/by-id/ {print $2; exit}' | cut -d/ -f3
+ | awk '/disk\/by-id/ {print $2; exit}' | cut -d/ -f3-
elif is_mpath_device $device; then
udevadm info -q all -n $DEV_DSKDIR/$device \
| awk '/disk\/by-id\/dm-uuid/ {print $2; exit}' \
diff --git a/tests/zfs-tests/include/commands.cfg b/tests/zfs-tests/include/commands.cfg
index 47357dca57fb..daa794551682 100644
--- a/tests/zfs-tests/include/commands.cfg
+++ b/tests/zfs-tests/include/commands.cfg
@@ -98,7 +98,8 @@ export SYSTEM_FILES_COMMON='awk
uname
uniq
vmstat
- wc'
+ wc
+ xargs'
export SYSTEM_FILES_FREEBSD='chflags
compress
@@ -130,12 +131,14 @@ export SYSTEM_FILES_LINUX='attr
chattr
exportfs
fallocate
+ flock
free
getfattr
groupadd
groupdel
groupmod
hostid
+ logger
losetup
lsattr
lsblk
@@ -145,20 +148,20 @@ export SYSTEM_FILES_LINUX='attr
md5sum
mkswap
modprobe
+ mountpoint
mpstat
nsenter
parted
perf
setfattr
+ setpriv
sha256sum
udevadm
unshare
useradd
userdel
usermod
-
- flock
- logger'
+ wipefs'
export ZFS_FILES='zdb
zfs
@@ -169,6 +172,7 @@ export ZFS_FILES='zdb
raidz_test
arc_summary
arcstat
+ zilstat
dbufstat
mount.zfs
zed
@@ -180,9 +184,13 @@ export ZFS_FILES='zdb
export ZFSTEST_FILES='badsend
btree_test
chg_usr_exec
+ clonefile
+ clone_mmap_cached
+ clone_mmap_write
devname2devid
dir_rd_update
draid
+ file_fadvise
file_append
file_check
file_trunc
@@ -205,6 +213,7 @@ export ZFSTEST_FILES='badsend
randwritecomp
readmmap
read_dos_attributes
+ renameat2
rename_dir
rm_lnkcnt_zero_file
send_doall
@@ -224,4 +233,5 @@ export ZFSTEST_FILES='badsend
truncate_test
ereports
zfs_diff-socket
- dosmode_readonly_write'
+ dosmode_readonly_write
+ idmap_util'
diff --git a/tests/zfs-tests/include/default.cfg.in b/tests/zfs-tests/include/default.cfg.in
index a9a17de34ae7..db70a02a7828 100644
--- a/tests/zfs-tests/include/default.cfg.in
+++ b/tests/zfs-tests/include/default.cfg.in
@@ -8,7 +8,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -80,7 +80,7 @@ export TESTPOOL=testpool
export TESTPOOL1=testpool1
export TESTPOOL2=testpool2
export TESTPOOL3=testpool3
-export PERFPOOL=perfpool
+export PERFPOOL=${PERFPOOL:-perfpool}
# some test file system names
export TESTFS=testfs
@@ -156,7 +156,7 @@ done
export MAX_PARTITIONS=8
if [ "@ASAN_ENABLED@" = "yes" ]; then
- export ASAN_OPTIONS=abort_on_error=true:halt_on_error=true:allocator_may_return_null=true:disable_coredump=false:detect_stack_use_after_return=true
+ export ASAN_OPTIONS=abort_on_error=true:halt_on_error=true:allocator_may_return_null=true:disable_coredump=false:detect_stack_use_after_return=true:detect_odr_violation=1
# TODO
# disable memory leaks detection
diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib
index cb20318f44c5..dfab48d2cdaf 100644
--- a/tests/zfs-tests/include/libtest.shlib
+++ b/tests/zfs-tests/include/libtest.shlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -37,6 +37,12 @@
. ${STF_SUITE}/include/math.shlib
. ${STF_SUITE}/include/blkdev.shlib
+# On AlmaLinux 9 we will see $PWD = '.' instead of the full path. This causes
+# some tests to fail. Fix it up here.
+if [ "$PWD" = "." ] ; then
+ PWD="$(readlink -f $PWD)"
+fi
+
#
# Apply constrained path when available. This is required since the
# PATH may have been modified by sudo's secure_path behavior.
@@ -55,13 +61,8 @@ function compare_version_gte
[ "$(printf "$1\n$2" | sort -V | tail -n1)" = "$1" ]
}
-# Linux kernel version comparison function
-#
-# $1 Linux version ("4.10", "2.6.32") or blank for installed Linux version
-#
-# Used for comparison: if [ $(linux_version) -ge $(linux_version "2.6.32") ]
-#
-function linux_version
+# Helper function used by linux_version() and freebsd_version()
+function kernel_version
{
typeset ver="$1"
@@ -77,6 +78,24 @@ function linux_version
echo $((version * 100000 + major * 1000 + minor))
}
+# Linux kernel version comparison function
+#
+# $1 Linux version ("4.10", "2.6.32") or blank for installed Linux version
+#
+# Used for comparison: if [ $(linux_version) -ge $(linux_version "2.6.32") ]
+function linux_version {
+ kernel_version "$1"
+}
+
+# FreeBSD version comparison function
+#
+# $1 FreeBSD version ("13.2", "14.0") or blank for installed FreeBSD version
+#
+# Used for comparison: if [ $(freebsd_version) -ge $(freebsd_version "13.2") ]
+function freebsd_version {
+ kernel_version "$1"
+}
+
# Determine if this is a Linux test system
#
# Return 0 if platform Linux, 1 if otherwise
@@ -1265,7 +1284,7 @@ function is_shared_smb
datasetexists "$fs" || return
if is_linux; then
- net usershare list | grep -xFq "${fs//\//_}"
+ net usershare list | grep -xFq "${fs//[-\/]/_}"
else
log_note "SMB on $UNAME currently unsupported by the test framework"
return 1
@@ -1884,7 +1903,7 @@ function wait_hotspare_state # pool disk state timeout
#
# Return 0 is pool/disk matches expected state, 1 otherwise
#
-function check_vdev_state # pool disk state{online,offline,unavail}
+function check_vdev_state # pool disk state{online,offline,unavail,removed}
{
typeset pool=$1
typeset disk=${2#*$DEV_DSKDIR/}
@@ -1951,6 +1970,7 @@ function check_pool_status # pool token keyword <verbose>
# is_pool_removing - to check if the pool removing is a vdev
# is_pool_removed - to check if the pool remove is completed
# is_pool_discarding - to check if the pool checkpoint is being discarded
+# is_pool_replacing - to check if the pool is performing a replacement
#
function is_pool_resilvering #pool <verbose>
{
@@ -1968,6 +1988,12 @@ function is_pool_scrubbing #pool <verbose>
check_pool_status "$1" "scan" "scrub in progress since " $2
}
+function is_pool_error_scrubbing #pool <verbose>
+{
+ check_pool_status "$1" "scrub" "error scrub in progress since " $2
+ return $?
+}
+
function is_pool_scrubbed #pool <verbose>
{
check_pool_status "$1" "scan" "scrub repaired" $2
@@ -1978,11 +2004,23 @@ function is_pool_scrub_stopped #pool <verbose>
check_pool_status "$1" "scan" "scrub canceled" $2
}
+function is_pool_error_scrub_stopped #pool <verbose>
+{
+ check_pool_status "$1" "scrub" "error scrub canceled on " $2
+ return $?
+}
+
function is_pool_scrub_paused #pool <verbose>
{
check_pool_status "$1" "scan" "scrub paused since " $2
}
+function is_pool_error_scrub_paused #pool <verbose>
+{
+ check_pool_status "$1" "scrub" "error scrub paused since " $2
+ return $?
+}
+
function is_pool_removing #pool
{
check_pool_status "$1" "remove" "in progress since "
@@ -1997,6 +2035,10 @@ function is_pool_discarding #pool
{
check_pool_status "$1" "checkpoint" "discarding"
}
+function is_pool_replacing #pool
+{
+ zpool status "$1" | grep -qE 'replacing-[0-9]+'
+}
function wait_for_degraded
{
@@ -2983,12 +3025,15 @@ function wait_freeing #pool
# Wait for every device replace operation to complete
#
# $1 pool name
+# $2 timeout
#
-function wait_replacing #pool
+function wait_replacing #pool timeout
{
+ typeset timeout=${2:-300}
typeset pool=${1:-$TESTPOOL}
- while zpool status $pool | grep -qE 'replacing-[0-9]+'; do
- log_must sleep 1
+ for (( timer = 0; timer < $timeout; timer++ )); do
+ is_pool_replacing $pool || break;
+ sleep 1;
done
}
@@ -3308,6 +3353,21 @@ function set_tunable_impl
esac
}
+function save_tunable
+{
+ [[ ! -d $TEST_BASE_DIR ]] && return 1
+ [[ -e $TEST_BASE_DIR/tunable-$1 ]] && return 2
+ echo "$(get_tunable """$1""")" > "$TEST_BASE_DIR"/tunable-"$1"
+}
+
+function restore_tunable
+{
+ [[ ! -e $TEST_BASE_DIR/tunable-$1 ]] && return 1
+ val="$(cat $TEST_BASE_DIR/tunable-"""$1""")"
+ set_tunable64 "$1" "$val"
+ rm $TEST_BASE_DIR/tunable-$1
+}
+
#
# Get a global system tunable
#
@@ -3432,6 +3492,20 @@ function stat_size #<path>
esac
}
+function stat_mtime #<path>
+{
+ typeset path=$1
+
+ case "$UNAME" in
+ FreeBSD)
+ stat -f %m "$path"
+ ;;
+ *)
+ stat -c %Y "$path"
+ ;;
+ esac
+}
+
function stat_ctime #<path>
{
typeset path=$1
@@ -3666,7 +3740,7 @@ function arcstat_quiescence # stat echo
while $do_once || [ $stat1 -ne $stat2 ] || [ $stat2 -eq 0 ]; do
typeset stat1=$(get_arcstat $stat)
- sleep 2
+ sleep 0.5
typeset stat2=$(get_arcstat $stat)
do_once=false
done
diff --git a/tests/zfs-tests/include/math.shlib b/tests/zfs-tests/include/math.shlib
index 38d9fecea7cf..2b5e60180f59 100644
--- a/tests/zfs-tests/include/math.shlib
+++ b/tests/zfs-tests/include/math.shlib
@@ -118,22 +118,26 @@ function verify_ne # <a> <b> <type>
# A simple function to get a random number between two bounds (inclusive)
#
-# Probably not the most efficient for large ranges, but it's okay.
-#
-# Note since we're using $RANDOM, 32767 is the largest number we
+# Note since we're using $RANDOM, $min+32767 is the largest number we
# can accept as the upper bound.
#
# $1 lower bound
# $2 upper bound
+# [$3 how many]
function random_int_between
{
typeset -i min=$1
typeset -i max=$2
- typeset -i rand=0
+ typeset -i count
+ typeset -i i
- while [[ $rand -lt $min ]] ; do
- rand=$(( $RANDOM % $max + 1))
- done
+ if [[ -z "$3" ]]; then
+ count=1
+ else
+ count=$3
+ fi
- echo $rand
+ for (( i = 0; i < $count; i++ )); do
+ echo $(( (RANDOM % (max - min + 1)) + min ))
+ done
}
diff --git a/tests/zfs-tests/include/properties.shlib b/tests/zfs-tests/include/properties.shlib
index 14b3f4415b7d..3dfb295a40df 100644
--- a/tests/zfs-tests/include/properties.shlib
+++ b/tests/zfs-tests/include/properties.shlib
@@ -11,6 +11,7 @@
#
# Copyright (c) 2012, 2016, Delphix. All rights reserved.
+# Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
#
. $STF_SUITE/include/libtest.shlib
@@ -27,7 +28,7 @@ typeset -a canmount_prop_vals=('on' 'off' 'noauto')
typeset -a copies_prop_vals=('1' '2' '3')
typeset -a logbias_prop_vals=('latency' 'throughput')
typeset -a primarycache_prop_vals=('all' 'none' 'metadata')
-typeset -a redundant_metadata_prop_vals=('all' 'most')
+typeset -a redundant_metadata_prop_vals=('all' 'most' 'some' 'none')
typeset -a secondarycache_prop_vals=('all' 'none' 'metadata')
typeset -a snapdir_prop_vals=('hidden' 'visible')
typeset -a sync_prop_vals=('standard' 'always' 'disabled')
diff --git a/tests/zfs-tests/include/tunables.cfg b/tests/zfs-tests/include/tunables.cfg
index d6a2fe5db7c6..a619b846dd11 100644
--- a/tests/zfs-tests/include/tunables.cfg
+++ b/tests/zfs-tests/include/tunables.cfg
@@ -34,6 +34,7 @@ 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
DMU_OFFSET_NEXT_SYNC dmu_offset_next_sync zfs_dmu_offset_next_sync
+EMBEDDED_SLOG_MIN_MS embedded_slog_min_ms zfs_embedded_slog_min_ms
INITIALIZE_CHUNK_SIZE initialize_chunk_size zfs_initialize_chunk_size
INITIALIZE_VALUE initialize_value zfs_initialize_value
KEEP_LOG_SPACEMAPS_AT_EXPORT keep_log_spacemaps_at_export zfs_keep_log_spacemaps_at_export
@@ -62,6 +63,7 @@ MULTIHOST_IMPORT_INTERVALS multihost.import_intervals zfs_multihost_import_inter
MULTIHOST_INTERVAL multihost.interval zfs_multihost_interval
OVERRIDE_ESTIMATE_RECORDSIZE send.override_estimate_recordsize zfs_override_estimate_recordsize
PREFETCH_DISABLE prefetch.disable zfs_prefetch_disable
+RAIDZ_EXPAND_MAX_REFLOW_BYTES vdev.expand_max_reflow_bytes raidz_expand_max_reflow_bytes
REBUILD_SCRUB_ENABLED rebuild_scrub_enabled zfs_rebuild_scrub_enabled
REMOVAL_SUSPEND_PROGRESS removal_suspend_progress zfs_removal_suspend_progress
REMOVE_MAX_SEGMENT remove_max_segment zfs_remove_max_segment
@@ -69,6 +71,7 @@ RESILVER_MIN_TIME_MS resilver_min_time_ms zfs_resilver_min_time_ms
SCAN_LEGACY scan_legacy zfs_scan_legacy
SCAN_SUSPEND_PROGRESS scan_suspend_progress zfs_scan_suspend_progress
SCAN_VDEV_LIMIT scan_vdev_limit zfs_scan_vdev_limit
+SCRUB_AFTER_EXPAND scrub_after_expand zfs_scrub_after_expand
SEND_HOLES_WITHOUT_BIRTH_TIME send_holes_without_birth_time send_holes_without_birth_time
SLOW_IO_EVENTS_PER_SECOND slow_io_events_per_second zfs_slow_io_events_per_second
SPA_ASIZE_INFLATION spa.asize_inflation spa_asize_inflation
@@ -81,13 +84,17 @@ TRIM_TXG_BATCH trim.txg_batch zfs_trim_txg_batch
TXG_HISTORY txg.history zfs_txg_history
TXG_TIMEOUT txg.timeout zfs_txg_timeout
UNLINK_SUSPEND_PROGRESS UNSUPPORTED zfs_unlink_suspend_progress
+VDEV_FILE_LOGICAL_ASHIFT vdev.file.logical_ashift vdev_file_logical_ashift
VDEV_FILE_PHYSICAL_ASHIFT vdev.file.physical_ashift vdev_file_physical_ashift
+VDEV_MAX_AUTO_ASHIFT vdev.max_auto_ashift zfs_vdev_max_auto_ashift
VDEV_MIN_MS_COUNT vdev.min_ms_count zfs_vdev_min_ms_count
VDEV_VALIDATE_SKIP vdev.validate_skip vdev_validate_skip
VOL_INHIBIT_DEV UNSUPPORTED zvol_inhibit_dev
VOL_MODE vol.mode zvol_volmode
VOL_RECURSIVE vol.recursive UNSUPPORTED
VOL_USE_BLK_MQ UNSUPPORTED zvol_use_blk_mq
+BCLONE_ENABLED zfs_bclone_enabled zfs_bclone_enabled
+BCLONE_WAIT_DIRTY zfs_bclone_wait_dirty zfs_bclone_wait_dirty
XATTR_COMPAT xattr_compat zfs_xattr_compat
ZEVENT_LEN_MAX zevent.len_max zfs_zevent_len_max
ZEVENT_RETAIN_MAX zevent.retain_max zfs_zevent_retain_max
diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am
index 4c5b1121293e..d625c040b819 100644
--- a/tests/zfs-tests/tests/Makefile.am
+++ b/tests/zfs-tests/tests/Makefile.am
@@ -90,6 +90,10 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/alloc_class/alloc_class.kshlib \
functional/atime/atime.cfg \
functional/atime/atime_common.kshlib \
+ functional/bclone/bclone.cfg \
+ functional/bclone/bclone_common.kshlib \
+ functional/bclone/bclone_corner_cases.kshlib \
+ functional/block_cloning/block_cloning.kshlib \
functional/cache/cache.cfg \
functional/cache/cache.kshlib \
functional/cachefile/cachefile.cfg \
@@ -129,6 +133,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/channel_program/synctask_core/tst.snapshot_destroy.zcp \
functional/channel_program/synctask_core/tst.snapshot_neg.zcp \
functional/channel_program/synctask_core/tst.snapshot_recursive.zcp \
+ functional/channel_program/synctask_core/tst.snapshot_rename.zcp \
functional/channel_program/synctask_core/tst.snapshot_simple.zcp \
functional/checksum/default.cfg \
functional/clean_mirror/clean_mirror_common.kshlib \
@@ -177,6 +182,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/cli_root/zpool_expand/zpool_expand.cfg \
functional/cli_root/zpool_export/zpool_export.cfg \
functional/cli_root/zpool_export/zpool_export.kshlib \
+ functional/cli_root/zpool_get/vdev_get.cfg \
functional/cli_root/zpool_get/zpool_get.cfg \
functional/cli_root/zpool_get/zpool_get_parsable.cfg \
functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2 \
@@ -248,6 +254,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/cli_root/zpool_upgrade/zpool_upgrade.cfg \
functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib \
functional/cli_root/zpool_wait/zpool_wait.kshlib \
+ functional/cli_root/zhack/library.kshlib \
functional/cli_user/misc/misc.cfg \
functional/cli_user/zfs_list/zfs_list.cfg \
functional/cli_user/zfs_list/zfs_list.kshlib \
@@ -367,6 +374,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/upgrade/upgrade_common.kshlib \
functional/user_namespace/user_namespace.cfg \
functional/user_namespace/user_namespace_common.kshlib \
+ functional/userquota/13709_reproducer.bz2 \
functional/userquota/userquota.cfg \
functional/userquota/userquota_common.kshlib \
functional/vdev_zaps/vdev_zaps.kshlib \
@@ -377,7 +385,9 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/zvol/zvol_common.shlib \
functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg \
functional/zvol/zvol_misc/zvol_misc_common.kshlib \
- functional/zvol/zvol_swap/zvol_swap.cfg
+ functional/zvol/zvol_swap/zvol_swap.cfg \
+ functional/idmap_mount/idmap_mount.cfg \
+ functional/idmap_mount/idmap_mount_common.kshlib
nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/acl/off/cleanup.ksh \
@@ -409,6 +419,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/alloc_class/alloc_class_011_neg.ksh \
functional/alloc_class/alloc_class_012_pos.ksh \
functional/alloc_class/alloc_class_013_pos.ksh \
+ functional/alloc_class/alloc_class_014_neg.ksh \
+ functional/alloc_class/alloc_class_015_pos.ksh \
functional/alloc_class/cleanup.ksh \
functional/alloc_class/setup.ksh \
functional/append/file_append.ksh \
@@ -429,6 +441,43 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/atime/root_atime_on.ksh \
functional/atime/root_relatime_on.ksh \
functional/atime/setup.ksh \
+ functional/bclone/bclone_crossfs_corner_cases.ksh \
+ functional/bclone/bclone_crossfs_corner_cases_limited.ksh \
+ functional/bclone/bclone_crossfs_data.ksh \
+ functional/bclone/bclone_crossfs_embedded.ksh \
+ functional/bclone/bclone_crossfs_hole.ksh \
+ functional/bclone/bclone_diffprops_all.ksh \
+ functional/bclone/bclone_diffprops_checksum.ksh \
+ functional/bclone/bclone_diffprops_compress.ksh \
+ functional/bclone/bclone_diffprops_copies.ksh \
+ functional/bclone/bclone_diffprops_recordsize.ksh \
+ functional/bclone/bclone_prop_sync.ksh \
+ functional/bclone/bclone_samefs_corner_cases.ksh \
+ functional/bclone/bclone_samefs_corner_cases_limited.ksh \
+ functional/bclone/bclone_samefs_data.ksh \
+ functional/bclone/bclone_samefs_embedded.ksh \
+ functional/bclone/bclone_samefs_hole.ksh \
+ functional/bclone/cleanup.ksh \
+ functional/bclone/setup.ksh \
+ functional/block_cloning/cleanup.ksh \
+ functional/block_cloning/setup.ksh \
+ functional/block_cloning/block_cloning_clone_mmap_cached.ksh \
+ functional/block_cloning/block_cloning_clone_mmap_write.ksh \
+ functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh \
+ functional/block_cloning/block_cloning_copyfilerange_fallback.ksh \
+ functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh \
+ functional/block_cloning/block_cloning_copyfilerange.ksh \
+ functional/block_cloning/block_cloning_copyfilerange_partial.ksh \
+ functional/block_cloning/block_cloning_disabled_copyfilerange.ksh \
+ functional/block_cloning/block_cloning_disabled_ficlone.ksh \
+ functional/block_cloning/block_cloning_disabled_ficlonerange.ksh \
+ functional/block_cloning/block_cloning_ficlone.ksh \
+ functional/block_cloning/block_cloning_ficlonerange.ksh \
+ functional/block_cloning/block_cloning_ficlonerange_partial.ksh \
+ functional/block_cloning/block_cloning_cross_enc_dataset.ksh \
+ functional/block_cloning/block_cloning_replay.ksh \
+ functional/block_cloning/block_cloning_replay_encrypted.ksh \
+ functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh \
functional/bootfs/bootfs_001_pos.ksh \
functional/bootfs/bootfs_002_neg.ksh \
functional/bootfs/bootfs_003_pos.ksh \
@@ -536,6 +585,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/channel_program/synctask_core/tst.snapshot_destroy.ksh \
functional/channel_program/synctask_core/tst.snapshot_neg.ksh \
functional/channel_program/synctask_core/tst.snapshot_recursive.ksh \
+ functional/channel_program/synctask_core/tst.snapshot_rename.ksh \
functional/channel_program/synctask_core/tst.snapshot_simple.ksh \
functional/channel_program/synctask_core/tst.terminate_by_signal.ksh \
functional/chattr/chattr_001_pos.ksh \
@@ -556,6 +606,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/clean_mirror/clean_mirror_004_pos.ksh \
functional/clean_mirror/cleanup.ksh \
functional/clean_mirror/setup.ksh \
+ functional/cli_root/zinject/zinject_args.ksh \
functional/cli_root/zdb/zdb_002_pos.ksh \
functional/cli_root/zdb/zdb_003_pos.ksh \
functional/cli_root/zdb/zdb_004_pos.ksh \
@@ -563,11 +614,13 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zdb/zdb_006_pos.ksh \
functional/cli_root/zdb/zdb_args_neg.ksh \
functional/cli_root/zdb/zdb_args_pos.ksh \
+ functional/cli_root/zdb/zdb_backup.ksh \
functional/cli_root/zdb/zdb_block_size_histogram.ksh \
functional/cli_root/zdb/zdb_checksum.ksh \
functional/cli_root/zdb/zdb_decompress.ksh \
functional/cli_root/zdb/zdb_decompress_zstd.ksh \
functional/cli_root/zdb/zdb_display_block.ksh \
+ functional/cli_root/zdb/zdb_encrypted.ksh \
functional/cli_root/zdb/zdb_label_checksum.ksh \
functional/cli_root/zdb/zdb_object_range_neg.ksh \
functional/cli_root/zdb/zdb_object_range_pos.ksh \
@@ -717,6 +770,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_mount/zfs_mount_all_fail.ksh \
functional/cli_root/zfs_mount/zfs_mount_all_mountpoints.ksh \
functional/cli_root/zfs_mount/zfs_mount_encrypted.ksh \
+ functional/cli_root/zfs_mount/zfs_mount_recursive.ksh \
functional/cli_root/zfs_mount/zfs_mount_remount.ksh \
functional/cli_root/zfs_mount/zfs_mount_test_race.ksh \
functional/cli_root/zfs_mount/zfs_multi_mount.ksh \
@@ -766,6 +820,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_receive/zfs_receive_raw.ksh \
functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh \
functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh \
+ functional/cli_root/zfs_receive/zfs_receive_corrective.ksh \
+ functional/cli_root/zfs_receive/zfs_receive_compressed_corrective.ksh \
+ functional/cli_root/zfs_receive/zfs_receive_large_block_corrective.ksh \
functional/cli_root/zfs_rename/cleanup.ksh \
functional/cli_root/zfs_rename/setup.ksh \
functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh \
@@ -842,6 +899,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_set/zfs_set_003_neg.ksh \
functional/cli_root/zfs_set/zfs_set_feature_activation.ksh \
functional/cli_root/zfs_set/zfs_set_keylocation.ksh \
+ functional/cli_root/zfs_set/zfs_set_nomount.ksh \
functional/cli_root/zfs_share/cleanup.ksh \
functional/cli_root/zfs_share/setup.ksh \
functional/cli_root/zfs_share/zfs_share_001_pos.ksh \
@@ -858,6 +916,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_share/zfs_share_012_pos.ksh \
functional/cli_root/zfs_share/zfs_share_013_pos.ksh \
functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh \
+ functional/cli_root/zfs_share/zfs_share_after_mount.ksh \
functional/cli_root/zfs_snapshot/cleanup.ksh \
functional/cli_root/zfs_snapshot/setup.ksh \
functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh \
@@ -922,12 +981,16 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs/zfs_001_neg.ksh \
functional/cli_root/zfs/zfs_002_pos.ksh \
functional/cli_root/zfs/zfs_003_neg.ksh \
- functional/cli_root/zhack/zhack_label_checksum.ksh \
+ functional/cli_root/zhack/zhack_label_repair_001.ksh \
+ functional/cli_root/zhack/zhack_label_repair_002.ksh \
+ functional/cli_root/zhack/zhack_label_repair_003.ksh \
+ functional/cli_root/zhack/zhack_label_repair_004.ksh \
functional/cli_root/zpool_add/add_nested_replacing_spare.ksh \
functional/cli_root/zpool_add/add-o_ashift.ksh \
functional/cli_root/zpool_add/add_prop_ashift.ksh \
functional/cli_root/zpool_add/cleanup.ksh \
functional/cli_root/zpool_add/setup.ksh \
+ functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh \
functional/cli_root/zpool_add/zpool_add_001_pos.ksh \
functional/cli_root/zpool_add/zpool_add_002_pos.ksh \
functional/cli_root/zpool_add/zpool_add_003_pos.ksh \
@@ -1023,6 +1086,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_export/zpool_export_004_pos.ksh \
functional/cli_root/zpool_get/cleanup.ksh \
functional/cli_root/zpool_get/setup.ksh \
+ functional/cli_root/zpool_get/vdev_get_001_pos.ksh \
functional/cli_root/zpool_get/zpool_get_001_pos.ksh \
functional/cli_root/zpool_get/zpool_get_002_pos.ksh \
functional/cli_root/zpool_get/zpool_get_003_pos.ksh \
@@ -1041,6 +1105,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_import/import_cachefile_paths_changed.ksh \
functional/cli_root/zpool_import/import_cachefile_shared_device.ksh \
functional/cli_root/zpool_import/import_devices_missing.ksh \
+ functional/cli_root/zpool_import/import_log_missing.ksh \
functional/cli_root/zpool_import/import_paths_changed.ksh \
functional/cli_root/zpool_import/import_rewind_config_changed.ksh \
functional/cli_root/zpool_import/import_rewind_device_replaced.ksh \
@@ -1070,10 +1135,18 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh \
functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh \
functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh \
+ functional/cli_root/zpool_import/zpool_import_hostid_changed.ksh \
+ functional/cli_root/zpool_import/zpool_import_hostid_changed_unclean_export.ksh \
+ functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile.ksh \
+ functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile_unclean_export.ksh \
functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh \
functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh \
functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh \
functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh \
+ functional/cli_root/zpool_import/zpool_import_status.ksh \
+ functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh \
+ functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh \
+ functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh \
functional/cli_root/zpool_initialize/cleanup.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh \
@@ -1084,6 +1157,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh \
+ functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh \
@@ -1123,6 +1197,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_resilver/setup.ksh \
functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh \
functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh \
+ functional/cli_root/zpool_resilver/zpool_resilver_concurrent.ksh \
functional/cli_root/zpool_scrub/cleanup.ksh \
functional/cli_root/zpool_scrub/setup.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh \
@@ -1134,13 +1209,21 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh \
+ functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh \
+ functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh \
+ functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh \
+ functional/cli_root/zpool_scrub/zpool_error_scrub_004_pos.ksh \
functional/cli_root/zpool_set/cleanup.ksh \
functional/cli_root/zpool_set/setup.ksh \
functional/cli_root/zpool/setup.ksh \
+ functional/cli_root/zpool_set/vdev_set_001_pos.ksh \
+ functional/cli_root/zpool_set/zpool_set_common.kshlib \
functional/cli_root/zpool_set/zpool_set_001_pos.ksh \
functional/cli_root/zpool_set/zpool_set_002_neg.ksh \
functional/cli_root/zpool_set/zpool_set_003_neg.ksh \
functional/cli_root/zpool_set/zpool_set_ashift.ksh \
+ functional/cli_root/zpool_set/user_property_001_pos.ksh \
+ functional/cli_root/zpool_set/user_property_002_neg.ksh \
functional/cli_root/zpool_set/zpool_set_features.ksh \
functional/cli_root/zpool_split/cleanup.ksh \
functional/cli_root/zpool_split/setup.ksh \
@@ -1159,6 +1242,10 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_status/zpool_status_002_pos.ksh \
functional/cli_root/zpool_status/zpool_status_003_pos.ksh \
functional/cli_root/zpool_status/zpool_status_004_pos.ksh \
+ functional/cli_root/zpool_status/zpool_status_005_pos.ksh \
+ functional/cli_root/zpool_status/zpool_status_006_pos.ksh \
+ functional/cli_root/zpool_status/zpool_status_007_pos.ksh \
+ functional/cli_root/zpool_status/zpool_status_008_pos.ksh \
functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh \
functional/cli_root/zpool_sync/cleanup.ksh \
functional/cli_root/zpool_sync/setup.ksh \
@@ -1227,6 +1314,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_user/misc/arcstat_001_pos.ksh \
functional/cli_user/misc/arc_summary_001_pos.ksh \
functional/cli_user/misc/arc_summary_002_neg.ksh \
+ functional/cli_user/misc/zilstat_001_pos.ksh \
functional/cli_user/misc/cleanup.ksh \
functional/cli_user/misc/setup.ksh \
functional/cli_user/misc/zdb_001_neg.ksh \
@@ -1313,6 +1401,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/compression/setup.ksh \
functional/cp_files/cleanup.ksh \
functional/cp_files/cp_files_001_pos.ksh \
+ functional/cp_files/cp_files_002_pos.ksh \
+ functional/cp_files/cp_stress.ksh \
functional/cp_files/setup.ksh \
functional/crtime/cleanup.ksh \
functional/crtime/crtime_001_pos.ksh \
@@ -1358,12 +1448,20 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/events/events_001_pos.ksh \
functional/events/events_002_pos.ksh \
functional/events/setup.ksh \
+ functional/events/zed_cksum_config.ksh \
+ functional/events/zed_cksum_reported.ksh \
functional/events/zed_fd_spill.ksh \
+ functional/events/zed_io_config.ksh \
functional/events/zed_rc_filter.ksh \
+ functional/events/zed_slow_io.ksh \
+ functional/events/zed_slow_io_many_vdevs.ksh \
functional/exec/cleanup.ksh \
functional/exec/exec_001_pos.ksh \
functional/exec/exec_002_neg.ksh \
functional/exec/setup.ksh \
+ functional/fadvise/cleanup.ksh \
+ functional/fadvise/fadvise_sequential.ksh \
+ functional/fadvise/setup.ksh \
functional/fallocate/cleanup.ksh \
functional/fallocate/fallocate_prealloc.ksh \
functional/fallocate/fallocate_punch-hole.ksh \
@@ -1373,6 +1471,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/fault/auto_online_001_pos.ksh \
functional/fault/auto_online_002_pos.ksh \
functional/fault/auto_replace_001_pos.ksh \
+ functional/fault/auto_replace_002_pos.ksh \
functional/fault/auto_spare_001_pos.ksh \
functional/fault/auto_spare_002_pos.ksh \
functional/fault/auto_spare_ashift.ksh \
@@ -1476,6 +1575,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/migration/setup.ksh \
functional/mmap/cleanup.ksh \
functional/mmap/mmap_libaio_001_pos.ksh \
+ functional/mmap/mmap_mixed.ksh \
functional/mmap/mmap_read_001_pos.ksh \
functional/mmap/mmap_seek_001_pos.ksh \
functional/mmap/mmap_sync_001_pos.ksh \
@@ -1493,6 +1593,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/mmp/mmp_on_zdb.ksh \
functional/mmp/mmp_reset_interval.ksh \
functional/mmp/mmp_write_distribution.ksh \
+ functional/mmp/mmp_write_slow_disk.ksh \
functional/mmp/mmp_write_uberblocks.ksh \
functional/mmp/multihost_history.ksh \
functional/mmp/setup.ksh \
@@ -1524,6 +1625,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/no_space/enospc_002_pos.ksh \
functional/no_space/enospc_003_pos.ksh \
functional/no_space/enospc_df.ksh \
+ functional/no_space/enospc_ganging.ksh \
functional/no_space/enospc_rm.ksh \
functional/no_space/setup.ksh \
functional/online_offline/cleanup.ksh \
@@ -1533,7 +1635,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/online_offline/setup.ksh \
functional/pam/cleanup.ksh \
functional/pam/pam_basic.ksh \
+ functional/pam/pam_change_unmounted.ksh \
functional/pam/pam_nounmount.ksh \
+ functional/pam/pam_recursive.ksh \
functional/pam/pam_short_password.ksh \
functional/pam/setup.ksh \
functional/pool_checkpoint/checkpoint_after_rewind.ksh \
@@ -1605,8 +1709,14 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/raidz/cleanup.ksh \
functional/raidz/raidz_001_neg.ksh \
functional/raidz/raidz_002_pos.ksh \
- functional/raidz/raidz_003_pos.ksh \
- functional/raidz/raidz_004_pos.ksh \
+ functional/raidz/raidz_expand_001_pos.ksh \
+ functional/raidz/raidz_expand_002_pos.ksh \
+ functional/raidz/raidz_expand_003_neg.ksh \
+ functional/raidz/raidz_expand_003_pos.ksh \
+ functional/raidz/raidz_expand_004_pos.ksh \
+ functional/raidz/raidz_expand_005_pos.ksh \
+ functional/raidz/raidz_expand_006_neg.ksh \
+ functional/raidz/raidz_expand_007_neg.ksh \
functional/raidz/setup.ksh \
functional/redacted_send/cleanup.ksh \
functional/redacted_send/redacted_compressed.ksh \
@@ -1682,6 +1792,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/removal/removal_with_export.ksh \
functional/removal/removal_with_faulted.ksh \
functional/removal/removal_with_ganging.ksh \
+ functional/removal/removal_with_indirect.ksh \
functional/removal/removal_with_remove.ksh \
functional/removal/removal_with_scrub.ksh \
functional/removal/removal_with_send.ksh \
@@ -1698,6 +1809,11 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/rename_dirs/cleanup.ksh \
functional/rename_dirs/rename_dirs_001_pos.ksh \
functional/rename_dirs/setup.ksh \
+ functional/renameat2/cleanup.ksh \
+ functional/renameat2/setup.ksh \
+ functional/renameat2/renameat2_exchange.ksh \
+ functional/renameat2/renameat2_noreplace.ksh \
+ functional/renameat2/renameat2_whiteout.ksh \
functional/replacement/attach_import.ksh \
functional/replacement/attach_multiple.ksh \
functional/replacement/attach_rebuild.ksh \
@@ -1771,11 +1887,12 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/rsend/rsend_027_pos.ksh \
functional/rsend/rsend_028_neg.ksh \
functional/rsend/rsend_029_neg.ksh \
+ functional/rsend/rsend_030_pos.ksh \
+ functional/rsend/rsend_031_pos.ksh \
functional/rsend/send-c_embedded_blocks.ksh \
functional/rsend/send-c_incremental.ksh \
functional/rsend/send-c_lz4_disabled.ksh \
functional/rsend/send-c_mixed_compression.ksh \
- functional/rsend/send-cpL_varied_recsize.ksh \
functional/rsend/send-c_props.ksh \
functional/rsend/send-c_recv_dedup.ksh \
functional/rsend/send-c_recv_lz4_disabled.ksh \
@@ -1784,9 +1901,13 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/rsend/send-c_verify_contents.ksh \
functional/rsend/send-c_verify_ratio.ksh \
functional/rsend/send-c_volume.ksh \
+ functional/rsend/send-c_zstream_recompress.ksh \
functional/rsend/send-c_zstreamdump.ksh \
+ functional/rsend/send-cpL_varied_recsize.ksh \
functional/rsend/send_doall.ksh \
+ functional/rsend/send_encrypted_incremental.ksh \
functional/rsend/send_encrypted_files.ksh \
+ functional/rsend/send_encrypted_freeobjects.ksh \
functional/rsend/send_encrypted_hierarchy.ksh \
functional/rsend/send_encrypted_props.ksh \
functional/rsend/send_encrypted_truncated_files.ksh \
@@ -1799,6 +1920,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/rsend/send_partial_dataset.ksh \
functional/rsend/send_raw_ashift.ksh \
functional/rsend/send_raw_spill_block.ksh \
+ functional/rsend/send_raw_large_blocks.ksh \
functional/rsend/send_realloc_dnode_size.ksh \
functional/rsend/send_realloc_encrypted_files.ksh \
functional/rsend/send_realloc_files.ksh \
@@ -1855,6 +1977,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/snapshot/snapshot_015_pos.ksh \
functional/snapshot/snapshot_016_pos.ksh \
functional/snapshot/snapshot_017_pos.ksh \
+ functional/snapshot/snapshot_018_pos.ksh \
functional/snapused/cleanup.ksh \
functional/snapused/setup.ksh \
functional/snapused/snapused_001_pos.ksh \
@@ -1922,6 +2045,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/userquota/userspace_003_pos.ksh \
functional/userquota/userspace_encrypted.ksh \
functional/userquota/userspace_send_encrypted.ksh \
+ functional/userquota/userspace_encrypted_13709.ksh \
functional/vdev_zaps/cleanup.ksh \
functional/vdev_zaps/setup.ksh \
functional/vdev_zaps/vdev_zaps_001_pos.ksh \
@@ -1951,6 +2075,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/xattr/xattr_012_pos.ksh \
functional/xattr/xattr_013_pos.ksh \
functional/xattr/xattr_compat.ksh \
+ functional/zap_shrink/cleanup.ksh \
+ functional/zap_shrink/zap_shrink_001_pos.ksh \
+ functional/zap_shrink/setup.ksh \
functional/zpool_influxdb/cleanup.ksh \
functional/zpool_influxdb/setup.ksh \
functional/zpool_influxdb/zpool_influxdb.ksh \
@@ -1987,4 +2114,11 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/zvol/zvol_swap/zvol_swap_003_pos.ksh \
functional/zvol/zvol_swap/zvol_swap_004_pos.ksh \
functional/zvol/zvol_swap/zvol_swap_005_pos.ksh \
- functional/zvol/zvol_swap/zvol_swap_006_pos.ksh
+ functional/zvol/zvol_swap/zvol_swap_006_pos.ksh \
+ functional/idmap_mount/cleanup.ksh \
+ functional/idmap_mount/setup.ksh \
+ functional/idmap_mount/idmap_mount_001.ksh \
+ functional/idmap_mount/idmap_mount_002.ksh \
+ functional/idmap_mount/idmap_mount_003.ksh \
+ functional/idmap_mount/idmap_mount_004.ksh \
+ functional/idmap_mount/idmap_mount_005.ksh
diff --git a/tests/zfs-tests/tests/functional/acl/acl.cfg b/tests/zfs-tests/tests/functional/acl/acl.cfg
index 8fa85d673bb7..e350f18469d6 100644
--- a/tests/zfs-tests/tests/functional/acl/acl.cfg
+++ b/tests/zfs-tests/tests/functional/acl/acl.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/acl_common.kshlib b/tests/zfs-tests/tests/functional/acl/acl_common.kshlib
index 5f4f91485e8e..2844f5dc13dc 100644
--- a/tests/zfs-tests/tests/functional/acl/acl_common.kshlib
+++ b/tests/zfs-tests/tests/functional/acl/acl_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/off/cleanup.ksh b/tests/zfs-tests/tests/functional/acl/off/cleanup.ksh
index bb58a8cf2e7b..58ce22d547a2 100755
--- a/tests/zfs-tests/tests/functional/acl/off/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/off/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh b/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh
index bab2109b9d58..fa304aeb917d 100755
--- a/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh
+++ b/tests/zfs-tests/tests/functional/acl/off/dosmode.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/off/posixmode.ksh b/tests/zfs-tests/tests/functional/acl/off/posixmode.ksh
index 63870caa3234..df278ae2366c 100755
--- a/tests/zfs-tests/tests/functional/acl/off/posixmode.ksh
+++ b/tests/zfs-tests/tests/functional/acl/off/posixmode.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/off/setup.ksh b/tests/zfs-tests/tests/functional/acl/off/setup.ksh
index 9a5b598a59d7..9a0b949ad938 100755
--- a/tests/zfs-tests/tests/functional/acl/off/setup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/off/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh b/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh
index bb58a8cf2e7b..58ce22d547a2 100755
--- a/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh b/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh
index d8bf8a638e7b..3bb3760507ca 100755
--- a/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh b/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh
index bb58a8cf2e7b..58ce22d547a2 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh
index 65c15388cf20..803c7816fedc 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh
index ac718ec58897..4c0bc372b78b 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh
index bdd77bd37603..2a9c173ccb2c 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh
index 6c6b592fbb9e..ffb5b4db71b4 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -35,6 +35,7 @@
# STRATEGY:
# 1. Prepare an appropriate ACL on the test directory
# 2. Change the owner of the directory
+# 3. Reset and set the ACLs for test directory owned by the user
#
verify_runnable "both"
@@ -44,6 +45,8 @@ log_must setfacl -d -m u:$ZFS_ACL_STAFF1:rwx $TESTDIR
log_must setfacl -b $TESTDIR
log_must chown $ZFS_ACL_STAFF1 $TESTDIR
+log_must setfacl -b $TESTDIR
+log_must setfacl -d -m u:$ZFS_ACL_STAFF1:rwx $TESTDIR
log_must chown 0 $TESTDIR
log_pass "chown works with POSIX ACLs"
diff --git a/tests/zfs-tests/tests/functional/acl/posix/setup.ksh b/tests/zfs-tests/tests/functional/acl/posix/setup.ksh
index 526c78e17f1a..8ed9ab7e471e 100755
--- a/tests/zfs-tests/tests/functional/acl/posix/setup.ksh
+++ b/tests/zfs-tests/tests/functional/acl/posix/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh
new file mode 100755
index 000000000000..1b52014fd2d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh
@@ -0,0 +1,38 @@
+#!/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/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Setting the special_small_blocks property greater than recordsize fails.
+#
+
+verify_runnable "global"
+
+claim="Setting the special_small_blocks property greater than recordsize fails"
+
+log_assert $claim
+log_onexit cleanup
+log_must disk_setup
+
+for size in 512 4096 32768 131072 524288 1048576
+do
+ let bigger=$size*2
+ log_mustnot zpool create -O recordsize=$size \
+ -O special_small_blocks=$bigger \
+ $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh
new file mode 100755
index 000000000000..49c468af6702
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.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/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Can set special_small_blocks property less than or equal to recordsize.
+#
+
+verify_runnable "global"
+
+claim="Can set special_small_blocks property less than or equal to recordsize"
+
+log_assert $claim
+log_onexit cleanup
+log_must disk_setup
+
+for size in 8192 32768 131072 524288 1048576
+do
+ let smaller=$size/2
+ log_must zpool create -O recordsize=$size \
+ -O special_small_blocks=$smaller \
+ $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+ log_must zpool destroy -f "$TESTPOOL"
+
+ log_must zpool create -O recordsize=$size \
+ -O special_small_blocks=$size \
+ $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+ log_must zpool destroy -f "$TESTPOOL"
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/append/cleanup.ksh b/tests/zfs-tests/tests/functional/append/cleanup.ksh
index 307feabd17c6..7d8f3aafb771 100755
--- a/tests/zfs-tests/tests/functional/append/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/append/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/append/file_append.ksh b/tests/zfs-tests/tests/functional/append/file_append.ksh
index b40d10c05edb..52c3aff17b79 100755
--- a/tests/zfs-tests/tests/functional/append/file_append.ksh
+++ b/tests/zfs-tests/tests/functional/append/file_append.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/append/setup.ksh b/tests/zfs-tests/tests/functional/append/setup.ksh
index e692d7b1bc0c..4642f3a1925c 100755
--- a/tests/zfs-tests/tests/functional/append/setup.ksh
+++ b/tests/zfs-tests/tests/functional/append/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/append/threadsappend_001_pos.ksh b/tests/zfs-tests/tests/functional/append/threadsappend_001_pos.ksh
index 8154214a0ca7..8ce79c12a04a 100755
--- a/tests/zfs-tests/tests/functional/append/threadsappend_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/append/threadsappend_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/arc/cleanup.ksh b/tests/zfs-tests/tests/functional/arc/cleanup.ksh
index 63a47ba7daf3..72a091d25157 100755
--- a/tests/zfs-tests/tests/functional/arc/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/arc/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh
index aaab800b60ab..e51cf179d8ef 100755
--- a/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh
index e253553f07c0..2908895d0c6a 100755
--- a/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh
index 91cec74881a6..7be57bc9f255 100755
--- a/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/arc/setup.ksh b/tests/zfs-tests/tests/functional/arc/setup.ksh
index 60699d365eb5..a499d7415077 100755
--- a/tests/zfs-tests/tests/functional/arc/setup.ksh
+++ b/tests/zfs-tests/tests/functional/arc/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/atime.cfg b/tests/zfs-tests/tests/functional/atime/atime.cfg
index c1532eb47fd3..eece764248cd 100644
--- a/tests/zfs-tests/tests/functional/atime/atime.cfg
+++ b/tests/zfs-tests/tests/functional/atime/atime.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh b/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh
index 274a4da0dcb9..9006afbeed97 100755
--- a/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -62,11 +62,9 @@ do
mtpt=$(snapshot_mountpoint $dst)
log_mustnot check_atime_updated $mtpt/$TESTFILE
else
- if is_linux; then
- log_must zfs set relatime=off $dst
- fi
-
log_must zfs set atime=on $dst
+ log_must zfs set relatime=off $dst
+
log_must check_atime_updated $mtpt/$TESTFILE
log_must check_atime_updated $mtpt/$TESTFILE
fi
diff --git a/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh b/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh
index c8579337c053..8fde4f23455c 100755
--- a/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh b/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh
index d3eec92effbc..28d973c71f83 100755
--- a/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -62,6 +62,7 @@ do
else
log_must zfs set atime=on $dst
log_must zfs set relatime=on $dst
+
log_must check_atime_updated $mtpt/$TESTFILE
log_mustnot check_atime_updated $mtpt/$TESTFILE
fi
diff --git a/tests/zfs-tests/tests/functional/atime/atime_common.kshlib b/tests/zfs-tests/tests/functional/atime/atime_common.kshlib
index fce85c379865..1755f0b49732 100644
--- a/tests/zfs-tests/tests/functional/atime/atime_common.kshlib
+++ b/tests/zfs-tests/tests/functional/atime/atime_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/cleanup.ksh b/tests/zfs-tests/tests/functional/atime/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/atime/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/atime/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/root_atime_off.ksh b/tests/zfs-tests/tests/functional/atime/root_atime_off.ksh
index 7eb2ed937287..9c1bf3150570 100755
--- a/tests/zfs-tests/tests/functional/atime/root_atime_off.ksh
+++ b/tests/zfs-tests/tests/functional/atime/root_atime_off.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh b/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh
index 44d471a2128f..3b6a0d9004ce 100755
--- a/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh
+++ b/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -65,11 +65,10 @@ do
mtpt=$(snapshot_mountpoint $dst)
log_mustnot check_atime_updated $mtpt/$TESTFILE
else
- if is_linux; then
- log_must zfs set relatime=off $(dirname $dst)
- fi
-
log_must zfs set atime=on $(dirname $dst)
+ # inherited relatime won't apply because of mount option, set explicitly
+ log_must zfs set relatime=off $dst
+
log_must check_atime_updated $mtpt/$TESTFILE
log_must check_atime_updated $mtpt/$TESTFILE
fi
diff --git a/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh b/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh
index 120129425afa..062325938ef2 100755
--- a/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh
+++ b/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -68,6 +68,7 @@ do
else
log_must zfs set atime=on $(dirname $dst)
log_must zfs set relatime=on $(dirname $dst)
+
log_must check_atime_updated $mtpt/$TESTFILE
log_mustnot check_atime_updated $mtpt/$TESTFILE
fi
diff --git a/tests/zfs-tests/tests/functional/atime/setup.ksh b/tests/zfs-tests/tests/functional/atime/setup.ksh
index 3720e7521cc2..f662bffbc374 100755
--- a/tests/zfs-tests/tests/functional/atime/setup.ksh
+++ b/tests/zfs-tests/tests/functional/atime/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bclone/TODO b/tests/zfs-tests/tests/functional/bclone/TODO
new file mode 100644
index 000000000000..7cd4ee898fc4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/TODO
@@ -0,0 +1,4 @@
+- If dedup enabled, block_cloning uses dedup.
+- check when block cloning doesn't suppose to work
+- check block cloning between two different pools
+- block cloning from a snapshot
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone.cfg b/tests/zfs-tests/tests/functional/bclone/bclone.cfg
new file mode 100644
index 000000000000..f72d17c1beca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone.cfg
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+# TODO: We should calculate that based on ashift.
+export MINBLOCKSIZE=512
+
+export TESTSRCFS="$TESTPOOL/$TESTFS/src"
+export TESTDSTFS="$TESTPOOL/$TESTFS/dst"
+export TESTSRCDIR="$TESTDIR/src"
+export TESTDSTDIR="$TESTDIR/dst"
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib b/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib
new file mode 100644
index 000000000000..84b92b4dcdc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib
@@ -0,0 +1,291 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/tests/functional/bclone/bclone.cfg
+
+export RECORDSIZE=$(zfs get -Hp -o value recordsize $TESTPOOL/$TESTFS)
+
+MINBLKSIZE1=512
+MINBLKSIZE2=1024
+
+function verify_block_cloning
+{
+ if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+ fi
+}
+
+function verify_crossfs_block_cloning
+{
+ if is_linux && [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
+ log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3"
+ fi
+
+ # Cross dataset block cloning only supported on FreeBSD 14+
+ # https://github.com/freebsd/freebsd-src/commit/969071be938c
+ if is_freebsd && [ $(freebsd_version) -lt $(freebsd_version 14.0) ] ; then
+ log_unsupported "Cloning across datasets not supported in $(uname -r)"
+ fi
+}
+
+# Unused.
+function size_to_dsize
+{
+ typeset -r size=$1
+ typeset -r dir=$2
+
+ typeset -r dataset=$(df $dir | tail -1 | awk '{print $1}')
+ typeset -r recordsize=$(get_prop recordsize $dataset)
+ typeset -r copies=$(get_prop copies $dataset)
+ typeset dsize
+
+ if [[ $size -le $recordsize ]]; then
+ dsize=$(( ((size - 1) / MINBLOCKSIZE + 1) * MINBLOCKSIZE ))
+ else
+ dsize=$(( ((size - 1) / recordsize + 1) * recordsize ))
+ fi
+ dsize=$((dsize*copies))
+
+ echo $dsize
+}
+
+function test_file_integrity
+{
+ typeset -r original_checksum=$1
+ typeset -r clone=$2
+ typeset -r filesize=$3
+
+ typeset -r clone_checksum=$(sha256digest $clone)
+
+ if [[ $original_checksum != $clone_checksum ]]; then
+ log_fail "Clone $clone is corrupted with file size $filesize"
+ fi
+}
+
+function verify_pool_prop_eq
+{
+ typeset -r prop=$1
+ typeset -r expected=$2
+
+ typeset -r value=$(get_pool_prop $prop $TESTPOOL)
+ if [[ $value != $expected ]]; then
+ log_fail "Pool property $prop is incorrect: expected $expected, got $value"
+ fi
+}
+
+function verify_pool_props
+{
+ typeset -r oused=$1
+ typeset -r osaved=$2
+ typeset dsize=$3
+ typeset ratio=$4
+
+ if [[ $dsize -eq 0 ]]; then
+ ratio=1
+ elif [[ $ratio -eq 1 ]]; then
+ dsize=0
+ fi
+ verify_pool_prop_eq bcloneused $(($oused+$dsize))
+ verify_pool_prop_eq bclonesaved $(($osaved+dsize*(ratio-1)))
+ if [[ $oused -eq 0 ]]; then
+ verify_pool_prop_eq bcloneratio "${ratio}.00"
+ fi
+}
+
+# Function to test file copying and integrity check.
+function bclone_test
+{
+ typeset -r datatype=$1
+ typeset filesize=$2
+ typeset -r embedded=$3
+ typeset -r srcdir=$4
+ typeset -r dstdir=$5
+ typeset dsize
+ typeset oused
+ typeset osaved
+
+ typeset -r original="${srcdir}/original"
+ typeset -r clone="${dstdir}/clone"
+
+ log_note "Testing file copy with datatype $datatype, file size $filesize, embedded $embedded"
+
+ # Save current block cloning stats for later use.
+ sync_pool $TESTPOOL
+ oused=$(get_pool_prop bcloneused $TESTPOOL)
+ osaved=$(get_pool_prop bclonesaved $TESTPOOL)
+
+ # Create a test file with known content.
+ case $datatype in
+ random|text)
+ if [[ $datatype = "random" ]]; then
+ dd if=/dev/urandom of=$original bs=$filesize count=1 2>/dev/null
+ else
+ filesize=$(((filesize/4)*4))
+ dd if=/dev/urandom bs=$(((filesize/4)*3)) count=1 | \
+ openssl base64 -A > $original
+ fi
+ sync_pool $TESTPOOL
+ clonefile -f $original "${clone}-tmp"
+ sync_pool $TESTPOOL
+ # It is hard to predict block sizes that will be used,
+ # so just do one clone and take it from bcloneused.
+ dsize=$(get_pool_prop bcloneused $TESTPOOL)
+ dsize=$(($dsize-$oused))
+ if [[ $embedded = "false" ]]; then
+ log_must test $dsize -gt 0
+ fi
+ rm -f "${clone}-tmp"
+ sync_pool $TESTPOOL
+ ;;
+ hole)
+ log_must truncate_test -s $filesize -f $original
+ dsize=0
+ ;;
+ *)
+ log_fail "Unknown datatype $datatype"
+ ;;
+ esac
+ if [[ $embedded = "true" ]]; then
+ dsize=0
+ fi
+
+ typeset -r original_checksum=$(sha256digest $original)
+
+ sync_pool $TESTPOOL
+
+ # Create a first clone of the entire file.
+ clonefile -f $original "${clone}0"
+ # Try to clone the clone in the same transaction group.
+ clonefile -f "${clone}0" "${clone}2"
+
+ # Clone the original again...
+ clonefile -f $original "${clone}1"
+ # ...and overwrite it in the same transaction group.
+ clonefile -f $original "${clone}1"
+
+ # Clone the clone...
+ clonefile -f "${clone}1" "${clone}3"
+ sync_pool $TESTPOOL
+ # ...and overwrite in the new transaction group.
+ clonefile -f "${clone}1" "${clone}3"
+
+ sync_pool $TESTPOOL
+
+ # Test removal of the pending clones (before they are committed to disk).
+ clonefile -f $original "${clone}4"
+ clonefile -f "${clone}4" "${clone}5"
+ rm -f "${clone}4" "${clone}5"
+
+ # Clone into one file, but remove another file, but with the same data in
+ # the same transaction group.
+ clonefile -f $original "${clone}5"
+ sync_pool $TESTPOOL
+ clonefile -f $original "${clone}4"
+ rm -f "${clone}5"
+ test_file_integrity $original_checksum "${clone}4" $filesize
+ sync_pool $TESTPOOL
+ test_file_integrity $original_checksum "${clone}4" $filesize
+
+ clonefile -f "${clone}4" "${clone}5"
+ # Verify integrity of the cloned file before it is committed to disk.
+ test_file_integrity $original_checksum "${clone}5" $filesize
+
+ sync_pool $TESTPOOL
+
+ # Verify integrity in the new transaction group.
+ test_file_integrity $original_checksum "${clone}0" $filesize
+ test_file_integrity $original_checksum "${clone}1" $filesize
+ test_file_integrity $original_checksum "${clone}2" $filesize
+ test_file_integrity $original_checksum "${clone}3" $filesize
+ test_file_integrity $original_checksum "${clone}4" $filesize
+ test_file_integrity $original_checksum "${clone}5" $filesize
+
+ verify_pool_props $oused $osaved $dsize 7
+
+ # Clear cache and test after fresh import.
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ # Cloned uncached file.
+ clonefile -f $original "${clone}6"
+ # Cloned uncached clone.
+ clonefile -f "${clone}6" "${clone}7"
+
+ # Cache the file.
+ cat $original >/dev/null
+ clonefile -f $original "${clone}8"
+ clonefile -f "${clone}8" "${clone}9"
+
+ test_file_integrity $original_checksum "${clone}6" $filesize
+ test_file_integrity $original_checksum "${clone}7" $filesize
+ test_file_integrity $original_checksum "${clone}8" $filesize
+ test_file_integrity $original_checksum "${clone}9" $filesize
+
+ sync_pool $TESTPOOL
+
+ verify_pool_props $oused $osaved $dsize 11
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ test_file_integrity $original_checksum "${clone}0" $filesize
+ test_file_integrity $original_checksum "${clone}1" $filesize
+ test_file_integrity $original_checksum "${clone}2" $filesize
+ test_file_integrity $original_checksum "${clone}3" $filesize
+ test_file_integrity $original_checksum "${clone}4" $filesize
+ test_file_integrity $original_checksum "${clone}5" $filesize
+ test_file_integrity $original_checksum "${clone}6" $filesize
+ test_file_integrity $original_checksum "${clone}7" $filesize
+ test_file_integrity $original_checksum "${clone}8" $filesize
+ test_file_integrity $original_checksum "${clone}9" $filesize
+
+ rm -f $original
+ rm -f "${clone}1" "${clone}3" "${clone}5" "${clone}7"
+
+ sync_pool $TESTPOOL
+
+ test_file_integrity $original_checksum "${clone}0" $filesize
+ test_file_integrity $original_checksum "${clone}2" $filesize
+ test_file_integrity $original_checksum "${clone}4" $filesize
+ test_file_integrity $original_checksum "${clone}6" $filesize
+ test_file_integrity $original_checksum "${clone}8" $filesize
+ test_file_integrity $original_checksum "${clone}9" $filesize
+
+ verify_pool_props $oused $osaved $dsize 6
+
+ rm -f "${clone}0" "${clone}2" "${clone}4" "${clone}8" "${clone}9"
+
+ sync_pool $TESTPOOL
+
+ test_file_integrity $original_checksum "${clone}6" $filesize
+
+ verify_pool_props $oused $osaved $dsize 1
+
+ rm -f "${clone}6"
+
+ sync_pool $TESTPOOL
+
+ verify_pool_props $oused $osaved $dsize 1
+}
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib b/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib
new file mode 100644
index 000000000000..aeb8efe91715
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib
@@ -0,0 +1,325 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+function first_half_checksum
+{
+ typeset -r file=$1
+
+ dd if=$file bs=$HALFRECORDSIZE count=1 2>/dev/null | sha256digest
+}
+
+function second_half_checksum
+{
+ typeset -r file=$1
+
+ dd if=$file bs=$HALFRECORDSIZE count=1 skip=1 2>/dev/null | sha256digest
+}
+
+function bclone_corner_cases_init
+{
+ typeset -r srcdir=$1
+ typeset -r dstdir=$2
+
+ export RECORDSIZE=4096
+ export HALFRECORDSIZE=$((RECORDSIZE / 2))
+
+ export CLONE="$dstdir/clone0"
+ export ORIG0="$srcdir/orig0"
+ export ORIG1="$srcdir/orig1"
+ export ORIG2="$srcdir/orig2"
+
+ # Create source files.
+ log_must dd if=/dev/urandom of="$ORIG0" bs=$RECORDSIZE count=1
+ log_must dd if=/dev/urandom of="$ORIG1" bs=$RECORDSIZE count=1
+ log_must dd if=/dev/urandom of="$ORIG2" bs=$RECORDSIZE count=1
+
+ export FIRST_HALF_ORIG0_CHECKSUM=$(first_half_checksum $ORIG0)
+ export FIRST_HALF_ORIG1_CHECKSUM=$(first_half_checksum $ORIG1)
+ export FIRST_HALF_ORIG2_CHECKSUM=$(first_half_checksum $ORIG2)
+ export SECOND_HALF_ORIG0_CHECKSUM=$(second_half_checksum $ORIG0)
+ export SECOND_HALF_ORIG1_CHECKSUM=$(second_half_checksum $ORIG1)
+ export SECOND_HALF_ORIG2_CHECKSUM=$(second_half_checksum $ORIG2)
+ export ZEROS_CHECKSUM=$(dd if=/dev/zero bs=$HALFRECORDSIZE count=1 2>/dev/null | sha256digest)
+ export FIRST_HALF_CHECKSUM=""
+ export SECOND_HALF_CHECKSUM=""
+}
+
+function cache_clone
+{
+ typeset -r cached=$1
+
+ case "$cached" in
+ "cached")
+ dd if=$CLONE of=/dev/null bs=$RECORDSIZE 2>/dev/null
+ ;;
+ "uncached")
+ ;;
+ *)
+ log_fail "invalid cached: $cached"
+ ;;
+ esac
+}
+
+function create_existing
+{
+ typeset -r existing=$1
+
+ case "$existing" in
+ "no")
+ ;;
+ "small empty")
+ log_must truncate_test -s $HALFRECORDSIZE -f $CLONE
+ ;;
+ "full empty")
+ log_must truncate_test -s $RECORDSIZE -f $CLONE
+ ;;
+ "small data")
+ log_must dd if=/dev/urandom of=$CLONE bs=$HALFRECORDSIZE count=1 \
+ 2>/dev/null
+ ;;
+ "full data")
+ log_must dd if=/dev/urandom of=$CLONE bs=$RECORDSIZE count=1 2>/dev/null
+ ;;
+ *)
+ log_fail "invalid existing: $existing"
+ ;;
+ esac
+}
+
+function create_clone
+{
+ typeset -r clone=$1
+ typeset -r file=$2
+
+ case "$clone" in
+ "no")
+ ;;
+ "yes")
+ clonefile -f $file $CLONE
+ case "$file" in
+ $ORIG0)
+ FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG0_CHECKSUM
+ SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG0_CHECKSUM
+ ;;
+ $ORIG2)
+ FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG2_CHECKSUM
+ SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG2_CHECKSUM
+ ;;
+ *)
+ log_fail "invalid file: $file"
+ ;;
+ esac
+ ;;
+ *)
+ log_fail "invalid clone: $clone"
+ ;;
+ esac
+}
+
+function overwrite_clone
+{
+ typeset -r overwrite=$1
+
+ case "$overwrite" in
+ "no")
+ ;;
+ "free")
+ log_must truncate_test -s 0 -f $CLONE
+ log_must truncate_test -s $RECORDSIZE -f $CLONE
+ FIRST_HALF_CHECKSUM=$ZEROS_CHECKSUM
+ SECOND_HALF_CHECKSUM=$ZEROS_CHECKSUM
+ ;;
+ "full")
+ log_must dd if=$ORIG1 of=$CLONE bs=$RECORDSIZE count=1 2>/dev/null
+ FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG1_CHECKSUM
+ SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG1_CHECKSUM
+ ;;
+ "first half")
+ log_must dd if=$ORIG1 of=$CLONE bs=$HALFRECORDSIZE skip=0 seek=0 \
+ count=1 conv=notrunc 2>/dev/null
+ FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG1_CHECKSUM
+ ;;
+ "second half")
+ log_must dd if=$ORIG1 of=$CLONE bs=$HALFRECORDSIZE skip=1 seek=1 \
+ count=1 conv=notrunc 2>/dev/null
+ SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG1_CHECKSUM
+ ;;
+ *)
+ log_fail "invalid overwrite: $overwrite"
+ ;;
+ esac
+}
+
+function checksum_compare
+{
+ typeset -r compare=$1
+ typeset first_half_calculated_checksum second_half_calculated_checksum
+
+ case "$compare" in
+ "no")
+ ;;
+ "yes")
+ first_half_calculated_checksum=$(first_half_checksum $CLONE)
+ second_half_calculated_checksum=$(second_half_checksum $CLONE)
+
+ if [[ $first_half_calculated_checksum != $FIRST_HALF_CHECKSUM ]] || \
+ [[ $second_half_calculated_checksum != $SECOND_HALF_CHECKSUM ]]; then
+ return 1
+ fi
+ ;;
+ *)
+ log_fail "invalid compare: $compare"
+ ;;
+ esac
+}
+
+function bclone_corner_cases_test
+{
+ typeset cached existing
+ typeset first_clone first_overwrite
+ typeset read_after read_before
+ typeset second_clone second_overwrite
+ typeset -r srcdir=$1
+ typeset -r dstdir=$2
+ typeset limit=$3
+ typeset -i count=0
+ typeset oused
+ typeset osaved
+
+ if [[ $srcdir != "count" ]]; then
+ if [[ -n "$limit" ]]; then
+ typeset -r total_count=$(bclone_corner_cases_test count)
+ limit=$(random_int_between 1 $total_count $((limit*2)) | sort -nu | head -n $limit | xargs)
+ fi
+ bclone_corner_cases_init $srcdir $dstdir
+
+ # Save current block cloning stats for later use.
+ sync_pool $TESTPOOL
+ oused=$(get_pool_prop bcloneused $TESTPOOL)
+ osaved=$(get_pool_prop bclonesaved $TESTPOOL)
+ fi
+
+ #
+ # (create) / (cache) / (clone) / (overwrite) / (read) / (clone) / (overwrite) / (read) / read next txg
+ #
+ for existing in "no" "small empty" "full empty" "small data" "full data"; do
+ for cached in "uncached" "cached"; do
+ for first_clone in "no" "yes"; do
+ for first_overwrite in "no" "free" "full" "first half" "second half"; do
+ for read_before in "no" "yes"; do
+ for second_clone in "no" "yes"; do
+ for second_overwrite in "no" "free" "full" "first half" "second half"; do
+ for read_after in "no" "yes"; do
+ if [[ $first_clone = "no" ]] && \
+ [[ $second_clone = "no" ]]; then
+ continue
+ fi
+ if [[ $first_clone = "no" ]] && \
+ [[ $read_before = "yes" ]]; then
+ continue
+ fi
+ if [[ $second_clone = "no" ]] && \
+ [[ $read_before = "yes" ]] && \
+ [[ $read_after = "yes" ]]; then
+ continue
+ fi
+
+ count=$((count+1))
+
+ if [[ $srcdir = "count" ]]; then
+ # Just counting.
+ continue
+ fi
+
+ if [[ -n "$limit" ]]; then
+ if ! echo " $limit " | grep -q " $count "; then
+ continue
+ fi
+ fi
+
+ FIRST_HALF_CHECKSUM=""
+ SECOND_HALF_CHECKSUM=""
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ create_existing "$existing"
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ cache_clone "$cached"
+
+ create_clone "$first_clone" "$ORIG0"
+
+ overwrite_clone "$first_overwrite"
+
+ if checksum_compare $read_before; then
+ log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before"
+ else
+ log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before"
+ fi
+
+ create_clone "$second_clone" "$ORIG2"
+
+ overwrite_clone "$second_overwrite"
+
+ if checksum_compare $read_after; then
+ log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / second_overwrite: $second_overwrite / read_after: $read_after"
+ else
+ log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / second_overwrite: $second_overwrite / read_after: $read_after"
+ fi
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ if checksum_compare "yes"; then
+ log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / second_overwrite: $second_overwrite / read_after: $read_after / read_next_txg"
+ else
+ log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / second_overwrite: $second_overwrite / read_after: $read_after / read_next_txg"
+ fi
+
+ rm -f "$CLONE"
+ sync_pool $TESTPOOL
+ verify_pool_prop_eq bcloneused $oused
+ verify_pool_prop_eq bclonesaved $osaved
+ done
+ done
+ done
+ done
+ done
+ done
+ done
+ done
+
+ if [[ $srcdir = "count" ]]; then
+ echo $count
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh
new file mode 100755
index 000000000000..35188cddb063
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh
@@ -0,0 +1,45 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify various corner cases in block cloning across datasets"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+log_must zfs set recordsize=$RECORDSIZE $TESTDSTFS
+
+bclone_corner_cases_test $TESTSRCDIR $TESTDSTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh
new file mode 100755
index 000000000000..1fc1bbd07fd9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh
@@ -0,0 +1,45 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify various corner cases in block cloning across datasets"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+log_must zfs set recordsize=$RECORDSIZE $TESTDSTFS
+
+bclone_corner_cases_test $TESTSRCDIR $TESTDSTDIR 100
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh
new file mode 100755
index 000000000000..e2fe25d451dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh
@@ -0,0 +1,46 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning properly clones regular files across datasets"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+
+for filesize in 1 107 113 511 512 513 4095 4096 4097 131071 131072 131073 \
+ 1048575 1048576 1048577 4194303 4194304 4194305; do
+ bclone_test random $filesize false $TESTSRCDIR $TESTDSTDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh
new file mode 100755
index 000000000000..6a6fe1d309a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh
@@ -0,0 +1,50 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning properly clones small files (with embedded blocks) across datasets"
+
+# Enable ZLE compression to make sure what is the maximum amount of data we
+# can store in BP.
+log_must zfs set compress=zle $TESTSRCFS
+log_must zfs set compress=zle $TESTDSTFS
+
+# Test BP_IS_EMBEDDED().
+# Maximum embedded payload size is 112 bytes, but the buffer is extended to
+# 512 bytes first and then compressed. 107 random bytes followed by 405 zeros
+# gives exactly 112 bytes after compression with ZLE.
+for filesize in 1 2 4 8 16 32 64 96 107; do
+ bclone_test random $filesize true $TESTSRCDIR $TESTDSTDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh
new file mode 100755
index 000000000000..d4c33d6da30f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh
@@ -0,0 +1,45 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning properly clones sparse files (files with holes) across datasets"
+
+# Compression doesn't matter here.
+
+# Test BP_IS_HOLE().
+for filesize in 1 511 512 513 4095 4096 4097 131071 131072 131073 \
+ 1048575 1048576 1048577 4194303 4194304 4194305; do
+ bclone_test hole $filesize false $TESTSRCDIR $TESTDSTDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh
new file mode 100755
index 000000000000..a5e7282fe6a8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh
@@ -0,0 +1,86 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning across datasets with different properties"
+
+log_must zfs set checksum=off $TESTSRCFS
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set copies=1 $TESTSRCFS
+log_must zfs set recordsize=131072 $TESTSRCFS
+log_must zfs set checksum=fletcher2 $TESTDSTFS
+log_must zfs set compress=lz4 $TESTDSTFS
+log_must zfs set copies=3 $TESTDSTFS
+log_must zfs set recordsize=8192 $TESTDSTFS
+
+FILESIZE=$(random_int_between 2 32767)
+FILESIZE=$((FILESIZE * 64))
+bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+
+log_must zfs set checksum=sha256 $TESTSRCFS
+log_must zfs set compress=zstd $TESTSRCFS
+log_must zfs set copies=2 $TESTSRCFS
+log_must zfs set recordsize=262144 $TESTSRCFS
+log_must zfs set checksum=off $TESTDSTFS
+log_must zfs set compress=off $TESTDSTFS
+log_must zfs set copies=1 $TESTDSTFS
+log_must zfs set recordsize=131072 $TESTDSTFS
+
+FILESIZE=$(random_int_between 2 32767)
+FILESIZE=$((FILESIZE * 64))
+bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+
+log_must zfs set checksum=sha512 $TESTSRCFS
+log_must zfs set compress=gzip $TESTSRCFS
+log_must zfs set copies=2 $TESTSRCFS
+log_must zfs set recordsize=512 $TESTSRCFS
+log_must zfs set checksum=fletcher4 $TESTDSTFS
+log_must zfs set compress=lzjb $TESTDSTFS
+log_must zfs set copies=3 $TESTDSTFS
+log_must zfs set recordsize=16384 $TESTDSTFS
+
+FILESIZE=$(random_int_between 2 32767)
+FILESIZE=$((FILESIZE * 64))
+bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+
+log_must zfs inherit checksum $TESTSRCFS
+log_must zfs inherit compress $TESTSRCFS
+log_must zfs inherit copies $TESTSRCFS
+log_must zfs inherit recordsize $TESTSRCFS
+log_must zfs inherit checksum $TESTDSTFS
+log_must zfs inherit compress $TESTDSTFS
+log_must zfs inherit copies $TESTDSTFS
+log_must zfs inherit recordsize $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh
new file mode 100755
index 000000000000..7e064a0dfd73
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh
@@ -0,0 +1,62 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning across datasets with different checksum properties"
+
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+
+for srcprop in "${checksum_prop_vals[@]}"; do
+ for dstprop in "${checksum_prop_vals[@]}"; do
+ if [[ $srcprop == $dstprop ]]; then
+ continue
+ fi
+ log_must zfs set checksum=$srcprop $TESTSRCFS
+ log_must zfs set checksum=$dstprop $TESTDSTFS
+ # 15*8=120, which is greater than 113, so we are sure the data won't
+ # be embedded into BP.
+ # 32767*8=262136, which is larger than a single default recordsize of
+ # 131072.
+ FILESIZE=$(random_int_between 15 32767)
+ FILESIZE=$((FILESIZE * 8))
+ bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+ done
+done
+
+log_must zfs inherit checksum $TESTSRCFS
+log_must zfs inherit checksum $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh
new file mode 100755
index 000000000000..e1d6e5949218
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh
@@ -0,0 +1,59 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning across datasets with different compression properties"
+
+for srcprop in "${compress_prop_vals[@]}"; do
+ for dstprop in "${compress_prop_vals[@]}"; do
+ if [[ $srcprop == $dstprop ]]; then
+ continue
+ fi
+ log_must zfs set compress=$srcprop $TESTSRCFS
+ log_must zfs set compress=$dstprop $TESTDSTFS
+ # 15*8=120, which is greater than 113, so we are sure the data won't
+ # be embedded into BP.
+ # 32767*8=262136, which is larger than a single default recordsize of
+ # 131072.
+ FILESIZE=$(random_int_between 15 32767)
+ FILESIZE=$((FILESIZE * 8))
+ bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+ done
+done
+
+log_must zfs inherit compress $TESTSRCFS
+log_must zfs inherit compress $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh
new file mode 100755
index 000000000000..ac823e1ec394
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh
@@ -0,0 +1,59 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning across datasets with different copies properties"
+
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+
+for srcprop in "${copies_prop_vals[@]}"; do
+ for dstprop in "${copies_prop_vals[@]}"; do
+ log_must zfs set copies=$srcprop $TESTSRCFS
+ log_must zfs set copies=$dstprop $TESTDSTFS
+ # 15*8=120, which is greater than 113, so we are sure the data won't
+ # be embedded into BP.
+ # 32767*8=262136, which is larger than a single default recordsize of
+ # 131072.
+ FILESIZE=$(random_int_between 15 32767)
+ FILESIZE=$((FILESIZE * 8))
+ bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+ done
+done
+
+log_must zfs inherit copies $TESTSRCFS
+log_must zfs inherit copies $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh
new file mode 100755
index 000000000000..d833e6123106
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh
@@ -0,0 +1,65 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning across datasets with different recordsize properties"
+
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set compress=off $TESTDSTFS
+
+# recsize_prop_vals[] array contains too many entries and the tests take too
+# long. Let's use only a subset of them.
+typeset -a bclone_recsize_prop_vals=('512' '4096' '131072' '1048576')
+
+for srcprop in "${bclone_recsize_prop_vals[@]}"; do
+ for dstprop in "${bclone_recsize_prop_vals[@]}"; do
+ if [[ $srcprop == $dstprop ]]; then
+ continue
+ fi
+ log_must zfs set recordsize=$srcprop $TESTSRCFS
+ log_must zfs set recordsize=$dstprop $TESTDSTFS
+ # 2*64=128, which is greater than 113, so we are sure the data won't
+ # be embedded into BP.
+ # 32767*64=2097088, which is larger than the largest recordsize (1MB).
+ FILESIZE=$(random_int_between 2 32767)
+ FILESIZE=$((FILESIZE * 64))
+ bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+ done
+done
+
+log_must zfs inherit recordsize $TESTSRCFS
+log_must zfs inherit recordsize $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh
new file mode 100755
index 000000000000..f8aa1c875c60
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh
@@ -0,0 +1,66 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+verify_crossfs_block_cloning
+
+log_assert "Verify block cloning with all sync property settings"
+
+log_must zfs set compress=zle $TESTSRCFS
+log_must zfs set compress=zle $TESTDSTFS
+
+for prop in "${sync_prop_vals[@]}"; do
+ log_must zfs set sync=$prop $TESTSRCFS
+ # 32767*8=262136, which is larger than a single default recordsize of
+ # 131072.
+ FILESIZE=$(random_int_between 1 32767)
+ FILESIZE=$((FILESIZE * 8))
+ bclone_test random $FILESIZE false $TESTSRCDIR $TESTSRCDIR
+done
+
+for srcprop in "${sync_prop_vals[@]}"; do
+ log_must zfs set sync=$srcprop $TESTSRCFS
+ for dstprop in "${sync_prop_vals[@]}"; do
+ log_must zfs set sync=$dstprop $TESTDSTFS
+ # 32767*8=262136, which is larger than a single default recordsize of
+ # 131072.
+ FILESIZE=$(random_int_between 1 32767)
+ FILESIZE=$((FILESIZE * 8))
+ bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR
+ done
+done
+
+log_must zfs inherit sync $TESTSRCFS
+log_must zfs inherit sync $TESTDSTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh
new file mode 100755
index 000000000000..4aa2914da299
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh
@@ -0,0 +1,42 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+
+log_assert "Verify various corner cases in block cloning within the same dataset"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS
+
+bclone_corner_cases_test $TESTSRCDIR $TESTSRCDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh
new file mode 100755
index 000000000000..b4737700eb7d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh
@@ -0,0 +1,42 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+
+log_assert "Verify various corner cases in block cloning within the same dataset"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS
+
+bclone_corner_cases_test $TESTSRCDIR $TESTSRCDIR 100
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh
new file mode 100755
index 000000000000..e964f7bbf641
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh
@@ -0,0 +1,44 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+
+log_assert "Verify block cloning properly clones regular files within the same dataset"
+
+# Disable compression to make sure we won't use embedded blocks.
+log_must zfs set compress=off $TESTSRCFS
+
+for filesize in 1 107 113 511 512 513 4095 4096 4097 131071 131072 131073 \
+ 1048575 1048576 1048577 4194303 4194304 4194305; do
+ bclone_test random $filesize false $TESTSRCDIR $TESTSRCDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh
new file mode 100755
index 000000000000..df393a878015
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh
@@ -0,0 +1,48 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+
+log_assert "Verify block cloning properly clones small files (with embedded blocks) within the same dataset"
+
+# Enable ZLE compression to make sure what is the maximum amount of data we
+# can store in BP.
+log_must zfs set compress=zle $TESTSRCFS
+
+# Test BP_IS_EMBEDDED().
+# Maximum embedded payload size is 112 bytes, but the buffer is extended to
+# 512 bytes first and then compressed. 107 random bytes followed by 405 zeros
+# gives exactly 112 bytes after compression with ZLE.
+for filesize in 1 2 4 8 16 32 64 96 107; do
+ bclone_test random $filesize true $TESTSRCDIR $TESTSRCDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh
new file mode 100755
index 000000000000..3c6e345e6e64
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh
@@ -0,0 +1,44 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "both"
+
+verify_block_cloning
+
+log_assert "Verify block cloning properly clones sparse files (files with holes) within the same dataset"
+
+# Compression doesn't matter here.
+
+# Test BP_IS_HOLE().
+for filesize in 1 511 512 513 4095 4096 4097 131071 131072 131073 \
+ 1048575 1048576 1048577 4194303 4194304 4194305; do
+ bclone_test hole $filesize false $TESTSRCDIR $TESTSRCDIR
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_003_pos.ksh b/tests/zfs-tests/tests/functional/bclone/cleanup.ksh
index bf22632c7eff..0021ccb57ae0 100755
--- a/tests/zfs-tests/tests/functional/raidz/raidz_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bclone/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -21,21 +21,24 @@
#
#
-# Copyright (c) 2020 by vStack. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
-. $STF_SUITE/include/libtest.shlib
-
#
-# DESCRIPTION:
-# Call the raidz_test tool with -S and -e to test all supported raidz
-# implementations with expanded map and default reflow offset.
-# This options will test several raidz block geometries and several zio
-# parameters that affect raidz block layout. Data reconstruction performs
-# all combinations of failed disks. Wall time is set to 5min, but actual
-# runtime might be longer.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
-log_must raidz_test -S -e -t 60
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone.cfg
+
+log_must zfs destroy $TESTSRCFS
+log_must zfs destroy $TESTDSTFS
+
+default_cleanup_noexit
+
+if tunable_exists BCLONE_ENABLED ; then
+ log_must restore_tunable BCLONE_ENABLED
+fi
-log_pass "raidz_test parameter sweep test with expanded map succeeded."
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bclone/setup.ksh b/tests/zfs-tests/tests/functional/bclone/setup.ksh
new file mode 100755
index 000000000000..9d26088c5a8a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bclone/setup.ksh
@@ -0,0 +1,50 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2023 by Pawel Jakub Dawidek
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone.cfg
+
+if ! command -v clonefile > /dev/null ; then
+ log_unsupported "clonefile program required to test block cloning"
+fi
+
+if tunable_exists BCLONE_ENABLED ; then
+ log_must save_tunable BCLONE_ENABLED
+ log_must set_tunable32 BCLONE_ENABLED 1
+fi
+
+DISK=${DISKS%% *}
+
+default_setup_noexit $DISK "true"
+log_must zpool set feature@block_cloning=enabled $TESTPOOL
+log_must zfs create $TESTSRCFS
+log_must zfs create $TESTDSTFS
+log_pass
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib b/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib
new file mode 100644
index 000000000000..50f3a3d262c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib
@@ -0,0 +1,58 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+function have_same_content
+{
+ typeset hash1=$(md5digest $1)
+ typeset hash2=$(md5digest $2)
+
+ log_must [ "$hash1" = "$hash2" ]
+}
+
+#
+# get_same_blocks dataset1 path/to/file1 dataset2 path/to/file2
+#
+# Returns a space-separated list of the indexes (starting at 0) of the L0
+# blocks that are shared between both files (by first DVA and checksum).
+# Assumes that the two files have the same content, use have_same_content to
+# confirm that.
+#
+function get_same_blocks
+{
+ KEY=$5
+ if [ ${#KEY} -gt 0 ]; then
+ KEY="--key=$KEY"
+ fi
+ typeset zdbout=${TMPDIR:-$TEST_BASE_DIR}/zdbout.$$
+ zdb $KEY -vvvvv $1 -O $2 | \
+ awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.a
+ zdb $KEY -vvvvv $3 -O $4 | \
+ awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.b
+ echo $(sort -n $zdbout.a $zdbout.b | uniq -d | cut -f1 -d' ')
+}
+
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_cached.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_cached.ksh
new file mode 100755
index 000000000000..b0ef8ec99533
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_cached.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# When the destination file is mmaped and is already cached we need to
+# update mmaped pages after successful clone.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Create a two test files with random content.
+# 3. mmap the files, read them and clone from one to the other using
+# clone_mmap_cached.
+# 4. clone_mmap_cached also verifies if the content of the destination
+# file was updated while reading it from mmaped memory.
+#
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+VDIR=$TEST_BASE_DIR/disk-bclone
+VDEV="$VDIR/a"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $VDIR
+}
+
+log_onexit cleanup
+
+log_assert "Test for clone into mmaped and cached file"
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s 1G $VDEV
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV
+log_must zfs create $TESTPOOL/$TESTFS
+
+for opts in "--" "-i" "-o" "-io"
+do
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/src bs=1M count=1
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/dst bs=1M count=1
+
+ # Clear cache.
+ log_must zpool export $TESTPOOL
+ log_must zpool import -d $VDIR $TESTPOOL
+
+ log_must clone_mmap_cached $opts /$TESTPOOL/$TESTFS/src /$TESTPOOL/$TESTFS/dst
+
+ sync_pool $TESTPOOL
+ log_must sync
+
+ log_must have_same_content /$TESTPOOL/$TESTFS/src /$TESTPOOL/$TESTFS/dst
+ blocks=$(get_same_blocks $TESTPOOL/$TESTFS src $TESTPOOL/$TESTFS dst)
+ # FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
+ log_must [ "$blocks" = "$(seq -s " " 0 7 | sed 's/ $//')" ]
+done
+
+log_pass "Clone properly updates mmapped and cached pages"
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_write.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_write.ksh
new file mode 100755
index 000000000000..6215b3178e7e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_clone_mmap_write.ksh
@@ -0,0 +1,79 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# A PANIC is triggered in dbuf_redirty() if we clone a file, mmap it
+# and write from the map into the file. PR#15656 fixes this scenario.
+# This scenario also causes data corruption on FreeBSD, which is fixed
+# by PR#15665.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Create a test file
+# 3. Clone, mmap and write to the file using clone_mmap_write
+# 5. Synchronize cached writes
+# 6. Verfiy data is correctly written to the disk
+#
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+VDIR=$TEST_BASE_DIR/disk-bclone
+VDEV="$VDIR/a"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $VDIR
+}
+
+log_onexit cleanup
+
+log_assert "Test for clone, mmap and write scenario"
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s 1G $VDEV
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV
+log_must zfs create $TESTPOOL/$TESTFS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file bs=1M count=512
+log_must clone_mmap_write /$TESTPOOL/$TESTFS/file /$TESTPOOL/$TESTFS/clone
+
+sync_pool $TESTPOOL
+log_must sync
+
+log_must have_same_content /$TESTPOOL/$TESTFS/file /$TESTPOOL/$TESTFS/clone
+blocks=$(get_same_blocks $TESTPOOL/$TESTFS file $TESTPOOL/$TESTFS clone)
+# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
+log_must [ "$blocks" = "$(seq -s " " 1 4095 | sed 's/ $//')" ]
+
+log_pass "Clone, mmap and write does not cause data corruption or " \
+ "trigger panic"
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh
new file mode 100755
index 000000000000..0599739abee6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh
@@ -0,0 +1,60 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+claim="The copy_file_range syscall can clone whole files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 0 0 524288
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh
new file mode 100755
index 000000000000..ad83d30291ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "global"
+
+verify_crossfs_block_cloning
+
+claim="The copy_file_range syscall can clone across datasets."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must zfs create $TESTPOOL/$TESTFS2
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must \
+ clonefile -f /$TESTPOOL/$TESTFS1/file1 /$TESTPOOL/$TESTFS2/file2 0 0 524288
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/$TESTFS1/file1 /$TESTPOOL/$TESTFS2/file2
+
+typeset blocks=$(get_same_blocks \
+ $TESTPOOL/$TESTFS1 file1 $TESTPOOL/$TESTFS2 file2)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh
new file mode 100755
index 000000000000..475910be7478
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+# Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+claim="copy_file_range will fall back to copy when cloning not possible."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+
+log_note "Copying entire file with copy_file_range"
+
+log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 0 0 524288
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
+
+typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+
+log_note "Copying within a block with copy_file_range"
+
+log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 32768 32768 65536
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
+
+typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
+log_must [ "$blocks" = "1 2 3" ]
+
+
+log_note "Copying across a block with copy_file_range"
+
+log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 327680 327680 131072
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
+
+typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
+log_must [ "$blocks" = "1" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh
new file mode 100755
index 000000000000..00982f68db86
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+# Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+claim="copy_file_range will fall back to copy when cloning on same txg"
+
+log_assert $claim
+
+typeset timeout=$(get_tunable TXG_TIMEOUT)
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ set_tunable64 TXG_TIMEOUT $timeout
+}
+
+log_onexit cleanup
+
+log_must set_tunable64 TXG_TIMEOUT 5000
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must sync_pool $TESTPOOL true
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=128K count=4
+log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 0 0 524288
+
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
+
+typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
+log_must [ "$blocks" = "" ]
+
+log_pass $claim
+
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh
new file mode 100755
index 000000000000..38c46e4741cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+claim="The copy_file_range syscall can clone parts of a file."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must dd if=/$TESTPOOL/file1 of=/$TESTPOOL/file2 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "" ]
+
+log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 131072 131072 262144
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "1 2" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh
new file mode 100755
index 000000000000..702e23267f7e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh
@@ -0,0 +1,169 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Kay Pedersen <mail@mkwg.de>
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+verify_runnable "global"
+
+verify_crossfs_block_cloning
+
+claim="Block cloning across encrypted datasets."
+
+log_assert $claim
+
+DS1="$TESTPOOL/encrypted1"
+DS2="$TESTPOOL/encrypted2"
+DS1_NC="$TESTPOOL/notcrypted1"
+PASSPHRASE="top_secret"
+
+function prepare_enc
+{
+ log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+ log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $DS1"
+ log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $DS2"
+ log_must zfs create $DS1/child1
+ log_must zfs create $DS1/child2
+ log_must zfs create $DS1_NC
+
+ log_note "Create test file"
+ # we must wait until the src file txg is written to the disk otherwise we
+ # will fallback to normal copy. See "dmu_read_l0_bps" in
+ # "zfs/module/zfs/dmu.c" and "zfs_clone_range" in
+ # "zfs/module/zfs/zfs_vnops.c"
+ log_must dd if=/dev/urandom of=/$DS1/file bs=128K count=4
+ log_must dd if=/dev/urandom of=/$DS1/child1/file bs=128K count=4
+ log_must dd if=/dev/urandom of=/$DS1_NC/file bs=128K count=4
+ log_must sync_pool $TESTPOOL
+}
+
+function cleanup_enc
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+function clone_and_check
+{
+ I_FILE="$1"
+ O_FILE=$2
+ I_DS=$3
+ O_DS=$4
+ SAME_BLOCKS=$5
+ # the CLONE option provides a choice between copy_file_range
+ # which should clone and a dd which is a copy no matter what
+ CLONE=$6
+ SNAPSHOT=$7
+ if [ ${#SNAPSHOT} -gt 0 ]; then
+ I_FILE=".zfs/snapshot/$SNAPSHOT/$1"
+ fi
+ if [ $CLONE ]; then
+ log_must clonefile -f "/$I_DS/$I_FILE" "/$O_DS/$O_FILE" 0 0 524288
+ else
+ log_must dd if="/$I_DS/$I_FILE" of="/$O_DS/$O_FILE" bs=128K
+ fi
+ log_must sync_pool $TESTPOOL
+
+ log_must have_same_content "/$I_DS/$I_FILE" "/$O_DS/$O_FILE"
+
+ if [ ${#SNAPSHOT} -gt 0 ]; then
+ I_DS="$I_DS@$SNAPSHOT"
+ I_FILE="$1"
+ fi
+ typeset blocks=$(get_same_blocks \
+ $I_DS $I_FILE $O_DS $O_FILE $PASSPHRASE)
+ log_must [ "$blocks" = "$SAME_BLOCKS" ]
+}
+
+log_onexit cleanup_enc
+
+prepare_enc
+
+log_note "Cloning entire file with copy_file_range across different enc" \
+ "roots, should fallback"
+# we are expecting no same block map.
+clone_and_check "file" "clone" $DS1 $DS2 "" true
+log_note "check if the file is still readable and the same after" \
+ "unmount and key unload, shouldn't fail"
+typeset hash1=$(md5digest "/$DS1/file")
+log_must zfs umount $DS1 && zfs unload-key $DS1
+typeset hash2=$(md5digest "/$DS2/clone")
+log_must [ "$hash1" = "$hash2" ]
+
+cleanup_enc
+prepare_enc
+
+log_note "Cloning entire file with copy_file_range across different child datasets"
+# clone shouldn't work because of deriving a new master key for the child
+# we are expecting no same block map.
+clone_and_check "file" "clone" $DS1 "$DS1/child1" "" true
+clone_and_check "file" "clone" "$DS1/child1" "$DS1/child2" "" true
+
+cleanup_enc
+prepare_enc
+
+log_note "Copying entire file with copy_file_range across same snapshot"
+log_must zfs snapshot -r $DS1@s1
+log_must sync_pool $TESTPOOL
+log_must rm -f "/$DS1/file"
+log_must sync_pool $TESTPOOL
+clone_and_check "file" "clone" "$DS1" "$DS1" "0 1 2 3" true "s1"
+
+cleanup_enc
+prepare_enc
+
+log_note "Copying entire file with copy_file_range across different snapshot"
+clone_and_check "file" "file" $DS1 $DS2 "" true
+log_must zfs snapshot -r $DS2@s1
+log_must sync_pool $TESTPOOL
+log_must rm -f "/$DS1/file" "/$DS2/file"
+log_must sync_pool $TESTPOOL
+clone_and_check "file" "clone" "$DS2" "$DS1" "" true "s1"
+typeset hash1=$(md5digest "/$DS1/.zfs/snapshot/s1/file")
+log_note "destroy the snapshot and check if the file is still readable and" \
+ "has the same content"
+log_must zfs destroy -r $DS2@s1
+log_must sync_pool $TESTPOOL
+typeset hash2=$(md5digest "/$DS1/file")
+log_must [ "$hash1" = "$hash2" ]
+
+cleanup_enc
+prepare_enc
+
+log_note "Copying with copy_file_range from non encrypted to encrypted"
+clone_and_check "file" "copy" $DS1_NC $DS1 "" true
+
+cleanup_enc
+prepare_enc
+
+log_note "Copying with copy_file_range from encrypted to non encrypted"
+clone_and_check "file" "copy" $DS1 $DS1_NC "" true
+
+log_must sync_pool $TESTPOOL
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh
new file mode 100755
index 000000000000..3d916ab92165
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh
@@ -0,0 +1,60 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+claim="The copy_file_range syscall copies files when block cloning is disabled."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=disabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 0 0 524288
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlone.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlone.ksh
new file mode 100755
index 000000000000..10a2715ea253
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlone.ksh
@@ -0,0 +1,50 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+claim="The FICLONE ioctl fails when block cloning is disabled."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=disabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_mustnot clonefile -c /$TESTPOOL/file1 /$TESTPOOL/file2
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlonerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlonerange.ksh
new file mode 100755
index 000000000000..e8461e6d3c38
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlonerange.ksh
@@ -0,0 +1,50 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+claim="The FICLONERANGE ioctl fails when block cloning is disabled."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=disabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_mustnot clonefile -r /$TESTPOOL/file1 /$TESTPOOL/file2 0 0 524288
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh
new file mode 100755
index 000000000000..3f227fb68ee3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh
@@ -0,0 +1,56 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+claim="The FICLONE ioctl can clone files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must clonefile -c /$TESTPOOL/file1 /$TESTPOOL/file2
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh
new file mode 100755
index 000000000000..cefc4336aefd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh
@@ -0,0 +1,56 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+claim="The FICLONERANGE ioctl can clone whole files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must clonefile -r /$TESTPOOL/file1 /$TESTPOOL/file2 0 0 524288
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh
new file mode 100755
index 000000000000..067f55aaa65b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+claim="The FICLONERANGE ioctl can clone parts of a file."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must dd if=/$TESTPOOL/file1 of=/$TESTPOOL/file2 bs=128K count=4
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "" ]
+
+log_must clonefile -r /$TESTPOOL/file1 /$TESTPOOL/file2 131072 131072 262144
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
+
+typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
+log_must [ "$blocks" = "1 2" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh
new file mode 100755
index 000000000000..919f320dea3f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh
@@ -0,0 +1,90 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by iXsystems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# Test for LWB buffer overflow with multiple VDEVs ZIL when 128KB
+# block write is split into two 68KB ones, trying to write maximum
+# sizes 128KB TX_CLONE_RANGE record with 1022 block pointers into
+# 68KB buffer.
+#
+# STRATEGY:
+# 1. Create a pool with multiple VDEVs ZIL
+# 2. Write maximum sizes TX_CLONE_RANGE record with 1022 block
+# pointers into 68KB buffer
+# 3. Sync TXG
+# 4. Clone the file
+# 5. Synchronize cached writes
+#
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+VDIR=$TEST_BASE_DIR/disk-bclone
+VDEV="$VDIR/a $VDIR/b $VDIR/c"
+LDEV="$VDIR/e $VDIR/f"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $VDIR
+}
+
+log_onexit cleanup
+
+log_assert "Test for LWB buffer overflow with multiple VDEVs ZIL"
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s $MINVDEVSIZE $VDEV $LDEV
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV \
+ log mirror $LDEV
+log_must zfs create -o recordsize=32K $TESTPOOL/$TESTFS
+# Each ZIL log entry can fit 130816 bytes for a block cloning operation,
+# so it can store 1022 block pointers. When LWB optimization is enabled,
+# an assert is hit when 128KB block write is split into two 68KB ones
+# for 2 SLOG devices
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 bs=32K count=1022 \
+ conv=fsync
+sync_pool $TESTPOOL
+log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/file2
+log_must sync
+
+sync_pool $TESTPOOL
+log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/file2
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 $TESTPOOL/$TESTFS file2)
+# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
+log_must [ "$blocks" = "$(seq -s " " 0 1021 | sed 's/ $//')" ]
+
+log_pass "LWB buffer overflow is not triggered with multiple VDEVs ZIL"
+
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh
new file mode 100755
index 000000000000..530152004686
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh
@@ -0,0 +1,132 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly for cloned files. This
+# test is ported from slog_replay tests for block cloning.
+#
+# STRATEGY:
+# 1. Create an empty file system (TESTFS)
+# 2. Create regular files and sync
+# 3. Freeze TESTFS
+# 4. Clone the file
+# 5. Unmount filesystem
+# <At this stage TESTFS is frozen, the intent log contains a
+# complete set of deltas to replay it>
+# 6. Remount TESTFS <which replays the intent log>
+# 7. Compare clone file with the original file
+#
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+export VDIR=$TEST_BASE_DIR/disk-bclone
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export LDEV="$VDIR/e $VDIR/f"
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s $MINVDEVSIZE $VDEV $LDEV
+
+claim="The slogs are replayed correctly for cloned files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR $VDIR $VDIR2
+}
+
+log_onexit cleanup
+
+#
+# 1. Create an empty file system (TESTFS)
+#
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV \
+ log mirror $LDEV
+log_must zfs create $TESTPOOL/$TESTFS
+
+#
+# 2. TX_WRITE: Create two files and sync txg
+#
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 \
+ oflag=sync bs=128k count=4
+log_must zfs set recordsize=16K $TESTPOOL/$TESTFS
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file2 \
+ oflag=sync bs=16K count=2048
+sync_pool $TESTPOOL
+
+#
+# 3. Checkpoint for ZIL Replay
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 4. TX_CLONE_RANGE: Clone the file
+#
+log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must clonefile -f /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is frozen, the intent log contains a complete set
+# of deltas to replay for clone files.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+#
+# 7. Compare clone file with the original file
+#
+log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must have_same_content /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 \
+ $TESTPOOL/$TESTFS clone1)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
+ $TESTPOOL/$TESTFS clone2)
+# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
+log_must [ "$blocks" = "$(seq -s " " 0 2047 | sed 's/ $//')" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh
new file mode 100755
index 000000000000..0967415b7b7b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh
@@ -0,0 +1,134 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly for encrypted cloned files.
+# This test is ported from slog_replay tests for block cloning.
+#
+# STRATEGY:
+# 1. Create an encrypted file system (TESTFS)
+# 2. Create regular files and sync
+# 3. Freeze TESTFS
+# 4. Clone the file
+# 5. Unmount filesystem
+# <At this stage TESTFS is frozen, the intent log contains a
+# complete set of deltas to replay it>
+# 6. Remount encrypted TESTFS <which replays the intent log>
+# 7. Compare clone file with the original file
+#
+
+verify_runnable "global"
+
+if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+export VDIR=$TEST_BASE_DIR/disk-bclone
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export LDEV="$VDIR/e $VDIR/f"
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s $MINVDEVSIZE $VDEV $LDEV
+export PASSPHRASE="password"
+
+claim="The slogs are replayed correctly for encrypted cloned files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR $VDIR $VDIR2
+}
+
+log_onexit cleanup
+
+#
+# 1. Create an encrypted file system (TESTFS)
+#
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV \
+ log mirror $LDEV
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS"
+
+#
+# 2. TX_WRITE: Create two files and sync txg
+#
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 \
+ oflag=sync bs=128k count=4
+log_must zfs set recordsize=16K $TESTPOOL/$TESTFS
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file2 \
+ oflag=sync bs=16K count=2048
+sync_pool $TESTPOOL
+
+#
+# 3. Checkpoint for ZIL Replay
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 4. TX_CLONE_RANGE: Clone the file
+#
+log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must clonefile -f /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is frozen, the intent log contains a complete set
+# of deltas to replay for clone files.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must eval "echo $PASSPHRASE | zpool import -l -f -d $VDIR $TESTPOOL"
+
+#
+# 7. Compare clone file with the original file
+#
+log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must have_same_content /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 \
+ $TESTPOOL/$TESTFS clone1 $PASSPHRASE)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
+ $TESTPOOL/$TESTFS clone2 $PASSPHRASE)
+# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
+log_must [ "$blocks" = "$(seq -s " " 0 2047 | sed 's/ $//')" ]
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh b/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh
new file mode 100755
index 000000000000..b985445a5d12
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh
@@ -0,0 +1,38 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+verify_runnable "global"
+
+default_cleanup_noexit
+
+if tunable_exists BCLONE_ENABLED ; then
+ log_must restore_tunable BCLONE_ENABLED
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/block_cloning/setup.ksh b/tests/zfs-tests/tests/functional/block_cloning/setup.ksh
new file mode 100755
index 000000000000..a9b13f062a4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/block_cloning/setup.ksh
@@ -0,0 +1,44 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+if ! command -v clonefile > /dev/null ; then
+ log_unsupported "clonefile program required to test block cloning"
+fi
+if ! command -v clone_mmap_cached > /dev/null ; then
+ log_unsupported "clone_mmap_cached program required to test block cloning"
+fi
+
+verify_runnable "global"
+
+if tunable_exists BCLONE_ENABLED ; then
+ log_must save_tunable BCLONE_ENABLED
+ log_must set_tunable32 BCLONE_ENABLED 1
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh
index 6f2f54ebdddc..add455eb13ee 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh
index 172b69400807..a4324a63c710 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh
index 78559dd186c8..e1d27d1cc6df 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh
index 5ea0f6c1a95f..fa341622f3cf 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh
index 42c82b88fba6..39a9a85b44a7 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh
index 2738d3916e2c..cdd69f4a5b2f 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh
index 2e71df86c62b..5750fe9338eb 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh
index bcf74f2cdee2..270a3d706339 100755
--- a/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh b/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh
index 71d8ced18206..eb542c0092fc 100755
--- a/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/bootfs/setup.ksh b/tests/zfs-tests/tests/functional/bootfs/setup.ksh
index 273f239137b0..2f89df767e4d 100755
--- a/tests/zfs-tests/tests/functional/bootfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/bootfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache.cfg b/tests/zfs-tests/tests/functional/cache/cache.cfg
index 07e482d7df96..84dd78438d61 100644
--- a/tests/zfs-tests/tests/functional/cache/cache.cfg
+++ b/tests/zfs-tests/tests/functional/cache/cache.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache.kshlib b/tests/zfs-tests/tests/functional/cache/cache.kshlib
index 9948c6280185..63cc0b28ecf1 100644
--- a/tests/zfs-tests/tests/functional/cache/cache.kshlib
+++ b/tests/zfs-tests/tests/functional/cache/cache.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh
index 955c9f12019f..c77668cf7deb 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh
index 888645c353e8..5f1dc75c9919 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh
index 566c5c6ac675..f2a2777dc6ce 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh
index 38fee608bbc8..fe74cbaf1dae 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh
index 35e15abe2602..59afbb0186b6 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh
index 46bd5fc8b3ef..2f00b43f3424 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh
index e2cdc0a28d38..721dd2e04837 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh
index 93866dd3097f..d0c3f621b756 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh
index 7a0586648f84..1d83e144266e 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh
index 1d9fc5a8922b..b912eeec8769 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh
index caa7e6e900b7..0e48ac5e2a9e 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh
index be250158bf7e..945db71bf113 100755
--- a/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh
@@ -31,15 +31,13 @@
# 2. Set l2arc_write_max to a value larger than the cache device.
# 3. Create a file larger than the cache device and random read
# for 10 sec.
-# 4. Verify that l2arc_write_max is set back to the default.
-# 5. Set l2arc_write_max to a value less than the cache device size but
-# larger than the default (64MB).
-# 6. Record the l2_size.
-# 7. Random read for 1 sec.
-# 8. Record the l2_size again.
-# 9. If (6) <= (8) then we have not looped around yet.
-# 10. If (6) > (8) then we looped around. Break out of the loop and test.
-# 11. Destroy pool.
+# 4. Set l2arc_write_max to a value less than the cache device size but
+# larger than the default (256MB).
+# 5. Record the l2_size.
+# 6. Random read for 1 sec.
+# 7. Record the l2_size again.
+# 8. If (5) <= (7) then we have not looped around yet.
+# 9. Destroy pool.
#
verify_runnable "global"
@@ -87,14 +85,13 @@ log_must truncate -s $VDEV_SZ $VDEV
log_must zpool create -f $TESTPOOL $VDEV cache $VCACHE
+# Actually, this test relies on atime writes to force the L2 ARC discards
+log_must zfs set relatime=off $TESTPOOL
+
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
-typeset write_max2=$(get_tunable L2ARC_WRITE_MAX)
-
-log_must test $write_max2 -eq $write_max
-
-log_must set_tunable32 L2ARC_WRITE_MAX $(( 64 * 1024 * 1024 ))
+log_must set_tunable32 L2ARC_WRITE_MAX $(( 256 * 1024 * 1024 ))
export RUNTIME=1
typeset do_once=true
@@ -105,8 +102,6 @@ while $do_once || [[ $l2_size1 -le $l2_size2 ]]; do
do_once=false
done
-log_must test $l2_size1 -gt $l2_size2
-
log_must zpool destroy $TESTPOOL
log_pass "Looping around a cache device succeeds."
diff --git a/tests/zfs-tests/tests/functional/cache/cleanup.ksh b/tests/zfs-tests/tests/functional/cache/cleanup.ksh
index 258f92d19e0e..23d9e2d45286 100755
--- a/tests/zfs-tests/tests/functional/cache/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cache/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cache/setup.ksh b/tests/zfs-tests/tests/functional/cache/setup.ksh
index 0493637fcca8..84d11a4d70e6 100755
--- a/tests/zfs-tests/tests/functional/cache/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cache/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg b/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg
index bd48cfdf2f87..47b0853184e0 100644
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib b/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib
index 7723e3083f1d..463355371c75 100644
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh
index f164a1fad32f..256c2d38878b 100755
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh
index 9268f9786355..71039c11b2be 100755
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh
index a5f427cb4135..4a6d28f69333 100755
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh
index 841b141e16fc..59a3b7dcf995 100755
--- a/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh b/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cachefile/setup.ksh b/tests/zfs-tests/tests/functional/cachefile/setup.ksh
index 47c7893bfdd6..de6c2be66b7b 100755
--- a/tests/zfs-tests/tests/functional/cachefile/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cachefile/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.ksh
new file mode 100755
index 000000000000..0561e4b7c635
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.ksh
@@ -0,0 +1,41 @@
+#!/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) 2022 by Andriy Gapon. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure basic snapshot functionality works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname1=testsnap1
+snapname2=testsnap2
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.snapshot_rename.zcp $fs $snapname1 $snapname2
+
+log_pass "Snapshot renaming works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.zcp
new file mode 100644
index 000000000000..ef893d1551d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_rename.zcp
@@ -0,0 +1,27 @@
+--
+-- 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) 2022 by Andriy Gapon. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap>"
+
+args = ...
+argv = args["argv"]
+assert(zfs.sync.snapshot(argv[1] .. "@" .. argv[2]) == 0)
+assert(zfs.sync.rename_snapshot(argv[1], argv[2], argv[3]) == 0)
+snaps = {}
+for s in zfs.list.snapshots(argv[1]) do
+ table.insert(snaps, s)
+end
+assert(#snaps == 1)
+assert(snaps[1] == (argv[1] .. "@" .. argv[3]))
diff --git a/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh b/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh
index cb8c2ead593a..c263c0f4fadf 100755
--- a/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh b/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh
index cad1b0a38a4d..758de3fd277d 100755
--- a/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/chattr/cleanup.ksh b/tests/zfs-tests/tests/functional/chattr/cleanup.ksh
index 59875d609ad9..59a93a652d05 100755
--- a/tests/zfs-tests/tests/functional/chattr/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/chattr/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/chattr/setup.ksh b/tests/zfs-tests/tests/functional/chattr/setup.ksh
index 85c9b6ea6351..d9fc7be4e4fe 100755
--- a/tests/zfs-tests/tests/functional/chattr/setup.ksh
+++ b/tests/zfs-tests/tests/functional/chattr/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/checksum/cleanup.ksh b/tests/zfs-tests/tests/functional/checksum/cleanup.ksh
index 19b0f35cf768..7d2380db5c6d 100755
--- a/tests/zfs-tests/tests/functional/checksum/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/checksum/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/checksum/default.cfg b/tests/zfs-tests/tests/functional/checksum/default.cfg
index a7e143e75ea3..ca13be4e4d5d 100644
--- a/tests/zfs-tests/tests/functional/checksum/default.cfg
+++ b/tests/zfs-tests/tests/functional/checksum/default.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh b/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh
index c9cefcd43dae..7257da488383 100755
--- a/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/checksum/filetest_002_pos.ksh b/tests/zfs-tests/tests/functional/checksum/filetest_002_pos.ksh
index 921a4b392a45..23e7aa577484 100755
--- a/tests/zfs-tests/tests/functional/checksum/filetest_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/checksum/filetest_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -76,7 +76,7 @@ while [[ $j -lt ${#CHECKSUM_TYPES[*]} ]]; do
log_must zpool export $TESTPOOL
log_must zpool import $TESTPOOL
- log_mustnot eval "cat $TESTDIR/test_$type >/dev/null"
+ log_mustnot eval "dd if=$TESTDIR/test_$type of=/dev/null bs=$WRITESZ count=$NWRITES"
cksum=$(zpool status -P -v $TESTPOOL | grep "$firstvdev" | \
awk '{print $5}')
diff --git a/tests/zfs-tests/tests/functional/checksum/setup.ksh b/tests/zfs-tests/tests/functional/checksum/setup.ksh
index 204069de7383..be72cacc0fc2 100755
--- a/tests/zfs-tests/tests/functional/checksum/setup.ksh
+++ b/tests/zfs-tests/tests/functional/checksum/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh
index 8dd337a6efb9..f644b8f81325 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh
index a156368d0c89..6246b0c09f07 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh
index 144dcf1c0b72..3a64001eb5ac 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh
index ce1aac56d85a..cfbd81941023 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib
index cf1d77d9ccb5..1a75816f2c03 100644
--- a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh b/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh
index d5614bef0420..3b54cff0e4c6 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/default.cfg b/tests/zfs-tests/tests/functional/clean_mirror/default.cfg
index dfe7f1d0ba33..83ec31f29930 100644
--- a/tests/zfs-tests/tests/functional/clean_mirror/default.cfg
+++ b/tests/zfs-tests/tests/functional/clean_mirror/default.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh b/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh
index 0024f284d8f5..8d14f2d96e2d 100755
--- a/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh
+++ b/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib
index 1e4917affff7..bdb2d86f0380 100644
--- a/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh
index cb88def7cc3e..688d488ceb62 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -57,8 +57,8 @@ set -A args "create" "add" "destroy" "import fakepool" \
"add raidz1 fakepool" "add raidz2 fakepool" \
"setvprop" "blah blah" "-%" "--?" "-*" "-=" \
"-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \
- "-t" "-w" "-z" "-E" "-H" "-I" "-J" "-K" \
- "-Q" "-R" "-T" "-W"
+ "-t" "-w" "-z" "-E" "-H" "-I" "-J" \
+ "-Q" "-R" "-W"
log_assert "Execute zdb using invalid parameters."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh
index 75654c29b1ef..37f45eae55f1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_backup.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_backup.ksh
new file mode 100755
index 000000000000..d98ab86ab667
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_backup.ksh
@@ -0,0 +1,55 @@
+#!/bin/ksh
+
+#
+# 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) 2023, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+write_count=8
+blksize=131072
+
+tmpfile=$TEST_BASE_DIR/tmpfile
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm $tmpfile.1 $tmpfile.2
+}
+
+log_onexit cleanup
+
+log_assert "Verify that zfs send and zdb -B produce the same stream"
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+file_write -o create -w -f $TESTDIR/file -b $blksize -c $write_count
+
+snap=$TESTPOOL/$TESTFS@snap
+log_must zfs snapshot $snap
+typeset -i objsetid=$(zfs get -Ho value objsetid $snap)
+
+sync_pool $TESTPOOL
+
+log_must eval "zfs send -ecL $snap > $tmpfile.1"
+log_must eval "zdb -B $TESTPOOL/$objsetid ecL > $tmpfile.2"
+
+typeset sum1=$(cat $tmpfile.1 | md5sum)
+typeset sum2=$(cat $tmpfile.2 | md5sum)
+
+log_must test "$sum1" = "$sum2"
+
+log_pass "zfs send and zdb -B produce the same stream"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh
index 0a4d24fa695a..cfa26f54b11f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh
@@ -204,11 +204,11 @@ function histo_check_test_pool
# 4096 blocksize count for asize. For verification we stick
# to just lsize counts.
#
- # The max_variance is hard-coded here at 12% to leave us some
- # margin. Testing has shown this normally to be in the range
- # of 2%-8%, but it may be as large as 11%.
+ # Variances are expected since this test does not account for
+ # metadata. The hardcoded limit here is empirical and should
+ # not be construed as deterministic.
###################
- let max_variance=12
+ let max_variance=15
let fail_value=0
let error_count=0
log_note "Comparisons for ${pool}"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted.ksh
new file mode 100755
index 000000000000..0218c2ea1033
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+# Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zdb -K ...' should enable reading from an encrypt dataset
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Write some data to a file
+# 3. Run zdb -dddd on the file, confirm it can't be read
+# 4. Run zdb -K ... -ddddd on the file, confirm it can be read
+#
+
+verify_runnable "both"
+
+dataset="$TESTPOOL/$TESTFS2"
+file="$TESTDIR2/somefile"
+
+function cleanup
+{
+ datasetexists $dataset && destroy_dataset $dataset -f
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+log_must default_setup_noexit $DISKS
+
+log_assert "'zdb -K' should enable reading from an encrypted dataset"
+
+log_must eval "echo $PASSPHRASE | zfs create -o mountpoint=$TESTDIR2" \
+ "-o encryption=on -o keyformat=passphrase $dataset"
+
+echo 'my great encrypted text' > $file
+
+typeset -i obj=$(ls -i $file | cut -d' ' -f1)
+typeset -i size=$(wc -c < $file)
+
+log_note "test file $file is objid $obj, size $size"
+
+sync_pool $TESTPOOL true
+
+log_must eval "zdb -dddd $dataset $obj | grep -q 'object encrypted'"
+
+log_must eval "zdb -K $PASSPHRASE -dddd $dataset $obj | grep -q 'size\s$size$'"
+
+log_pass "'zdb -K' enables reading from an encrypted dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh
index c6e45c80dd30..24ffd4751688 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh
index 044ccb185c48..de434cc47b31 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh
index 6c85e0c13ab4..2f592642c3ba 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh
index f84ac43e67c9..eed1c9ccf54f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh
index 40953415c6b9..8815d150bbdb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
index ec21c81aba1b..b6cb0c60034f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh
index d247991fbbdb..d9f935900f90 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh
index 985554f8cd2e..0a74ee3a879d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh
index e6ffa26c0208..e8d5d73dd841 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh
index 96eb3ea48d64..755079ed57df 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh
index ac3bc891c86f..c113fb27aaf9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh
index 1c4c579f26bd..993b279411d0 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh
index 6f17b176734a..e965ec1251b3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh
index f2f7a5bcd077..30fafca90054 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh
index 5f42006de289..a615392d70dc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh
index 2f2b0ca18d64..96f0c16a45f4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh
index 6cdf5717fa92..e328d5b64158 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh
index f5e862593e1e..8c8d37276d1d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh
index d4cf2095012b..f76b49af706f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
index eb85e65c790e..ec3244c7a804 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
index 1273ed59df30..5617bd01ba42 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh
index 672692b59e42..1f8d770fc99f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh
index aa895956c936..5b10189e8f57 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh
index 94e72bce4e67..cfb3d3308db8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh
index dc007b11160d..ab250d4f2782 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh
index 6a8b81ac5b87..d15629fb2bd0 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh
index 6dc9306b33ef..28017b59a00f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib
index 4130ba446334..16d19bdbd8aa 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg
index 785d5a001603..807285ea6c73 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh
index f74b2c9816f3..7b34ec33f3bf 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh
index 84f758904bd9..74b39cdaf983 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh
index 120de10281db..798354db954b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh
index bd01623b3627..cc429419e67a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh
index 1321854d21cd..22f154400a1b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh
index 551ae78cd239..733402fed39a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh
index c49c77703409..bb6f9a21db13 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh
index d82f10f71f71..650d7dbcc3bd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
index 6722a659eb65..f23f0a969df8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh
index d4784d6530e5..a872881b5494 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh
index c5012d4f34a8..2bbe6d84815f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh
index 2a140d954876..71706d4b0f65 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh
index d3855cb315c1..3fa5e246d8e4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh
index 2482a68dc089..8010c6df4586 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
index bf8e145e5112..76a63a094807 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh
index e838ba8a5947..8f25922aa7ac 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh
index f4288f715b22..479ee930f27f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
index a62739b07ec8..5bb720bf1d6b 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh
index 11157e93c78d..1f977628295e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh
index 128921226a73..2eff646ea76a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh
index 8b7e59b412b4..2c61bb7ecebb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh
index d618f21e9eb5..fedc30d550a4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh
index 1c5b2cf1c741..f91909c2bc56 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh
index 7dbcb242041d..2a9381cab5fa 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh
index 57eb736fd88b..cafb87a42368 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh
index f8b8f9005514..29e1e5e95cf6 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh
index 57e5761bc064..aa841151603c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh
index 369029775f4b..91e6dfd96e1d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
index 51b3d2e513cc..bcc24efa6515 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh
index 9692385996d1..2a909eba4f87 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh
index b3286c31e6fa..935a85285e8e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh
index 6717787d06e6..65986f6bd1a2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh
index e96899118a89..db80ccf1883f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh
index 20597c9a5feb..6101bae032c8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh
index 13685ef6f4bc..d9be907909db 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh
index e19936ef88dc..feed960b17e4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh
index 63dfb6a50b52..08a6bb7529b5 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh
index 9f3dd47cde7d..6be432036845 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
index 1e80d4d2b7ef..5686b63b41cc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh
index e1f53845fd9c..1b6e211e0681 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
index 9b4eecf37127..12f157dedf19 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
index d5388e6ef2ae..2084e0c18b10 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh
index b5ff02217237..3b16891a6b18 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh
index fd6f8f8bb078..f69103b7c373 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh
index 563b3e00dd89..ff05a75725ad 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh
index 9692385996d1..2a909eba4f87 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh
index aba317f54237..f1bd3d6e1fd3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh
index 8e37e8dbcae0..0bb93a0789bf 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh
index 3f7e4ff972ed..d27fa84c5d14 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh
index 2c0808110276..fa33bdb02ffa 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh
index d397bcf4e9f0..60a1450f4c06 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh
index 6cc5528ce5d7..43e4db5b09bf 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
index 4a85999b4ab8..f174eeeeaae9 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
@@ -123,7 +123,10 @@ if not httpd:
with open('$HTTPS_PORT_FILE', 'w') as portf:
print(port, file=portf)
-httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, keyfile='/$TESTPOOL/snakeoil.key', certfile='$SSL_CA_CERT_FILE', ssl_version=ssl.PROTOCOL_TLS)
+sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+sslctx.check_hostname = False
+sslctx.load_cert_chain(certfile='$SSL_CA_CERT_FILE', keyfile='/$TESTPOOL/snakeoil.key')
+httpd.socket = httpd.socket = sslctx.wrap_socket(httpd.socket, server_side=True)
os.chdir('$STF_SUITE/tests/functional/cli_root/zfs_load-key')
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
index c8e46895d2a6..739baf16086a 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -31,6 +31,7 @@
export mountcmd=mount
export mountforce="$mountcmd -f"
export mountall="$mountcmd -a"
+export mountrecursive="$mountcmd -R"
export unmountcmd=unmount
export unmountforce="$unmountcmd -f"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
index 23cab2511a41..8d06a32e7f52 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh
index c46a35695492..68ec78478571 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh
index 8ee3e029fb4a..50161bc0a45d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh
index 59d8c235f8fe..1beb501f5b64 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh
index 4874c6d6530a..9dcd8af0bb35 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh
index b42b2496e4b9..b94d83f45119 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh
index 5edce35c721e..e9ab472795eb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -94,7 +94,7 @@ while (( depth < MAXDEPTH )); do
done
log_must zfs set mountpoint=$mtpt $TESTPOOL/$TESTFS
-log_must zfs $mountcmd $TESTPOOL/$TESTFS
+log_must ismounted $TESTPOOL/$TESTFS
log_must zfs set overlay=off $TESTPOOL/$TESTFS
if ! is_illumos; then
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh
index a11f53d79ba0..84f478c938bd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh
index 6a251330f62d..0437c61a2c40 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -71,7 +71,7 @@ log_must mkfile 1M $testfile $testfile1
log_must zfs unmount $fs1
log_must zfs set mountpoint=$mntpnt $fs1
-log_must zfs mount $fs1
+log_must ismounted $fs1
log_must zfs unmount $fs1
log_must zfs mount -O $fs1
@@ -85,7 +85,7 @@ log_must ls $mntpnt/$TESTFILE1 $mntpnt/$TESTFILE2
# Verify $TESTFILE2 was created in $fs1, rather than $fs
log_must zfs unmount $fs1
log_must zfs set mountpoint=$mntpnt1 $fs1
-log_must zfs mount $fs1
+log_must ismounted $fs1
log_must ls $testfile1 $mntpnt1/$TESTFILE2
# Verify $TESTFILE2 was not created in $fs, and $fs is accessible again.
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh
index 978a5a4f2eea..02b3477a4452 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh
index 53ebf1f26248..2c26157be835 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh
index 95e2bc39727a..0e0879823619 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh
index 5ff094d2c479..66958f2f0884 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh
@@ -25,13 +25,12 @@
# STRATEGY:
# 1. Unmount the dataset
# 2. Create a new empty directory
-# 3. Set the dataset's mountpoint
-# 4. Attempt to mount the dataset
-# 5. Verify the mount succeeds
-# 6. Unmount the dataset
-# 7. Create a file in the directory created in step 2
-# 8. Attempt to mount the dataset
-# 9. Verify the mount succeeds
+# 3. Set the dataset's mountpoint, this should mount the dataset
+# 4. Verify the mount succeeds
+# 5. Unmount the dataset
+# 6. Create a file in the directory created in step 2
+# 7. Attempt to mount the dataset
+# 8. Verify the mount succeeds
#
verify_runnable "both"
@@ -43,7 +42,7 @@ fs=$TESTPOOL/$TESTFS
log_must zfs umount $fs
log_must mkdir -p $TESTDIR
log_must zfs set mountpoint=$TESTDIR $fs
-log_must zfs mount $fs
+log_must ismounted $fs
log_must zfs umount $fs
log_must touch $TESTDIR/testfile.$$
log_must zfs mount $fs
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh
index 765e242796b8..5fd963c03997 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_recursive.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_recursive.ksh
new file mode 100755
index 000000000000..0e5cc5d6955e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_recursive.ksh
@@ -0,0 +1,146 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2024, iXsystems Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Verify zfs mount -R <filesystems/s> functionality.
+#
+# STRATEGY:
+# 1. Create nested datasets
+# 2. Unmount all datasets
+# 3. Recusrively mount root datasets, this should mount all datasets
+# present in a pool
+# 4. Unmount all datasets
+# 5. Recusrsively mount child datasets with children. This should mount
+# child datasets, but not the root dataset or parent datasets
+# 6. Unmount all datasets
+# 7. Mount root dataset recursively again and confirm all child
+# datasets are mounted.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must datasetexists $TESTPOOL/$TESTFS1 && \
+ destroy_dataset $TESTPOOL/$TESTFS1 -R
+ log_must datasetexists $TESTPOOL/$TESTFS2 && \
+ destroy_dataset $TESTPOOL/$TESTFS2 -R
+ log_must datasetexists $TESTPOOL/$TESTFS3 && \
+ destroy_dataset $TESTPOOL/$TESTFS3 -R
+}
+
+function setup_all
+{
+ log_must datasetexists $TESTPOOL/$TESTFS || zfs create $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS1
+ log_must zfs create $TESTPOOL/$TESTFS2
+ log_must zfs create $TESTPOOL/$TESTFS3
+ log_must zfs create $TESTPOOL/$TESTFS2/child1
+ log_must zfs create $TESTPOOL/$TESTFS2/child2
+ log_must zfs create $TESTPOOL/$TESTFS2/child3
+ log_must zfs create $TESTPOOL/$TESTFS2/child2/subchild
+ log_must zfs create $TESTPOOL/$TESTFS3/child
+}
+
+log_assert "Verify that 'zfs $mountrecursive' successfully, " \
+ "mounts the dataset along with all its children."
+
+log_onexit cleanup
+
+log_must setup_all
+
+log_must zfs $unmountall
+
+log_must zfs $mountrecursive $TESTPOOL
+
+log_must mounted $TESTPOOL
+log_must mounted $TESTPOOL/$TESTFS
+log_must mounted $TESTPOOL/$TESTFS1
+log_must mounted $TESTPOOL/$TESTFS2
+log_must mounted $TESTPOOL/$TESTFS3
+log_must mounted $TESTPOOL/$TESTFS2/child1
+log_must mounted $TESTPOOL/$TESTFS2/child2
+log_must mounted $TESTPOOL/$TESTFS2/child3
+log_must mounted $TESTPOOL/$TESTFS2/child2/subchild
+log_must mounted $TESTPOOL/$TESTFS3/child
+
+log_must zfs $unmountall
+
+log_mustnot mounted $TESTPOOL
+log_mustnot mounted $TESTPOOL/$TESTFS
+log_mustnot mounted $TESTPOOL/$TESTFS1
+log_mustnot mounted $TESTPOOL/$TESTFS2
+log_mustnot mounted $TESTPOOL/$TESTFS3
+log_mustnot mounted $TESTPOOL/$TESTFS2/child1
+log_mustnot mounted $TESTPOOL/$TESTFS2/child2
+log_mustnot mounted $TESTPOOL/$TESTFS2/child3
+log_mustnot mounted $TESTPOOL/$TESTFS2/child2/subchild
+log_mustnot mounted $TESTPOOL/$TESTFS3/child
+
+log_must zfs $mountrecursive $TESTPOOL/$TESTFS2 $TESTPOOL/$TESTFS3
+
+log_mustnot mounted $TESTPOOL
+log_mustnot mounted $TESTPOOL/$TESTFS
+log_mustnot mounted $TESTPOOL/$TESTFS1
+log_must mounted $TESTPOOL/$TESTFS2
+log_must mounted $TESTPOOL/$TESTFS3
+log_must mounted $TESTPOOL/$TESTFS2/child1
+log_must mounted $TESTPOOL/$TESTFS2/child2
+log_must mounted $TESTPOOL/$TESTFS2/child3
+log_must mounted $TESTPOOL/$TESTFS2/child2/subchild
+log_must mounted $TESTPOOL/$TESTFS3/child
+
+log_must zfs $unmountall
+
+log_mustnot mounted $TESTPOOL
+log_mustnot mounted $TESTPOOL/$TESTFS
+log_mustnot mounted $TESTPOOL/$TESTFS1
+log_mustnot mounted $TESTPOOL/$TESTFS2
+log_mustnot mounted $TESTPOOL/$TESTFS3
+log_mustnot mounted $TESTPOOL/$TESTFS2/child1
+log_mustnot mounted $TESTPOOL/$TESTFS2/child2
+log_mustnot mounted $TESTPOOL/$TESTFS2/child3
+log_mustnot mounted $TESTPOOL/$TESTFS2/child2/subchild
+log_mustnot mounted $TESTPOOL/$TESTFS3/child
+
+log_must zfs $mountrecursive $TESTPOOL/$TESTFS2/child2
+
+log_must mounted $TESTPOOL/$TESTFS2/child2
+log_must mounted $TESTPOOL/$TESTFS2/child2/subchild
+log_mustnot mounted $TESTPOOL
+log_mustnot mounted $TESTPOOL/$TESTFS
+log_mustnot mounted $TESTPOOL/$TESTFS1
+log_mustnot mounted $TESTPOOL/$TESTFS2
+log_mustnot mounted $TESTPOOL/$TESTFS3
+log_mustnot mounted $TESTPOOL/$TESTFS2/child1
+log_mustnot mounted $TESTPOOL/$TESTFS2/child3
+log_mustnot mounted $TESTPOOL/$TESTFS3/child
+
+log_pass "'zfs $mountrecursive' behaves as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh
index 259f0e99b65c..ed35b6e831a6 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh
index b0265c5ee4a1..2241b77bf806 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh
@@ -117,7 +117,9 @@ usage:
For the property list, run: zfs set|get
-For the delegated permission list, run: zfs allow|unallow")
+For the delegated permission list, run: zfs allow|unallow
+
+For further help on a command or topic, run: zfs help [<topic>]")
cnt=0
for cmd in ${neg_cmds[@]}; do
log_mustnot zfs program $cmd $TESTPOOL $TESTZCP $TESTDS 2>&1
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh
index 3e2e2ce319a6..13a5febb25c1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
index 6407328efd91..02d7c097a519 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh
index dc3ffd65ed38..173c46d76449 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh
index 1a774da2c15c..fa7c82ee87ab 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh
index 7dedaf91bed6..8d1ba8238a10 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh
index b8a5ab9c1707..653b21139f54 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh
index 289ddc6713bc..aa2deb9c3efd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh
index 7f08f28a9379..1aca734f46a1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh
index 95db7d9e6b4e..26740dcc4f6b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh
index c37c9a6269e7..33dc403aefcc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh
index e4998138f701..7bb00caed5a3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh
index 746a05015f8c..75bee687f5b7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh
index f53a4ac71b68..fd3194fe9895 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh
@@ -163,6 +163,7 @@ before_clone=$(get_prop written $TESTPOOL/$TESTFS1)
log_must zfs clone $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1/snap1.clone
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/snap1.clone/testfile bs=1M \
count=40
+sync_pool
after_clone=$(get_prop written $TESTPOOL/$TESTFS1)
within_percent $before_clone $after_clone 99.5 || \
log_fail "unexpected written for clone $before_clone $after_clone"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh
index cec69d4709f4..e3a213302614 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh
index 878189bafa2f..5fd3ff953096 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh
index 6e27130e0248..dc1653b698ee 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-wR-encrypted-mix.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh
index 2b4a086965e8..d8051c919f4d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh
index ba3fc49bd84c..9fb25a3e42b4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh
index 48cebc87f039..9cac9f54df16 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh
index 2860cab2b679..9f4b32ade733 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh
index 6a708a45e177..1841e07bdb00 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh
index 06a0804515a7..1406882645d1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh
index ec2437db929f..e88b2853c85c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh
index f948dfd6690b..be112d0cd394 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh
index 6cda13690cbd..c7cfe3cba71c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
index c91172ee048e..3e24d3e2e3b7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_compressed_corrective.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_compressed_corrective.ksh
new file mode 100755
index 000000000000..7f8eb0b138ee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_compressed_corrective.ksh
@@ -0,0 +1,193 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+# Copyright (c) 2022 Axcient.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# OpenZFS should be able to heal data using corrective recv when the send file
+# was generated with the --compressed flag
+#
+# STRATEGY:
+# 0. Create a file, checksum the file to be corrupted then compare it's checksum
+# with the one obtained after healing under different testing scenarios:
+# 1. Test healing (aka corrective) recv from a full send file
+# 2. Test healing recv (aka heal recv) from an incremental send file
+# 3. Test healing recv when compression on-disk is off but source was compressed
+# 4. Test heal recv when compression on-disk is on but source was uncompressed
+# 5. Test heal recv when compression doesn't match between send file and on-disk
+# 6. Test healing recv of an encrypted dataset using an unencrypted send file
+# 7. Test healing recv (on an encrypted dataset) using a raw send file
+# 8. Test healing when specifying destination filesystem only (no snapshot)
+# 9. Test incremental recv aftear healing recv
+#
+
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+
+backup=$TEST_BASE_DIR/backup
+raw_backup=$TEST_BASE_DIR/raw_backup
+ibackup=$TEST_BASE_DIR/ibackup
+unc_backup=$TEST_BASE_DIR/unc_backup
+
+function cleanup
+{
+ log_must rm -f $backup $raw_backup $ibackup $unc_backup
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ log_must zpool create -f $TESTPOOL $DISK
+}
+
+function test_corrective_recv
+{
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_must eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+
+ # make sure we will read the corruption from disk by flushing the ARC
+ log_must zinject -a
+
+ log_must eval "zfs recv -c $1 < $2"
+
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_mustnot eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+ typeset cksum=$(md5digest $file)
+ [[ "$cksum" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum != $checksum)"
+}
+
+log_onexit cleanup
+
+log_assert "ZFS corrective receive should be able to heal data corruption"
+
+typeset passphrase="password"
+typeset file="/$TESTPOOL/$TESTFS1/$TESTFILE0"
+
+log_must eval "poolexists $TESTPOOL && destroy_pool $TESTPOOL"
+log_must zpool create -f -o feature@head_errlog=disabled $TESTPOOL $DISK
+
+log_must eval "echo $passphrase > /$TESTPOOL/pwd"
+
+log_must zfs create -o primarycache=none \
+ -o atime=off -o compression=lz4 $TESTPOOL/$TESTFS1
+
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+log_must eval "echo 'aaaaaaaa' >> "$file
+typeset checksum=$(md5digest $file)
+
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1
+
+# create full send file
+log_must eval "zfs send --compressed $TESTPOOL/$TESTFS1@snap1 > $backup"
+
+log_must dd if=/dev/urandom of=$file"1" bs=1024 count=1024 oflag=sync
+log_must eval "echo 'bbbbbbbb' >> "$file"1"
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2
+# create incremental send file
+log_must eval "zfs send -c -i $TESTPOOL/$TESTFS1@snap1 \
+ $TESTPOOL/$TESTFS1@snap2 > $ibackup"
+
+corrupt_blocks_at_level $file 0
+# test healing recv from a full send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap1 $backup
+
+corrupt_blocks_at_level $file"1" 0
+# test healing recv from an incremental send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap2 $ibackup
+
+# create new uncompressed dataset using our send file
+log_must eval "zfs recv -o compression=off -o primarycache=none \
+ $TESTPOOL/$TESTFS2 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/$TESTFS2)
+[[ "$compr" == "off" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/$TESTFS2/$TESTFILE0" 0
+# test healing recv when compression on-disk is off but source was compressed
+test_corrective_recv "$TESTPOOL/$TESTFS2@snap1" $backup
+
+# create a full sendfile from an uncompressed source
+log_must eval "zfs send --compressed $TESTPOOL/$TESTFS2@snap1 > $unc_backup"
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ $TESTPOOL/testfs3 < $unc_backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs3)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs3/$TESTFILE0" 0
+# test healing recv when compression on-disk is on but source was uncompressed
+test_corrective_recv "$TESTPOOL/testfs3@snap1" $unc_backup
+
+# create new compressed dataset using our send file
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ $TESTPOOL/testfs4 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs4)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs4/$TESTFILE0" 0
+# test healing recv when compression doesn't match between send file and on-disk
+test_corrective_recv "$TESTPOOL/testfs4@snap1" $backup
+
+# create new encrypted (and compressed) dataset using our send file
+log_must eval "zfs recv -o encryption=aes-256-ccm -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pwd -o primarycache=none \
+ $TESTPOOL/testfs5 < $backup"
+typeset encr=$(get_prop encryption $TESTPOOL/testfs5)
+[[ "$encr" == "aes-256-ccm" ]] || \
+ log_fail "Unexpected encryption $encr in recved dataset"
+log_must eval "zfs send --raw $TESTPOOL/testfs5@snap1 > $raw_backup"
+log_must eval "zfs send --compressed $TESTPOOL/testfs5@snap1 > $backup"
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+# test healing recv of an encrypted dataset using an unencrypted send file
+test_corrective_recv "$TESTPOOL/testfs5@snap1" $backup
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+log_must zfs unmount $TESTPOOL/testfs5
+log_must zfs unload-key $TESTPOOL/testfs5
+# test healing recv (on an encrypted dataset) using a raw send file
+test_corrective_recv "$TESTPOOL/testfs5@snap1" $raw_backup
+# non raw send file healing an encrypted dataset with an unloaded key will fail
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap1 < $backup"
+
+log_must zfs rollback -r $TESTPOOL/$TESTFS1@snap1
+corrupt_blocks_at_level $file 0
+# test healing when specifying destination filesystem only (no snapshot)
+test_corrective_recv $TESTPOOL/$TESTFS1 $backup
+# test incremental recv aftear healing recv
+log_must eval "zfs recv $TESTPOOL/$TESTFS1 < $ibackup"
+
+# test that healing recv can not be combined with incompatible recv options
+log_mustnot eval "zfs recv -h -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -F -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -s -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -u -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -d -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -e -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+
+# ensure healing recv doesn't work when snap GUIDS don't match
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap2 < $backup"
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5 < $backup"
+
+# test that healing recv doesn't work on non-existing snapshots
+log_mustnot eval "zfs recv -c $TESTPOOL/$TESTFS1@missing < $backup"
+
+log_pass "OpenZFS corrective recv works for data healing"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_corrective.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_corrective.ksh
new file mode 100755
index 000000000000..261fc5eed8cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_corrective.ksh
@@ -0,0 +1,209 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+# Copyright (c) 2022 Axcient.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# OpenZFS should be able to heal data using corrective recv
+#
+# STRATEGY:
+# 0. Create a file, checksum the file to be corrupted then compare it's checksum
+# with the one obtained after healing under different testing scenarios:
+# 1. Test healing (aka corrective) recv from a full send file
+# 2. Test healing recv (aka heal recv) from an incremental send file
+# 3. Test healing recv when compression on-disk is off but source was compressed
+# 4. Test heal recv when compression on-disk is on but source was uncompressed
+# 5. Test heal recv when compression doesn't match between send file and on-disk
+# 6. Test healing recv of an encrypted dataset using an unencrypted send file
+# 7. Test healing recv (on an encrypted dataset) using a raw send file
+# 8. Test healing when specifying destination filesystem only (no snapshot)
+# 9. Test incremental recv aftear healing recv
+#
+
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+
+backup=$TEST_BASE_DIR/backup
+raw_backup=$TEST_BASE_DIR/raw_backup
+ibackup=$TEST_BASE_DIR/ibackup
+unc_backup=$TEST_BASE_DIR/unc_backup
+
+function cleanup
+{
+ log_must rm -f $backup $raw_backup $ibackup $unc_backup
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ log_must zpool create -f $TESTPOOL $DISK
+}
+
+function test_corrective_recv
+{
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_must eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+
+ # make sure we will read the corruption from disk by flushing the ARC
+ log_must zinject -a
+
+ log_must eval "zfs recv -c $1 < $2"
+
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_mustnot eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+ typeset cksum=$(md5digest $file)
+ [[ "$cksum" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum != $checksum)"
+}
+
+log_onexit cleanup
+
+log_assert "ZFS corrective receive should be able to heal data corruption"
+
+typeset passphrase="password"
+typeset file="/$TESTPOOL/$TESTFS1/$TESTFILE0"
+
+log_must eval "poolexists $TESTPOOL && destroy_pool $TESTPOOL"
+log_must zpool create -f $TESTPOOL $DISK
+
+log_must eval "echo $passphrase > /$TESTPOOL/pwd"
+
+log_must zfs create -o primarycache=none \
+ -o atime=off -o compression=lz4 $TESTPOOL/$TESTFS1
+
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+log_must eval "echo 'aaaaaaaa' >> "$file
+typeset checksum=$(md5digest $file)
+
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1
+
+# create full send file
+log_must eval "zfs send $TESTPOOL/$TESTFS1@snap1 > $backup"
+
+log_must dd if=/dev/urandom of=$file"1" bs=1024 count=1024 oflag=sync
+log_must eval "echo 'bbbbbbbb' >> "$file"1"
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2
+# create incremental send file
+log_must eval "zfs send -i $TESTPOOL/$TESTFS1@snap1 \
+ $TESTPOOL/$TESTFS1@snap2 > $ibackup"
+
+corrupt_blocks_at_level $file 0
+# test healing recv from a full send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap1 $backup
+
+corrupt_blocks_at_level $file"1" 0
+# test healing recv from an incremental send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap2 $ibackup
+
+# create new uncompressed dataset using our send file
+log_must eval "zfs recv -o compression=off -o primarycache=none \
+ $TESTPOOL/$TESTFS2 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/$TESTFS2)
+[[ "$compr" == "off" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/$TESTFS2/$TESTFILE0" 0
+# test healing recv when compression on-disk is off but source was compressed
+test_corrective_recv "$TESTPOOL/$TESTFS2@snap1" $backup
+
+# create a full sendfile from an uncompressed source
+log_must eval "zfs send $TESTPOOL/$TESTFS2@snap1 > $unc_backup"
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ $TESTPOOL/testfs3 < $unc_backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs3)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs3/$TESTFILE0" 0
+# test healing recv when compression on-disk is on but source was uncompressed
+test_corrective_recv "$TESTPOOL/testfs3@snap1" $unc_backup
+
+# create new compressed dataset using our send file
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ $TESTPOOL/testfs4 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs4)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs4/$TESTFILE0" 0
+# test healing recv when compression doesn't match between send file and on-disk
+test_corrective_recv "$TESTPOOL/testfs4@snap1" $backup
+
+# create new encrypted (and compressed) dataset using our send file
+log_must eval "zfs recv -o encryption=aes-256-ccm -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pwd -o primarycache=none \
+ $TESTPOOL/testfs5 < $backup"
+typeset encr=$(get_prop encryption $TESTPOOL/testfs5)
+[[ "$encr" == "aes-256-ccm" ]] || \
+ log_fail "Unexpected encryption $encr in recved dataset"
+log_must eval "zfs send --raw $TESTPOOL/testfs5@snap1 > $raw_backup"
+log_must eval "zfs send $TESTPOOL/testfs5@snap1 > $backup"
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+# test healing recv of an encrypted dataset using an unencrypted send file
+test_corrective_recv "$TESTPOOL/testfs5@snap1" $backup
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+log_must zfs unmount $TESTPOOL/testfs5
+log_must zfs unload-key $TESTPOOL/testfs5
+# test healing recv (on an encrypted dataset) using a raw send file
+# This is a special case since with unloaded keys we cannot report errors
+# in the filesystem.
+log_must zpool scrub -w $TESTPOOL
+log_must zpool status -v $TESTPOOL
+log_mustnot eval "zpool status -v $TESTPOOL | \
+ grep \"permission denied\""
+# make sure we will read the corruption from disk by flushing the ARC
+log_must zinject -a
+log_must eval "zfs recv -c $TESTPOOL/testfs5@snap1 < $raw_backup"
+
+log_must zpool scrub -w $TESTPOOL
+log_must zpool status -v $TESTPOOL
+log_mustnot eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+typeset cksum=$(md5digest $file)
+[[ "$cksum" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum != $checksum)"
+
+# non raw send file healing an encrypted dataset with an unloaded key will fail
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap1 < $backup"
+
+log_must zfs rollback -r $TESTPOOL/$TESTFS1@snap1
+corrupt_blocks_at_level $file 0
+# test healing when specifying destination filesystem only (no snapshot)
+test_corrective_recv $TESTPOOL/$TESTFS1 $backup
+# test incremental recv aftear healing recv
+log_must eval "zfs recv $TESTPOOL/$TESTFS1 < $ibackup"
+
+# test that healing recv can not be combined with incompatible recv options
+log_mustnot eval "zfs recv -h -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -F -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -s -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -u -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -d -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -e -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+
+# ensure healing recv doesn't work when snap GUIDS don't match
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap2 < $backup"
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5 < $backup"
+
+# test that healing recv doesn't work on non-existing snapshots
+log_mustnot eval "zfs recv -c $TESTPOOL/$TESTFS1@missing < $backup"
+
+log_pass "OpenZFS corrective recv works for data healing"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_large_block_corrective.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_large_block_corrective.ksh
new file mode 100755
index 000000000000..fbcd33f60704
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_large_block_corrective.ksh
@@ -0,0 +1,194 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+# Copyright (c) 2022 Axcient.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# OpenZFS should be able to heal data using corrective recv when the send file
+# was generated with the --large-block flag
+#
+# STRATEGY:
+# 0. Create a file, checksum the file to be corrupted then compare it's checksum
+# with the one obtained after healing under different testing scenarios:
+# 1. Test healing (aka corrective) recv from a full send file
+# 2. Test healing recv (aka heal recv) from an incremental send file
+# 3. Test healing recv when compression on-disk is off but source was compressed
+# 4. Test heal recv when compression on-disk is on but source was uncompressed
+# 5. Test heal recv when compression doesn't match between send file and on-disk
+# 6. Test healing recv of an encrypted dataset using an unencrypted send file
+# 7. Test healing recv (on an encrypted dataset) using a raw send file
+# 8. Test healing when specifying destination filesystem only (no snapshot)
+# 9. Test incremental recv aftear healing recv
+#
+
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+
+backup=$TEST_BASE_DIR/backup
+raw_backup=$TEST_BASE_DIR/raw_backup
+ibackup=$TEST_BASE_DIR/ibackup
+unc_backup=$TEST_BASE_DIR/unc_backup
+
+function cleanup
+{
+ log_must rm -f $backup $raw_backup $ibackup $unc_backup
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ log_must zpool create -f $TESTPOOL $DISK
+}
+
+function test_corrective_recv
+{
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_must eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+
+ # make sure we will read the corruption from disk by flushing the ARC
+ log_must zinject -a
+
+ log_must eval "zfs recv -c $1 < $2"
+
+ log_must zpool scrub -w $TESTPOOL
+ log_must zpool status -v $TESTPOOL
+ log_mustnot eval "zpool status -v $TESTPOOL | \
+ grep \"Permanent errors have been detected\""
+ typeset cksum=$(md5digest $file)
+ [[ "$cksum" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum != $checksum)"
+}
+
+log_onexit cleanup
+
+log_assert "ZFS corrective receive should be able to heal data corruption"
+
+typeset passphrase="password"
+typeset file="/$TESTPOOL/$TESTFS1/$TESTFILE0"
+
+log_must eval "poolexists $TESTPOOL && destroy_pool $TESTPOOL"
+log_must zpool create -f -o feature@large_blocks=enabled \
+ -o feature@head_errlog=disabled $TESTPOOL $DISK
+
+log_must eval "echo $passphrase > /$TESTPOOL/pwd"
+
+log_must zfs create -o recordsize=1m -o primarycache=none \
+ -o atime=off -o compression=lz4 $TESTPOOL/$TESTFS1
+
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+log_must eval "echo 'aaaaaaaa' >> "$file
+typeset checksum=$(md5digest $file)
+
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1
+
+# create full send file
+log_must eval "zfs send -L $TESTPOOL/$TESTFS1@snap1 > $backup"
+
+log_must dd if=/dev/urandom of=$file"1" bs=1024 count=1024 oflag=sync
+log_must eval "echo 'bbbbbbbb' >> "$file"1"
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2
+# create incremental send file
+log_must eval "zfs send -Li $TESTPOOL/$TESTFS1@snap1 \
+ $TESTPOOL/$TESTFS1@snap2 > $ibackup"
+
+corrupt_blocks_at_level $file 0
+# test healing recv from a full send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap1 $backup
+
+corrupt_blocks_at_level $file"1" 0
+# test healing recv from an incremental send file
+test_corrective_recv $TESTPOOL/$TESTFS1@snap2 $ibackup
+
+# create new uncompressed dataset using our send file
+log_must eval "zfs recv -o compression=off -o primarycache=none \
+ $TESTPOOL/$TESTFS2 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/$TESTFS2)
+[[ "$compr" == "off" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/$TESTFS2/$TESTFILE0" 0
+# test healing recv when compression on-disk is off but source was compressed
+test_corrective_recv "$TESTPOOL/$TESTFS2@snap1" $backup
+
+# create a full sendfile from an uncompressed source
+log_must eval "zfs send -L $TESTPOOL/$TESTFS2@snap1 > $unc_backup"
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ -o recordsize=1m $TESTPOOL/testfs3 < $unc_backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs3)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs3/$TESTFILE0" 0
+# test healing recv when compression on-disk is on but source was uncompressed
+test_corrective_recv "$TESTPOOL/testfs3@snap1" $unc_backup
+
+# create new compressed dataset using our send file
+log_must eval "zfs recv -o compression=gzip -o primarycache=none \
+ -o recordsize=1m $TESTPOOL/testfs4 < $backup"
+typeset compr=$(get_prop compression $TESTPOOL/testfs4)
+[[ "$compr" == "gzip" ]] || \
+ log_fail "Unexpected compression $compr in recved dataset"
+corrupt_blocks_at_level "/$TESTPOOL/testfs4/$TESTFILE0" 0
+# test healing recv when compression doesn't match between send file and on-disk
+test_corrective_recv "$TESTPOOL/testfs4@snap1" $backup
+
+# create new encrypted (and compressed) dataset using our send file
+log_must eval "zfs recv -o encryption=aes-256-ccm -o keyformat=passphrase \
+ -o recordsize=1m -o keylocation=file:///$TESTPOOL/pwd -o primarycache=none \
+ $TESTPOOL/testfs5 < $backup"
+typeset encr=$(get_prop encryption $TESTPOOL/testfs5)
+[[ "$encr" == "aes-256-ccm" ]] || \
+ log_fail "Unexpected encryption $encr in recved dataset"
+log_must eval "zfs send -L --raw $TESTPOOL/testfs5@snap1 > $raw_backup"
+log_must eval "zfs send -L $TESTPOOL/testfs5@snap1 > $backup"
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+# test healing recv of an encrypted dataset using an unencrypted send file
+test_corrective_recv "$TESTPOOL/testfs5@snap1" $backup
+corrupt_blocks_at_level "/$TESTPOOL/testfs5/$TESTFILE0" 0
+log_must zfs unmount $TESTPOOL/testfs5
+log_must zfs unload-key $TESTPOOL/testfs5
+# test healing recv (on an encrypted dataset) using a raw send file
+test_corrective_recv "$TESTPOOL/testfs5@snap1" $raw_backup
+# non raw send file healing an encrypted dataset with an unloaded key will fail
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap1 < $backup"
+
+log_must zfs rollback -r $TESTPOOL/$TESTFS1@snap1
+corrupt_blocks_at_level $file 0
+# test healing when specifying destination filesystem only (no snapshot)
+test_corrective_recv $TESTPOOL/$TESTFS1 $backup
+# test incremental recv aftear healing recv
+log_must eval "zfs recv -o recordsize=1m $TESTPOOL/$TESTFS1 < $ibackup"
+
+# test that healing recv can not be combined with incompatible recv options
+log_mustnot eval "zfs recv -h -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -F -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -s -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -u -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -d -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+log_mustnot eval "zfs recv -e -c $TESTPOOL/$TESTFS1@snap1 < $backup"
+
+# ensure healing recv doesn't work when snap GUIDS don't match
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5@snap2 < $backup"
+log_mustnot eval "zfs recv -c $TESTPOOL/testfs5 < $backup"
+
+# test that healing recv doesn't work on non-existing snapshots
+log_mustnot eval "zfs recv -c $TESTPOOL/$TESTFS1@missing < $backup"
+
+log_pass "OpenZFS corrective recv works for data healing"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
index 5d76c220fc45..7e12d30d0e7e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
@@ -25,20 +25,27 @@
# ZFS should receive to an encrypted child dataset.
#
# STRATEGY:
-# 1. Snapshot the default dataset
-# 2. Create an encrypted dataset
-# 3. Attempt to receive a stream to an encrypted child
-# 4. Attempt to receive a stream with properties to an encrypted child
-# 5. Attempt to receive a replication stream to an encrypted child
-# 6. Unmount and unload the encrypted dataset keys
-# 7. Attempt to receive a snapshot stream to an encrypted child
+# 1. Snapshot the default dataset
+# 2. Create an encrypted dataset
+# 3. Attempt to receive a stream to an encrypted child
+# 4. Unload the key
+# 5. Attempt to receive an incremental stream to an encrypted child (must fail)
+# 6. Attempt to receive a stream with properties to an unencrypted child
+# 7. Attempt to receive an incremental stream to an unencrypted child
+# 8. Attempt to receive with -o encryption=off to an unencrypted child
+# 9. Attempt to receive a replication stream to an unencrypted child
+# 10. Attempt to receive a snapshot stream to an encrypted child (must fail)
#
verify_runnable "both"
function cleanup
{
+ datasetexists $TESTPOOL/encrypted && \
+ destroy_dataset $TESTPOOL/encrypted -r
+
snapexists $snap && destroy_dataset $snap -f
+ snapexists $snap2 && destroy_dataset $snap2 -f
datasetexists $TESTPOOL/$TESTFS1 && \
destroy_dataset $TESTPOOL/$TESTFS1 -r
@@ -50,15 +57,17 @@ log_assert "ZFS should receive encrypted filesystems into child dataset"
typeset passphrase="password"
typeset snap="$TESTPOOL/$TESTFS@snap"
+typeset snap2="$TESTPOOL/$TESTFS@snap2"
typeset testfile="testfile"
log_must zfs snapshot $snap
+log_must zfs snapshot $snap2
log_must eval "echo $passphrase | zfs create -o encryption=on" \
"-o keyformat=passphrase $TESTPOOL/$TESTFS1"
log_note "Verifying ZFS will receive to an encrypted child"
-log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
+log_must eval "zfs send $snap | zfs receive -u $TESTPOOL/$TESTFS1/c1"
log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c1)" != "off"
# Unload the key, the following tests won't require it and we will test
@@ -66,10 +75,17 @@ log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c1)" != "off"
log_must zfs unmount $TESTPOOL/$TESTFS1
log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_note "Verifying ZFS will not receive an incremental into an encrypted" \
+ "dataset when the key is unloaded"
+log_mustnot eval "zfs send -i $snap $snap2 | zfs receive $TESTPOOL/$TESTFS1/c1"
+
log_note "Verifying 'send -p' will receive to an unencrypted child"
-log_must eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2"
+log_must eval "zfs send -p $snap | zfs receive -u $TESTPOOL/$TESTFS1/c2"
log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2)" == "off"
+log_note "Verifying 'send -i' will receive to an unencrypted child"
+log_must eval "zfs send -i $snap $snap2 | zfs receive $TESTPOOL/$TESTFS1/c2"
+
# For completeness add the property override case.
log_note "Verifying recv -o encyption=off' will receive to an unencrypted child"
log_must eval "zfs send $snap | \
@@ -84,4 +100,15 @@ log_note "Verifying ZFS will not receive to an encrypted child when the" \
"parent key is unloaded"
log_mustnot eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c4"
+# Verify that replication can override encryption properties
+log_note "Verifying replication can override encryption properties for plain dataset"
+typeset key_location="/$TESTPOOL/pkey1"
+log_must eval "echo $passphrase > $key_location"
+log_must eval "zfs send -R $snap2 | zfs recv -s -F -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=file://$key_location" \
+ "-o mountpoint=none $TESTPOOL/encrypted"
+log_must test "$(get_prop 'encryption' $TESTPOOL/encrypted)" != "off"
+log_must test "$(get_prop 'keyformat' $TESTPOOL/encrypted)" == "passphrase"
+log_must test "$(get_prop 'keylocation' $TESTPOOL/encrypted)" == "file://$key_location"
+
log_pass "ZFS can receive encrypted filesystems into child dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh
index 0a5b6c36111b..f8f253a3b615 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh
index 03701d4f5522..0f22179024bc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
index 9a8f38dc2443..8d3da7cdeaa0 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
index cafffbd85266..a3d735756fad 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh
index c76b5a2fe5c3..a4fb95c8d10e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh
index 6d51f612b311..05f1474b1854 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh
index 0bd4aca3a7fd..26ee9cb923df 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh
index b1438e8663e3..224fceaddd08 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh
index 5ef77de0c751..3717d1d9dad2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh
index 4d1605152201..5d67a4ed9547 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh
index 2a3f8a8ccd7b..5b8d7c78dfc1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh
index 229163839058..6f5974cc235e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh
index 7e8119766bf7..7eef546380b2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh
index 171770fa32a1..b631ea886823 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh
index 71d72619d646..43632c7d34ba 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh
index 6daf001797e6..16c93e9f4e14 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh
index 73790f58cd45..f33a971729ed 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh
index 57bae24277e1..d0b6984d21cb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh
index 7ec55ce0f3d2..416139f7aa3b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh
index 7f90630360ff..49eabfeb7223 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh
index 707e8f121ddb..93abeb1338ce 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh
index d3341b1c27fc..562e5242d3c8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
index d6c8934d9753..215f3c350785 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh
index 607bbf06eafd..5290f06205b2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh
index 659660dc0fe7..3b03063d0c1c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh
index 1e3109108bae..e798a7bec5c2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh
index 9537d5077b1a..be59742c9051 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
index cc1b24697d21..29eb82a22cd6 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh
index cec69d4709f4..e3a213302614 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg
index bbc4d3ac833e..49f7245f9c58 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh
index 2c7bac851608..a8b22756a6d5 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh
index c55ce08d006e..f575c0cc8da7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh
index b04c9d3b240c..211225dd6fbe 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh
index 66a3da69f74b..ea3a759ddadc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh
index de8b28534fe1..174b21feb23e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
index c5dfb89394f4..d7ee161eb3be 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
@@ -119,33 +119,33 @@ full_size=$(zfs send $full_snapshot 2>&1 | wc -c)
incremental_size=$(zfs send $incremental_snapshot 2>&1 | wc -c)
incremental_send=$(zfs send -i $full_snapshot $incremental_snapshot 2>&1 | wc -c)
-log_note "verify zfs send -nv"
-options="-nv"
+log_note "verify zfs send -nvV"
+options="-nvV"
refer_size=$(get_prop refer $full_snapshot)
estimate_size=$(get_estimate_size $full_snapshot $options)
log_must verify_size_estimates $options $full_size
-log_note "verify zfs send -Pnv"
-options="-Pnv"
+log_note "verify zfs send -PnvV"
+options="-PnvV"
estimate_size=$(get_estimate_size $full_snapshot $options)
log_must verify_size_estimates $options $full_size
-log_note "verify zfs send -nv for multiple snapshot send"
-options="-nv"
+log_note "verify zfs send -nvV for multiple snapshot send"
+options="-nvV"
refer_size=$(get_prop refer $incremental_snapshot)
estimate_size=$(get_estimate_size $incremental_snapshot $options)
log_must verify_size_estimates $options $incremental_size
-log_note "verify zfs send -vPn for multiple snapshot send"
-options="-vPn"
+log_note "verify zfs send -vVPn for multiple snapshot send"
+options="-vVPn"
estimate_size=$(get_estimate_size $incremental_snapshot $options)
log_must verify_size_estimates $options $incremental_size
-log_note "verify zfs send -inv for incremental send"
-options="-nvi"
+log_note "verify zfs send -invV for incremental send"
+options="-nvVi"
refer_size=$(get_prop refer $incremental_snapshot)
deduct_size=$(get_prop refer $full_snapshot)
refer_size=$(echo "$refer_size - $deduct_size" | bc)
@@ -155,8 +155,8 @@ log_must verify_size_estimates $options $incremental_send
estimate_size=$(get_estimate_size $incremental_snapshot $options $full_bookmark)
log_must verify_size_estimates $options $incremental_send
-log_note "verify zfs send -ivPn for incremental send"
-options="-vPni"
+log_note "verify zfs send -ivVPn for incremental send"
+options="-vVPni"
estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
log_must verify_size_estimates $options $incremental_send
@@ -186,16 +186,16 @@ for ds in $datasets; do
datasetexists $ds@snap64 || log_fail "Create $ds@snap64 snapshot fail."
done
recursive_size=$(zfs send -R $full_snapshot 2>&1 | wc -c)
-log_note "verify zfs send -Rnv for recursive send"
-options="-Rnv"
+log_note "verify zfs send -RnvV for recursive send"
+options="-RnvV"
refer_size=$(get_prop refer $full_snapshot)
refer_size=$(echo "$refer_size * 3" | bc)
estimate_size=$(get_estimate_size $full_snapshot $options)
log_must verify_size_estimates $options $recursive_size
-log_note "verify zfs send -RvPn for recursive send"
-options="-RvPn"
+log_note "verify zfs send -RvVPn for recursive send"
+options="-RvVPn"
estimate_size=$(get_estimate_size $full_snapshot $options)
log_must verify_size_estimates $options $recursive_size
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_skip_missing.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_skip_missing.ksh
index 17b191a36173..06a53fcddd5e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_skip_missing.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_skip_missing.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh
index bffc47f817dd..de073bf1132f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh
index caad211bcf65..b4f24f5adf19 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh
index fe8aa2fd1e07..4eb11423d9e4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh
index bb7cd4cccc39..d628d6fc6ab1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh
index b370118a7f76..fa9948445d9f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh
index e75114efdec0..b3f1afc63ab2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh
index cab7c185e16a..91b08a838bd1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh
index fad025cac246..b6c8bb2f47e9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh
index 06da5f2f3ce8..ebeed4a7dab7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh
index 30efef1c383f..c1f5affa3414 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh
index 603e84dcd07f..c227a6fb8aa8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -35,7 +35,9 @@
#
# DESCRIPTION:
# If ZFS is currently managing the file system but it is currently unmounted,
-# and the mountpoint property is changed, the file system remains unmounted.
+# and the mountpoint property is changed, the file system should be mounted
+# if it is a valid mountpoint and canmount allows to mount, otherwise it
+# should not be mounted.
#
# STRATEGY:
# 1. Setup a pool and create fs, ctr within it.
@@ -62,7 +64,7 @@ function cleanup
}
log_assert "Setting a valid mountpoint for an unmounted file system, \
- it remains unmounted."
+ it gets mounted."
log_onexit cleanup
old_fs_mpt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
@@ -83,7 +85,11 @@ while (( i < ${#dataset[@]} )); do
while (( j < ${#values[@]} )); do
set_n_check_prop "${values[j]}" "mountpoint" \
"${dataset[i]}"
- log_mustnot ismounted ${dataset[i]}
+ if [ "${dataset[i]}" = "$TESTPOOL/$TESTFS" ]; then
+ log_must ismounted ${dataset[i]}
+ else
+ log_mustnot ismounted ${dataset[i]}
+ fi
(( j += 1 ))
done
cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh
index 38bbda0d1fae..01b505e4ab1a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh
index 7ba6d7fb659d..d6daf0e1b74e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh
index 0ddafe178e3a..b75143ed61bd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh
index 4adac420f748..20d6b634429a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh
index b929047cf129..9430c1ac4070 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh
index e24376a2bf74..d3d041f3395d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh
index 9692385996d1..2a909eba4f87 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh
index fa32c2774f8b..3097d931f683 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh
index 29a709397422..a41fa6c251b3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh
index 16b9638787e2..b897dffcbd27 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh
index 12cff78ea4ca..868abc82f394 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh
index 3d8c1e7be18d..80f279cbe992 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh
index 8ab52679eb9a..bcd367773722 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh
index 318a9aae6b45..0443b63376f1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh
index e58fe9bfe93c..0701c9ef0f28 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh
index 2178175cd5b6..946f6983b161 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh
index fd5f7f285f5b..5901ba7dc461 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -33,7 +33,9 @@
#
# DESCRIPTION:
-# 'zfs set mountpoint/sharenfs' should fail when the mountpoint is invalid
+# 'zfs set mountpoint/sharenfs' should set the property when mountpoint
+# is invalid. Setting the property should be successful, but dataset
+# should not be mounted, as mountpoint is invalid.
#
# STRATEGY:
# 1. Create invalid scenarios
@@ -62,10 +64,12 @@ longpath=$(gen_dataset_name 1030 "abcdefg")
log_must zfs create -o mountpoint=legacy $TESTPOOL/foo
# Do the negative testing about "property may be set but unable to remount filesystem"
-log_mustnot eval "zfs set mountpoint=$badpath $TESTPOOL/foo >/dev/null 2>&1"
+set_n_check_prop "$badpath" "mountpoint" "$TESTPOOL/foo"
+log_mustnot ismounted $TESTPOOL/foo
# Do the negative testing about "property may be set but unable to reshare filesystem"
-log_mustnot eval "zfs set sharenfs=on $TESTPOOL/foo >/dev/null 2>&1"
+set_n_check_prop "on" "sharenfs" "$TESTPOOL/foo"
+log_mustnot ismounted $TESTPOOL/foo
# Do the negative testing about "sharenfs property can not be set to null"
log_mustnot eval "zfs set sharenfs= $TESTPOOL/foo >/dev/null 2>&1"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
index 2858275cf2b9..484c7d862276 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh
index c5e6fb9c1140..760301c11758 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_nomount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_nomount.ksh
new file mode 100755
index 000000000000..ebf08711423c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_nomount.ksh
@@ -0,0 +1,103 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by iXsystems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs set -u' should update the mountpoint, sharenfs and sharesmb
+# properties without mounting and sharing the dataset. Validate the
+# bevaior while dataset is mounted and unmounted.
+#
+# STRATEGY:
+# 1. Confirm dataset is currently mounted
+# 2. Update the mountpoint with -u flag
+# 3. Confirm mountpoint property is updated with new value
+# 4. Confirm dataset is still mounted at previous mountpoint
+# 5. Unmount the dataset
+# 6. Confirm dataset is unmounted
+# 7. Mount the dataset
+# 8. Confirm dataset is mounted at new mountpoint, that was set with -u flag.
+# 9. Update and mount the dataset at previous mountpoint.
+# 10. Unmount the dataset
+# 11. Update mountpoint property with zfs set -u
+# 12. Confirm dataset is not mounted
+# 13. Update sharenfs property with zfs set -u
+# 14. Confirm dataset is not mounted
+# 15. Update sharesmb property with zfs set -u
+# 16. Confirm dataset is not mounted
+# 17. Mount the dataset and confirm dataset is mounted at new mountpoint
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ if is_linux; then
+ log_must zfs set sharesmb=off $TESTPOOL/$TESTFS
+ fi
+ rm -r $newmpt
+}
+
+log_assert "'zfs set -u' sets the mountpoint and share properties without " \
+ "mounting the dataset"
+log_onexit cleanup
+
+oldmpt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+newmpt=$TEST_BASE_DIR/abc
+
+# Test while dataset is mounted
+log_must ismounted $TESTPOOL/$TESTFS
+log_must zfs set -u mountpoint=$newmpt $TESTPOOL/$TESTFS
+log_must check_user_prop $TESTPOOL/$TESTFS mountpoint $newmpt
+log_must eval "[[ "$(mount | grep $TESTPOOL/$TESTFS | awk '{print $3}')" == $oldmpt ]]"
+log_must zfs unmount $TESTPOOL/$TESTFS
+log_mustnot ismounted $TESTPOOL/$TESTFS
+log_must zfs mount $TESTPOOL/$TESTFS
+log_must eval "[[ "$(mount | grep $TESTPOOL/$TESTFS | awk '{print $3}')" == $newmpt ]]"
+
+# Test while dataset is unmounted
+log_must zfs set mountpoint=$oldmpt $TESTPOOL/$TESTFS
+log_must ismounted $TESTPOOL/$TESTFS
+log_must zfs unmount $TESTPOOL/$TESTFS
+log_must zfs set -u mountpoint=$newmpt $TESTPOOL/$TESTFS
+log_mustnot ismounted $TESTPOOL/$TESTFS
+log_must zfs set -u sharenfs=on $TESTPOOL/$TESTFS
+log_mustnot ismounted $TESTPOOL/$TESTFS
+if is_linux; then
+ log_must zfs set -u sharesmb=on $TESTPOOL/$TESTFS
+ log_mustnot ismounted $TESTPOOL/$TESTFS
+fi
+log_must zfs mount $TESTPOOL/$TESTFS
+log_must check_user_prop $TESTPOOL/$TESTFS mountpoint $newmpt
+log_must eval "[[ "$(mount | grep $TESTPOOL/$TESTFS | awk '{print $3}')" == $newmpt ]]"
+
+log_must zfs set mountpoint=$oldmpt $TESTPOOL/$TESTFS
+log_must ismounted $TESTPOOL/$TESTFS
+
+log_pass "'zfs set -u' functions correctly"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh
index 1601087f712c..4310985e6624 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg
index 5c31c8fbb6e7..4c52ddef529d 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh
index 6d4396aa1912..b8e9407e756e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh
index 588a30f46de9..65cbe3f2a89d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh
index b99c72ca14e5..b2cb8f5c470f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh
index 6c48875f5268..a00a3ddcc8ac 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
index 719dd645028a..85854085f560 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh
index d5394017d780..64d6e9515549 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
index 553605000d1b..6a21dd22b93c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh
index 34fbd389949d..3ac845510b24 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
index ddd65e88859b..07aa52afd201 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh
index 238a5862920b..946fa36f1ffc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh
index efd7a2d0c7bd..7bd50e7514a8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh
index fe38d5559542..70eb5abd02fb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_013_pos.ksh
index e9766de49285..1aacebbe44d2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_after_mount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_after_mount.ksh
new file mode 100755
index 000000000000..0d4b66ea854c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_after_mount.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Proxmox. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+# DESCRIPTION:
+# Verify that nfs shares persist after zfs mount -a
+#
+# STRATEGY:
+# 1. Verify that the filesystem is not shared.
+# 2. Enable the 'sharenfs' property
+# 3. Verify filesystem is shared
+# 4. Invoke 'zfs mount -a'
+# 5. Verify filesystem is still shared
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ is_shared $TESTPOOL/$TESTFS && \
+ log_must unshare_fs $TESTPOOL/$TESTFS
+ log_must zfs share -a
+}
+
+
+log_onexit cleanup
+
+cleanup
+
+log_must zfs set sharenfs="on" $TESTPOOL/$TESTFS
+log_must is_shared $TESTPOOL/$TESTFS
+log_must is_exported $TESTPOOL/$TESTFS
+
+log_must zfs mount -a
+log_must is_shared $TESTPOOL/$TESTFS
+log_must is_exported $TESTPOOL/$TESTFS
+
+log_pass "Verify that nfs shares persist after zfs mount -a"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh
index 22b8af4e89d8..d779689f83bd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -98,11 +98,26 @@ function test_share # filesystem
zfs set sharenfs=on $filesystem || \
sub_fail "zfs set sharenfs=on $filesystem failed."
- is_shared $mntp || \
- sub_fail "File system $filesystem is not shared (set sharenfs)."
#
- # Verify 'zfs share' works as well.
+ # Verify 'zfs share' results in a shared mount. We check this
+ # multiple times because of Fedora 37+ it's been observed in
+ # the CI that the share may not be immediately reported.
+ #
+ for retry in $(seq 1 10); do
+ is_shared $mntp && break
+
+ log_note "Wait $retry / 10 for is_shared $mntp (set sharenfs)"
+
+ if [[ $retry -eq 10 ]]; then
+ sub_fail "File system $filesystem is not shared (set sharenfs)."
+ fi
+
+ sleep 1
+ done
+
+ #
+ # Verify 'zfs unshare' works as well.
#
zfs unshare $filesystem || \
sub_fail "zfs unshare $filesystem failed."
@@ -112,9 +127,23 @@ function test_share # filesystem
zfs share $filesystem || \
sub_fail "zfs share $filesystem failed."
- is_shared $mntp || \
- sub_fail "file system $filesystem is not shared (zfs share)."
+ #
+ # Verify 'zfs share' results in a shared mount. We check this
+ # multiple times because of Fedora 37+ it's been observed in
+ # the CI that the share may not be immediately reported.
+ #
+ for retry in $(seq 1 10); do
+ is_shared $mntp && break
+
+ log_note "Wait $retry / 10 for is_shared $mntp (zfs share)"
+
+ if [[ $retry -eq 10 ]]; then
+ sub_fail "File system $filesystem is not shared (zfs share)."
+ fi
+
+ sleep 1
+ done
#log_note "Sharing a shared file system fails."
zfs share $filesystem && \
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh
index d247991fbbdb..d9f935900f90 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh
index b3f2b0262687..b76d7c5f2560 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
index fb22367be869..cbad8a572067 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh
index 2b89af9e5a43..2b883e4943ef 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh
index 4ae68d411dd0..11904554a49c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh
index ca8ff8ca4357..7b6b01da07cb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh
index 62bf71390c70..53f3015393eb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh
index be5bbc8346d6..c9f9803c673e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh
index 6b711286c68d..785ea8659705 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh
index 40b936dee977..5d1840447fc4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh
index 627910abd6ed..a2f890f15f32 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh
index 7d6a7e13db22..a2ee99c24171 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh
index 261bce4386e9..f40ac985e80c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh
index c9d24224337f..523b30ff9bfe 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh
index 59ed7e9500dd..1d52498de0dc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh
index 5a0b88a0b14d..5bb46ec973ad 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh
index 4bb5cc2e05ba..08a9aeaa9bad 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh
index 3ab1d941e860..3624a7e8de5b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh
index 03eb2aea3fdd..a2f0c7a26405 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
index c8e46895d2a6..06d25faf0356 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
index 3fc5509a612e..929452403b2e 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh
index 6036eb27a062..6395a1b64363 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh
index b8a50785868f..c5cabbde1642 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh
index 985c3d2b1fe2..e4b292436a29 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh
index bcc25ccd0f80..e139321e04ab 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh
index eaea4696dfb4..23963ceaa82c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh
index 0afb9b6f8501..aca84ed39856 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh
index cdf4a5a26661..1a8665b86ea8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh
index e85a0f3cbf68..3524efcd076d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh
index 814d603db5e0..ece19ca1bbdf 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh
index b5a01b53aeab..f98d48ad92d3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh
index c92287ad75e4..d296118e1924 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
index 3955f0ee3590..4f0ef6bd389f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
index 2fb8ae7814ea..e5f786e0ae28 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
index 6e66deda9bee..6d081ab6ee89 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh
index fd916040b1bc..bae5e335158b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh
index 7df3136dd6b4..0404e0d6ede5 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
index b6e5178cf2bb..ab8bfa3791b7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh
index 36817a092099..0fc5bbaf3f6a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_008_pos.ksh
index 21d5ac79bbdc..1ade9c92691e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh
index e2d0604fded2..6b9dbd6b6dfa 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh
index c9f36017df9a..ab5ca7b27e6f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
index 9c7d273b385c..948123e81157 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh
index db8b96f50568..7f5f65978ebf 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh
index 994ee2b3475a..ea5baf8e5483 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh
index 57f74ca28513..e2a85ada96aa 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh
index 0b8fef5cd043..5367503f270d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh
index 5fcdc6e26852..ab200674b098 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh
index f5eef319330b..9c4eab3ff79e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh
index 6c6f94754d3c..a7d366e650ea 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib b/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib
new file mode 100644
index 000000000000..880a78861630
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib
@@ -0,0 +1,361 @@
+#!/bin/ksh
+
+#
+# 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 vStack. All rights reserved.
+#
+
+. "$STF_SUITE"/include/libtest.shlib
+. "$STF_SUITE"/include/blkdev.shlib
+
+#
+# Description:
+#
+# Test whether zhack label repair commands can recover detached devices
+# and corrupted checksums with a variety of sizes, and ensure
+# the purposes of either command is cleanly separated from the others.
+#
+# Strategy:
+#
+# Tests are done on loopback devices with sizes divisible by label size and sizes that are not.
+#
+# Test one:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Export the pool.
+# 3. Corrupt all label checksums in the pool
+# 4. Check that pool cannot be imported
+# 5. Verify that it cannot be imported after using zhack label repair -u
+# to ensure that the -u option will quit on corrupted checksums.
+# 6. Use zhack label repair -c on device
+# 7. Check that pool can be imported and that data is intact
+#
+# Test two:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Verify that the remaining detached device cannot be imported
+# 6. Verify that it cannot be imported after using zhack label repair -c
+# to ensure that the -c option will not undetach a device.
+# 7. Use zhack label repair -u on device
+# 8. Verify that the detached device can be imported and that data is intact
+#
+# Test three:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Corrupt all label checksums on the remaining device
+# 6. Verify that the remaining detached device cannot be imported
+# 7. Verify that it cannot be imported after using zhack label repair -u
+# to ensure that the -u option will quit on corrupted checksums.
+# 8. Verify that it cannot be imported after using zhack label repair -c
+# -c should repair the checksums, but not undetach a device.
+# 9. Use zhack label repair -u on device
+# 10. Verify that the detached device can be imported and that data is intact
+#
+# Test four:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Corrupt all label checksums on the remaining device
+# 6. Verify that the remaining detached device cannot be imported
+# 7. Use zhack label repair -cu on device to attempt to fix checksums and
+# undetach the device in a single operation.
+# 8. Verify that the detached device can be imported and that data is intact
+#
+
+log_assert "Verify zhack label repair <operation> <vdev> will repair label checksums and uberblocks"
+log_onexit cleanup
+
+LABEL_SIZE="$((2**18))"
+LABEL_NVLIST_END="$((LABEL_SIZE / 2))"
+LABEL_CKSUM_SIZE="32"
+LABEL_CKSUM_START="$(( LABEL_NVLIST_END - LABEL_CKSUM_SIZE ))"
+
+VIRTUAL_DISK=$TEST_BASE_DIR/disk
+VIRTUAL_MIRROR_DISK=$TEST_BASE_DIR/mirrordisk
+
+VIRTUAL_DEVICE=
+VIRTUAL_MIRROR_DEVICE=
+
+function cleanup_lo
+{
+ L_DEVICE="$1"
+
+ if [[ -e $L_DEVICE ]]; then
+ if is_linux; then
+ log_must losetup -d "$L_DEVICE"
+ elif is_freebsd; then
+ log_must mdconfig -d -u "$L_DEVICE"
+ else
+ log_must lofiadm -d "$L_DEVICE"
+ fi
+ fi
+}
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && destroy_pool "$TESTPOOL"
+ cleanup_lo "$VIRTUAL_DEVICE"
+ cleanup_lo "$VIRTUAL_MIRROR_DEVICE"
+ VIRTUAL_DEVICE=
+ VIRTUAL_MIRROR_DEVICE=
+ [[ -f "$VIRTUAL_DISK" ]] && log_must rm "$VIRTUAL_DISK"
+ [[ -f "$VIRTUAL_MIRROR_DISK" ]] && log_must rm "$VIRTUAL_MIRROR_DISK"
+}
+
+RAND_MAX="$((2**15 - 1))"
+function get_devsize
+{
+ if [ "$RANDOM" -gt "$(( RAND_MAX / 2 ))" ]; then
+ echo "$(( MINVDEVSIZE + RANDOM ))"
+ else
+ echo "$MINVDEVSIZE"
+ fi
+}
+
+function pick_logop
+{
+ L_SHOULD_SUCCEED="$1"
+
+ l_logop="log_mustnot"
+ if [ "$L_SHOULD_SUCCEED" == true ]; then
+ l_logop="log_must"
+ fi
+
+ echo "$l_logop"
+}
+
+function check_dataset
+{
+ L_SHOULD_SUCCEED="$1"
+ L_LOGOP="$(pick_logop "$L_SHOULD_SUCCEED")"
+
+ "$L_LOGOP" mounted "$TESTPOOL"/"$TESTFS"
+
+ "$L_LOGOP" test -f "$TESTDIR"/"test"
+}
+
+function setup_dataset
+{
+ log_must zfs create "$TESTPOOL"/"$TESTFS"
+
+ log_must mkdir -p "$TESTDIR"
+ log_must zfs set mountpoint="$TESTDIR" "$TESTPOOL"/"$TESTFS"
+
+ log_must mounted "$TESTPOOL"/"$TESTFS"
+
+ log_must touch "$TESTDIR"/"test"
+ log_must test -f "$TESTDIR"/"test"
+
+ log_must zpool sync "$TESTPOOL"
+
+ check_dataset true
+}
+
+function get_practical_size
+{
+ L_SIZE="$1"
+
+ if [ "$((L_SIZE % LABEL_SIZE))" -ne 0 ]; then
+ echo "$(((L_SIZE / LABEL_SIZE) * LABEL_SIZE))"
+ else
+ echo "$L_SIZE"
+ fi
+}
+
+function corrupt_sized_label_checksum
+{
+ L_SIZE="$1"
+ L_LABEL="$2"
+ L_DEVICE="$3"
+
+ L_PRACTICAL_SIZE="$(get_practical_size "$L_SIZE")"
+
+ typeset -a L_OFFSETS=("$LABEL_CKSUM_START" \
+ "$((LABEL_SIZE + LABEL_CKSUM_START))" \
+ "$(((L_PRACTICAL_SIZE - LABEL_SIZE*2) + LABEL_CKSUM_START))" \
+ "$(((L_PRACTICAL_SIZE - LABEL_SIZE) + LABEL_CKSUM_START))")
+
+ dd if=/dev/urandom of="$L_DEVICE" \
+ seek="${L_OFFSETS["$L_LABEL"]}" bs=1 count="$LABEL_CKSUM_SIZE" \
+ conv=notrunc
+}
+
+function corrupt_labels
+{
+ L_SIZE="$1"
+ L_DISK="$2"
+
+ corrupt_sized_label_checksum "$L_SIZE" 0 "$L_DISK"
+ corrupt_sized_label_checksum "$L_SIZE" 1 "$L_DISK"
+ corrupt_sized_label_checksum "$L_SIZE" 2 "$L_DISK"
+ corrupt_sized_label_checksum "$L_SIZE" 3 "$L_DISK"
+}
+
+function try_import_and_repair
+{
+ L_REPAIR_SHOULD_SUCCEED="$1"
+ L_IMPORT_SHOULD_SUCCEED="$2"
+ L_OP="$3"
+ L_POOLDISK="$4"
+ L_REPAIR_LOGOP="$(pick_logop "$L_REPAIR_SHOULD_SUCCEED")"
+ L_IMPORT_LOGOP="$(pick_logop "$L_IMPORT_SHOULD_SUCCEED")"
+
+ log_mustnot zpool import "$TESTPOOL" -d "$L_POOLDISK"
+
+ "$L_REPAIR_LOGOP" zhack label repair "$L_OP" "$L_POOLDISK"
+
+ "$L_IMPORT_LOGOP" zpool import "$TESTPOOL" -d "$L_POOLDISK"
+
+ check_dataset "$L_IMPORT_SHOULD_SUCCEED"
+}
+
+function prepare_vdev
+{
+ L_SIZE="$1"
+ L_BACKFILE="$2"
+
+ l_devname=
+ if truncate -s "$L_SIZE" "$L_BACKFILE"; then
+ if is_linux; then
+ l_devname="$(losetup -f "$L_BACKFILE" --show)"
+ elif is_freebsd; then
+ l_devname=/dev/"$(mdconfig -a -t vnode -f "$L_BACKFILE")"
+ else
+ l_devname="$(lofiadm -a "$L_BACKFILE")"
+ fi
+ fi
+ echo "$l_devname"
+}
+
+function run_test_one
+{
+ L_SIZE="$1"
+
+ VIRTUAL_DEVICE="$(prepare_vdev "$L_SIZE" "$VIRTUAL_DISK")"
+ log_must test -e "$VIRTUAL_DEVICE"
+
+ log_must zpool create "$TESTPOOL" "$VIRTUAL_DEVICE"
+
+ setup_dataset
+
+ log_must zpool export "$TESTPOOL"
+
+ corrupt_labels "$L_SIZE" "$VIRTUAL_DISK"
+
+ try_import_and_repair false false "-u" "$VIRTUAL_DEVICE"
+
+ try_import_and_repair true true "-c" "$VIRTUAL_DEVICE"
+
+ cleanup
+
+ log_pass "zhack label repair corruption test passed with a randomized size of $L_SIZE"
+}
+
+function make_mirrored_pool
+{
+ L_SIZE="$1"
+
+ VIRTUAL_DEVICE="$(prepare_vdev "$L_SIZE" "$VIRTUAL_DISK")"
+ log_must test -e "$VIRTUAL_DEVICE"
+ VIRTUAL_MIRROR_DEVICE="$(prepare_vdev "$L_SIZE" "$VIRTUAL_MIRROR_DISK")"
+ log_must test -e "$VIRTUAL_MIRROR_DEVICE"
+
+ log_must zpool create "$TESTPOOL" "$VIRTUAL_DEVICE"
+ log_must zpool attach "$TESTPOOL" "$VIRTUAL_DEVICE" "$VIRTUAL_MIRROR_DEVICE"
+}
+
+function export_and_cleanup_vdisk
+{
+ log_must zpool export "$TESTPOOL"
+
+ cleanup_lo "$VIRTUAL_DEVICE"
+
+ VIRTUAL_DEVICE=
+
+ log_must rm "$VIRTUAL_DISK"
+}
+
+function run_test_two
+{
+ L_SIZE="$1"
+
+ make_mirrored_pool "$L_SIZE"
+
+ setup_dataset
+
+ log_must zpool detach "$TESTPOOL" "$VIRTUAL_MIRROR_DEVICE"
+
+ export_and_cleanup_vdisk
+
+ try_import_and_repair false false "-c" "$VIRTUAL_MIRROR_DEVICE"
+
+ try_import_and_repair true true "-u" "$VIRTUAL_MIRROR_DEVICE"
+
+ cleanup
+
+ log_pass "zhack label repair detached test passed with a randomized size of $L_SIZE"
+}
+
+function run_test_three
+{
+ L_SIZE="$1"
+
+ make_mirrored_pool "$L_SIZE"
+
+ setup_dataset
+
+ log_must zpool detach "$TESTPOOL" "$VIRTUAL_MIRROR_DEVICE"
+
+ export_and_cleanup_vdisk
+
+ corrupt_labels "$L_SIZE" "$VIRTUAL_MIRROR_DISK"
+
+ try_import_and_repair false false "-u" "$VIRTUAL_MIRROR_DEVICE"
+
+ try_import_and_repair true false "-c" "$VIRTUAL_MIRROR_DEVICE"
+
+ try_import_and_repair true true "-u" "$VIRTUAL_MIRROR_DEVICE"
+
+ cleanup
+
+ log_pass "zhack label repair corruption and detached test passed with a randomized size of $L_SIZE"
+}
+
+function run_test_four
+{
+ L_SIZE="$1"
+
+ make_mirrored_pool "$L_SIZE"
+
+ setup_dataset
+
+ log_must zpool detach "$TESTPOOL" "$VIRTUAL_MIRROR_DEVICE"
+
+ export_and_cleanup_vdisk
+
+ corrupt_labels "$L_SIZE" "$VIRTUAL_MIRROR_DISK"
+
+ try_import_and_repair true true "-cu" "$VIRTUAL_MIRROR_DEVICE"
+
+ cleanup
+
+ log_pass "zhack label repair corruption and detached single-command test passed with a randomized size of $L_SIZE."
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_checksum.ksh b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_checksum.ksh
deleted file mode 100755
index 67c7e7c4487d..000000000000
--- a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_checksum.ksh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/ksh
-
-#
-# 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 vStack. All rights reserved.
-#
-
-. $STF_SUITE/include/libtest.shlib
-. $STF_SUITE/include/blkdev.shlib
-
-#
-# Description:
-# zhack label repair <vdev> will calculate and rewrite label checksum if invalid
-#
-# Strategy:
-# 1. Create pool with some number of vdevs and export it
-# 2. Corrupt all labels checksums
-# 3. Check that pool cannot be imported
-# 4. Use zhack to repair labels checksums
-# 5. Check that pool can be imported
-#
-
-log_assert "Verify zhack label repair <vdev> will repair labels checksums"
-log_onexit cleanup
-
-VIRTUAL_DISK=$TEST_BASE_DIR/disk
-
-function cleanup
-{
- poolexists $TESTPOOL && destroy_pool $TESTPOOL
- [[ -f $VIRTUAL_DISK ]] && log_must rm $VIRTUAL_DISK
-}
-
-log_must truncate -s $(($MINVDEVSIZE * 8)) $VIRTUAL_DISK
-
-log_must zpool create $TESTPOOL $VIRTUAL_DISK
-log_must zpool export $TESTPOOL
-
-log_mustnot zhack label repair $VIRTUAL_DISK
-
-corrupt_label_checksum 0 $VIRTUAL_DISK
-corrupt_label_checksum 1 $VIRTUAL_DISK
-corrupt_label_checksum 2 $VIRTUAL_DISK
-corrupt_label_checksum 3 $VIRTUAL_DISK
-
-log_mustnot zpool import $TESTPOOL -d $TEST_BASE_DIR
-
-log_must zhack label repair $VIRTUAL_DISK
-
-log_must zpool import $TESTPOOL -d $TEST_BASE_DIR
-
-cleanup
-
-log_pass "zhack label repair works correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh
new file mode 100755
index 000000000000..2a511e9efcb6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh
+
+#
+# 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.
+#
+
+#
+# Description:
+#
+# Test whether zhack label repair can recover
+# corrupted checksums on devices of varied size,
+# but not undetached devices.
+#
+# Strategy:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Export the pool.
+# 3. Corrupt all label checksums in the pool
+# 4. Check that pool cannot be imported
+# 5. Verify that it cannot be imported after using zhack label repair -u
+# to ensure that the -u option will quit on corrupted checksums.
+# 6. Use zhack label repair -c on device
+# 7. Check that pool can be imported and that data is intact
+
+. "$STF_SUITE"/tests/functional/cli_root/zhack/library.kshlib
+
+run_test_one "$(get_devsize)"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_002.ksh b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_002.ksh
new file mode 100755
index 000000000000..4f1e61a39857
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_002.ksh
@@ -0,0 +1,31 @@
+#!/bin/ksh
+
+#
+# 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.
+#
+
+#
+# Description:
+#
+# Test whether zhack label repair can recover
+# detached drives on devices of varied size, but not
+# repair corrupted checksums.
+#
+# Strategy:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Verify that the remaining detached device cannot be imported
+# 6. Verify that it cannot be imported after using zhack label repair -c
+# to ensure that the -c option will not undetach a device.
+# 7. Use zhack label repair -u on device
+# 8. Verify that the detached device can be imported and that data is intact
+
+. "$STF_SUITE"/tests/functional/cli_root/zhack/library.kshlib
+
+run_test_two "$(get_devsize)"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_003.ksh b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_003.ksh
new file mode 100755
index 000000000000..7e82363d2f46
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_003.ksh
@@ -0,0 +1,33 @@
+#!/bin/ksh
+
+#
+# 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.
+#
+
+#
+# Description:
+#
+# Test whether zhack label repair can recover a device of varied size with
+# corrupted checksums and which has been detached.
+#
+# Strategy:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Corrupt all label checksums on the remaining device
+# 6. Verify that the remaining detached device cannot be imported
+# 7. Verify that it cannot be imported after using zhack label repair -u
+# to ensure that the -u option will quit on corrupted checksums.
+# 8. Verify that it cannot be imported after using zhack label repair -c
+# -c should repair the checksums, but not undetach a device.
+# 9. Use zhack label repair -u on device
+# 10. Verify that the detached device can be imported and that data is intact
+
+. "$STF_SUITE"/tests/functional/cli_root/zhack/library.kshlib
+
+run_test_three "$(get_devsize)"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_004.ksh b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_004.ksh
new file mode 100755
index 000000000000..0b739402b199
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_004.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh
+
+#
+# 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.
+#
+
+#
+# Description:
+#
+# Test whether zhack label repair can recover a device of varied size with
+# corrupted checksums and which has been detached (in one command).
+#
+# Strategy:
+#
+# 1. Create pool on a loopback device with some test data
+# 2. Detach either device from the mirror
+# 3. Export the pool
+# 4. Remove the non-detached device and its backing file
+# 5. Corrupt all label checksums on the remaining device
+# 6. Verify that the remaining detached device cannot be imported
+# 7. Use zhack label repair -cu on device to attempt to fix checksums and
+# undetach the device in a single operation.
+# 8. Verify that the detached device can be imported and that data is intact
+
+. "$STF_SUITE"/tests/functional/cli_root/zhack/library.kshlib
+
+run_test_four "$(get_devsize)"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh b/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh
new file mode 100755
index 000000000000..dd9ef9ddd229
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2024, Klara Inc.
+#
+
+#
+# TODO: this only checks that the set of valid device fault types. It should
+# check all the other options, and that they work, and everything really.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_assert "Check zinject parameters."
+
+log_onexit cleanup
+
+DISK1=${DISKS%% *}
+
+function cleanup
+{
+ zinject -c all
+ default_cleanup_noexit
+}
+
+function test_device_fault
+{
+ typeset -a errno=("io" "decompress" "decrypt" "nxio" "dtl" "corrupt" "noop")
+ for e in ${errno[@]}; do
+ log_must eval \
+ "zinject -d $DISK1 -e $e -T read -f 0.001 $TESTPOOL"
+ done
+ zinject -c all
+}
+
+default_mirror_setup_noexit $DISKS
+
+test_device_fault
+
+log_pass "zinject parameters work as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh
index 4e3b6b0e9f47..200e914f3f5b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh
index 25decd78863b..de4ca0c4ea2c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
index ef88925dc92f..bd564cc6d8c3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
index 00f24bdff020..215af6188420 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh
index 80a2213d9aa8..51871934dd22 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -22,7 +22,7 @@
#
# Copyright 2017, loli10K. All rights reserved.
-# Copyright (c) 2020 by Delphix. All rights reserved.
+# Copyright (c) 2020, 2024 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
@@ -44,7 +44,7 @@ verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
poolexists $TESTPOOL && destroy_pool $TESTPOOL
rm -f $disk1 $disk2
}
@@ -57,13 +57,26 @@ disk2=$TEST_BASE_DIR/disk2
log_must mkfile $SIZE $disk1
log_must mkfile $SIZE $disk2
+logical_ashift=$(get_tunable VDEV_FILE_LOGICAL_ASHIFT)
orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
+max_auto_ashift=$(get_tunable VDEV_MAX_AUTO_ASHIFT)
+opt=""
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
+ #
+ # Need to add the --allow-ashift-mismatch option to disable the
+ # ashift mismatch checks in zpool add.
+ #
+ if [[ $ashift -eq $orig_ashift ]]; then
+ opt=""
+ else
+ opt="--allow-ashift-mismatch"
+ fi
+
log_must zpool create $TESTPOOL $disk1
- log_must zpool add -o ashift=$ashift $TESTPOOL $disk2
+ log_must zpool add $opt -o ashift=$ashift $TESTPOOL $disk2
log_must verify_ashift $disk2 $ashift
# clean things for the next run
@@ -75,12 +88,13 @@ do
# Make sure we can also set the ashift using the tunable.
#
log_must zpool create $TESTPOOL $disk1
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $ashift
- log_must zpool add $TESTPOOL $disk2
- log_must verify_ashift $disk2 $ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $ashift
+ log_must zpool add $opt $TESTPOOL $disk2
+ exp=$(( (ashift <= max_auto_ashift) ? ashift : logical_ashift ))
+ log_must verify_ashift $disk2 $exp
# clean things for the next run
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
log_must zpool destroy $TESTPOOL
log_must zpool labelclear $disk1
log_must zpool labelclear $disk2
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh
index 677d0762eecb..e86de0deae62 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh
index df04ecc5b89e..6a3283d0618f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -22,7 +22,7 @@
#
# Copyright 2017, loli10K. All rights reserved.
-# Copyright (c) 2020 by Delphix. All rights reserved.
+# Copyright (c) 2020, 2024 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
@@ -44,7 +44,7 @@ verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
poolexists $TESTPOOL && destroy_pool $TESTPOOL
log_must rm -f $disk1 $disk2
}
@@ -63,13 +63,18 @@ orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
# the ashift using the -o ashift property should still
# be honored.
#
-log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
+log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
+ if [ $ashift -eq $orig_ashift ];then
+ opt=""
+ else
+ opt="--allow-ashift-mismatch"
+ fi
log_must zpool create -o ashift=$ashift $TESTPOOL $disk1
- log_must zpool add $TESTPOOL $disk2
+ log_must zpool add $opt $TESTPOOL $disk2
log_must verify_ashift $disk2 $ashift
# clean things for the next run
@@ -82,8 +87,13 @@ for ashift in ${ashifts[@]}
do
for cmdval in ${ashifts[@]}
do
+ if [ $ashift -eq $cmdval ];then
+ opt=""
+ else
+ opt="--allow-ashift-mismatch"
+ fi
log_must zpool create -o ashift=$ashift $TESTPOOL $disk1
- log_must zpool add -o ashift=$cmdval $TESTPOOL $disk2
+ log_must zpool add $opt -o ashift=$cmdval $TESTPOOL $disk2
log_must verify_ashift $disk2 $cmdval
# clean things for the next run
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh
index 33bd94fdc4f9..f3691e9207a9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh
index 13bd33ee42aa..ef19ba998678 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh
new file mode 100755
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add--allow-ashift-mismatch.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg
index a634b8b3c617..1831e6563e8c 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib
index e10357340b40..cc850e3e451f 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh
index 191ec839a955..9ef96f554744 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh
index 67810bbf985b..afee34a33469 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -65,4 +65,15 @@ log_mustnot vdevs_in_pool $TESTPOOL $DISK2
log_must zpool add -f $TESTPOOL $DISK2
log_must vdevs_in_pool $TESTPOOL $DISK2
+log_must zpool destroy $TESTPOOL
+
+create_pool $TESTPOOL mirror $DISK0 $DISK1
+log_must poolexists $TESTPOOL
+
+log_mustnot zpool add $TESTPOOL $DISK2
+log_mustnot vdevs_in_pool $TESTPOOL $DISK2
+
+log_must zpool add --allow-replication-mismatch $TESTPOOL $DISK2
+log_must vdevs_in_pool $TESTPOOL $DISK2
+
log_pass "'zpool add -f <pool> <vdev> ...' executes successfully."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh
index 3816444667cf..62eddff7f6b6 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh
index 64e52960d3d6..cecda56ab125 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -70,8 +70,12 @@ if is_freebsd; then
recursive=$(get_tunable VOL_RECURSIVE)
log_must set_tunable64 VOL_RECURSIVE 1
fi
-log_must zpool add $TESTPOOL $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL
+log_must zpool add --allow-ashift-mismatch $TESTPOOL $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL
log_must vdevs_in_pool "$TESTPOOL" "$ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL"
+# Give zed a chance to finish processing the event, otherwise
+# a race condition can lead to stuck "zpool destroy $TESTPOOL"
+sleep 1
+
log_pass "'zpool add <pool> <vdev> ...' adds zfs volume to the pool successfully"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh
index c40f8db6f026..0e9d9f5f030f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -75,7 +75,9 @@ log_must poolexists $TESTPOOL1
unset NOINUSE_CHECK
log_mustnot zpool add -f $TESTPOOL $DISK1
+log_mustnot zpool add --allow-in-use $TESTPOOL $DISK1
log_mustnot zpool add -f $TESTPOOL $mnttab_dev
+log_mustnot zpool add --allow-in-use $TESTPOOL $mnttab_dev
if is_linux; then
log_mustnot zpool add $TESTPOOL $vfstab_dev
else
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh
index 2c3f488ea267..836d6d21c746 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh
index 4e9535c1c6b5..a7df42fc788f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh
index 77a899f70c83..c43f90792a9d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh
index 0a9fa868cb81..a13a27160e76 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -64,7 +64,9 @@ log_mustnot zpool add -f $TESTPOOL $DISK0
for type in "" "mirror" "raidz" "draid" "spare" "log" "dedup" "special" "cache"
do
log_mustnot zpool add -f $TESTPOOL $type $DISK0 $DISK1
+ log_mustnot zpool add --allow-in-use $TESTPOOL $type $DISK0 $DISK1
log_mustnot zpool add -f $TESTPOOL $type $DISK1 $DISK1
+ log_mustnot zpool add --allow-in-use $TESTPOOL $type $DISK1 $DISK1
done
log_pass "'zpool add' get fail as expected if vdevs are the same or vdev is " \
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh
index 771b689c93fd..22860e9caf1d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -138,7 +138,7 @@ function zpool_create_forced_add
while ((j < ${#add_args[@]})); do
log_must zpool create $TESTPOOL1 ${create_args[$i]}
log_mustnot zpool add $TESTPOOL1 ${add_args[$j]}
- log_must zpool add -f $TESTPOOL1 ${add_args[$j]}
+ log_must zpool add --allow-replication-mismatch $TESTPOOL1 ${add_args[$j]}
log_must zpool destroy -f $TESTPOOL1
((j += 1))
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh
index 73dec9240326..fa1ce9c64d33 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
index 745f60507bed..574cb7654d10 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -35,14 +35,14 @@
#
# STRATEGY:
# 1. Create various pools with different ashift values.
-# 2. Verify 'attach -o ashift=<n>' works only with allowed values.
+# 2. Verify 'attach' works.
#
verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
rm -f $disk1 $disk2
}
@@ -61,31 +61,19 @@ orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
# the ashift using the -o ashift property should still
# be honored.
#
-log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
+log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
- for cmdval in ${ashifts[@]}
- do
- log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
- log_must verify_ashift $disk1 $ashift
-
- # ashift_of(attached_disk) <= ashift_of(existing_vdev)
- if [[ $cmdval -le $ashift ]]
- then
- log_must zpool attach -o ashift=$cmdval $TESTPOOL1 \
- $disk1 $disk2
- log_must verify_ashift $disk2 $ashift
- else
- log_mustnot zpool attach -o ashift=$cmdval $TESTPOOL1 \
- $disk1 $disk2
- fi
- # clean things for the next run
- log_must zpool destroy $TESTPOOL1
- log_must zpool labelclear $disk1
- log_must zpool labelclear $disk2
- done
+ log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+ log_must verify_ashift $disk1 $ashift
+ log_must zpool attach $TESTPOOL1 $disk1 $disk2
+ log_must verify_ashift $disk2 $ashift
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
done
typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh
index 2229f87e6208..23dc57ed3679 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh
index 01b8e41ee439..50993a52a5e2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
index e6977350af90..4b4b05c8993b 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh
index f1f926831baa..b1a295cd2337 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh
index 91a637b3377b..e8ba4e66420b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh
index 637fdd84288b..46c07bf56076 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh
index 9eb2a3608f17..e3d089d0469b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh
index a50487754053..2bce044319c4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh
index 426321db06d6..f6f46cb98e90 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh
index 115126b1ac5b..f9e3add1ed68 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg
index 976570d621b7..3f22136e7460 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib
index 9954bc23fc9f..4987bc3a9dac 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh
index 42f57beae2a3..f24a9c705622 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh
index 2f709086f751..21df8eb2b1ff 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh
index dd8d0107aed2..ae81828b3e8c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh
index 835cd1f547bd..9e73c29b3b00 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh
index 98f469108b15..26c0119242a1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh
index 79b41fdaec90..37790c03fee3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh
index 2873202cce91..ad0a282f731d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh
index 56bb64c64051..f33fb8a2281e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh
index e2f38990314c..bb74c9cdda5f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh
index 36bbaa7de33a..4bb9a6d8bb49 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh
index 9437033ae547..1dcbaff19eca 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh
index b9274c08b2ab..e3ed3f850958 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh
index 44ed950f7870..df14bde6b178 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh
index babf5ca9c66d..6e02b585a916 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh
index b3dd2cefc76c..eee869820f58 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh
index ded1e3c3966b..3892fbad165c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh
index 6ad662f95011..6da1709071ba 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh
index 694ea2163c94..deddb8ba58a5 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh
index 39097df2fb59..5711d9f2686a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh
index 264c75279d17..00e347897206 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh
index 717fcaa6ec51..0e9da881261e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh
index 780cf86d6c5e..d2ae03eee687 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh
index 3e3c9ce942b5..a09ae6abc972 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_001_pos.ksh
index 9717af505267..9e3e22db7cad 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_002_pos.ksh
index 2e1ff39311ab..acc3c06bacb0 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_003_pos.ksh
index 52cd00cf4ee4..8058691fcb12 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh
index 6b700fa362a4..dbcb6e5ce737 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh
index 1e4db20cfedf..485891c945a3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
index 67eff8edcf3b..38a7ec06076b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh
index 7ad4ae805565..db79b31a91ca 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh
index c72edffde67d..032878dcb12b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh
index 5c6b29c4939e..3dfaf22c15a1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
index a8ed95109f2a..4b0618017e38 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_006_pos.ksh
index fe98434d1bb6..292346ad96de 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_007_pos.ksh
index 8c812911b3b3..c7c133a219cd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -34,6 +34,7 @@
# STRATEGY:
# 1. Create a pool with a known feature set.
# 2. Verify only those features are active/enabled.
+# 3. Do this for all known feature sets
#
verify_runnable "global"
@@ -47,8 +48,11 @@ log_onexit cleanup
log_assert "creates a pool with a specified feature set enabled"
-log_must zpool create -f -o compatibility=compat-2020 $TESTPOOL $DISKS
-check_feature_set $TESTPOOL compat-2020
-log_must zpool destroy -f $TESTPOOL
+for compat in "$ZPOOL_COMPAT_DIR"/*
+do
+ log_must zpool create -f -o compatibility="${compat##*/}" $TESTPOOL $DISKS
+ check_feature_set $TESTPOOL "${compat##*/}"
+ log_must zpool destroy -f $TESTPOOL
+done
log_pass "creates a pool with a specified feature set enabled"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_008_pos.ksh
index 0580d444e724..99db3d31a088 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_009_pos.ksh
index 052c18dcee2b..cd3111496461 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
index 906cba700573..c67212ce14af 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh
index c25b6c9230a7..e5248a1bad9a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh
index a634f10f1114..258c64754790 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh
index 75b77b4bde72..12718eb8d987 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh
index 2229f87e6208..23dc57ed3679 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh
index 74f8e1e664fa..5d1523fa0f92 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear_retained.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear_retained.ksh
index c16094f54038..0eda2de1f6cb 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear_retained.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear_retained.ksh
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_duplicates.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_duplicates.ksh
index 9097ac008334..5bc369480d90 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_duplicates.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_duplicates.ksh
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh
index 82a1a1131f06..2e98cdfc6f4a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh
index 059c3839050b..2b21521f867d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh
index 9832a441c20b..ff052d23f659 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
index bec5fb1638aa..0a9c1954f123 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh
index c49777e6b3c4..c58e933f11be 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -54,6 +54,14 @@
verify_runnable "global"
+# We override $org_size and $exp_size from zpool_expand.cfg to make sure we get
+# an expected free space value every time. Otherwise, if we left it
+# configurable, the free space ratio to pool size ratio would diverge too much
+# much at low $org_size values.
+#
+org_size=$((1024 * 1024 * 1024))
+exp_size=$(($org_size * 2))
+
function cleanup
{
poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
@@ -68,6 +76,30 @@ function cleanup
unload_scsi_debug
}
+# Wait for the size of a pool to autoexpand to $1 and the total free space to
+# expand to $2 (both values allowing a 10% tolerance).
+#
+# Wait for up to 10 seconds for this to happen (typically takes 1-2 seconds)
+#
+function wait_for_autoexpand
+{
+ typeset exp_new_size=$1
+ typeset exp_new_free=$2
+
+ for i in $(seq 1 10) ; do
+ typeset new_size=$(get_pool_prop size $TESTPOOL1)
+ typeset new_free=$(get_prop avail $TESTPOOL1)
+ # Values need to be within 90% of each other (10% tolerance)
+ if within_percent $new_size $exp_new_size 90 > /dev/null && \
+ within_percent $new_free $exp_new_free 90 > /dev/null ; then
+ return
+ fi
+ sleep 1
+ done
+ log_fail "$TESTPOOL never expanded to $exp_new_size with $exp_new_free" \
+ " free space (got $new_size with $new_free free space)"
+}
+
log_onexit cleanup
log_assert "zpool can be autoexpanded after set autoexpand=on on vdev expansion"
@@ -105,63 +137,38 @@ for type in " " mirror raidz draid:1s; do
log_note "Expanding loopback, scsi_debug, and file vdevs"
log_must truncate -s $exp_size $FILE_LO
log_must losetup -c $DEV1
- sleep 3
echo "2" > /sys/bus/pseudo/drivers/scsi_debug/virtual_gb
echo "1" > /sys/class/block/$DEV2/device/rescan
block_device_wait
- sleep 3
log_must truncate -s $exp_size $FILE_RAW
log_must zpool online -e $TESTPOOL1 $FILE_RAW
- typeset expand_size=$(get_pool_prop size $TESTPOOL1)
- typeset zfs_expand_size=$(get_prop avail $TESTPOOL1)
-
- log_note "$TESTPOOL1 $type has previous size: $prev_size and " \
- "expanded size: $expand_size"
- # compare available pool size from zfs
- if [[ $zfs_expand_size -gt $zfs_prev_size ]]; then
- # check for zpool history for the pool size expansion
- if [[ $type == " " ]]; then
- typeset expansion_size=$(($exp_size-$org_size))
- typeset size_addition=$(zpool history -il $TESTPOOL1 |\
- grep "pool '$TESTPOOL1' size:" | \
- grep "vdev online" | \
- grep -c "(+${expansion_size}")
-
- if [[ $size_addition -ne 3 ]]; then
- log_fail "pool $TESTPOOL1 has not expanded, " \
- "$size_addition/3 vdevs expanded"
- fi
- elif [[ $type == "mirror" ]]; then
- typeset expansion_size=$(($exp_size-$org_size))
- zpool history -il $TESTPOOL1 | \
- grep "pool '$TESTPOOL1' size:" | \
- grep "vdev online" | \
- grep -q "(+${expansion_size})" ||
- log_fail "pool $TESTPOOL1 has not expanded"
- elif [[ $type == "draid:1s" ]]; then
- typeset expansion_size=$((2*($exp_size-$org_size)))
- zpool history -il $TESTPOOL1 | \
- grep "pool '$TESTPOOL1' size:" | \
- grep "vdev online" | \
- grep -q "(+${expansion_size})" ||
- log_fail "pool $TESTPOOL has not expanded"
- else
- typeset expansion_size=$((3*($exp_size-$org_size)))
- zpool history -il $TESTPOOL1 | \
- grep "pool '$TESTPOOL1' size:" | \
- grep "vdev online" | \
- grep -q "(+${expansion_size})" ||
- log_fail "pool $TESTPOOL has not expanded"
- fi
- else
- log_fail "pool $TESTPOOL1 is not autoexpanded after vdev " \
- "expansion. Previous size: $zfs_prev_size and expanded " \
- "size: $zfs_expand_size"
+
+ # The expected free space values below were observed at the time of
+ # this commit. However, we know ZFS overhead will change over time,
+ # and thus we do not do an exact comparison to these values in
+ # wait_for_autoexpand. Rather, we make sure the free space
+ # is within some small percentage threshold of these values.
+ typeset exp_new_size=$(($prev_size * 2))
+ if [[ "$type" == " " ]] ; then
+ exp_new_free=6045892608
+ elif [[ "$type" == "mirror" ]] ; then
+ exp_new_free=1945997312
+ elif [[ "$type" == "raidz" ]] ; then
+ exp_new_free=3977637338
+ elif [[ "$type" == "draid:1s" ]] then
+ exp_new_free=1946000384
fi
+ wait_for_autoexpand $exp_new_size $exp_new_free
+
+ expand_size=$(get_pool_prop size $TESTPOOL1)
+
+ log_note "$TESTPOOL1 '$type' grew from $prev_size -> $expand_size with" \
+ "free space from $zfs_prev_size -> $(get_prop avail $TESTPOOL1)"
+
cleanup
done
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh
index ccd266c727be..34357ca070b5 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh
index 5bd8b56ffd0d..68b17592e2f8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh
index 09e2b6da2148..e50c1f8b1606 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh
index 54ec73b67b26..5e8f1d7053e8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh
index 023920dae1e9..57bbf32711e3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg
index 349399263da8..0cedb61c25d9 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib
index 5484f20674d5..54f805ea71a4 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh
index 111453c7a161..f084ac023997 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh
index 913a4cd6a34c..8bdaddc43da4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh
index a2ee7fbdf908..ec4eae3d5685 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh
index 9be3f23c4fda..4b4038bb8bfd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh
index 6c992b5f02ae..dde462e66cf9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh
index 063ad743b7a8..03d149cd967a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg
new file mode 100644
index 000000000000..c3b9efd6464a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg
@@ -0,0 +1,75 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+
+# Set the expected properties of a vdev
+typeset -a properties=(
+ capacity
+ state
+ guid
+ asize
+ psize
+ ashift
+ size
+ free
+ allocated
+ comment
+ expandsize
+ fragmentation
+ bootsize
+ parity
+ path
+ devid
+ physpath
+ encpath
+ fru
+ parent
+ children
+ numchildren
+ read_errors
+ write_errors
+ checksum_errors
+ initialize_errors
+ null_ops
+ read_ops
+ write_ops
+ free_ops
+ claim_ops
+ trim_ops
+ null_bytes
+ read_bytes
+ write_bytes
+ free_bytes
+ claim_bytes
+ trim_bytes
+ removing
+ allocating
+ failfast
+ checksum_n
+ checksum_t
+ io_n
+ io_t
+ slow_io_n
+ slow_io_t
+)
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh
new file mode 100755
index 000000000000..bca2337861d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_get/vdev_get.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool get <pool> root works as expected
+#
+# STRATEGY:
+#
+# 1. use zpool get to retrieve properties from root vdev
+# 2. verify expected properties match detected properties
+#
+
+log_assert "zpool get all on root vdev"
+
+EXPECT="$(zpool get -H all ${TESTPOOL} root | wc -l)"
+if [ $? -ne 0 ]; then
+ log_fail "cannot retrieve properties from root vdev"
+fi
+
+i=0;
+while [ $i -lt "${#properties[@]}" ]
+do
+ log_must zpool get -H "${properties[$i]}" "$TESTPOOL" root
+ i=$(($i+1))
+done
+
+EXPECT=$((EXPECT))
+if [ $i -gt $EXPECT ]; then
+ log_fail "found vdev properties not in vdev_get.cfg: $i/$EXPECT."
+elif [ $i -lt $EXPECT ]; then
+ log_fail "expected properties not found in vdev_get.cfg: $i/$EXPECT."
+fi
+
+log_pass "zpool get all on root vdev"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
index 7849ed22634e..6ebce9459190 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -58,6 +58,9 @@ typeset -a properties=(
"multihost"
"autotrim"
"compatibility"
+ "bcloneused"
+ "bclonesaved"
+ "bcloneratio"
"feature@async_destroy"
"feature@empty_bpobj"
"feature@lz4_compress"
@@ -83,6 +86,7 @@ typeset -a properties=(
"feature@log_spacemap"
"feature@device_rebuild"
"feature@draid"
+ "feature@redaction_list_spill"
)
if is_linux || is_freebsd; then
@@ -100,5 +104,8 @@ if is_linux || is_freebsd; then
"feature@zilsaxattr"
"feature@head_errlog"
"feature@blake3"
+ "feature@block_cloning"
+ "feature@vdev_zaps_v2"
+ "feature@raidz_expansion"
)
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh
index d3b21d663f16..49017fb5eef4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh
index de39aa260f61..fef573c8dd7d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh
index 7c2e214b7da0..2a4c98b61c65 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh
index bbdd32933c81..873f58ee7f31 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh
index 4481dab69f7b..e00690fd94a7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
index e7b95a47223b..22778b41177d 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh
index e4998138f701..7bb00caed5a3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh
index b2a852a4c9b5..06829b1da5a2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh
index b5cd8d529ed0..052108479079 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh
index 0146aa5bc1dd..5796c60a3772 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh
index bee0e11a4ff4..a1f0284c97ed 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_log_missing.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_log_missing.ksh
new file mode 100755
index 000000000000..f12cac78540f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_log_missing.ksh
@@ -0,0 +1,75 @@
+#!/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/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# Import with missing log device should not remove spare/cache.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Add spare, cache and log devices to the pool.
+# 3. Export the pool.
+# 4. Remove the log device.
+# 5. Import the pool with -m flag.
+# 6. Verify that spare and cache are still present in the pool.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_missing_log
+{
+ typeset poolcreate="$1"
+ typeset cachevdev="$2"
+ typeset sparevdev="$3"
+ typeset logvdev="$4"
+ typeset missingvdev="$4"
+
+ log_note "$0: pool '$poolcreate', adding $cachevdev, $sparevdev," \
+ "$logvdev then moving away $missingvdev."
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ log_must zpool add $TESTPOOL1 cache $cachevdev spare $sparevdev \
+ log $logvdev
+
+ log_must_busy zpool export $TESTPOOL1
+
+ log_must mv $missingvdev $BACKUP_DEVICE_DIR
+
+ log_must zpool import -m -d $DEVICE_DIR $TESTPOOL1
+
+ CACHE_PRESENT=$(zpool status -v $TESTPOOL1 | grep $cachevdev)
+
+ SPARE_PRESENT=$(zpool status -v $TESTPOOL1 | grep $sparevdev)
+
+ if [ -z "$CACHE_PRESENT"] || [ -z "SPARE_PRESENT"]
+ then
+ log_fail "cache/spare vdev missing after importing with missing" \
+ "log device"
+ fi
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+
+ log_note ""
+}
+
+log_must mkdir -p $BACKUP_DEVICE_DIR
+
+test_missing_log "$VDEV0" "$VDEV1" "$VDEV2" "$VDEV3"
+
+log_pass "zpool import succeeded with missing log device"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh
index 22e619d7411b..47f85fc493c1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg
index 25f541ebf185..cf9c6a8499af 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -26,6 +26,7 @@
#
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2023 by Klara, Inc.
#
. $STF_SUITE/include/libtest.shlib
@@ -63,3 +64,7 @@ export VDEV4=$DEVICE_DIR/${DEVICE_FILE}4
export VDEV5=$DEVICE_DIR/${DEVICE_FILE}5
export ALTER_ROOT=/alter_import-test
+
+export HOSTID_FILE="/etc/hostid"
+export HOSTID1=01234567
+export HOSTID2=89abcdef
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib
index 559810ff0e30..50157fa80578 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib
@@ -11,6 +11,7 @@
#
# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2023 by Klara, Inc.
#
. $STF_SUITE/include/libtest.shlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh
index e159c1a04195..4d061eff21f4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh
index 95ebe0ae294d..d677f8fb4916 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh
index dfda989deab9..56914dd4a0f9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh
index 657e28be2563..494542d59a99 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh
index 79f026ede55f..b8805cd5803b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh
index 2353bb07d040..d648b3262d8a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh
index 928efebdd2d5..d7967eb5ef39 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh
index f8da584aad1c..9489ce1460a4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh
index e7886ef3c859..be18907f6c12 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh
index 212024dfcb34..107f0d88282d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh
index b54168941722..19d4f56709da 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh
index a9d5e2b319a4..bf499808eb3e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh
index 7fef6254fa68..956f851c536f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh
index d70bced265f3..6e5e06515458 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_016_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_016_pos.ksh
index 5434625cb985..7c1dd10c5c08 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_016_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_016_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_017_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_017_pos.ksh
index 2e6cef265c4f..b8547852d01f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_017_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_017_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh
index 9f5503454d95..c16a37620a02 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh
index 973efb7acf3c..7c31229afcdc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh
index 88fde66adf04..be4d41596211 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh
index e92c95f54c52..31828a47a8c1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed.ksh
new file mode 100755
index 000000000000..bc82b7cc1ee8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed.ksh
@@ -0,0 +1,59 @@
+#!/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.
+# Copyright (c) 2023 by Klara, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool that was cleanly exported should be importable without force even if
+# the local hostid doesn't match the on-disk hostid.
+#
+# STRATEGY:
+# 1. Set a hostid.
+# 2. Create a pool.
+# 3. Export the pool.
+# 4. Change the hostid.
+# 5. Verify that importing the pool without force succeeds.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ rm -f $HOSTID_FILE
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+# 1. Set a hostid.
+log_must zgenhostid -f $HOSTID1
+
+# 2. Create a pool.
+log_must zpool create $TESTPOOL1 $VDEV0
+
+# 3. Export the pool.
+log_must zpool export $TESTPOOL1
+
+# 4. Change the hostid.
+log_must zgenhostid -f $HOSTID2
+
+# 5. Verify that importing the pool without force succeeds.
+log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+
+log_pass "zpool import can import cleanly exported pool when hostid changes."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile.ksh
new file mode 100755
index 000000000000..07c43482d68f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile.ksh
@@ -0,0 +1,65 @@
+#!/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.
+# Copyright (c) 2023 by Klara, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool that was cleanly exported should be importable from a cachefile
+# without force even if the local hostid doesn't match the on-disk hostid.
+#
+# STRATEGY:
+# 1. Set a hostid.
+# 2. Create a pool with a cachefile.
+# 3. Backup the cachfile.
+# 4. Export the pool.
+# 5. Change the hostid.
+# 6. Verify that importing the pool from the cachefile succeeds
+# without force.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ rm -f $HOSTID_FILE $CPATH $CPATHBKP
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+# 1. Set a hostid.
+log_must zgenhostid -f $HOSTID1
+
+# 2. Create a pool.
+log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $VDEV0
+
+# 3. Backup the cachfile.
+log_must cp $CPATH $CPATHBKP
+
+# 4. Export the pool.
+log_must zpool export $TESTPOOL1
+
+# 5. Change the hostid.
+log_must zgenhostid -f $HOSTID2
+
+# 6. Verify that importing the pool from the cachefile succeeds without force.
+log_must zpool import -c $CPATHBKP $TESTPOOL1
+
+log_pass "zpool import can import cleanly exported pool from cachefile " \
+ "when hostid changes."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile_unclean_export.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile_unclean_export.ksh
new file mode 100755
index 000000000000..dcb1ac1ab69f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_cachefile_unclean_export.ksh
@@ -0,0 +1,75 @@
+#!/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.
+# Copyright (c) 2023 by Klara, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool that wasn't cleanly exported should not be importable from a cachefile
+# without force if the local hostid doesn't match the on-disk hostid.
+#
+# STRATEGY:
+# 1. Set a hostid.
+# 2. Create a pool.
+# 3. Backup the cachefile.
+# 4. Simulate the pool being torn down without export:
+# 4.1. Copy the underlying device state.
+# 4.2. Export the pool.
+# 4.3. Restore the device state from the copy.
+# 5. Change the hostid.
+# 6. Verify that importing the pool from the cachefile fails.
+# 7. Verify that importing the pool from the cachefile with force
+# succeeds.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ rm -f $HOSTID_FILE $CPATH $CPATHBKP $VDEV0.bak
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+# 1. Set a hostid.
+log_must zgenhostid -f $HOSTID1
+
+# 2. Create a pool.
+log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $VDEV0
+
+# 3. Backup the cachfile.
+log_must cp $CPATH $CPATHBKP
+
+# 4. Simulate the pool being torn down without export.
+log_must cp $VDEV0 $VDEV0.bak
+log_must zpool export $TESTPOOL1
+log_must cp -f $VDEV0.bak $VDEV0
+log_must rm -f $VDEV0.bak
+
+# 5. Change the hostid.
+log_must zgenhostid -f $HOSTID2
+
+# 6. Verify that importing the pool from the cachefile fails.
+log_mustnot zpool import -c $CPATHBKP $TESTPOOL1
+
+# 7. Verify that importing the pool from the cachefile with force succeeds.
+log_must zpool import -f -c $CPATHBKP $TESTPOOL1
+
+log_pass "zpool import from cachefile requires force if not cleanly " \
+ "exported and hostid changes."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_unclean_export.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_unclean_export.ksh
new file mode 100755
index 000000000000..ad8cca642dbc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_hostid_changed_unclean_export.ksh
@@ -0,0 +1,70 @@
+#!/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.
+# Copyright (c) 2023 by Klara, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool that wasn't cleanly exported should not be importable without force if
+# the local hostid doesn't match the on-disk hostid.
+#
+# STRATEGY:
+# 1. Set a hostid.
+# 2. Create a pool.
+# 3. Simulate the pool being torn down without export:
+# 3.1. Copy the underlying device state.
+# 3.2. Export the pool.
+# 3.3. Restore the device state from the copy.
+# 4. Change the hostid.
+# 5. Verify that importing the pool fails.
+# 6. Verify that importing the pool with force succeeds.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ rm -f $HOSTID_FILE $VDEV0.bak
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+# 1. Set a hostid.
+log_must zgenhostid -f $HOSTID1
+
+# 2. Create a pool.
+log_must zpool create $TESTPOOL1 $VDEV0
+
+# 3. Simulate the pool being torn down without export.
+log_must cp $VDEV0 $VDEV0.bak
+log_must zpool export $TESTPOOL1
+log_must cp -f $VDEV0.bak $VDEV0
+log_must rm -f $VDEV0.bak
+
+# 4. Change the hostid.
+log_must zgenhostid -f $HOSTID2
+
+# 5. Verify that importing the pool fails.
+log_mustnot zpool import -d $DEVICE_DIR $TESTPOOL1
+
+# 6. Verify that importing the pool with force succeeds.
+log_must zpool import -d $DEVICE_DIR -f $TESTPOOL1
+
+log_pass "zpool import requires force if not cleanly exported " \
+ "and hostid changed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh
index 22cec24ff457..488024cfd0e1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh
index 60af3f321947..7f0cf79a4ad9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh
index ac76f879c2e8..964b38f9e860 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh
new file mode 100755
index 000000000000..c681d1b7dd23
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh
@@ -0,0 +1,165 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# Verify that admin commands to different pool are not blocked by import
+#
+# STRATEGY:
+# 1. Create 2 pools
+# 2. Export one of the pools
+# 4. Import the pool with an injected delay
+# 5. Execute some admin commands against both pools
+# 6. Verify that the admin commands to the non-imported pool don't stall
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ zinject -c all
+ destroy_pool $TESTPOOL1
+ destroy_pool $TESTPOOL2
+}
+
+function pool_import
+{
+ typeset dir=$1
+ typeset pool=$2
+
+ SECONDS=0
+ errmsg=$(zpool import -d $dir -f $pool 2>&1 > /dev/null)
+ if [[ $? -eq 0 ]]; then
+ echo ${pool}: imported in $SECONDS secs
+ echo $SECONDS > ${DEVICE_DIR}/${pool}-import
+ else
+ echo ${pool}: import failed $errmsg in $SECONDS secs
+ fi
+}
+
+function pool_add_device
+{
+ typeset pool=$1
+ typeset device=$2
+ typeset devtype=$3
+
+ SECONDS=0
+ errmsg=$(zpool add $pool $devtype $device 2>&1 > /dev/null)
+ if [[ $? -eq 0 ]]; then
+ echo ${pool}: added $devtype vdev in $SECONDS secs
+ echo $SECONDS > ${DEVICE_DIR}/${pool}-add
+ else
+ echo ${pool}: add $devtype vdev failed ${errmsg}, in $SECONDS secs
+ fi
+}
+
+function pool_stats
+{
+ typeset stats=$1
+ typeset pool=$2
+
+ SECONDS=0
+ errmsg=$(zpool $stats $pool 2>&1 > /dev/null)
+ if [[ $? -eq 0 ]]; then
+ echo ${pool}: $stats in $SECONDS secs
+ echo $SECONDS > ${DEVICE_DIR}/${pool}-${stats}
+ else
+ echo ${pool}: $stats failed ${errmsg}, in $SECONDS secs
+ fi
+}
+
+function pool_create
+{
+ typeset pool=$1
+ typeset device=$2
+
+ SECONDS=0
+ errmsg=$(zpool create $pool $device 2>&1 > /dev/null)
+ if [[ $? -eq 0 ]]; then
+ echo ${pool}: created in $SECONDS secs
+ echo $SECONDS > ${DEVICE_DIR}/${pool}-create
+ else
+ echo ${pool}: create failed ${errmsg}, in $SECONDS secs
+ fi
+}
+
+log_assert "Simple admin commands to different pool not blocked by import"
+
+log_onexit cleanup
+
+#
+# create two pools and export one
+#
+log_must zpool create $TESTPOOL1 $VDEV0
+log_must zpool export $TESTPOOL1
+log_must zpool create $TESTPOOL2 $VDEV1
+
+#
+# import pool asyncronously with an injected 10 second delay
+#
+log_must zinject -P import -s 10 $TESTPOOL1
+pool_import $DEVICE_DIR $TESTPOOL1 &
+
+sleep 2
+
+#
+# run some admin commands on the pools while the import is in progress
+#
+
+pool_add_device $TESTPOOL1 $VDEV2 "log" &
+pool_add_device $TESTPOOL2 $VDEV3 "cache" &
+pool_stats "status" $TESTPOOL1 &
+pool_stats "status" $TESTPOOL2 &
+pool_stats "list" $TESTPOOL1 &
+pool_stats "list" $TESTPOOL2 &
+pool_create $TESTPOOL1 $VDEV4 &
+wait
+
+log_must zpool sync $TESTPOOL1 $TESTPOOL2
+
+zpool history $TESTPOOL1
+zpool history $TESTPOOL2
+
+log_must test "5" -lt $(<${DEVICE_DIR}/${TESTPOOL1}-import)
+
+#
+# verify that commands to second pool did not wait for import to finish
+#
+log_must test "2" -gt $(<${DEVICE_DIR}/${TESTPOOL2}-status)
+log_must test "2" -gt $(<${DEVICE_DIR}/${TESTPOOL2}-list)
+log_must test "2" -gt $(<${DEVICE_DIR}/${TESTPOOL2}-add)
+[[ -e ${DEVICE_DIR}/${TESTPOOL1}-create ]] && log_fail "unexpected pool create"
+
+log_pass "Simple admin commands to different pool not blocked by import"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh
new file mode 100755
index 000000000000..339dc2575ede
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh
@@ -0,0 +1,130 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# Verify that pool imports by same name only have one winner
+#
+# STRATEGY:
+# 1. Create 4 single disk pools with the same name
+# 2. Generate some ZIL records (for a longer import)
+# 3. Export the pools
+# 4. Import the pools in parallel
+# 5. Repeat with using matching guids
+#
+
+verify_runnable "global"
+
+POOLNAME="import_pool"
+DEV_DIR_PREFIX="$DEVICE_DIR/$POOLNAME"
+VDEVSIZE=$((512 * 1024 * 1024))
+
+log_assert "parallel pool imports by same name only have one winner"
+
+# each pool has its own device directory
+for i in {0..3}; do
+ log_must mkdir -p ${DEV_DIR_PREFIX}$i
+ log_must truncate -s $VDEVSIZE ${DEV_DIR_PREFIX}$i/${DEVICE_FILE}$i
+done
+
+function cleanup
+{
+ zinject -c all
+ log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
+ log_must set_tunable64 METASLAB_DEBUG_LOAD 0
+
+ destroy_pool $POOLNAME
+
+ log_must rm -rf $DEV_DIR_PREFIX*
+}
+
+log_onexit cleanup
+
+log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
+log_must set_tunable64 METASLAB_DEBUG_LOAD 1
+
+function import_pool
+{
+ typeset dir=$1
+ typeset pool=$2
+ typeset newname=$3
+
+ SECONDS=0
+ errmsg=$(zpool import -N -d $dir -f $pool $newname 2>&1 > /dev/null)
+ if [[ $? -eq 0 ]]; then
+ touch $dir/imported
+ echo "imported $pool in $SECONDS secs"
+ elif [[ $errmsg == *"cannot import"* ]]; then
+ echo "pool import failed: $errmsg, waited $SECONDS secs"
+ touch $dir/failed
+ fi
+}
+
+#
+# create four exported pools with the same name
+#
+for i in {0..3}; do
+ log_must zpool create $POOLNAME ${DEV_DIR_PREFIX}$i/${DEVICE_FILE}$i
+ log_must zpool export $POOLNAME
+done
+log_must zinject -P import -s 10 $POOLNAME
+
+#
+# import the pools in parallel, expecting only one winner
+#
+for i in {0..3}; do
+ import_pool ${DEV_DIR_PREFIX}$i $POOLNAME &
+done
+wait
+
+# check the result of background imports
+typeset num_imports=0
+typeset num_cannot=0
+for i in {0..3}; do
+ if [[ -f ${DEV_DIR_PREFIX}$i/imported ]]; then
+ ((num_imports += 1))
+ fi
+ if [[ -f ${DEV_DIR_PREFIX}$i/failed ]]; then
+ ((num_cannot += 1))
+ loser=$i
+ fi
+done
+[[ $num_imports -eq "1" ]] || log_fail "expecting an import"
+[[ $num_cannot -eq "3" ]] || \
+ log_fail "expecting 3 pool exists errors, found $num_cannot"
+
+log_note "$num_imports imported and $num_cannot failed (expected)"
+
+log_pass "parallel pool imports by same name only have one winner"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh
new file mode 100755
index 000000000000..71b2437a37ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh
@@ -0,0 +1,137 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+# test uses 8 vdevs
+export MAX_NUM=8
+
+#
+# DESCRIPTION:
+# Verify that pool imports can occur in parallel
+#
+# STRATEGY:
+# 1. Create 8 pools
+# 2. Generate some ZIL records
+# 3. Export the pools
+# 4. Import half of the pools synchronously to baseline sequential cost
+# 5. Import the other half asynchronously to demonstrate parallel savings
+# 6. Export 4 pools
+# 7. Test zpool import -a
+#
+
+verify_runnable "global"
+
+#
+# override the minimum sized vdevs
+#
+VDEVSIZE=$((512 * 1024 * 1024))
+increase_device_sizes $VDEVSIZE
+
+POOLNAME="import_pool"
+
+function cleanup
+{
+ zinject -c all
+ log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
+ log_must set_tunable64 METASLAB_DEBUG_LOAD 0
+
+ for i in {0..$(($MAX_NUM - 1))}; do
+ destroy_pool $POOLNAME-$i
+ done
+ # reset the devices
+ increase_device_sizes 0
+ increase_device_sizes $FILE_SIZE
+}
+
+log_assert "Pool imports can occur in parallel"
+
+log_onexit cleanup
+
+log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
+log_must set_tunable64 METASLAB_DEBUG_LOAD 1
+
+
+#
+# create some exported pools with import delay injectors
+#
+for i in {0..$(($MAX_NUM - 1))}; do
+ log_must zpool create $POOLNAME-$i $DEVICE_DIR/${DEVICE_FILE}$i
+ log_must zpool export $POOLNAME-$i
+ log_must zinject -P import -s 12 $POOLNAME-$i
+done
+wait
+
+#
+# import half of the pools synchronously
+#
+SECONDS=0
+for i in {0..3}; do
+ log_must zpool import -d $DEVICE_DIR -f $POOLNAME-$i
+done
+sequential_time=$SECONDS
+log_note "sequentially imported 4 pools in $sequential_time seconds"
+
+#
+# import half of the pools in parallel
+#
+SECONDS=0
+for i in {4..7}; do
+ log_must zpool import -d $DEVICE_DIR -f $POOLNAME-$i &
+done
+wait
+parallel_time=$SECONDS
+log_note "asyncronously imported 4 pools in $parallel_time seconds"
+
+log_must test $parallel_time -lt $(($sequential_time / 3))
+
+#
+# export pools with import delay injectors
+#
+for i in {4..7}; do
+ log_must zpool export $POOLNAME-$i
+ log_must zinject -P import -s 12 $POOLNAME-$i
+done
+wait
+
+#
+# now test zpool import -a
+#
+SECONDS=0
+log_must zpool import -a -d $DEVICE_DIR -f
+parallel_time=$SECONDS
+log_note "asyncronously imported 4 pools in $parallel_time seconds"
+
+log_must test $parallel_time -lt $(($sequential_time / 3))
+
+log_pass "Pool imports occur in parallel"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh
index 4e49e8d01d88..4d6005d2cb02 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_status.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_status.ksh
new file mode 100755
index 000000000000..c96961bf6419
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_status.ksh
@@ -0,0 +1,132 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# During a pool import, the 'import_progress' kstat contains details
+# on the import progress.
+#
+# STRATEGY:
+# 1. Create test pool with several devices
+# 2. Generate some ZIL records and spacemap logs
+# 3. Export the pool
+# 4. Import the pool in the background and monitor the kstat content
+# 5. Check the zfs debug messages for import progress
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
+ log_must set_tunable64 METASLAB_DEBUG_LOAD 0
+
+ destroy_pool $TESTPOOL1
+}
+
+log_assert "During a pool import, the 'import_progress' kstat contains " \
+ "notes on the progress"
+
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2
+typeset guid=$(zpool get -H -o value guid $TESTPOOL1)
+
+log_must zfs create -o recordsize=8k $TESTPOOL1/fs
+#
+# This dd command works around an issue where ZIL records aren't created
+# after freezing the pool unless a ZIL header already exists. Create a file
+# synchronously to force ZFS to write one out.
+#
+log_must dd if=/dev/zero of=/$TESTPOOL1/fs/sync conv=fsync bs=1 count=1
+
+#
+# Overwrite some blocks to populate spacemap logs
+#
+log_must dd if=/dev/urandom of=/$TESTPOOL1/fs/00 bs=1M count=200
+sync_all_pools
+log_must dd if=/dev/urandom of=/$TESTPOOL1/fs/00 bs=1M count=200
+sync_all_pools
+
+#
+# Freeze the pool to retain intent log records
+#
+log_must zpool freeze $TESTPOOL1
+
+# fill_fs [destdir] [dirnum] [filenum] [bytes] [num_writes] [data]
+log_must fill_fs /$TESTPOOL1/fs 1 2000 100 1024 R
+
+log_must zpool list -v $TESTPOOL1
+
+#
+# Unmount filesystem and export the pool
+#
+# At this stage the zfs intent log contains
+# a set of records to replay.
+#
+log_must zfs unmount /$TESTPOOL1/fs
+
+log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
+log_must zpool export $TESTPOOL1
+
+log_must set_tunable64 METASLAB_DEBUG_LOAD 1
+log_note "Starting zpool import in background at" $(date +'%H:%M:%S')
+zpool import -d $DEVICE_DIR -f $guid &
+pid=$!
+
+#
+# capture progress until import is finished
+#
+log_note waiting for pid $pid to exit
+kstat import_progress
+while [[ -d /proc/"$pid" ]]; do
+ line=$(kstat import_progress | grep -v pool_guid)
+ if [[ -n $line ]]; then
+ echo $line
+ fi
+ if [[ -f /$TESTPOOL1/fs/00 ]]; then
+ break;
+ fi
+ sleep 0.0001
+done
+log_note "zpool import completed at" $(date +'%H:%M:%S')
+
+entries=$(kstat dbgmsg | grep "spa_import_progress_set_notes_impl(): 'testpool1'" | wc -l)
+log_note "found $entries progress notes in dbgmsg"
+log_must test $entries -gt 20
+
+log_must zpool status $TESTPOOL1
+
+log_pass "During a pool import, the 'import_progress' kstat contains " \
+ "notes on the progress"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh
index 3c7dbd31705d..92005b4efd7f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh
index 2a695025d214..56733758c633 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh
index 386d2a5dc237..c29c4b07e524 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh
index dedd466e4e6e..feca7f9af721 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh
index 55bd3188c966..79f47f0f8ba2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh
index 69b27c26c9bc..e5d528d6cef8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh
index 59b266d321c3..7de3f20223fd 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh
index 5003b5f10bdb..facbd0efda59 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh
index bce3da5267cd..2f030c78a01b 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh
new file mode 100755
index 000000000000..17f776cfbc20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_uninit.ksh
@@ -0,0 +1,141 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (C) 2023 Lawrence Livermore National Security, LLC.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Starting, stopping, uninitializing, and restart an initialize works.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Verify uninitialize succeeds for uninitialized pool.
+# 3. Verify pool wide cancel|suspend + uninit
+# a. Start initializing and verify that initializing is active.
+# b. Verify uninitialize fails when actively initializing.
+# c. Cancel or suspend initializing and verify that initializing is not active.
+# d. Verify uninitialize succeeds after being cancelled.
+# 4. Verify per-disk cancel|suspend + uninit
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+DISK3="$(echo $DISKS | cut -d' ' -f3)"
+
+function status_check # pool disk1-state disk2-state disk3-state
+{
+ typeset pool="$1"
+ typeset disk1_state="$2"
+ typeset disk2_state="$3"
+ typeset disk3_state="$4"
+
+ state=$(zpool status -i "$pool" | grep "$DISK1" | grep "$disk1_state")
+ if [[ -z "$state" ]]; then
+ log_fail "DISK1 state; expected='$disk1_state' got '$state'"
+ fi
+
+ state=$(zpool status -i "$pool" | grep "$DISK2" | grep "$disk2_state")
+ if [[ -z "$state" ]]; then
+ log_fail "DISK2 state; expected='$disk2_state' got '$state'"
+ fi
+
+ state=$(zpool status -i "$pool" | grep "$DISK3" | grep "$disk3_state")
+ if [[ -z "$state" ]]; then
+ log_fail "DISK3 state; expected='$disk3_state' got '$state'"
+ fi
+}
+
+function status_check_all # pool disk-state
+{
+ typeset pool="$1"
+ typeset disk_state="$2"
+
+ status_check "$pool" "$disk_state" "$disk_state" "$disk_state"
+}
+
+# 1. Create a one-disk pool.
+log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3
+status_check_all $TESTPOOL "uninitialized"
+
+# 2. Verify uninitialize succeeds for uninitialized pool.
+log_must zpool initialize -u $TESTPOOL
+status_check_all $TESTPOOL "uninitialized"
+
+# 3. Verify pool wide cancel + uninit
+log_must zpool initialize $TESTPOOL
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_mustnot zpool initialize -u $TESTPOOL
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_must zpool initialize -c $TESTPOOL
+status_check_all $TESTPOOL "uninitialized"
+
+log_must zpool initialize -u $TESTPOOL
+status_check_all $TESTPOOL "uninitialized"
+
+# 3. Verify pool wide suspend + uninit
+log_must zpool initialize $TESTPOOL
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_mustnot zpool initialize -u $TESTPOOL
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_must zpool initialize -s $TESTPOOL
+status_check_all $TESTPOOL "suspended"
+
+log_must zpool initialize -u $TESTPOOL
+status_check_all $TESTPOOL "uninitialized"
+
+# 4. Verify per-disk cancel|suspend + uninit
+log_must zpool initialize $TESTPOOL
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_must zpool initialize -c $TESTPOOL $DISK1
+log_must zpool initialize -s $TESTPOOL $DISK2
+log_mustnot zpool initialize -u $TESTPOOL $DISK3
+status_check $TESTPOOL "uninitialized" "suspended" "[[:digit:]]* initialized"
+
+log_must zpool initialize -u $TESTPOOL $DISK1
+status_check $TESTPOOL "uninitialized" "suspended" "[[:digit:]]* initialized"
+
+log_must zpool initialize -u $TESTPOOL $DISK2
+status_check $TESTPOOL "uninitialized" "uninitialized" "[[:digit:]]* initialized"
+
+log_must zpool initialize $TESTPOOL $DISK1
+status_check $TESTPOOL "[[:digit:]]* initialized" "uninitialized" "[[:digit:]]* initialized"
+
+log_must zpool initialize $TESTPOOL $DISK2
+status_check_all $TESTPOOL "[[:digit:]]* initialized"
+
+log_must zpool initialize -s $TESTPOOL
+status_check_all $TESTPOOL "suspended"
+
+log_must zpool initialize -u $TESTPOOL $DISK1 $DISK2 $DISK3
+status_check_all $TESTPOOL "uninitialized"
+
+log_pass "Initialize start + cancel/suspend + uninit + start works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh
index bd4ca069c49b..3055478841fc 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh
index 2ccc57b475b7..794d61c4e13f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh
index 5e40eee4b83e..dc44727d8757 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh
index 2229f87e6208..23dc57ed3679 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh
index 4f3c187b91d5..23bb47545e81 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh
index 14e0ab3fa75b..be31eb69c4f2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh
index ceef4cc3161d..a881c7622de2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh
index 2229f87e6208..23dc57ed3679 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh
index e104a9323f27..8cf64dfab713 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh
index 79855e64a809..a0e7f21072fe 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh
index 307fae7196d2..af286ff9047f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh
index 8ce094bcc701..405f6fa1da8e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
index 1b8312e99372..8baaeb0b3299 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh
index 0c098a61e238..e87336ed00b3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh
index 4ab7ac659b83..ddaed845e0db 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh
index 4e132d9d00b5..dc1745bf130e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
index f1b957e620c9..9595e51241b3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -35,14 +35,14 @@
#
# STRATEGY:
# 1. Create various pools with different ashift values.
-# 2. Verify 'replace -o ashift=<n>' works only with allowed values.
+# 2. Verify 'replace' works.
#
verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
rm -f $disk1 $disk2
}
@@ -61,31 +61,21 @@ orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
# the ashift using the -o ashift property should still
# be honored.
#
-log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
+log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
do
- for cmdval in ${ashifts[@]}
- do
- log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
- log_must verify_ashift $disk1 $ashift
- # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
- if [[ $cmdval -le $ashift ]]
- then
- log_must zpool replace -o ashift=$cmdval $TESTPOOL1 \
- $disk1 $disk2
- log_must verify_ashift $disk2 $ashift
- wait_replacing $TESTPOOL1
- else
- log_mustnot zpool replace -o ashift=$cmdval $TESTPOOL1 \
- $disk1 $disk2
- fi
- # clean things for the next run
- log_must zpool destroy $TESTPOOL1
- log_must zpool labelclear $disk1
- log_must zpool labelclear $disk2
- done
+ log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+ log_must verify_ashift $disk1 $ashift
+ # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
+ log_must zpool replace $TESTPOOL1 $disk1 $disk2
+ log_must verify_ashift $disk2 $ashift
+ wait_replacing $TESTPOOL1
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
done
typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh
index a524c4b17ae5..b4ac18e5ea25 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -34,17 +34,15 @@
#
# STRATEGY:
# 1. Create a pool with default values.
-# 2. Verify 'zpool replace' uses the ashift pool property value when
-# replacing an existing device.
-# 3. Verify the default ashift value can still be overridden by manually
-# specifying '-o ashift=<n>' from the command line.
+# 2. Override the pool ashift property.
+# 3. Verify 'zpool replace' works.
#
verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
rm -f $disk1 $disk2
}
@@ -63,7 +61,7 @@ orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
# the ashift using the -o ashift property should still
# be honored.
#
-log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
+log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
for ashift in ${ashifts[@]}
@@ -72,21 +70,9 @@ do
do
log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
log_must zpool set ashift=$pprop $TESTPOOL1
- # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
- if [[ $pprop -le $ashift ]]
- then
- log_must zpool replace $TESTPOOL1 $disk1 $disk2
- wait_replacing $TESTPOOL1
- log_must verify_ashift $disk2 $ashift
- else
- # cannot replace if pool prop ashift > vdev ashift
- log_mustnot zpool replace $TESTPOOL1 $disk1 $disk2
- # verify we can override the pool prop value manually
- log_must zpool replace -o ashift=$ashift $TESTPOOL1 \
- $disk1 $disk2
- wait_replacing $TESTPOOL1
- log_must verify_ashift $disk2 $ashift
- fi
+ log_must zpool replace $TESTPOOL1 $disk1 $disk2
+ wait_replacing $TESTPOOL1
+ log_must verify_ashift $disk2 $ashift
# clean things for the next run
log_must zpool destroy $TESTPOOL1
log_must zpool labelclear $disk1
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh
index 2229f87e6208..23dc57ed3679 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh
index 725e495ebb89..6049c1a3697c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh
index c74e23919cd1..066eb36b6f36 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh
index 48ceecdf9eb7..02ab31958a15 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
index 2b8c9e954ad7..16984432ee27 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh
index abd514086630..3f4115aff089 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_concurrent.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_concurrent.ksh
new file mode 100755
index 000000000000..4c3b09796869
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_concurrent.ksh
@@ -0,0 +1,101 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 Hewlett Packard Enterprise Development LP.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool clear' doesn't cause concurrent resilvers
+#
+# STRATEGY:
+# 1. Create N(10) virtual disk files.
+# 2. Create draid pool based on the virtual disk files.
+# 3. Fill the filesystem with directories and files.
+# 4. Force-fault 2 vdevs and verify distributed spare is kicked in.
+# 5. Free the distributed spare by replacing the faulty drive.
+# 6. Run zpool clear and verify that it does not initiate 2 resilvers
+# concurrently while distributed spare gets kicked in.
+#
+
+verify_runnable "global"
+
+typeset -ir devs=10
+typeset -ir nparity=1
+typeset -ir ndata=8
+typeset -ir dspare=1
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && destroy_pool "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$BASEDIR/vdev$i"
+ done
+
+ for dir in $BASEDIR; do
+ if [[ -d $dir ]]; then
+ log_must rm -rf $dir
+ fi
+ done
+
+ zed_stop
+ zed_cleanup
+}
+
+log_assert "Verify zpool clear on draid pool doesn't cause concurrent resilvers"
+log_onexit cleanup
+
+setup_test_env $TESTPOOL draid${nparity}:${ndata}d:${dspare}s $devs
+
+# ZED needed for sequential resilver
+zed_setup
+log_must zed_start
+
+log_must zpool offline -f $TESTPOOL $BASEDIR/vdev5
+log_must wait_vdev_state $TESTPOOL draid1-0-0 "ONLINE" 60
+log_must zpool wait -t resilver $TESTPOOL
+log_must zpool offline -f $TESTPOOL $BASEDIR/vdev6
+
+log_must zpool labelclear -f $BASEDIR/vdev5
+log_must zpool labelclear -f $BASEDIR/vdev6
+
+log_must zpool replace -w $TESTPOOL $BASEDIR/vdev5
+sync_pool $TESTPOOL
+
+log_must zpool events -c
+log_must zpool clear $TESTPOOL
+log_must wait_vdev_state $TESTPOOL draid1-0-0 "ONLINE" 60
+log_must zpool wait -t resilver $TESTPOOL
+log_must zpool wait -t scrub $TESTPOOL
+
+nof_resilver=$(zpool events | grep -c resilver_start)
+if [ $nof_resilver = 1 ] ; then
+ log_must verify_pool $TESTPOOL
+ log_pass "zpool clear on draid pool doesn't cause concurrent resilvers"
+else
+ log_fail "FAIL: sequential and healing resilver initiated concurrently"
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh
index e487afd8ae4d..8b5b5975774d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh
index 03eb9901cb3e..c725664380f2 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh
index 936fd798e9dd..a0652219ae7d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh
new file mode 100755
index 000000000000..e414cd1beaad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh
@@ -0,0 +1,79 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2019, Delphix. All rights reserved.
+# Copyright (c) 2023, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify scrub -e, -p, and -s show the right status.
+#
+# STRATEGY:
+# 1. Create a pool and create a 10MB file in it.
+# 2. Start a error scrub (-e) and verify it's doing a scrub.
+# 3. Pause error scrub (-p) and verify it's paused.
+# 4. Try to pause a paused error scrub (-p) and make sure that fails.
+# 5. Resume the paused error scrub and verify again it's doing a scrub.
+# 6. Verify zpool scrub -s succeed when the system is error scrubbing.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must zinject -c all
+ rm -f /$TESTPOOL/10m_file
+}
+
+log_onexit cleanup
+
+log_assert "Verify scrub -e, -p, and -s show the right status."
+
+log_must fio --rw=write --name=job --size=10M --filename=/$TESTPOOL/10m_file
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+log_must zinject -t data -e checksum -f 100 -am /$TESTPOOL/10m_file
+
+# create some error blocks
+dd if=/$TESTPOOL/10m_file bs=1M count=1 || true
+
+# sync error blocks to disk
+log_must sync_pool $TESTPOOL
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+log_must zpool scrub -e $TESTPOOL
+log_must is_pool_error_scrubbing $TESTPOOL true
+log_must zpool scrub -p $TESTPOOL
+log_must is_pool_error_scrub_paused $TESTPOOL true
+log_mustnot zpool scrub -p $TESTPOOL
+log_must is_pool_error_scrub_paused $TESTPOOL true
+log_must zpool scrub -e $TESTPOOL
+log_must is_pool_error_scrubbing $TESTPOOL true
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_error_scrub_stopped $TESTPOOL true
+
+log_pass "Verified scrub -e, -p, and -s show expected status."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh
new file mode 100755
index 000000000000..daa11c3949c6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh
@@ -0,0 +1,99 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2019, Delphix. All rights reserved.
+# Copyright (c) 2023, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify regular scrub and error scrub can't run at the same time.
+#
+# STRATEGY:
+# 1. Create a pool and create a 10MB file in it.
+# 2. Start a scrub and verify it's doing a scrub.
+# 3. Start a error scrub (-e) and verify it fails.
+# 4. Pause scrub (-p) and verify it's paused.
+# 5. Start a error scrub (-e) verify it fails again.
+# 6. Resume the paused scrub, verify it and cancel it.
+# 7. Start a error scrub (-e) and verify it's doing error scrub.
+# 8. Start a scrub and verify it fails.
+# 9. Cancel error scrub (-e) and verify it is canceled.
+# 10. Start scrub, verify it, cancel it and verify it.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must zinject -c all
+ rm -f /$TESTPOOL/10m_file
+}
+
+log_onexit cleanup
+
+log_assert "Verify regular scrub and error scrub can't run at the same time."
+
+log_must fio --rw=write --name=job --size=10M --filename=/$TESTPOOL/10m_file
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+log_must zinject -t data -e checksum -f 100 -am /$TESTPOOL/10m_file
+
+# create some error blocks before error scrub is requested.
+dd if=/$TESTPOOL/10m_file bs=1M count=1 || true
+# sync error blocks to disk
+log_must sync_pool $TESTPOOL
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_mustnot zpool scrub -e $TESTPOOL
+log_must zpool scrub -p $TESTPOOL
+log_must is_pool_scrub_paused $TESTPOOL true
+log_mustnot zpool scrub -e $TESTPOOL
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_scrub_stopped $TESTPOOL true
+
+# create some error blocks before error scrub is requested.
+dd if=/$TESTPOOL/10m_file bs=1M count=1 || true
+# sync error blocks to disk
+log_must sync_pool $TESTPOOL
+
+log_must zpool scrub -e $TESTPOOL
+log_must is_pool_error_scrubbing $TESTPOOL true
+log_mustnot zpool scrub $TESTPOOL
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_error_scrub_stopped $TESTPOOL true
+
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_scrub_stopped $TESTPOOL true
+
+log_pass "Verified regular scrub and error scrub can't run at the same time."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh
new file mode 100755
index 000000000000..d0066fdbb4a3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh
@@ -0,0 +1,109 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2019, Delphix. All rights reserved.
+# Copyright (c) 2023, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify error scrub clears the errorlog, if errors no longer exist.
+#
+# STRATEGY:
+# 1. Create a pool and create file in it.
+# 2. Zinject errors and read using dd to log errors to disk.
+# 3. Make sure file name is mentioned in the list of error files.
+# 4. Start error scrub and wait for it finish.
+# 5. Check scrub ran and errors are still reported.
+# 6. Clear corruption and error scrub again.
+# 7. Check scrub ran and errors are cleared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ zinject -c all
+ rm -f /$TESTPOOL2/$TESTFILE0
+ destroy_pool $TESTPOOL2
+}
+
+log_onexit cleanup
+
+log_assert "Verify error scrub clears the errorlog, if errors no longer exist."
+
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f -O primarycache=none $TESTPOOL2 $TESTDIR/vdev_a
+log_must zfs create $TESTPOOL2/$TESTFS1
+typeset file=/$TESTPOOL2/$TESTFS1/$TESTFILE0
+log_must dd if=/dev/urandom of=$file bs=2M count=10
+
+lastfs="$(zfs list -r $TESTPOOL2 | tail -1 | awk '{print $1}')"
+for i in {1..3}; do
+ log_must zfs snap $lastfs@snap$i
+ log_must zfs clone $lastfs@snap$i $TESTPOOL2/clone$i
+ lastfs="$(zfs list -r $TESTPOOL2/clone$i | tail -1 | awk '{print $1}')"
+done
+
+log_must zinject -t data -e checksum -f 100 -a $file
+dd if=$file of=/dev/null bs=2M count=10
+
+# Important: sync error log to disk
+log_must sync_pool $TESTPOOL2
+
+# Check reported errors
+log_must zpool status -v $TESTPOOL2
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2/$TESTFS1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/$TESTFS1@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+# Check errors are reported if corruption persists
+log_must zpool scrub -e -w $TESTPOOL2
+log_must eval "zpool status -v | grep 'error blocks'"
+log_must zpool status -v $TESTPOOL2
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2/$TESTFS1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/$TESTFS1@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+# Check errors are cleared
+log_must zinject -c all
+log_must zpool scrub -e -w $TESTPOOL2
+log_must zpool status -v $TESTPOOL2
+log_must eval "zpool status -v | grep 'error blocks'"
+log_mustnot eval "zpool status -v | grep '$TESTFILE0'"
+
+
+log_pass "Verify error scrub clears the errorlog, if errors no longer exist."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_004_pos.ksh
new file mode 100755
index 000000000000..c88b9b0c8d33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_error_scrub_004_pos.ksh
@@ -0,0 +1,54 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2023, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify error scrub clears the errorlog, if errors no longer exist.
+#
+# STRATEGY:
+# 1. Create a pool with head_errlog disabled.
+# 2. Run an error scrub and verify it is not supported.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -f /$TESTPOOL2/$TESTFILE0
+ destroy_pool $TESTPOOL2
+}
+
+log_onexit cleanup
+
+log_assert "Verify error scrub cannot run without the head_errlog feature."
+
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f -o feature@head_errlog=disabled $TESTPOOL2 $TESTDIR/vdev_a
+log_mustnot zpool scrub -ew $TESTPOOL2
+
+log_pass "Verify error scrub cannot run without the head_errlog feature."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
index f98b1c0613f6..d95c1decd5de 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
index 96bc185dd40c..0368c5809995 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh
index 116d622960f9..e11825f91589 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh
index 12dc044e9e08..1e1412ee0da9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh
index a7ae7f16b1af..846473be9736 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh
index 69a33983d379..62d529486509 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh
index 7a07e643343d..815f26179132 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh
index 4b51cd9625ec..be06d6147af7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_001_pos.ksh
new file mode 100755
index 000000000000..4b9097933f37
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_001_pos.ksh
@@ -0,0 +1,89 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2023 by Klara Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS can set any valid user-defined pool property.
+#
+# STRATEGY:
+# 1. Combine all kind of valid characters into a valid user-defined
+# property name.
+# 2. Random get a string as the value.
+# 3. Verify all the valid user-defined pool properties can be set to a
+# pool.
+#
+
+verify_runnable "both"
+
+log_assert "ZFS can set any valid user-defined pool property."
+log_onexit cleanup_user_prop $TESTPOOL
+
+typeset -a names=()
+typeset -a values=()
+
+# Longest property name (255 bytes, which is the 256-byte limit minus 1 byte
+# for the null byte)
+names+=("$(awk 'BEGIN { printf "x:"; while (c++ < (256 - 2 - 1)) printf "a" }')")
+values+=("long-property-name")
+# Longest property value (the limits are 1024 on FreeBSD and 4096 on Linux, so
+# pick the right one; the longest value can use limit minus 1 bytes for the
+# null byte)
+if is_linux; then
+ typeset ZFS_MAXPROPLEN=4096
+else
+ typeset ZFS_MAXPROPLEN=1024
+fi
+names+=("long:property:value")
+values+=("$(awk -v max="$ZFS_MAXPROPLEN" 'BEGIN { while (c++ < (max - 1)) printf "A" }')")
+# Valid property names
+for i in {1..10}; do
+ typeset -i len
+ ((len = RANDOM % 32))
+ names+=("$(valid_user_property $len)")
+ ((len = RANDOM % 512))
+ values+=("$(user_property_value $len)")
+done
+
+typeset -i i=0
+while ((i < ${#names[@]})); do
+ typeset name="${names[$i]}"
+ typeset value="${values[$i]}"
+
+ log_must eval "zpool set $name='$value' $TESTPOOL"
+ log_must eval "check_user_prop $TESTPOOL $name '$value'"
+
+ ((i += 1))
+done
+
+log_pass "ZFS can set any valid user-defined pool property passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_002_neg.ksh
new file mode 100755
index 000000000000..7c8fcba6e471
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/user_property_002_neg.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2023 by Klara Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS can handle any invalid user-defined pool property.
+#
+# STRATEGY:
+# 1. Combine all kind of invalid user pool property names.
+# 2. Random get a string as the value.
+# 3. Verify all the invalid user-defined pool properties can not be set
+# to the pool.
+#
+
+verify_runnable "both"
+
+log_assert "ZFS can handle any invalid user pool property."
+log_onexit cleanup_user_prop $TESTPOOL
+
+typeset -a names=()
+typeset -a values=()
+
+# Too long property name (256 bytes, which is the 256-byte limit minus 1 byte
+# for the null byte plus 1 byte to reach back over the limit)
+names+=("$(awk 'BEGIN { printf "x:"; while (c++ < (256 - 2 - 1 + 1)) printf "a" }')")
+values+=("too-long-property-name")
+# Too long property value (the limits are 1024 on FreeBSD and 4096 on Linux, so
+# pick the right one; the too long value is, e.g., the limit minus 1 bytes for the
+# null byte plus 1 byte to reach back over the limit)
+if is_linux; then
+ typeset ZFS_MAXPROPLEN=4096
+else
+ typeset ZFS_MAXPROPLEN=1024
+fi
+names+=("too:long:property:value")
+values+=("$(awk -v max="$ZFS_MAXPROPLEN" 'BEGIN { while (c++ < (max - 1 + 1)) printf "A" }')")
+# Invalid property names
+for i in {1..10}; do
+ typeset -i len
+ ((len = RANDOM % 32))
+ names+=("$(invalid_user_property $len)")
+ ((len = RANDOM % 512))
+ values+=("$(user_property_value $len)")
+done
+
+typeset -i i=0
+while ((i < ${#names[@]})); do
+ typeset name="${names[$i]}"
+ typeset value="${values[$i]}"
+
+ log_mustnot zpool set $name=$value $TESTPOOL
+ log_mustnot check_user_prop $TESTPOOL \"$name\" \"$value\"
+
+ ((i += 1))
+done
+
+log_pass "ZFS can handle invalid user pool property passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh
new file mode 100755
index 000000000000..a1f3efb90577
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh
@@ -0,0 +1,52 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool set comment property on root vdev
+#
+# STRATEGY:
+# 1. set a property on root vdev
+# 2. verify the property is set
+#
+
+log_assert "zpool set comment property on root vdev"
+
+log_must zpool set comment="openzfs" ${TESTPOOL} root
+
+COMMENT="$(zpool get -H -o value comment ${TESTPOOL} root)"
+if [ $? -ne 0 ]; then
+ log_fail "cant retrieve comment property from root vdev"
+fi
+
+if [ "$COMMENT" != "openzfs" ]; then
+ log_fail "unexpected value for comment property: $COMMENT != \"openzfs\""
+fi
+
+log_pass "zpool set comment property on root vdev"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh
index 6e4e6be6a18e..3eb1411c8c86 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh
index 34d7fd821464..ab592d433a80 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh
index 1d637b77af00..7e93c8725355 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh
index 09b5f50d5e18..41fef8f7cdb4 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -42,7 +42,7 @@ verify_runnable "global"
function cleanup
{
- log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
+ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT $orig_ashift
destroy_pool $TESTPOOL1
rm -f $disk
}
@@ -60,7 +60,7 @@ orig_ashift=$(get_tunable VDEV_FILE_PHYSICAL_ASHIFT)
# the ashift using the -o ashift property should still
# be honored.
#
-log_must set_tunable64 VDEV_FILE_PHYSICAL_ASHIFT 16
+log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
disk=$TEST_BASE_DIR/disk
log_must mkfile $SIZE $disk
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
new file mode 100644
index 000000000000..346e4a16b2ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
@@ -0,0 +1,178 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2023 by Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A VALID_NAME_CHAR a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ 0 1 2 3 4 5 6 7 8 9 ':' '-' '.' '_'
+set -A INVALID_NAME_CHAR A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
+ '`' '~' '!' '@' '#' '$' '%' '^' '&' '(' ')' '+' '=' '|' "\\" '{' '[' ']' \
+ '}' ';' '"' '<' ',' '>' '?' '/' ' '
+set -A ALL_CHAR ${VALID_NAME_CHAR[*]} ${INVALID_NAME_CHAR[*]}
+
+#
+# Cleanup all the user properties of the pool.
+#
+# $1 pool name
+#
+function cleanup_user_prop
+{
+ typeset pool=$1
+
+ typeset user_prop
+ user_prop=$(zpool get -H -o property all $pool | grep ":")
+
+ typeset prop
+ for prop in $user_prop; do
+ zpool set $prop="" $pool ||
+ log_must zpool set $prop="" $pool
+ done
+}
+
+#
+# Random select character from the specified character set and combine into a
+# random string
+#
+# $1 character set name
+# $2 String length
+#
+function random_string
+{
+ typeset char_set=${1:-VALID_NAME_CHAR}
+ typeset -i len=${2:-5}
+
+ eval typeset -i count=\${#$char_set[@]}
+
+ # No consumers want an empty string.
+ ((len == 0)) && len=3
+
+ typeset str
+ typeset -i i=0
+ while ((i < len)); do
+ typeset -i ind
+ ((ind = RANDOM % count))
+ eval str=\${str}\${$char_set[\$ind]}
+
+ ((i += 1))
+ done
+
+ echo "$str"
+}
+
+#
+# Get valid user-defined property name
+#
+# $1 user-defined property name length
+#
+function valid_user_property
+{
+ typeset -i sumlen=${1:-10}
+ ((sumlen < 2 )) && sumlen=2
+ typeset -i len
+ ((len = RANDOM % sumlen))
+ typeset part1 part2
+
+ while true; do
+ part1="$(random_string VALID_NAME_CHAR $len)"
+ if [[ "$part1" == "-"* ]]; then
+ continue
+ fi
+ break
+ done
+ ((len = sumlen - (len + 1)))
+
+ while true; do
+ part2="$(random_string VALID_NAME_CHAR $len)"
+ if [[ -z $part1 && -z $part2 ]]; then
+ continue
+ fi
+ break
+ done
+
+ echo "${part1}:${part2}"
+}
+
+#
+# Get invalid user-defined property name
+#
+# $1 user-defined property name length
+#
+function invalid_user_property
+{
+ typeset -i sumlen=${1:-10}
+ ((sumlen == 0)) && sumlen=1
+ typeset -i len
+ ((len = RANDOM % sumlen))
+
+ typeset part1 part2
+ while true; do
+ part1="$(random_string VALID_NAME_CHAR $len)"
+ ((len = sumlen - len))
+ part2="$(random_string INVALID_NAME_CHAR $len)"
+
+ # Avoid $part1 is *:* and $part2 is "=*"
+ if [[ "$part1" == *":"* && "$part2" == "="* ]]; then
+ continue
+ fi
+ break
+ done
+
+ echo "${part1}${part2}"
+}
+
+#
+# Get user-defined property value
+#
+# $1 user-defined property name length
+#
+function user_property_value
+{
+ typeset -i len=${1:-100}
+
+ random_string ALL_CHAR $len
+}
+
+#
+# Check if the user-defined property is identical to the expected value.
+#
+# $1 pool
+# $2 user property
+# $3 expected value
+#
+function check_user_prop
+{
+ typeset pool=$1
+ typeset user_prop="$2"
+ typeset expect_value="$3"
+ typeset value=$(zpool get -p -H -o value "$user_prop" $pool 2>&1)
+
+ [ "$expect_value" = "$value" ]
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_dryrun_output.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_dryrun_output.ksh
index 2267ea7bd895..410b1fe7a03e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_dryrun_output.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_dryrun_output.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh
index 88c0601032a5..076a08802fbe 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh
index e2751b112597..d6f32cdc7ac6 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -51,7 +51,7 @@ else
fi
set -A args "" "-x" "-v" "-x $testpool" "-v $testpool" "-xv $testpool" \
- "-vx $testpool"
+ "-vx $testpool" "-e $testpool" "-es $testpool"
log_assert "Executing 'zpool status' with correct options succeeds"
@@ -64,4 +64,6 @@ while [[ $i -lt ${#args[*]} ]]; do
(( i = i + 1 ))
done
+cleanup
+
log_pass "'zpool status' with correct options succeeded"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_003_pos.ksh
index e0c2ed669e32..52b22dd833f0 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -37,6 +37,7 @@
# 3. Read the file
# 4. Take a snapshot and make a clone
# 5. Verify we see "snapshot, clone and filesystem" output in 'zpool status -v'
+# and 'zpool status -ev'
function cleanup
{
@@ -61,10 +62,14 @@ dd if=/$TESTPOOL2/10m_file bs=1M || true
log_must zfs snapshot $TESTPOOL2@snap
log_must zfs clone $TESTPOOL2@snap $TESTPOOL2/clone
+log_must zfs create $TESTPOOL2/$TESTFS1
# Look to see that snapshot, clone and filesystem our files report errors
+log_must zpool status -v $TESTPOOL2
log_must eval "zpool status -v | grep '$TESTPOOL2@snap:/10m_file'"
log_must eval "zpool status -v | grep '$TESTPOOL2/clone/10m_file'"
log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
+log_must eval "zpool status -ev | grep '$TESTPOOL2/10m_file'"
+log_mustnot eval "zpool status -v | grep '$TESTFS1'"
log_pass "'zpool status -v' outputs affected filesystem, snapshot & clone"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_004_pos.ksh
index 6d8571950eec..111d598dfb7d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -74,6 +74,7 @@ log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
# Check that enabling the feature reports the error properly.
log_must zpool set feature@head_errlog=enabled $TESTPOOL2
+log_must zpool status -v $TESTPOOL2
log_must eval "zpool status -v | grep '$TESTPOOL2@snap:/10m_file'"
log_must eval "zpool status -v | grep '$TESTPOOL2/clone/10m_file'"
log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_005_pos.ksh
new file mode 100755
index 000000000000..ec4c67fb42f5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_005_pos.ksh
@@ -0,0 +1,90 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022 George Amanakis. All rights reserved.
+#
+
+#
+# DESCRIPTION:
+# Verify correct output with 'zpool status -v' after corrupting a file
+#
+# STRATEGY:
+# 1. Create a pool, an encrypted filesystem and a file
+# 2. zinject checksum errors
+# 3. Unmount the filesystem and unload the key
+# 4. Scrub the pool
+# 5. Verify we report that errors were detected but we do not report
+# the filename since the key is not loaded.
+# 6. Load the key and mount the encrypted fs.
+# 7. Verify we report errors in the pool in 'zpool status -v'
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL2
+ rm -f $TESTDIR/vdev_a
+}
+
+log_assert "Verify reporting errors with unloaded keys works"
+log_onexit cleanup
+
+typeset passphrase="password"
+typeset file="/$TESTPOOL2/$TESTFS1/$TESTFILE0"
+
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f -o feature@head_errlog=enabled $TESTPOOL2 $TESTDIR/vdev_a
+
+log_must eval "echo $passphrase > /$TESTPOOL2/pwd"
+
+log_must zfs create -o encryption=aes-256-ccm -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL2/pwd -o primarycache=none \
+ $TESTPOOL2/$TESTFS1
+
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+log_must eval "echo 'aaaaaaaa' >> "$file
+
+corrupt_blocks_at_level $file 0
+log_must zfs umount $TESTPOOL2/$TESTFS1
+log_must zfs unload-key -a
+log_must zpool sync $TESTPOOL2
+log_must zpool scrub $TESTPOOL2
+log_must zpool wait -t scrub $TESTPOOL2
+log_must zpool status -v $TESTPOOL2
+log_mustnot eval "zpool status -v $TESTPOOL2 | \
+ grep \"permission denied\""
+log_mustnot eval "zpool status -v $TESTPOOL2 | grep '$file'"
+
+log_must eval "cat /$TESTPOOL2/pwd | zfs load-key $TESTPOOL2/$TESTFS1"
+log_must zfs mount $TESTPOOL2/$TESTFS1
+log_must zpool status -v $TESTPOOL2
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v $TESTPOOL2 | grep '$file'"
+
+log_pass "Verify reporting errors with unloaded keys works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_006_pos.ksh
new file mode 100755
index 000000000000..d6f4a4fe2d86
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_006_pos.ksh
@@ -0,0 +1,97 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 George Amanakis. All rights reserved.
+#
+
+#
+# DESCRIPTION:
+# Verify reporting errors when deleting files
+#
+# STRATEGY:
+# 1. Create a pool, and a file
+# 2. zinject checksum errors
+# 3. Create snapshots and clones like:
+# fs->snap1->clone1->snap2->clone2->...
+# 4. Read the original file and immediately delete it
+# 5. Delete the file in clone2
+# 6. Snapshot clone2->snapxx and clone into snapxx->clonexx
+# 7. Verify we report errors in the pool in 'zpool status -v'
+# 8. Promote clone1
+# 9. Verify we report errors in the pool in 'zpool status -v'
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL2
+ rm -f $TESTDIR/vdev_a
+}
+
+log_assert "Verify reporting errors when deleting files"
+log_onexit cleanup
+
+typeset file="/$TESTPOOL2/$TESTFILE0"
+
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f -o feature@head_errlog=enabled $TESTPOOL2 $TESTDIR/vdev_a
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+log_must zinject -t data -e checksum -f 100 -am $file
+
+for i in {1..3}; do
+ lastfs="$(zfs list -r $TESTPOOL2 | tail -1 | awk '{print $1}')"
+ log_must zfs snap $lastfs@snap$i
+ log_must zfs clone $lastfs@snap$i $TESTPOOL2/clone$i
+done
+
+log_mustnot dd if=$file of=/dev/null bs=1024
+log_must rm $file /$TESTPOOL2/clone2/$TESTFILE0
+log_must zfs snap $TESTPOOL2/clone2@snapxx
+log_must zfs clone $TESTPOOL2/clone2@snapxx $TESTPOOL2/clonexx
+log_must zpool status -v $TESTPOOL2
+
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clonexx/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+log_must zfs promote $TESTPOOL2/clone1
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clonexx/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+log_pass "Verify reporting errors when deleting files"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_007_pos.ksh
new file mode 100755
index 000000000000..666ac9bfc9dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_007_pos.ksh
@@ -0,0 +1,111 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 George Amanakis. All rights reserved.
+#
+
+#
+# DESCRIPTION:
+# Verify reporting errors when deleting corrupted files after scrub
+#
+# STRATEGY:
+# 1. Create a pool, and a file
+# 2. Corrupt the file
+# 3. Create snapshots and clones like:
+# fs->snap1->clone1->snap2->clone2->...
+# 4. Read the original file and immediately delete it
+# 5. Delete the file in clone2
+# 6. Snapshot clone2->snapxx and clone into snapxx->clonexx
+# 7. Verify we report errors in the pool in 'zpool status -v'
+# 8. Promote clone1
+# 9. Verify we report errors in the pool in 'zpool status -v'
+# 10. Delete the corrupted file and origin snapshots.
+# 11. Verify we do not report data errors anymore, without requiring
+# a scrub.
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL2
+ rm -f $TESTDIR/vdev_a
+}
+
+log_assert "Verify reporting errors when deleting corrupted files after scrub"
+log_onexit cleanup
+
+typeset file="/$TESTPOOL2/$TESTFS1/$TESTFILE0"
+
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f $TESTPOOL2 $TESTDIR/vdev_a
+log_must zfs create -o primarycache=none $TESTPOOL2/$TESTFS1
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
+corrupt_blocks_at_level $file 0
+
+lastfs="$(zfs list -r $TESTPOOL2 | tail -1 | awk '{print $1}')"
+for i in {1..3}; do
+ log_must zfs snap $lastfs@snap$i
+ log_must zfs clone $lastfs@snap$i $TESTPOOL2/clone$i
+ lastfs="$(zfs list -r $TESTPOOL2/clone$i | tail -1 | awk '{print $1}')"
+done
+
+log_must zpool scrub -w $TESTPOOL2
+log_must rm $file /$TESTPOOL2/clone2/$TESTFILE0
+log_must zfs snap $TESTPOOL2/clone2@snapxx
+log_must zfs clone $TESTPOOL2/clone2@snapxx $TESTPOOL2/clonexx
+log_must zpool status -v $TESTPOOL2
+
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2/$TESTFS1@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clonexx/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+log_must zfs promote $TESTPOOL2/clone1
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"Permanent errors have been detected\""
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap1:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone1@snap2:/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clone2/$TESTFILE0'"
+log_mustnot eval "zpool status -v | grep '$TESTPOOL2/clonexx/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone2@snap3:/$TESTFILE0'"
+log_must eval "zpool status -v | grep '$TESTPOOL2/clone3/$TESTFILE0'"
+
+log_must rm /$TESTPOOL2/clone1/$TESTFILE0
+log_must zfs destroy -R $TESTPOOL2/clone1@snap1
+log_must zfs destroy -R $TESTPOOL2/clone1@snap2
+log_must zfs list -r $TESTPOOL2
+log_must zpool status -v $TESTPOOL2
+log_must zpool sync
+log_must zpool status -v $TESTPOOL2
+log_must eval "zpool status -v $TESTPOOL2 | \
+ grep \"No known data errors\""
+
+log_pass "Verify reporting errors when deleting corrupted files after scrub"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_008_pos.ksh
new file mode 100755
index 000000000000..6be2ad5a7410
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_008_pos.ksh
@@ -0,0 +1,104 @@
+#!/bin/ksh -p
+
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2024 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool status -e' only shows unhealthy devices.
+#
+# STRATEGY:
+# 1. Create zpool
+# 2. Force DEGRADE, FAULT, or inject slow IOs for vdevs
+# 3. Verify vdevs are reported correctly with -e and -s
+# 4. Verify parents are reported as DEGRADED
+# 5. Verify healthy children are not reported
+#
+
+function cleanup
+{
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ zinject -c all
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ log_must rm -f $all_vdevs
+}
+
+log_assert "Verify 'zpool status -e'"
+
+log_onexit cleanup
+
+all_vdevs=$(echo $TESTDIR/vdev{1..6})
+log_must mkdir -p $TESTDIR
+log_must truncate -s $MINVDEVSIZE $all_vdevs
+
+OLD_SLOW_IO=$(get_tunable ZIO_SLOW_IO_MS)
+
+for raid_type in "draid2:3d:6c:1s" "raidz2"; do
+
+ log_must zpool create -f $TESTPOOL2 $raid_type $all_vdevs
+
+ # Check DEGRADED vdevs are shown.
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev4 "ONLINE"
+ log_must zinject -d $TESTDIR/vdev4 -A degrade $TESTPOOL2
+ log_must eval "zpool status -e $TESTPOOL2 | grep $TESTDIR/vdev4 | grep DEGRADED"
+
+ # Check FAULTED vdevs are shown.
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev5 "ONLINE"
+ log_must zinject -d $TESTDIR/vdev5 -A fault $TESTPOOL2
+ log_must eval "zpool status -e $TESTPOOL2 | grep $TESTDIR/vdev5 | grep FAULTED"
+
+ # Check no ONLINE vdevs are shown
+ log_mustnot eval "zpool status -e $TESTPOOL2 | grep ONLINE"
+
+ # Check no ONLINE slow vdevs are show. Then mark IOs greater than
+ # 10ms slow, delay IOs 20ms to vdev6, check slow IOs.
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev6 "ONLINE"
+ log_mustnot eval "zpool status -es $TESTPOOL2 | grep ONLINE"
+
+ log_must set_tunable64 ZIO_SLOW_IO_MS 10
+ log_must zinject -d $TESTDIR/vdev6 -D20:100 $TESTPOOL2
+ log_must mkfile 1048576 /$TESTPOOL2/testfile
+ sync_pool $TESTPOOL2
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+
+ # Check vdev6 slow IOs are only shown when requested with -s.
+ log_mustnot eval "zpool status -e $TESTPOOL2 | grep $TESTDIR/vdev6 | grep ONLINE"
+ log_must eval "zpool status -es $TESTPOOL2 | grep $TESTDIR/vdev6 | grep ONLINE"
+
+ # Pool level and top-vdev level status must be DEGRADED.
+ log_must eval "zpool status -e $TESTPOOL2 | grep $TESTPOOL2 | grep DEGRADED"
+ log_must eval "zpool status -e $TESTPOOL2 | grep $raid_type | grep DEGRADED"
+
+ # Check that healthy vdevs[1-3] aren't shown with -e.
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev1 "ONLINE"
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev2 "ONLINE"
+ log_must check_vdev_state $TESTPOOL2 $TESTDIR/vdev3 "ONLINE"
+ log_mustnot eval "zpool status -es $TESTPOOL2 | grep $TESTDIR/vdev1 | grep ONLINE"
+ log_mustnot eval "zpool status -es $TESTPOOL2 | grep $TESTDIR/vdev2 | grep ONLINE"
+ log_mustnot eval "zpool status -es $TESTPOOL2 | grep $TESTDIR/vdev3 | grep ONLINE"
+
+ log_must zinject -c all
+ log_must zpool status -es $TESTPOOL2
+
+ zpool destroy $TESTPOOL2
+done
+
+log_pass "Verify zpool status -e shows only unhealthy vdevs"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh
index 635125fc0d1e..f5c68aca53e0 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh
index 89c146249e71..3167a5097b5a 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh
index 181e62b113c1..3d866cfd9f20 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh
index bdbf3db53336..9342cbe880ae 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh
@@ -60,7 +60,7 @@ log_must set_tunable64 VDEV_MIN_MS_COUNT 64
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
log_must mkdir "$TESTDIR"
log_must truncate -s $LARGESIZE "$LARGEFILE"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh
index d5aaf49aebc5..41d1decd13ce 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh
@@ -52,7 +52,7 @@ LARGEFILE="$TESTDIR/largefile"
# Reduce trim size to allow for tighter tolerance below when checking.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
log_must mkdir "$TESTDIR"
log_must truncate -s $LARGESIZE "$LARGEFILE"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh
index 1fab5305adc0..3b6f28dd7970 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh
index 860ba0f061a6..94301e865bc8 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
index 993fafc0324d..977aca621278 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
index 0bc2cfab0470..0889946e8f27 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh
index b49c19c5551c..bd44db9eb6be 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh
index 16ab14907055..8e5f3dd3a9b1 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh
index 0ac3470dedfe..559fdf2b0980 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh
index 0e278c81ccb4..bbadfc1f1d1d 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh
index b294af06cf46..46c93119561f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh
index 4c16f81082ca..c8280086e2e7 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh
index 696c8c66cc1c..018d9c1739fe 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh
index 71d59b93a4ca..aae7120bd69f 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh
index 22ffda2114a5..f32eac17bce9 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_features_001_pos.ksh
index 5170d31b46da..448de3e4041e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_features_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_features_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh
index 5c3d06f228ce..853d40e0355b 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh
index 59fe057e8ca6..1edc9fa82047 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh
index af301829c196..d48aae19c746 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh
index e3dc8c179c0a..bbc2565f3b36 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg b/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg
index 1a96ff5d93fa..9c76a8780b4a 100644
--- a/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -29,7 +29,7 @@
#
if is_linux; then
- # these are the set of setable ZFS properties
+ # these are the set of settable ZFS properties
PROP_NAMES="\
acltype atime \
checksum compression devices \
@@ -81,7 +81,7 @@ elif is_freebsd; then
hidden"
else
- # these are the set of setable ZFS properties
+ # these are the set of settable ZFS properties
PROP_NAMES="\
aclinherit aclmode atime \
checksum compression devices \
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh
index fc0ebde10025..9e49c7188ce5 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh
index 490da6c8caa7..ee889dfc2682 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh
index ec91ded976ff..a70dc47fcc95 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh
index ce474657b42c..74dc1956105d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh
index 7497553ed8a5..4cb615b07cd2 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh
index aa74bcf40c1f..c77641ad8d7a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh
index fabba4f13e9c..c1bdf6a83cea 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh
index 0657b9143670..352dcae6301b 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh
index 284c9f76dff1..c52c7bbfd170 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh
index 8e4c39bfce75..b5779ec8b56a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh
index dd92f534d3a1..64cbbd57cc58 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh
index 38c11a051028..3eec6306a60d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh
index ac275b01e5f9..a7c0d78e4a8f 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh
index 51b5162decfc..bda0702c7581 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh
index 6ecb66a3584c..9bdcd519716a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh
index 9cfb79210b11..1ec198415705 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh
index 0d15c0c8e5ae..4ef9ac28af51 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh
index 232d9574b51c..8c770ae4cc22 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh
index 604887f6a2d8..e382141393c1 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh
index 5b0a773f15a9..d421643314cf 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh
index 62b5bf39f43c..f6f5b13556c9 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh
index fd65feb8c001..d03907293501 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zilstat_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zilstat_001_pos.ksh
new file mode 100755
index 000000000000..9deee67a56ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zilstat_001_pos.ksh
@@ -0,0 +1,37 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+is_freebsd && ! python3 -c 'import sysctl' 2>/dev/null && log_unsupported "python3 sysctl module missing"
+
+set -A args "" "-s \",\"" "-v" \
+ "-f time,cwc,imnb,imsb"
+
+log_assert "zilstat generates output and doesn't return an error code"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must eval "zilstat ${args[i]} > /dev/null"
+ ((i = i + 1))
+done
+log_pass "zilstat generates output and doesn't return an error code"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh
index 00a86eebafe6..13c4ad0f1362 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh
index 7bcd911543ed..b68a3eae9920 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh
index b0fadca8c9fe..959f2aea991d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh
index 5d6ef5ff3e4d..f73169ac5b75 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh
index 77d08ee39009..15a44abd4dda 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh
index acc93fe74826..fabac4dbcddb 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh
index dbc540cebbe7..35f200148fc8 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh
index 9bca4668d3d1..9f5c7c224f07 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh
index c8abf4da58e6..d3179be3970d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh
index 47082e3524e3..916905e24ec1 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh
index 09fd775ff4cc..66dd71507abd 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh
index f3460186725c..3eb091ef2573 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh
index 523883c6f0dd..1f8b5dc94c9e 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh
index cd290515357f..e3c0699e096c 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh
index 1168e6bdac9f..91632c539e66 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh
index 6211e6575540..fb6f5847c0fd 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh
index bf9ee4cfadb0..730c18e085ba 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh
index 03d01f20e959..8c89379f5690 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh
index 9cd811a5487c..a5a44be812f0 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh
index aa380010574f..eebe13ad30b3 100755
--- a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh
index 115e00c47be5..635042bc11bc 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh
index b4c588282ff7..0196b795395d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg
index 59f367cfa544..de343510186d 100644
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib
index d993c3037444..4c0d9b5b4606 100644
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh
index 5d995a79ba33..318b42e86bdf 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh
index 4951097aca51..cc0659f0761e 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh
index 8e3a5680d34d..896f629a260a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh
index 727c0aef0883..cc3f2084a8b0 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh
index 0f60113b76fe..1049ba9dbe1b 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh
index 4f3504ac41ba..dda1c4f18ca0 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh
index 77eb6bd34f40..009d931c100d 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh
index 0d64eb0ec624..5fea262a4f61 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh
index 22450d89dfd2..60d350573a15 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh
index 11f51350af56..efd279faed1a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh
index d99d42984780..eeb2c47dcb27 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh
index 333177accbe5..72c5367522ff 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh
index b6bcf71bffff..5f490b54a795 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh
index a20321950113..3ff871b0d2d9 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
index 53652ec11b5a..10b4761fe233 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh
index d275e063b13a..76aa23035dd9 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh
index 4c57413f1464..a54124a58e5c 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh
index 4ed38d475cd7..001c7292bed2 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh
index 79cd6e9f908e..17d29ee4f548 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh
index 6a9af3bc28c3..4c719075a741 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh
index c8105fb4a50a..4cac07371660 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh
index 5363043a8307..a0d17ba7c94c 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh
index 3f64fdf1a708..e3c9187355ae 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh
index fa7d3f3f2d56..69b5448b458a 100755
--- a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/cleanup.ksh b/tests/zfs-tests/tests/functional/compression/cleanup.ksh
index 0573003b6af5..f3647ea2bbee 100755
--- a/tests/zfs-tests/tests/functional/compression/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/compression/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress.cfg b/tests/zfs-tests/tests/functional/compression/compress.cfg
index b2373064505f..6c955807c482 100644
--- a/tests/zfs-tests/tests/functional/compression/compress.cfg
+++ b/tests/zfs-tests/tests/functional/compression/compress.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh
index fb3bae3b6725..cddd45a628f4 100755
--- a/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh
index e7c6d6c6e57e..1f7d234c10bf 100755
--- a/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh
index d5b7256b52d6..f8028ad218a1 100755
--- a/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh
index b924bcd0ba62..ba851343712f 100755
--- a/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/compress_zstd_bswap.ksh b/tests/zfs-tests/tests/functional/compression/compress_zstd_bswap.ksh
index 9726cf0dd5a6..73428e8af510 100755
--- a/tests/zfs-tests/tests/functional/compression/compress_zstd_bswap.ksh
+++ b/tests/zfs-tests/tests/functional/compression/compress_zstd_bswap.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/compression/setup.ksh b/tests/zfs-tests/tests/functional/compression/setup.ksh
index 677cb12d79ac..1eeefeaa18c1 100755
--- a/tests/zfs-tests/tests/functional/compression/setup.ksh
+++ b/tests/zfs-tests/tests/functional/compression/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cp_files/.gitignore b/tests/zfs-tests/tests/functional/cp_files/.gitignore
new file mode 100644
index 000000000000..d15225ac8429
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/.gitignore
@@ -0,0 +1 @@
+seekflood
diff --git a/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh b/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh b/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh
index 3a814ca3621f..5a48f0fbc522 100755
--- a/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh b/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh
new file mode 100755
index 000000000000..4db968ffae05
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh
@@ -0,0 +1,161 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2024 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify all cp --reflink modes work with modified file.
+#
+# STRATEGY:
+# 1. Verify "cp --reflink=never|auto|always" behaves as expected.
+# Two different modes of operation are tested.
+#
+# a. zfs_bclone_wait_dirty=0: FICLONE and FICLONERANGE fail with EINVAL
+# when there are dirty blocks which cannot be immediately cloned.
+# This is the default behavior.
+#
+# b. zfs_bclone_wait_dirty=1: FICLONE and FICLONERANGE wait for
+# dirty blocks to be written to disk allowing the clone to succeed.
+# The downside to this is it may be slow which depending on the
+# situtation may defeat the point of making a clone.
+#
+
+verify_runnable "global"
+verify_block_cloning
+
+if ! is_linux; then
+ log_unsupported "cp --reflink is a GNU coreutils option"
+fi
+
+function cleanup
+{
+ datasetexists $TESTPOOL/cp-reflink && \
+ destroy_dataset $$TESTPOOL/cp-reflink -f
+ log_must set_tunable32 BCLONE_WAIT_DIRTY 0
+}
+
+function verify_copy
+{
+ src_cksum=$(sha256digest $1)
+ dst_cksum=$(sha256digest $2)
+
+ if [[ "$src_cksum" != "$dst_cksum" ]]; then
+ log_must ls -l $CP_TESTDIR
+ log_fail "checksum mismatch ($src_cksum != $dst_cksum)"
+ fi
+}
+
+log_assert "Verify all cp --reflink modes work with modified file"
+
+log_onexit cleanup
+
+SRC_FILE=src.data
+DST_FILE=dst.data
+SRC_SIZE=$((1024 + $RANDOM % 1024))
+
+# A smaller recordsize is used merely to speed up the test.
+RECORDSIZE=4096
+
+log_must zfs create -o recordsize=$RECORDSIZE $TESTPOOL/cp-reflink
+CP_TESTDIR=$(get_prop mountpoint $TESTPOOL/cp-reflink)
+
+log_must cd $CP_TESTDIR
+
+# Never wait on dirty blocks (zfs_bclone_wait_dirty=0)
+log_must set_tunable32 BCLONE_WAIT_DIRTY 0
+
+for mode in "never" "auto" "always"; do
+ log_note "Checking 'cp --reflink=$mode'"
+
+ # Create a new file and immediately copy it.
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$RECORDSIZE count=$SRC_SIZE
+
+ if [[ "$mode" == "always" ]]; then
+ log_mustnot cp --reflink=$mode $SRC_FILE $DST_FILE
+ log_must ls -l $CP_TESTDIR
+ else
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ fi
+ log_must rm -f $DST_FILE
+
+ # Append to an existing file and immediately copy it.
+ sync_pool $TESTPOOL
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$RECORDSIZE seek=$SRC_SIZE \
+ count=1 conv=notrunc
+ if [[ "$mode" == "always" ]]; then
+ log_mustnot cp --reflink=$mode $SRC_FILE $DST_FILE
+ log_must ls -l $CP_TESTDIR
+ else
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ fi
+ log_must rm -f $DST_FILE
+
+ # Overwrite a random range of an existing file and immediately copy it.
+ sync_pool $TESTPOOL
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$((RECORDSIZE / 2)) \
+ seek=$(($RANDOM % $SRC_SIZE)) count=$((1 + $RANDOM % 16)) conv=notrunc
+ if [[ "$mode" == "always" ]]; then
+ log_mustnot cp --reflink=$mode $SRC_FILE $DST_FILE
+ log_must ls -l $CP_TESTDIR
+ else
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ fi
+ log_must rm -f $SRC_FILE $DST_FILE
+done
+
+# Wait on dirty blocks (zfs_bclone_wait_dirty=1)
+log_must set_tunable32 BCLONE_WAIT_DIRTY 1
+
+for mode in "never" "auto" "always"; do
+ log_note "Checking 'cp --reflink=$mode'"
+
+ # Create a new file and immediately copy it.
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$RECORDSIZE count=$SRC_SIZE
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ log_must rm -f $DST_FILE
+
+ # Append to an existing file and immediately copy it.
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$RECORDSIZE seek=$SRC_SIZE \
+ count=1 conv=notrunc
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ log_must rm -f $DST_FILE
+
+ # Overwrite a random range of an existing file and immediately copy it.
+ log_must dd if=/dev/urandom of=$SRC_FILE bs=$((RECORDSIZE / 2)) \
+ seek=$(($RANDOM % $SRC_SIZE)) count=$((1 + $RANDOM % 16)) conv=notrunc
+ log_must cp --reflink=$mode $SRC_FILE $DST_FILE
+ verify_copy $SRC_FILE $DST_FILE
+ log_must rm -f $SRC_FILE $DST_FILE
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh b/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh
new file mode 100755
index 000000000000..43bb8ab572d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh
@@ -0,0 +1,73 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+
+#
+# Copyright (c) 2023 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# https://github.com/openzfs/zfs/issues/15526 identified a dirty dnode
+# SEEK_HOLE/SEEK_DATA bug. https://github.com/openzfs/zfs/pull/15571
+# fixed the bug, and was backported to 2.1.14 and 2.2.2.
+#
+# This test is to ensure that the bug, as understood, will not recur.
+#
+# STRATEGY:
+#
+# 1. Run the 'seekflood' binary, for creation of files with timing
+# characteristics that can trigger #15526.
+# 2. A single run is not always a trigger, so run repeatedly.
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf /$TESTDIR/cp_stress
+}
+
+log_assert "Run the 'seekflood' binary repeatedly to try to trigger #15526"
+
+log_onexit cleanup
+
+log_must mkdir /$TESTPOOL/cp_stress
+
+MYPWD="$PWD"
+cd /$TESTPOOL/cp_stress
+CPUS=$(get_num_cpus)
+
+if is_freebsd ; then
+ # 'seekflood' takes longer on FreeBSD and can timeout the test
+ RUNS=3
+else
+ RUNS=10
+fi
+
+for i in $(seq 1 $RUNS) ; do
+ # Each run takes around 12 seconds.
+ log_must $STF_SUITE/tests/functional/cp_files/seekflood 2000 $CPUS
+done
+cd "$MYPWD"
+
+log_pass "No corruption detected"
diff --git a/tests/zfs-tests/tests/functional/cp_files/seekflood.c b/tests/zfs-tests/tests/functional/cp_files/seekflood.c
new file mode 100644
index 000000000000..02c2c8e6eca5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/seekflood.c
@@ -0,0 +1,180 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#define DATASIZE (4096)
+char data[DATASIZE];
+
+static int
+_open_file(int n, int wr)
+{
+ char buf[256];
+ int fd;
+
+ snprintf(buf, sizeof (buf), "testdata_%d_%d", getpid(), n);
+
+ if ((fd = open(buf, wr ? (O_WRONLY | O_CREAT) : O_RDONLY,
+ wr ? (S_IRUSR | S_IWUSR) : 0)) < 0) {
+ fprintf(stderr, "Error: open '%s' (%s): %s\n",
+ buf, wr ? "write" : "read", strerror(errno));
+ exit(1);
+ }
+
+ return (fd);
+}
+
+static void
+_write_file(int n, int fd)
+{
+ /* write a big ball of stuff */
+ ssize_t nwr = write(fd, data, DATASIZE);
+ if (nwr < 0) {
+ fprintf(stderr, "Error: write '%d_%d': %s\n",
+ getpid(), n, strerror(errno));
+ exit(1);
+ } else if (nwr < DATASIZE) {
+ fprintf(stderr, "Error: write '%d_%d': short write\n", getpid(),
+ n);
+ exit(1);
+ }
+}
+
+static int
+_seek_file(int n, int fd)
+{
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "Error: fstat '%d_%d': %s\n", getpid(), n,
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * A zero-sized file correctly has no data, so seeking the file is
+ * pointless.
+ */
+ if (st.st_size == 0)
+ return (0);
+
+ /* size is real, and we only write, so SEEK_DATA must find something */
+ if (lseek(fd, 0, SEEK_DATA) < 0) {
+ if (errno == ENXIO)
+ return (1);
+ fprintf(stderr, "Error: lseek '%d_%d': %s\n",
+ getpid(), n, strerror(errno));
+ exit(2);
+ }
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int nfiles = 0;
+ int nthreads = 0;
+
+ if (argc < 3 || (nfiles = atoi(argv[1])) == 0 ||
+ (nthreads = atoi(argv[2])) == 0) {
+ printf("usage: seekflood <nfiles> <threads>\n");
+ exit(1);
+ }
+
+ memset(data, 0x5a, DATASIZE);
+
+ /* fork off some flood threads */
+ for (int i = 0; i < nthreads; i++) {
+ if (!fork()) {
+ /* thread main */
+
+ /* create zero file */
+ int fd = _open_file(0, 1);
+ _write_file(0, fd);
+ close(fd);
+
+ int count = 0;
+
+ int h = 0, i, j, rfd, wfd;
+ for (i = 0; i < nfiles; i += 2, h++) {
+ j = i+1;
+
+ /* seek h, write i */
+ rfd = _open_file(h, 0);
+ wfd = _open_file(i, 1);
+ count += _seek_file(h, rfd);
+ _write_file(i, wfd);
+ close(rfd);
+ close(wfd);
+
+ /* seek i, write j */
+ rfd = _open_file(i, 0);
+ wfd = _open_file(j, 1);
+ count += _seek_file(i, rfd);
+ _write_file(j, wfd);
+ close(rfd);
+ close(wfd);
+ }
+
+ /* return count of failed seeks to parent */
+ exit(count < 256 ? count : 255);
+ }
+ }
+
+ /* wait for threads, take their seek fail counts from exit code */
+ int count = 0, crashed = 0;
+ for (int i = 0; i < nthreads; i++) {
+ int wstatus;
+ wait(&wstatus);
+ if (WIFEXITED(wstatus))
+ count += WEXITSTATUS(wstatus);
+ else
+ crashed++;
+ }
+
+ if (crashed) {
+ fprintf(stderr, "Error: child crashed; test failed\n");
+ exit(1);
+ }
+
+ if (count) {
+ fprintf(stderr, "Error: %d seek failures; test failed\n",
+ count);
+ exit(1);
+ }
+
+ exit(0);
+}
diff --git a/tests/zfs-tests/tests/functional/cp_files/setup.ksh b/tests/zfs-tests/tests/functional/cp_files/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/cp_files/setup.ksh
+++ b/tests/zfs-tests/tests/functional/cp_files/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/crtime/cleanup.ksh b/tests/zfs-tests/tests/functional/crtime/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/crtime/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/crtime/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/crtime/crtime_001_pos.ksh b/tests/zfs-tests/tests/functional/crtime/crtime_001_pos.ksh
index 4f9810553fa6..b2d0e7378652 100755
--- a/tests/zfs-tests/tests/functional/crtime/crtime_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/crtime/crtime_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/crtime/setup.ksh b/tests/zfs-tests/tests/functional/crtime/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/crtime/setup.ksh
+++ b/tests/zfs-tests/tests/functional/crtime/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/ctime/cleanup.ksh b/tests/zfs-tests/tests/functional/ctime/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/ctime/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/ctime/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh
index 035785772db4..6791067ff72f 100755
--- a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/ctime/setup.ksh b/tests/zfs-tests/tests/functional/ctime/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/ctime/setup.ksh
+++ b/tests/zfs-tests/tests/functional/ctime/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman.cfg b/tests/zfs-tests/tests/functional/deadman/deadman.cfg
index e767f3dd5a98..96dc06b78675 100644
--- a/tests/zfs-tests/tests/functional/deadman/deadman.cfg
+++ b/tests/zfs-tests/tests/functional/deadman/deadman.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman_ratelimit.ksh b/tests/zfs-tests/tests/functional/deadman/deadman_ratelimit.ksh
index 7c8fb08b7e01..4dd4c5b9a76c 100755
--- a/tests/zfs-tests/tests/functional/deadman/deadman_ratelimit.ksh
+++ b/tests/zfs-tests/tests/functional/deadman/deadman_ratelimit.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh b/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh
index 7b18ebdcb859..34a8821725a6 100755
--- a/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh
+++ b/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh b/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh
index f0774c4b29d9..592399be0e80 100755
--- a/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh
+++ b/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/cleanup.ksh b/tests/zfs-tests/tests/functional/delegate/cleanup.ksh
index 1951c00e2cf3..173a3ef2e136 100755
--- a/tests/zfs-tests/tests/functional/delegate/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/delegate.cfg b/tests/zfs-tests/tests/functional/delegate/delegate.cfg
index a9a46281b185..d78896fb0174 100644
--- a/tests/zfs-tests/tests/functional/delegate/delegate.cfg
+++ b/tests/zfs-tests/tests/functional/delegate/delegate.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
index 90045f0b3e55..5ddb6ca2ddc8 100644
--- a/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
+++ b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -861,7 +861,7 @@ function verify_fs_mount
fi
if ! ismounted $fs ; then
- log_must zfs set mountpoint=$newmntpt $fs
+ log_must zfs set -u mountpoint=$newmntpt $fs
log_must rm -rf $newmntpt
log_must mkdir $newmntpt
@@ -878,7 +878,7 @@ function verify_fs_mount
fi
log_must zfs umount $fs
log_must rm -rf $newmntpt
- log_must zfs set mountpoint=$mntpt $fs
+ log_must zfs set -u mountpoint=$mntpt $fs
fi
return 0
diff --git a/tests/zfs-tests/tests/functional/delegate/setup.ksh b/tests/zfs-tests/tests/functional/delegate/setup.ksh
index d783b417346a..dd2822442bd1 100755
--- a/tests/zfs-tests/tests/functional/delegate/setup.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh
index 22e52ccc90b7..4324e3f4cbf3 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh
index fc603eae19dc..9045f316ca81 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh
index d8eb58ae1d65..34a26cfc0ca4 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh
index 1462f5ebe984..f90cdd8aa5a9 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh
index 3feb598c4ced..d8e7b56021f7 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh
index 2fc05dee907a..a4e96adf088e 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh
index f3213254b97a..8855fa48e3a4 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh
index b0e1df32a64d..be187475e937 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh
index a6f12244ce2f..9b7995f651df 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh
index 3a8ef5e6251b..549928697edd 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh
index d4203a814341..44a98dde5ba2 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh
index fd95db92e049..dac66c0318bd 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh
index 178d250ca529..5d64880d030a 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh
index ea1de97614f3..471c5645bced 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh
index 35eb9a961ebc..98af7fba226f 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh
index d41d76bd0950..7e35d4cc38ec 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh
index a97f500ea98e..59bc6cc7d6de 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh
index 2bba43de9d14..5521eccebfd6 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh
index b1a221be0bd9..a25f60b41d0b 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh
index a8bd5ebcb6b4..1cda9cef9fb1 100755
--- a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/cleanup.ksh b/tests/zfs-tests/tests/functional/devices/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/devices/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/devices/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/devices.cfg b/tests/zfs-tests/tests/functional/devices/devices.cfg
index ba3c36ae8c4a..6024834aa3f6 100644
--- a/tests/zfs-tests/tests/functional/devices/devices.cfg
+++ b/tests/zfs-tests/tests/functional/devices/devices.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh b/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh
index 2f2802bc65a3..d130a3d0362d 100755
--- a/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh b/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh
index a768c4aa6b34..1cc7b2bd26eb 100755
--- a/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh b/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh
index 1fcd67409c11..909ca9c80d4b 100755
--- a/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/devices_common.kshlib b/tests/zfs-tests/tests/functional/devices/devices_common.kshlib
index fa7fdbecf5fd..800c565bfe67 100644
--- a/tests/zfs-tests/tests/functional/devices/devices_common.kshlib
+++ b/tests/zfs-tests/tests/functional/devices/devices_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/devices/setup.ksh b/tests/zfs-tests/tests/functional/devices/setup.ksh
index ee6cf83acb9e..c464156ceb60 100755
--- a/tests/zfs-tests/tests/functional/devices/setup.ksh
+++ b/tests/zfs-tests/tests/functional/devices/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh b/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/dos_attributes/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh b/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh
index c36c0183315e..2c99a4049c67 100755
--- a/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh
+++ b/tests/zfs-tests/tests/functional/dos_attributes/read_dos_attrs_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh b/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh
+++ b/tests/zfs-tests/tests/functional/dos_attributes/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh b/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh
index 9d66cd357599..4a7fb747f930 100755
--- a/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh
+++ b/tests/zfs-tests/tests/functional/dos_attributes/write_dos_attrs_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/cleanup.ksh b/tests/zfs-tests/tests/functional/events/cleanup.ksh
index 72570d9288fd..669b8ae99456 100755
--- a/tests/zfs-tests/tests/functional/events/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/events/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -26,8 +26,10 @@
. $STF_SUITE/include/libtest.shlib
+zed_stop
+
zed_cleanup all-debug.sh all-syslog.sh all-dumpfds
-zed_stop
+zed_events_drain
default_cleanup
diff --git a/tests/zfs-tests/tests/functional/events/events.cfg b/tests/zfs-tests/tests/functional/events/events.cfg
index 27046c1b0c6b..5dbdb3074f31 100644
--- a/tests/zfs-tests/tests/functional/events/events.cfg
+++ b/tests/zfs-tests/tests/functional/events/events.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/events_001_pos.ksh b/tests/zfs-tests/tests/functional/events/events_001_pos.ksh
index 189cf435e88e..b509a44606f0 100755
--- a/tests/zfs-tests/tests/functional/events/events_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/events/events_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/events_002_pos.ksh b/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
index 42088fc0905f..e355b8977378 100755
--- a/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/events_common.kshlib b/tests/zfs-tests/tests/functional/events/events_common.kshlib
index 73bf4cf357b5..7a0b032c3b2f 100644
--- a/tests/zfs-tests/tests/functional/events/events_common.kshlib
+++ b/tests/zfs-tests/tests/functional/events/events_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/setup.ksh b/tests/zfs-tests/tests/functional/events/setup.ksh
index 2f81d16b1814..0f058b8fe18c 100755
--- a/tests/zfs-tests/tests/functional/events/setup.ksh
+++ b/tests/zfs-tests/tests/functional/events/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh b/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh
new file mode 100755
index 000000000000..5aae3d034660
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh
@@ -0,0 +1,158 @@
+#!/bin/ksh -p
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+
+# DESCRIPTION:
+# Verify that vdev properties, checksum_n and checksum_t, work with ZED.
+#
+# STRATEGY:
+# 1. Create a pool with single vdev
+# 2. Set checksum_n/checksum_t to non-default values
+# 3. Inject checksum errors
+# 4. Verify that ZED degrades vdev
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+MOUNTDIR="$TEST_BASE_DIR/checksum_mount"
+FILEPATH="$MOUNTDIR/checksum_file"
+VDEV="$TEST_BASE_DIR/vdevfile.$$"
+POOL="checksum_pool"
+FILESIZE="10M"
+
+function cleanup
+{
+ log_must zed_stop
+
+ log_must zinject -c all
+ if poolexists $POOL ; then
+ destroy_pool $POOL
+ fi
+ log_must rm -fd $VDEV $MOUNTDIR
+}
+
+log_onexit cleanup
+
+log_assert "Test ZED checksum_N and checksum_T configurability"
+
+function do_setup
+{
+ log_must zpool create -f -m $MOUNTDIR $POOL $VDEV
+ log_must zpool events -c
+ log_must truncate -s 0 $ZED_DEBUG_LOG
+ log_must zfs set compression=off $POOL
+ log_must zfs set primarycache=none $POOL
+ log_must zfs set recordsize=512 $POOL
+}
+
+function do_clean
+{
+ log_must zinject -c all
+ log_must zpool destroy $POOL
+}
+
+function must_degrade
+{
+ log_must wait_vdev_state $POOL $VDEV "DEGRADED" 60
+}
+
+function mustnot_degrade
+{
+ log_must file_wait $ZED_DEBUG_LOG 5
+ log_must wait_vdev_state $POOL $VDEV "ONLINE" 60
+}
+
+# Test default settings of ZED:
+# checksum_n=10
+# checksum_t=600
+# fire 10 events, should degrade.
+function default_degrade
+{
+ do_setup
+
+ log_must mkfile $FILESIZE $FILEPATH
+ log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH
+
+ blk=0
+ for _ in {1..10}; do
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null
+ blk=$((blk+512))
+ done
+
+ must_degrade
+
+ do_clean
+}
+
+# Set checksum_t=1
+# fire 10 events over 2.5 seconds, should not degrade.
+function checksum_t_no_degrade
+{
+ do_setup
+
+ log_must zpool set checksum_t=1 $POOL $VDEV
+ log_must mkfile $FILESIZE $FILEPATH
+ log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH
+
+ blk=0
+ for _ in {1..10}; do
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null
+ blk=$((blk+512))
+ sleep 0.25
+ done
+
+ mustnot_degrade
+
+ do_clean
+}
+
+# Set checksum_n=1
+# fire 1 event, should degrade.
+function checksum_n_degrade
+{
+ do_setup
+
+ log_must zpool set checksum_n=1 $POOL $VDEV
+ log_must mkfile $FILESIZE $FILEPATH
+ log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH
+
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 2>/dev/null
+
+ must_degrade
+
+ do_clean
+}
+
+log_must truncate -s $MINVDEVSIZE $VDEV
+log_must mkdir -p $MOUNTDIR
+
+log_must zed_start
+default_degrade
+checksum_n_degrade
+checksum_t_no_degrade
+
+log_pass "Test ZED checksum_N and checksum_T configurability"
diff --git a/tests/zfs-tests/tests/functional/events/zed_cksum_reported.ksh b/tests/zfs-tests/tests/functional/events/zed_cksum_reported.ksh
new file mode 100755
index 000000000000..78acd76c2eeb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_cksum_reported.ksh
@@ -0,0 +1,124 @@
+#!/bin/ksh -p
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+# This software was developed by Rob Wing <rob.wing@klarasystems.com>
+# under sponsorship from Seagate Technology LLC and Klara Inc.
+
+# DESCRIPTION:
+# Verify that checksum errors are accurately reported to ZED
+#
+# STRATEGY:
+# 1. Create a mirrored/raidz pool
+# 2. Inject checksum error
+# 3. Verify checksum error count reported to ZED is not zero
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+MOUNTDIR="$TEST_BASE_DIR/checksum_mount"
+FILEPATH="$MOUNTDIR/checksum_file"
+VDEV="$TEST_BASE_DIR/vdevfile.$$"
+VDEV1="$TEST_BASE_DIR/vdevfile1.$$"
+POOL="checksum_pool"
+FILESIZE="10M"
+
+function cleanup
+{
+ log_must zed_stop
+
+ log_must zinject -c all
+ if poolexists $POOL ; then
+ destroy_pool $POOL
+ fi
+ log_must rm -fd $VDEV $MOUNTDIR
+}
+log_onexit cleanup
+
+log_assert "Test reported checksum errors to ZED"
+
+function setup_pool
+{
+ type="$1"
+
+ log_must zpool create -f -m $MOUNTDIR $POOL $type $VDEV $VDEV1
+ log_must zpool events -c
+ log_must truncate -s 0 $ZED_DEBUG_LOG
+ log_must zfs set compression=off $POOL
+ log_must zfs set primarycache=none $POOL
+}
+
+function do_clean
+{
+ log_must zinject -c all
+ log_must zpool destroy $POOL
+}
+
+function do_checksum_error
+{
+ log_must mkfile $FILESIZE $FILEPATH
+ log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH
+
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 2>/dev/null
+
+ log_must file_wait_event $ZED_DEBUG_LOG "ereport.fs.zfs.checksum" 10
+
+ # checksum error as reported from the vdev.
+ zpool_cksum=`zpool get -H -o value checksum_errors $POOL $VDEV`
+
+ # first checksum error reported to ZED.
+ zed_cksum=$(awk '/ZEVENT_CLASS=ereport.fs.zfs.checksum/, \
+ /ZEVENT_VDEV_CKSUM_ERRORS=/ { \
+ if ($1 ~ "ZEVENT_VDEV_CKSUM_ERRORS") \
+ { print $0; exit } }' $ZED_DEBUG_LOG)
+
+ log_must [ $zpool_cksum -gt 0 ]
+
+ log_mustnot [ "$zed_cksum" = "ZEVENT_VDEV_CKSUM_ERRORS=0" ]
+
+ log_must [ "$zed_cksum" = "ZEVENT_VDEV_CKSUM_ERRORS=1" ]
+}
+
+# Set checksum_n=1
+# fire 1 event, should degrade.
+function checksum_error
+{
+ type=$1
+
+ setup_pool $type
+ do_checksum_error
+ do_clean
+}
+
+log_must truncate -s $MINVDEVSIZE $VDEV
+log_must truncate -s $MINVDEVSIZE $VDEV1
+log_must mkdir -p $MOUNTDIR
+
+log_must zed_start
+checksum_error mirror
+checksum_error raidz
+
+log_pass "Test reported checksum errors to ZED"
diff --git a/tests/zfs-tests/tests/functional/events/zed_fd_spill.ksh b/tests/zfs-tests/tests/functional/events/zed_fd_spill.ksh
index d70dd0c7b445..4803f0f3de7c 100755
--- a/tests/zfs-tests/tests/functional/events/zed_fd_spill.ksh
+++ b/tests/zfs-tests/tests/functional/events/zed_fd_spill.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/zed_io_config.ksh b/tests/zfs-tests/tests/functional/events/zed_io_config.ksh
new file mode 100755
index 000000000000..637f979fe8d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_io_config.ksh
@@ -0,0 +1,150 @@
+#!/bin/ksh -p
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, Klara Inc.
+#
+
+# DESCRIPTION:
+# Verify that vdev properties, io_n and io_t, work with ZED.
+#
+# STRATEGY:
+# 1. Create a mirrored pool.
+# 3. Set io_n/io_t to non-default values
+# 3. Inject io errors
+# 4. Verify that ZED degrades vdev
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+MOUNTDIR="$TEST_BASE_DIR/io_mount"
+FILEPATH="$MOUNTDIR/io_file"
+VDEV="$TEST_BASE_DIR/vdevfile.$$"
+VDEV1="$TEST_BASE_DIR/vdevfile1.$$"
+POOL="io_pool"
+
+function cleanup
+{
+ log_must zed_stop
+
+ log_must zinject -c all
+ if poolexists $POOL ; then
+ destroy_pool $POOL
+ fi
+ log_must rm -fd $VDEV $VDEV1 $MOUNTDIR
+ log_must set_tunable32 PREFETCH_DISABLE $zfsprefetch
+}
+log_onexit cleanup
+
+log_assert "Test ZED io_n and io_t configurability"
+
+zfsprefetch=$(get_tunable PREFETCH_DISABLE)
+log_must set_tunable32 PREFETCH_DISABLE 1
+
+function setup_pool
+{
+ log_must zpool create -f -m $MOUNTDIR $POOL mirror $VDEV $VDEV1
+ log_must zpool events -c
+ log_must truncate -s 0 $ZED_DEBUG_LOG
+ log_must zfs set compression=off $POOL
+ log_must zfs set primarycache=none $POOL
+ log_must zfs set recordsize=512 $POOL
+}
+
+function do_clean
+{
+ log_must zinject -c all
+ log_must zpool destroy $POOL
+}
+
+# Test default ZED settings:
+# io_n=10 (events)
+# io_t=600 (seconds)
+# fire 10 events over 2.5 seconds, should degrade.
+function default_degrade
+{
+ setup_pool
+
+ log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64
+ log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL
+
+ blk=0
+ for _ in {1..10}; do
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null
+ blk=$((blk+512))
+ sleep 0.25
+ done
+
+ log_must wait_vdev_state $POOL $VDEV "FAULTED" 60
+ do_clean
+}
+
+# set io_n=1
+# fire 1 event, should degrade
+function io_n_degrade
+{
+ setup_pool
+
+ log_must zpool set io_n=1 $POOL $VDEV
+ log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64
+ log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL
+
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 2>/dev/null
+
+ log_must wait_vdev_state $POOL $VDEV "FAULTED" 60
+ do_clean
+}
+
+# set io_t=1
+# fire 10 events over 2.5 seconds, should not degrade
+function io_t_nodegrade
+{
+ setup_pool
+
+ log_must zpool set io_t=1 $POOL $VDEV
+ log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64
+ log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL
+
+ blk=0
+ for _ in {1..10}; do
+ dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null
+ blk=$((blk+512))
+ sleep 0.25
+ done
+
+ log_must file_wait $ZED_DEBUG_LOG 30
+ log_must wait_vdev_state $POOL $VDEV "ONLINE" 1
+
+ do_clean
+}
+
+log_must truncate -s $MINVDEVSIZE $VDEV
+log_must truncate -s $MINVDEVSIZE $VDEV1
+log_must mkdir -p $MOUNTDIR
+
+log_must zed_start
+default_degrade
+io_n_degrade
+io_t_nodegrade
+
+log_pass "Test ZED io_n and io_t configurability"
diff --git a/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh b/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh
index 0bef0ef1f96b..766468b5660d 100755
--- a/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh
+++ b/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/events/zed_slow_io.ksh b/tests/zfs-tests/tests/functional/events/zed_slow_io.ksh
new file mode 100755
index 000000000000..d9fabb2c3bc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_slow_io.ksh
@@ -0,0 +1,205 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+# DESCRIPTION:
+# Verify that vdev properties, slow_io_n and slow_io_t, work with ZED.
+#
+# STRATEGY:
+# 1. Create a pool with single vdev
+# 2. Set slow_io_n/slow_io_t to non-default values
+# 3. Inject slow io errors
+# 4. Verify that ZED degrades vdev
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+TESTDIR="$TEST_BASE_DIR/zed_slow_io"
+VDEV="$TEST_BASE_DIR/vdevfile.$$"
+TESTPOOL="slow_io_pool"
+FILEPATH="$TESTDIR/slow_io.testfile"
+
+OLD_SLOW_IO=$(get_tunable ZIO_SLOW_IO_MS)
+OLD_SLOW_IO_EVENTS=$(get_tunable SLOW_IO_EVENTS_PER_SECOND)
+
+verify_runnable "both"
+
+function do_setup
+{
+ log_must truncate -s 1G $VDEV
+ default_setup_noexit $VDEV
+ zed_events_drain
+ log_must zfs set compression=off $TESTPOOL
+ log_must zfs set primarycache=none $TESTPOOL
+ log_must zfs set prefetch=none $TESTPOOL
+ log_must zfs set recordsize=512 $TESTPOOL
+ for i in {1..10}; do
+ dd if=/dev/urandom of=${FILEPATH}$i bs=512 count=1 2>/dev/null
+ done
+ zpool sync
+}
+
+# intermediate cleanup
+function do_clean
+{
+ log_must zinject -c all
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $VDEV
+}
+
+# final cleanup
+function cleanup
+{
+ log_must zinject -c all
+
+ # if pool still exists then something failed so log additional info
+ if poolexists $TESTPOOL ; then
+ log_note "$(zpool status -s $TESTPOOL)"
+ echo "=================== zed log search ==================="
+ grep "Diagnosis Engine" $ZEDLET_DIR/zed.log
+ destroy_pool $TESTPOOL
+ fi
+ log_must zed_stop
+
+ log_must rm -f $VDEV
+
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
+}
+
+function start_slow_io
+{
+ zpool sync
+ log_must set_tunable64 ZIO_SLOW_IO_MS 10
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND 1000
+
+ log_must zinject -d $VDEV -D10:1 -T read $TESTPOOL
+ zpool sync
+}
+
+function stop_slow_io
+{
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
+
+ log_must zinject -c all
+}
+
+# Test default ZED settings:
+# inject 10 events over 2.5 seconds, should not degrade.
+function default_degrade
+{
+ do_setup
+
+ start_slow_io
+ for i in {1..10}; do
+ dd if=${FILEPATH}$i of=/dev/null count=1 bs=512 2>/dev/null
+ sleep 0.25
+ done
+ stop_slow_io
+ log_note "$(zpool status -s $TESTPOOL)"
+
+ # give slow ZED a chance to process the delay events
+ sleep 18
+ log_note "$(zpool status -s $TESTPOOL)"
+
+ degrades=$(grep "zpool_vdev_degrade" $ZEDLET_DIR/zed.log | wc -l)
+ log_note $degrades vdev degrades in ZED log
+ [ $degrades -eq "0" ] || \
+ log_fail "expecting no degrade events, found $degrades"
+
+ do_clean
+}
+
+# change slow_io_n, slow_io_t to 5 events in 60 seconds
+# fire more than 5 events, should degrade
+function slow_io_degrade
+{
+ do_setup
+
+ zpool set slow_io_n=5 $TESTPOOL $VDEV
+ zpool set slow_io_t=60 $TESTPOOL $VDEV
+
+ start_slow_io
+ for i in {1..16}; do
+ dd if=${FILEPATH}$i of=/dev/null count=1 bs=512 2>/dev/null
+ sleep 0.5
+ done
+ stop_slow_io
+ zpool sync
+
+ #
+ # wait up to 60 seconds for kernel to produce at least 5 delay events
+ #
+ typeset -i i=0
+ typeset -i events=0
+ while [[ $i -lt 60 ]]; do
+ events=$(zpool events | grep "ereport\.fs\.zfs.delay" | wc -l)
+ [[ $events -ge "5" ]] && break
+ i=$((i+1))
+ sleep 1
+ done
+ log_note "$events delay events found"
+
+ if [[ $events -ge "5" ]]; then
+ log_must wait_vdev_state $TESTPOOL $VDEV "DEGRADED" 10
+ fi
+
+ do_clean
+}
+
+# change slow_io_n, slow_io_t to 10 events in 1 second
+# inject events spaced 0.5 seconds apart, should not degrade
+function slow_io_no_degrade
+{
+ do_setup
+
+ zpool set slow_io_n=10 $TESTPOOL $VDEV
+ zpool set slow_io_t=1 $TESTPOOL $VDEV
+
+ start_slow_io
+ for i in {1..16}; do
+ dd if=${FILEPATH}$i of=/dev/null count=1 bs=512 2>/dev/null
+ sleep 0.5
+ done
+ stop_slow_io
+ zpool sync
+
+ log_mustnot wait_vdev_state $TESTPOOL $VDEV "DEGRADED" 45
+
+ do_clean
+}
+
+log_assert "Test ZED slow io configurability"
+log_onexit cleanup
+
+log_must zed_events_drain
+log_must zed_start
+
+default_degrade
+slow_io_degrade
+slow_io_no_degrade
+
+log_pass "Test ZED slow io configurability"
diff --git a/tests/zfs-tests/tests/functional/events/zed_slow_io_many_vdevs.ksh b/tests/zfs-tests/tests/functional/events/zed_slow_io_many_vdevs.ksh
new file mode 100755
index 000000000000..3357ae2e3510
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_slow_io_many_vdevs.ksh
@@ -0,0 +1,177 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023, Klara Inc.
+#
+
+# DESCRIPTION:
+# Verify that delay events from multiple vdevs doesnt degrade
+#
+# STRATEGY:
+# 1. Create a pool with a 3 disk raidz vdev
+# 2. Inject slow io errors
+# 3. Verify that ZED detects slow I/Os but doesn't degrade any vdevs
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+TESTDIR="$TEST_BASE_DIR/zed_slow_io"
+VDEV1="$TEST_BASE_DIR/vdevfile1.$$"
+VDEV2="$TEST_BASE_DIR/vdevfile2.$$"
+VDEV3="$TEST_BASE_DIR/vdevfile3.$$"
+VDEV4="$TEST_BASE_DIR/vdevfile4.$$"
+VDEVS="$VDEV1 $VDEV2 $VDEV3 $VDEV4"
+TESTPOOL="slow_io_pool"
+FILEPATH="$TESTDIR/slow_io.testfile"
+
+OLD_SLOW_IO=$(get_tunable ZIO_SLOW_IO_MS)
+OLD_SLOW_IO_EVENTS=$(get_tunable SLOW_IO_EVENTS_PER_SECOND)
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+
+ # if pool still exists then something failed so log additional info
+ if poolexists $TESTPOOL ; then
+ log_note "$(zpool status -s $TESTPOOL)"
+ echo "=================== zed log search ==================="
+ grep "Diagnosis Engine" $ZEDLET_DIR/zed.log
+ destroy_pool $TESTPOOL
+ fi
+ log_must zed_stop
+
+ log_must rm -f $VDEVS
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
+}
+
+function start_slow_io
+{
+ for vdev in $VDEVS
+ do
+ log_must zpool set slow_io_n=4 $TESTPOOL $vdev
+ log_must zpool set slow_io_t=60 $TESTPOOL $vdev
+ done
+ zpool sync
+
+ log_must set_tunable64 ZIO_SLOW_IO_MS 10
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND 1000
+
+ for vdev in $VDEVS
+ do
+ log_must zinject -d $vdev -D10:1 $TESTPOOL
+ done
+ zpool sync
+}
+
+function stop_slow_io
+{
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
+
+ log_must zinject -c all
+}
+
+function multiple_slow_vdevs_test
+{
+ log_must truncate -s 1G $VDEVS
+ default_raidz_setup_noexit $VDEVS
+
+ log_must zpool events -c
+ log_must zfs set compression=off $TESTPOOL
+ log_must zfs set primarycache=none $TESTPOOL
+ log_must zfs set recordsize=4K $TESTPOOL
+
+ log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=20
+ zpool sync
+
+ #
+ # Read the file with slow io injected on the disks
+ # This will cause multiple errors on each disk to trip ZED SERD
+ #
+ # pool: slow_io_pool
+ # state: ONLINE
+ # config:
+ #
+ # NAME STATE READ WRITE CKSUM SLOW
+ # slow_io_pool ONLINE 0 0 0 -
+ # raidz1-0 ONLINE 0 0 0 -
+ # /var/tmp/vdevfile1.499278 ONLINE 0 0 0 113
+ # /var/tmp/vdevfile2.499278 ONLINE 0 0 0 109
+ # /var/tmp/vdevfile3.499278 ONLINE 0 0 0 96
+ # /var/tmp/vdevfile4.499278 ONLINE 0 0 0 109
+ #
+ start_slow_io
+ dd if=$FILEPATH of=/dev/null bs=1M count=20 2>/dev/null
+ stop_slow_io
+
+ # count events available for processing
+ typeset -i i=0
+ typeset -i events=0
+ while [[ $i -lt 60 ]]; do
+ events=$(zpool events | grep "ereport\.fs\.zfs.delay" | wc -l)
+ [[ $events -ge "50" ]] && break
+ i=$((i+1))
+ sleep 1
+ done
+ log_note "$events delay events found"
+ if [[ $events -lt "50" ]]; then
+ log_note "bailing: not enough events to complete the test"
+ destroy_pool $TESTPOOL
+ return
+ fi
+
+ #
+ # give slow ZED a chance to process the delay events
+ #
+ typeset -i i=0
+ typeset -i skips=0
+ while [[ $i -lt 75 ]]; do
+ skips=$(grep "retiring case" \
+ $ZEDLET_DIR/zed.log | wc -l)
+ [[ $skips -gt "0" ]] && break
+ i=$((i+1))
+ sleep 1
+ done
+
+ log_note $skips degrade skips in ZED log after $i seconds
+ [ $skips -gt "0" ] || log_fail "expecting to see skips"
+
+ degrades=$(grep "zpool_vdev_degrade" $ZEDLET_DIR/zed.log | wc -l)
+ log_note $degrades vdev degrades in ZED log
+ [ $degrades -eq "0" ] || \
+ log_fail "expecting no degrade events, found $degrades"
+
+ destroy_pool $TESTPOOL
+}
+
+log_assert "Test ZED slow io across multiple vdevs"
+log_onexit cleanup
+
+log_must zed_events_drain
+log_must zed_start
+multiple_slow_vdevs_test
+
+log_pass "Test ZED slow io across multiple vdevs"
diff --git a/tests/zfs-tests/tests/functional/exec/cleanup.ksh b/tests/zfs-tests/tests/functional/exec/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/exec/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/exec/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh b/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh
index 5de8a79ea30f..097ecd5f49dd 100755
--- a/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh b/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh
index 2082659a3010..5cda647ef14f 100755
--- a/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/exec/setup.ksh b/tests/zfs-tests/tests/functional/exec/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/exec/setup.ksh
+++ b/tests/zfs-tests/tests/functional/exec/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fadvise/cleanup.ksh b/tests/zfs-tests/tests/functional/fadvise/cleanup.ksh
new file mode 100755
index 000000000000..8b5b43a74c16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fadvise/cleanup.ksh
@@ -0,0 +1,28 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+
+#
+# Portions Copyright (c) 2022 Information2 Software, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/fadvise/fadvise_sequential.ksh b/tests/zfs-tests/tests/functional/fadvise/fadvise_sequential.ksh
new file mode 100755
index 000000000000..7b7d1d379ac6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fadvise/fadvise_sequential.ksh
@@ -0,0 +1,80 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Portions Copyright (c) 2022 Information2 Software, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+
+#
+# DESCRIPTION:
+# Test posix_fadvise.
+#
+# STRATEGY:
+# 1. Set primarycache to metadata in order to disable prefetch
+# 2. Write some data to file
+# 3. get data_size field from arcstat
+# 4. call file_fadvise with POSIX_FADV_SEQUENTIAL
+# 5. get data_size field from arcstat again
+# 6. latter data_size should be bigger than former one
+#
+
+# NOTE: if HAVE_FILE_FADVISE is not defined former data_size
+# should less or eaqul to latter one
+
+verify_runnable "global"
+
+FILE=$TESTDIR/$TESTFILE0
+BLKSZ=$(get_prop recordsize $TESTPOOL)
+
+function cleanup
+{
+ log_must zfs set primarycache=all $TESTPOOL
+ [[ -e $TESTDIR ]] && log_must rm -Rf $TESTDIR/*
+}
+
+getstat() {
+ awk -v c="$1" '$1 == c {print $3; exit}' /proc/spl/kstat/zfs/arcstats
+}
+
+log_assert "Ensure fadvise prefetch data"
+
+log_onexit cleanup
+
+log_must zfs set primarycache=metadata $TESTPOOL
+
+log_must file_write -o create -f $FILE -b $BLKSZ -c 1000
+sync_pool $TESTPOOL
+
+data_size1=$(getstat data_size)
+
+log_must file_fadvise -f $FILE -a 2
+sleep 10
+
+data_size2=$(getstat data_size)
+log_note "original data_size is $data_size1, final data_size is $data_size2"
+
+log_must [ $data_size1 -le $data_size2 ]
+
+log_pass "Ensure data could be prefetched"
diff --git a/tests/zfs-tests/tests/functional/fadvise/setup.ksh b/tests/zfs-tests/tests/functional/fadvise/setup.ksh
new file mode 100755
index 000000000000..8ddd73307bb4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fadvise/setup.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+
+#
+# Portions Copyright (c) 2022 Information2 Software, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup_noexit $DISK
+log_pass
diff --git a/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh b/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh
index bdfa6147117b..c99f11a0e87c 100755
--- a/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh
index 7bb020fe5c19..35eb828d6ba6 100755
--- a/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh
+++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
index 92f4552f5bd7..d01017f9e09f 100755
--- a/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
+++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -23,6 +23,7 @@
#
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
# Copyright (c) 2021 by The FreeBSD Foundation.
+# Copyright (c) 2022 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
@@ -35,6 +36,10 @@
# 1. Create a dense file
# 2. Punch an assortment of holes in the file and verify the result.
#
+# Note: We can't compare exact block numbers as reported by du, because
+# different backing stores may allocate different numbers of blocks for
+# the same amount of data.
+#
verify_runnable "global"
@@ -60,27 +65,24 @@ function cleanup
[[ -e $TESTDIR ]] && log_must rm -f $FILE
}
-function check_reported_size
+function get_reported_size
{
- typeset expected_size=$1
-
- if ! [ -e "${FILE}" ]; then
+ if ! [ -e "$FILE" ]; then
log_fail "$FILE does not exist"
fi
-
- reported_size=$(du "${FILE}" | awk '{print $1}')
- if [ "$reported_size" != "$expected_size" ]; then
- log_fail "Incorrect reported size: $reported_size != $expected_size"
- fi
+
+ sync_pool $TESTPOOL >/dev/null 2>&1
+ du "$FILE" | awk '{print $1}'
}
function check_apparent_size
{
typeset expected_size=$1
- apparent_size=$(stat_size "${FILE}")
+ apparent_size=$(stat_size "$FILE")
if [ "$apparent_size" != "$expected_size" ]; then
- log_fail "Incorrect apparent size: $apparent_size != $expected_size"
+ log_fail \
+ "Incorrect apparent size: $apparent_size != $expected_size"
fi
}
@@ -90,30 +92,36 @@ log_onexit cleanup
# Create a dense file and check it is the correct size.
log_must file_write -o create -f $FILE -b $BLKSZ -c 8
-sync_pool $TESTPOOL
-log_must check_reported_size 1027
+full_size=$(get_reported_size)
-# Punch a hole for the first full block.
+# Punch a hole for the first full block. The reported size should decrease.
log_must punch_hole 0 $BLKSZ $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+one_hole=$(get_reported_size)
+[[ $full_size -gt $one_hole ]] || log_fail \
+ "One hole failure: $full_size -> $one_hole"
-# Partially punch a hole in the second block.
+# Partially punch a hole in the second block. The reported size should
+# remain constant.
log_must punch_hole $BLKSZ $((BLKSZ / 2)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+partial_hole=$(get_reported_size)
+[[ $one_hole -eq $partial_hole ]] || log_fail \
+ "Partial hole failure: $one_hole -> $partial_hole"
-# Punch a hole which overlaps the third and fourth block.
+# Punch a hole which overlaps the third and fourth block. The reported size
+# should remain constant.
log_must punch_hole $(((BLKSZ * 2) + (BLKSZ / 2))) $((BLKSZ)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+overlap_hole=$(get_reported_size)
+[[ $one_hole -eq $overlap_hole ]] || log_fail \
+ "Overlap hole failure: $one_hole -> $overlap_hole"
-# Punch a hole from the fifth block past the end of file. The apparent
-# file size should not change since --keep-size is implied.
+# Punch a hole from the fifth block past the end of file. The reported size
+# should decrease, and the apparent file size should not change since
+# --keep-size is implied.
apparent_size=$(stat_size $FILE)
log_must punch_hole $((BLKSZ * 4)) $((BLKSZ * 10)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 387
+eof_hole=$(get_reported_size)
+[[ $overlap_hole -gt $eof_hole ]] || log_fail \
+ "EOF hole failure: $overlap_hole -> $eof_hole"
log_must check_apparent_size $apparent_size
log_pass "Ensure holes can be punched in files making them sparse"
diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh
index e907b0f5d4c4..47dd06cc0dc3 100755
--- a/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh
+++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -23,6 +23,7 @@
#
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
# Copyright (c) 2021 by The FreeBSD Foundation.
+# Copyright (c) 2022 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
@@ -35,6 +36,10 @@
# 1. Create a dense file
# 2. Zero various ranges in the file and verify the result.
#
+# Note: We can't compare exact block numbers as reported by du, because
+# different backing stores may allocate different numbers of blocks for
+# the same amount of data.
+#
verify_runnable "global"
@@ -50,28 +55,24 @@ function cleanup
[[ -e $TESTDIR ]] && log_must rm -f $FILE
}
-# Helpfully, this function expects kilobytes, and check_apparent_size expects bytes.
-function check_reported_size
+function get_reported_size
{
- typeset expected_size=$1
-
- if ! [ -e "${FILE}" ]; then
+ if ! [ -e "$FILE" ]; then
log_fail "$FILE does not exist"
fi
-
- reported_size=$(du "${FILE}" | awk '{print $1}')
- if [ "$reported_size" != "$expected_size" ]; then
- log_fail "Incorrect reported size: $reported_size != $expected_size"
- fi
+
+ sync_pool $TESTPOOL >/dev/null 2>&1
+ du "$FILE" | awk '{print $1}'
}
function check_apparent_size
{
typeset expected_size=$1
- apparent_size=$(stat_size "${FILE}")
+ apparent_size=$(stat_size "$FILE")
if [ "$apparent_size" != "$expected_size" ]; then
- log_fail "Incorrect apparent size: $apparent_size != $expected_size"
+ log_fail \
+ "Incorrect apparent size: $apparent_size != $expected_size"
fi
}
@@ -82,38 +83,46 @@ log_onexit cleanup
# Create a dense file and check it is the correct size.
log_must file_write -o create -f $FILE -b $BLKSZ -c 8
sync_pool $TESTPOOL
-log_must check_reported_size 1027
+full_size=$(get_reported_size)
-# Zero a range covering the first full block.
+# Zero a range covering the first full block. The reported size should decrease.
log_must zero_range 0 $BLKSZ $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+one_range=$(get_reported_size)
+[[ $full_size -gt $one_range ]] || log_fail \
+ "One range failure: $full_size -> $one_range"
-# Partially zero a range in the second block.
+# Partially zero a range in the second block. The reported size should
+# remain constant.
log_must zero_range $BLKSZ $((BLKSZ / 2)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+partial_range=$(get_reported_size)
+[[ $one_range -eq $partial_range ]] || log_fail \
+ "Partial range failure: $one_range -> $partial_range"
-# Zero range which overlaps the third and fourth block.
+# Zero range which overlaps the third and fourth block. The reported size
+# should remain constant.
log_must zero_range $(((BLKSZ * 2) + (BLKSZ / 2))) $((BLKSZ)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 899
+overlap_range=$(get_reported_size)
+[[ $one_range -eq $overlap_range ]] || log_fail \
+ "Overlap range failure: $one_range -> $overlap_range"
# Zero range from the fifth block past the end of file, with --keep-size.
-# The apparent file size must not change, since we did specify --keep-size.
+# The reported size should decrease, and the apparent file size must not
+# change, since we did specify --keep-size.
apparent_size=$(stat_size $FILE)
log_must fallocate --keep-size --zero-range --offset $((BLKSZ * 4)) --length $((BLKSZ * 10)) "$FILE"
-sync_pool $TESTPOOL
-log_must check_reported_size 387
+eof_range=$(get_reported_size)
+[[ $overlap_range -gt $eof_range ]] || log_fail \
+ "EOF range failure: $overlap_range -> $eof_range"
log_must check_apparent_size $apparent_size
# Zero range from the fifth block past the end of file. The apparent
# file size should change since --keep-size is not implied, unlike
-# with PUNCH_HOLE.
+# with PUNCH_HOLE. The reported size should remain constant.
apparent_size=$(stat_size $FILE)
log_must zero_range $((BLKSZ * 4)) $((BLKSZ * 10)) $FILE
-sync_pool $TESTPOOL
-log_must check_reported_size 387
+eof_range2=$(get_reported_size)
+[[ $eof_range -eq $eof_range2 ]] || log_fail \
+ "Second EOF range failure: $eof_range -> $eof_range2"
log_must check_apparent_size $((BLKSZ * 14))
log_pass "Ensure ranges can be zeroed in files"
diff --git a/tests/zfs-tests/tests/functional/fallocate/setup.ksh b/tests/zfs-tests/tests/functional/fallocate/setup.ksh
index 586ac026aa43..51fa056fd36f 100755
--- a/tests/zfs-tests/tests/functional/fallocate/setup.ksh
+++ b/tests/zfs-tests/tests/functional/fallocate/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
index 17bde9a70636..c0387e1d3235 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
@@ -24,29 +24,28 @@
#
# DESCRIPTION:
-# Testing Fault Management Agent ZED Logic - Physically removed device is
-# made unavail and onlined when reattached
+# Testing Fault Management Agent ZED Logic - Physically detached device is
+# made removed and onlined when reattached
#
# STRATEGY:
# 1. Create a pool
# 2. Simulate physical removal of one device
-# 3. Verify the device is unavailable
+# 3. Verify the device is removed when detached
# 4. Reattach the device
# 5. Verify the device is onlined
# 6. Repeat the same tests with a spare device:
# zed will use the spare to handle the removed data device
# 7. Repeat the same tests again with a faulted spare device:
-# the removed data device should be unavailable
+# the removed data device should be removed
#
# NOTE: the use of 'block_device_wait' throughout the test helps avoid race
# conditions caused by mixing creation/removal events from partitioning the
# disk (zpool create) and events from physically removing it (remove_disk).
#
-# NOTE: the test relies on 'zpool sync' to prompt the kmods to transition a
-# vdev to the unavailable state. The ZED does receive a removal notification
-# but only relies on it to activate a hot spare. Additional work is planned
-# to extend an existing ioctl interface to allow the ZED to transition the
-# vdev in to a removed state.
+# NOTE: the test relies on ZED to transit state to removed on device removed
+# event. The ZED does receive a removal notification but only relies on it to
+# activate a hot spare. Additional work is planned to extend an existing ioctl
+# interface to allow the ZED to transition the vdev in to a removed state.
#
verify_runnable "both"
@@ -103,8 +102,8 @@ do
log_must mkfile 1m $mntpnt/file
sync_pool $TESTPOOL
- # 3. Verify the device is unavailable.
- log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+ # 3. Verify the device is removed.
+ log_must wait_vdev_state $TESTPOOL $removedev "REMOVED"
# 4. Reattach the device
insert_disk $removedev
@@ -122,6 +121,11 @@ done
# the removed data device
for conf in "${poolconfs[@]}"
do
+ # special vdev can not be replaced by a hot spare
+ if [[ $conf = *"special mirror"* ]]; then
+ continue
+ fi
+
# 1. Create a pool with a spare
log_must zpool create -f $TESTPOOL $conf
block_device_wait ${DEV_DSKDIR}/${removedev}
@@ -136,7 +140,7 @@ do
# 3. Verify the device is handled by the spare.
log_must wait_hotspare_state $TESTPOOL $sparedev "INUSE"
- log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+ log_must wait_vdev_state $TESTPOOL $removedev "REMOVED"
# 4. Reattach the device
insert_disk $removedev
@@ -170,8 +174,8 @@ do
log_must mkfile 1m $mntpnt/file
sync_pool $TESTPOOL
- # 4. Verify the device is unavailable
- log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+ # 4. Verify the device is removed
+ log_must wait_vdev_state $TESTPOOL $removedev "REMOVED"
# 5. Reattach the device
insert_disk $removedev
diff --git a/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh
index 3a1a610b8daf..950e80dfc186 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fault/auto_online_002_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_online_002_pos.ksh
index 60185ace34bb..09285b5108ee 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_online_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_online_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh
index 57180cdc1860..ae56ee9919bf 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -34,13 +34,14 @@
# 1. Update /etc/zfs/vdev_id.conf with scsidebug alias for a persistent path.
# This creates keys ID_VDEV and ID_VDEV_PATH and set phys_path="scsidebug".
# 2. Create a pool and set autoreplace=on (auto-replace is opt-in)
-# 3. Export a pool
+# 3. Export the pool
# 4. Wipe and offline the scsi_debug disk
-# 5. Import pool with missing disk
+# 5. Import the pool with missing disk
# 6. Re-online the wiped scsi_debug disk
-# 7. Verify the ZED detects the new unused disk and adds it back to the pool
+# 7. Verify ZED detects the new blank disk and replaces the missing vdev
+# 8. Verify that the scsi_debug disk was re-partitioned
#
-# Creates a raidz1 zpool using persistent disk path names
+# Creates a raidz1 zpool using persistent /dev/disk/by-vdev path names
# (ie not /dev/sdc)
#
# Auto-replace is opt in, and matches by phys_path.
@@ -54,6 +55,7 @@ fi
function cleanup
{
+ zpool status $TESTPOOL
destroy_pool $TESTPOOL
sed -i '/alias scsidebug/d' $VDEVID_CONF
unload_scsi_debug
@@ -82,11 +84,27 @@ log_must zpool create -f $TESTPOOL raidz1 $SD_DEVICE $DISK1 $DISK2 $DISK3
log_must zpool set autoreplace=on $TESTPOOL
# Add some data to the pool
-log_must mkfile $FSIZE /$TESTPOOL/data
+log_must zfs create $TESTPOOL/fs
+log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 Z
log_must zpool export $TESTPOOL
+# Record the partition UUID for later comparison
+part_uuid=$(udevadm info --query=property --property=ID_PART_TABLE_UUID \
+ --value /dev/disk/by-id/$SD_DEVICE_ID)
+[[ -z "$part_uuid" ]] || log_note original disk GPT uuid ${part_uuid}
+
+#
# Wipe and offline the disk
+#
+# Note that it is not enough to zero the disk to expunge the partitions.
+# You also need to inform the kernel (e.g., 'hdparm -z' or 'partprobe').
+#
+# Using partprobe is overkill and hdparm is not as common as wipefs. So
+# we use wipefs which lets the kernel know the partition was removed
+# from the device (i.e., calls BLKRRPART ioctl).
+#
log_must dd if=/dev/zero of=/dev/disk/by-id/$SD_DEVICE_ID bs=1M count=$SDSIZE
+log_must /usr/sbin/wipefs -a /dev/disk/by-id/$SD_DEVICE_ID
remove_disk $SD
block_device_wait
@@ -99,10 +117,24 @@ block_device_wait
insert_disk $SD $SD_HOST
# Wait for the new disk to be online and replaced
-log_must wait_vdev_state $TESTPOOL "scsidebug" "ONLINE" $MAXTIMEOUT
-log_must wait_replacing $TESTPOOL
+log_must wait_vdev_state $TESTPOOL "scsidebug" "ONLINE" 60
+log_must wait_replacing $TESTPOOL 60
# Validate auto-replace was successful
log_must check_state $TESTPOOL "" "ONLINE"
+#
+# Confirm the partition UUID changed so we know the new disk was relabeled
+#
+# Note: some older versions of udevadm don't support "--property" option so
+# we'll # skip this test when it is not supported
+#
+if [ ! -z "$part_uuid" ]; then
+ new_uuid=$(udevadm info --query=property --property=ID_PART_TABLE_UUID \
+ --value /dev/disk/by-id/$SD_DEVICE_ID)
+ log_note new disk GPT uuid ${new_uuid}
+ [[ "$part_uuid" = "$new_uuid" ]] && \
+ log_fail "The new disk was not relabeled as expected"
+fi
+
log_pass "Auto-replace test successful"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh
new file mode 100755
index 000000000000..2259e604317b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh
@@ -0,0 +1,192 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2023 by Klara, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Replace Test.
+# Verifys that auto-replace works with by-id paths.
+#
+# STRATEGY:
+# 1. Update /etc/zfs/vdev_id.conf with scsidebug alias for a persistent path.
+# This creates keys ID_VDEV and ID_VDEV_PATH and set phys_path="scsidebug".
+# 2. Create a pool and set autoreplace=on (auto-replace is opt-in)
+# 3. Export the pool
+# 4. Wipe and offline the scsi_debug disk
+# 5. Import the pool with missing disk
+# 6. Re-online the wiped scsi_debug disk with a new serial number
+# 7. Verify ZED detects the new blank disk and replaces the missing vdev
+# 8. Verify that the scsi_debug disk was re-partitioned
+#
+# Creates a raidz1 zpool using persistent /dev/disk/by-id path names
+#
+# Auto-replace is opt in, and matches by phys_path.
+#
+
+verify_runnable "both"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "Unsupported disks for this test."
+fi
+
+function cleanup
+{
+ zpool status $TESTPOOL
+ destroy_pool $TESTPOOL
+ sed -i '/alias scsidebug/d' $VDEVID_CONF
+ unload_scsi_debug
+}
+
+#
+# Wait until a vdev transitions to its replacement vdev
+#
+# Return 0 when vdev reaches expected state, 1 on timeout.
+#
+# Note: index +2 is to skip over root and raidz-0 vdevs
+#
+function wait_vdev_online # pool index oldguid timeout
+{
+ typeset pool=$1
+ typeset -i index=$2+2
+ typeset guid=$3
+ typeset timeout=${4:-60}
+ typeset -i i=0
+
+ while [[ $i -lt $timeout ]]; do
+ vdev_guids=( $(zpool get -H -o value guid $pool all-vdevs) )
+
+ if [ "${vdev_guids[$index]}" != "${guid}" ]; then
+ log_note "new vdev[$((index-2))]: ${vdev_guids[$index]}, replacing ${guid}"
+ return 0
+ fi
+
+ i=$((i+1))
+ sleep 1
+ done
+
+ return 1
+}
+log_assert "automated auto-replace with by-id paths"
+log_onexit cleanup
+
+load_scsi_debug $SDSIZE $SDHOSTS $SDTGTS $SDLUNS '512b'
+SD=$(get_debug_device)
+SD_DEVICE_ID=$(get_persistent_disk_name $SD)
+SD_HOST=$(get_scsi_host $SD)
+
+# Register vdev_id alias for scsi_debug device to create a persistent path
+echo "alias scsidebug /dev/disk/by-id/$SD_DEVICE_ID" >>$VDEVID_CONF
+block_device_wait
+
+SD_DEVICE=$(udevadm info -q all -n $DEV_DSKDIR/$SD | \
+ awk -F'=' '/ID_VDEV=/ {print $2; exit}')
+[ -z $SD_DEVICE ] && log_fail "vdev rule was not registered properly"
+
+log_must zpool events -c
+log_must zpool create -f $TESTPOOL raidz1 $SD_DEVICE_ID $DISK1 $DISK2 $DISK3
+
+vdev_guid=$(zpool get guid -H -o value $TESTPOOL $SD_DEVICE_ID)
+log_note original vdev guid ${vdev_guid}
+
+# Auto-replace is opt-in so need to set property
+log_must zpool set autoreplace=on $TESTPOOL
+
+# Add some data to the pool
+log_must zfs create $TESTPOOL/fs
+log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 Z
+log_must zpool export $TESTPOOL
+
+# Record the partition UUID for later comparison
+part_uuid=$(udevadm info --query=property --property=ID_PART_TABLE_UUID \
+ --value /dev/disk/by-id/$SD_DEVICE_ID)
+[[ -z "$part_uuid" ]] || log_note original disk GPT uuid ${part_uuid}
+
+#
+# Wipe and offline the disk
+#
+# Note that it is not enough to zero the disk to expunge the partitions.
+# You also need to inform the kernel (e.g., 'hdparm -z' or 'partprobe').
+#
+# Using partprobe is overkill and hdparm is not as common as wipefs. So
+# we use wipefs which lets the kernel know the partition was removed
+# from the device (i.e., calls BLKRRPART ioctl).
+#
+log_must dd if=/dev/zero of=/dev/disk/by-id/$SD_DEVICE_ID bs=1M count=$SDSIZE
+log_must /usr/sbin/wipefs -a /dev/disk/by-id/$SD_DEVICE_ID
+remove_disk $SD
+block_device_wait
+
+# Re-import pool with drive missing
+log_must zpool import $TESTPOOL
+log_must check_state $TESTPOOL "" "DEGRADED"
+block_device_wait
+
+#
+# Online an empty disk in the same physical location, with a different by-id
+# symlink. We use vpd_use_hostno to make sure the underlying serial number
+# changes for the new disk which in turn gives us a different by-id path.
+#
+# The original names were something like:
+# /dev/disk/by-id/scsi-SLinux_scsi_debug_16000-part1
+# /dev/disk/by-id/wwn-0x33333330000007d0-part1
+#
+# This new inserted disk, will have different links like:
+# /dev/disk/by-id/scsi-SLinux_scsi_debug_2000-part1
+# /dev/disk/by-id/wwn-0x0x3333333000003e80 -part1
+#
+echo '0' > /sys/bus/pseudo/drivers/scsi_debug/vpd_use_hostno
+
+insert_disk $SD $SD_HOST
+
+# make sure the physical path points to the same scsi-debug device
+SD_DEVICE_ID=$(get_persistent_disk_name $SD)
+echo "alias scsidebug /dev/disk/by-id/$SD_DEVICE_ID" >>$VDEVID_CONF
+block_device_wait
+
+# Wait for the new disk to be online and replaced
+log_must wait_vdev_online $TESTPOOL 0 $vdev_guid 45
+log_must wait_replacing $TESTPOOL 45
+
+# Validate auto-replace was successful
+log_must check_state $TESTPOOL "" "ONLINE"
+
+#
+# Confirm the partition UUID changed so we know the new disk was relabeled
+#
+# Note: some older versions of udevadm don't support "--property" option so
+# we'll # skip this test when it is not supported
+#
+if [ ! -z "$part_uuid" ]; then
+ new_uuid=$(udevadm info --query=property --property=ID_PART_TABLE_UUID \
+ --value /dev/disk/by-id/$SD_DEVICE_ID)
+ log_note new disk GPT uuid ${new_uuid}
+ [[ "$part_uuid" = "$new_uuid" ]] && \
+ log_fail "The new disk was not relabeled as expected"
+fi
+
+log_pass "automated auto-replace with by-id paths"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh
index e9517bad7131..bd32be9a4ff8 100755
--- a/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh
@@ -73,7 +73,7 @@ for type in "mirror" "raidz" "raidz2"; do
# 4. Inject CHECKSUM ERRORS on read with a zinject error handler
log_must zinject -d $FAULT_FILE -e corrupt -f 50 -T read $TESTPOOL
- log_must cp $TESTFILE /dev/null
+ log_must dd if=$TESTFILE of=/dev/null bs=1M count=64
# 5. Verify the ZED kicks in a hot spare and expected pool/device status
log_note "Wait for ZED to auto-spare"
diff --git a/tests/zfs-tests/tests/functional/fault/cleanup.ksh b/tests/zfs-tests/tests/functional/fault/cleanup.ksh
index 45b94723a543..2959236b59a3 100755
--- a/tests/zfs-tests/tests/functional/fault/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/fault/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -32,5 +32,6 @@ cleanup_devices $DISKS
zed_stop
zed_cleanup resilver_finish-start-scrub.sh
+zed_events_drain
log_pass
diff --git a/tests/zfs-tests/tests/functional/fault/fault.cfg b/tests/zfs-tests/tests/functional/fault/fault.cfg
index 108406e3e171..0cf2b05cce44 100644
--- a/tests/zfs-tests/tests/functional/fault/fault.cfg
+++ b/tests/zfs-tests/tests/functional/fault/fault.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/fault/setup.ksh b/tests/zfs-tests/tests/functional/fault/setup.ksh
index b78ee8ccdc98..61b9206ec1a6 100755
--- a/tests/zfs-tests/tests/functional/fault/setup.ksh
+++ b/tests/zfs-tests/tests/functional/fault/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -28,6 +28,7 @@
verify_runnable "global"
+zed_events_drain
zed_setup resilver_finish-start-scrub.sh
zed_start
diff --git a/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh b/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh
index 4fe00e2c7195..57911aa05ec9 100755
--- a/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh
+++ b/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh
index e0617961ba15..d5c930ecfbb2 100755
--- a/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh
index d275e063b13a..76aa23035dd9 100755
--- a/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh
index 60e481d998a2..9fa5ba6e13c4 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh
index c00b3b6c719a..e4aea2750669 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh
index 9a00ceeb3cef..c0df76624f56 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh
index 20989e1d7741..867382165235 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh
index 2cc587b47879..a77fe10ccf31 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh
index 1d167e3ae59f..8910f375b1c5 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh
index 3727bd5c11d2..a84e38aee87a 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh
index 59364574b165..ac755a338d55 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh
index 71e175171322..00a0d5784cdb 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh
index 0b61e1df2226..457c100ed989 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh
index a9425cca9857..02735d765426 100755
--- a/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/grow/grow.cfg b/tests/zfs-tests/tests/functional/grow/grow.cfg
index 10d15d7546c1..0d78416317c0 100644
--- a/tests/zfs-tests/tests/functional/grow/grow.cfg
+++ b/tests/zfs-tests/tests/functional/grow/grow.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh b/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh
index 9c047223ab39..ae2b261f4efa 100755
--- a/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh b/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh
index 44b38291f0a9..1d0215550145 100755
--- a/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/cleanup.ksh b/tests/zfs-tests/tests/functional/history/cleanup.ksh
index 32ed921ffe76..36e0311a34cb 100755
--- a/tests/zfs-tests/tests/functional/history/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/history/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history.cfg b/tests/zfs-tests/tests/functional/history/history.cfg
index e9200a2b5098..a508a7935684 100644
--- a/tests/zfs-tests/tests/functional/history/history.cfg
+++ b/tests/zfs-tests/tests/functional/history/history.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_001_pos.ksh b/tests/zfs-tests/tests/functional/history/history_001_pos.ksh
index 5b576b8a12aa..7180e9af767d 100755
--- a/tests/zfs-tests/tests/functional/history/history_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_002_pos.ksh b/tests/zfs-tests/tests/functional/history/history_002_pos.ksh
index b431cdc5f144..81f2ffb21731 100755
--- a/tests/zfs-tests/tests/functional/history/history_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_003_pos.ksh b/tests/zfs-tests/tests/functional/history/history_003_pos.ksh
index 1bebd4039746..9f27785d64f9 100755
--- a/tests/zfs-tests/tests/functional/history/history_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_004_pos.ksh b/tests/zfs-tests/tests/functional/history/history_004_pos.ksh
index 8bdc38f26d67..f7ec5df6fd31 100755
--- a/tests/zfs-tests/tests/functional/history/history_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_005_neg.ksh b/tests/zfs-tests/tests/functional/history/history_005_neg.ksh
index 5038af4a7c79..c4d699f39d6c 100755
--- a/tests/zfs-tests/tests/functional/history/history_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_006_neg.ksh b/tests/zfs-tests/tests/functional/history/history_006_neg.ksh
index a1e76e68b802..c8b6404b8c35 100755
--- a/tests/zfs-tests/tests/functional/history/history_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_007_pos.ksh b/tests/zfs-tests/tests/functional/history/history_007_pos.ksh
index 3d785183d094..714db4772aa3 100755
--- a/tests/zfs-tests/tests/functional/history/history_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_008_pos.ksh b/tests/zfs-tests/tests/functional/history/history_008_pos.ksh
index 26f728bb1779..eff313a31aef 100755
--- a/tests/zfs-tests/tests/functional/history/history_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_009_pos.ksh b/tests/zfs-tests/tests/functional/history/history_009_pos.ksh
index cf40df84ec83..be43193dc426 100755
--- a/tests/zfs-tests/tests/functional/history/history_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_010_pos.ksh b/tests/zfs-tests/tests/functional/history/history_010_pos.ksh
index 57a7cb4466d0..d972ba66d17b 100755
--- a/tests/zfs-tests/tests/functional/history/history_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/history/history_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/history_common.kshlib b/tests/zfs-tests/tests/functional/history/history_common.kshlib
index 95f9441bf692..2ee761cea93a 100644
--- a/tests/zfs-tests/tests/functional/history/history_common.kshlib
+++ b/tests/zfs-tests/tests/functional/history/history_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/history/setup.ksh b/tests/zfs-tests/tests/functional/history/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/history/setup.ksh
+++ b/tests/zfs-tests/tests/functional/history/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh b/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh
new file mode 100755
index 000000000000..4895aa23ee4a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/cleanup.ksh
@@ -0,0 +1,25 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg
new file mode 100644
index 000000000000..51998945d0d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount.cfg
@@ -0,0 +1,25 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+export UID1=1000000
+export GID1=1000000
+export UID2=2000000
+export GID2=2000000
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh
new file mode 100755
index 000000000000..e7187935e532
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_001.ksh
@@ -0,0 +1,76 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Test uid and gid of files in idmapped folder are mapped correctly
+#
+#
+# STRATEGY:
+# 1. Create files/folder owned by $UID1 and $GID1 under "idmap_test"
+# 2. Idmap the folder to "idmap_dest"
+# 3. Verify the owner of files/folder under "idmap_dest"
+#
+
+verify_runnable "global"
+
+export WORKDIR=$TESTDIR/idmap_test
+export IDMAPDIR=$TESTDIR/idmap_dest
+
+function cleanup
+{
+ log_must rm -rf $WORKDIR
+ if mountpoint $IDMAPDIR; then
+ log_must umount $IDMAPDIR
+ fi
+ log_must rm -rf $IDMAPDIR
+}
+
+log_onexit cleanup
+
+if ! idmap_util -c $TESTDIR; then
+ log_unsupported "Idmap mount not supported."
+fi
+
+log_must mkdir -p $WORKDIR
+log_must mkdir -p $IDMAPDIR
+log_must touch $WORKDIR/file1
+log_must mkdir $WORKDIR/subdir
+log_must ln -s $WORKDIR/file1 $WORKDIR/file1_sym
+log_must ln $WORKDIR/file1 $WORKDIR/subdir/file1_hard
+log_must touch $WORKDIR/subdir/file2
+log_must chown -R $UID1:$GID1 $WORKDIR
+log_must chown $UID2:$GID2 $WORKDIR/subdir/file2
+
+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR
+
+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/file1)"
+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/file1_sym)"
+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir)"
+log_must test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir/file1_hard)"
+log_mustnot test "$UID2 $GID2" = "$(stat -c '%u %g' $IDMAPDIR/subdir/file2)"
+
+log_pass "Owner verification of entries under idmapped folder is successful."
+
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh
new file mode 100755
index 000000000000..8cba90ea58b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_002.ksh
@@ -0,0 +1,97 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Perform file operations in idmapped folder, check owner in its base.
+#
+#
+# STRATEGY:
+# 1. Create folder "idmap_test"
+# 2. Idmap the folder to "idmap_dest"
+# 3. Do basic file operations in "idmap_dest" folder, verify the owner in
+# the base folder "idmap_test"
+#
+
+verify_runnable "global"
+
+export WORKDIR=$TESTDIR/idmap_test
+export IDMAPDIR=$TESTDIR/idmap_dest
+
+function cleanup
+{
+ log_must rm -rf $IDMAPDIR/*
+ if mountpoint $IDMAPDIR; then
+ log_must umount $IDMAPDIR
+ fi
+ log_must rm -rf $IDMAPDIR $WORKDIR
+}
+
+log_onexit cleanup
+
+if ! idmap_util -c $TESTDIR; then
+ log_unsupported "Idmap mount not supported."
+fi
+
+log_must mkdir -p $WORKDIR
+log_must mkdir -p $IDMAPDIR
+
+log_must chown $UID1:$GID1 $WORKDIR
+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR
+
+SETPRIV="setpriv --reuid $UID2 --regid $GID2 --clear-groups"
+
+log_must $SETPRIV touch $IDMAPDIR/file1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)"
+
+log_must $SETPRIV mv $IDMAPDIR/file1 $IDMAPDIR/file1_renamed
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_renamed)"
+
+log_must $SETPRIV mv $IDMAPDIR/file1_renamed $IDMAPDIR/file1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)"
+
+log_must $SETPRIV mkdir $IDMAPDIR/subdir
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir)"
+
+log_must $SETPRIV ln -s $IDMAPDIR/file1 $IDMAPDIR/file1_sym
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_sym)"
+
+log_must $SETPRIV ln $IDMAPDIR/file1 $IDMAPDIR/subdir/file1_hard
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir/file1_hard)"
+
+log_must $SETPRIV touch $IDMAPDIR/subdir/file2
+log_must $SETPRIV chown $UID2:$GID2 $IDMAPDIR/subdir/file2
+log_mustnot $SETPRIV chown $UID1 $IDMAPDIR/subdir/file2
+
+log_must $SETPRIV cp -r $IDMAPDIR/subdir $IDMAPDIR/subdir1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file2)"
+log_must $SETPRIV rm -rf $IDMAPDIR/subdir1
+
+log_must $SETPRIV cp -rp $IDMAPDIR/subdir $IDMAPDIR/subdir1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file1_hard)"
+log_must $SETPRIV rm -rf $IDMAPDIR/subdir1
+
+log_pass "Owner verification of entries under base folder is successful."
+
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh
new file mode 100755
index 000000000000..1f1a2aec655e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_003.ksh
@@ -0,0 +1,121 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Perform file operations in idmapped folder in user namespace,
+# then check the owner in its base.
+#
+#
+# STRATEGY:
+# 1. Create folder "idmap_test"
+# 2. Idmap the folder to "idmap_dest"
+# 3. Perform file operations in the idmapped folder in the user
+# namespace having the same idmap info as the idmapped mount
+# 4. Verify the owner of entries under the base folder "idmap_test"
+#
+
+verify_runnable "global"
+
+export WORKDIR=$TESTDIR/idmap_test
+export IDMAPDIR=$TESTDIR/idmap_dest
+
+function cleanup
+{
+ kill -TERM ${unshared_pid}
+ log_must rm -rf $IDMAPDIR/*
+ if mountpoint $IDMAPDIR; then
+ log_must umount $IDMAPDIR
+ fi
+ log_must rm -rf $IDMAPDIR $WORKDIR
+}
+
+log_onexit cleanup
+
+if ! idmap_util -c $TESTDIR; then
+ log_unsupported "Idmap mount not supported."
+fi
+
+log_must mkdir -p $WORKDIR
+log_must mkdir -p $IDMAPDIR
+
+log_must chown $UID1:$GID1 $WORKDIR
+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR
+
+# Create a user namespace with the same idmapping
+unshare -Urm echo test
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+unshare -Um /usr/bin/sleep 2h &
+unshared_pid=$!
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+# wait for userns to be ready
+sleep 1
+echo "${UID1} ${UID2} 1" > /proc/$unshared_pid/uid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to uid_map"
+fi
+echo "${GID1} ${GID2} 1" > /proc/$unshared_pid/gid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to gid_map"
+fi
+
+NSENTER="nsenter -t $unshared_pid --all -S ${UID1} -G ${GID1}"
+
+log_must $NSENTER touch $IDMAPDIR/file1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)"
+
+log_must $NSENTER mv $IDMAPDIR/file1 $IDMAPDIR/file1_renamed
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_renamed)"
+
+log_must $NSENTER mv $IDMAPDIR/file1_renamed $IDMAPDIR/file1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1)"
+
+log_must $NSENTER mkdir $IDMAPDIR/subdir
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir)"
+
+log_must $NSENTER ln -s $IDMAPDIR/file1 $IDMAPDIR/file1_sym
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/file1_sym)"
+
+log_must $NSENTER ln $IDMAPDIR/file1 $IDMAPDIR/subdir/file1_hard
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir/file1_hard)"
+
+log_must $NSENTER touch $IDMAPDIR/subdir/file2
+log_must $NSENTER chown $UID1:$GID1 $IDMAPDIR/subdir/file2
+log_mustnot $NSENTER chown $UID2 $IDMAPDIR/subdir/file2
+
+log_must $NSENTER cp -r $IDMAPDIR/subdir $IDMAPDIR/subdir1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file2)"
+log_must $NSENTER rm -rf $IDMAPDIR/subdir1
+
+log_must $NSENTER cp -rp $IDMAPDIR/subdir $IDMAPDIR/subdir1
+log_must test "$UID1 $GID1" = "$(stat -c '%u %g' $WORKDIR/subdir1/file1_hard)"
+log_must $NSENTER rm -rf $IDMAPDIR/subdir1
+
+log_pass "Owner verification of entries under the base folder is successful."
+
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh
new file mode 100755
index 000000000000..89f2f750d23c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_004.ksh
@@ -0,0 +1,106 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Test setgid bit is set properly on the idmapped mount
+# in a user namespace.
+#
+# STRATEGY:
+# 1. Create folder "idmap_test", set gid bit on it
+# 2. Idmap the folder to "idmap_dest"
+# 3. Create file and folder in the idmapped folder in the user
+# namespace having the same idmap info
+# 4. Verify the gid bit of the file and folder is set
+#
+
+verify_runnable "global"
+
+export WORKDIR=$TESTDIR/idmap_test
+export IDMAPDIR=$TESTDIR/idmap_dest
+
+function cleanup
+{
+ kill -TERM ${unshared_pid}
+ log_must rm -rf $IDMAPDIR/*
+ if mountpoint $IDMAPDIR; then
+ log_must umount $IDMAPDIR
+ fi
+ log_must rm -rf $IDMAPDIR $WORKDIR
+}
+
+log_onexit cleanup
+
+if ! idmap_util -c $TESTDIR; then
+ log_unsupported "Idmap mount not supported."
+fi
+
+log_must mkdir -p $WORKDIR
+log_must mkdir -p $IDMAPDIR
+
+log_must chown $UID1:$GID1 $WORKDIR
+# set gid bit
+log_must chmod 2755 $WORKDIR
+log_must idmap_util -m "u:${UID1}:${UID2}:1" -m "g:${GID1}:${GID2}:1" $WORKDIR $IDMAPDIR
+log_must test -g $IDMAPDIR
+
+# Create a user namespace with the same idmapping
+unshare -Urm echo test
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+unshare -Um /usr/bin/sleep 2h &
+unshared_pid=$!
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+# wait for userns to be ready
+sleep 1
+echo "${UID1} ${UID2} 1" > /proc/$unshared_pid/uid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to uid_map"
+fi
+echo "${GID1} ${GID2} 1" > /proc/$unshared_pid/gid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to gid_map"
+fi
+
+NSENTER="nsenter -t $unshared_pid --all -S ${UID1} -G ${GID1}"
+
+# gid bit can be set on the file
+log_must $NSENTER touch $IDMAPDIR/file1
+log_must $NSENTER chmod 2654 $IDMAPDIR/file1
+log_must test -g $WORKDIR/file1
+log_must test -g $IDMAPDIR/file1
+log_must test "$UID1 $GID1" = "$($NSENTER stat -c '%u %g' $IDMAPDIR/file1)"
+
+# gid bit is carried over to new folder
+log_must $NSENTER mkdir $IDMAPDIR/subdir
+log_must test -g $WORKDIR/subdir
+log_must test -g $IDMAPDIR/subdir
+log_must test "$UID1 $GID1" = "$($NSENTER stat -c '%u %g' $IDMAPDIR/subdir)"
+
+log_pass "Verification of setting gid bit in userns is successful."
+
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh
new file mode 100755
index 000000000000..a4ecea92c127
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_005.ksh
@@ -0,0 +1,138 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Test idmapped mount in a user namespace
+#
+# STRATEGY:
+# 1. Create a zoned dataset
+# 2. Create a user namespace and designate the dataset to the zone
+# 3. In the zone, mount the dataset to "idmap_test"
+# 4. In the zone, idmap mount the dataset mountpoint to "idmap_dest"
+# 5. Do some file operations in the idmapped mountpoint "idmap_dest"
+# 6. Check the owner of files/folder in the mount point "idmap_test"
+# 7. unmount the mountpoints in the zone
+# 8. Remount the dataset in global zone to "idmap_test"
+# 9. Check the owenr of filers/folder in the mountpoint "idmap_test"
+#
+
+verify_runnable "global"
+
+export WORKDIR=$TESTDIR/idmap_test
+export IDMAPDIR=$TESTDIR/idmap_dest
+
+function cleanup
+{
+ if [[ -v unshared_pid ]]; then
+ zfs unzone /proc/$unshared_pid/ns/user "$TESTPOOL/userns"
+ kill -TERM ${unshared_pid}
+ fi
+ if mountpoint $WORKDIR; then
+ log_must umount $WORKDIR
+ fi
+ log_must rm -rf $WORKDIR
+}
+
+log_onexit cleanup
+
+if ! idmap_util -c $TESTDIR; then
+ log_unsupported "Idmap mount not supported."
+fi
+
+unshare -Urm echo test
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+
+log_must zfs create -o zoned=off -o mountpoint=$WORKDIR "$TESTPOOL/userns"
+
+# "root" user and group in the user ns
+log_must chown 1000000:1000000 $WORKDIR
+log_must zfs set zoned=on "$TESTPOOL/userns"
+
+log_must mkdir -p $IDMAPDIR
+
+unshare -Um /usr/bin/sleep 2h &
+unshared_pid=$!
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to create user namespace"
+fi
+# wait for userns to be ready
+sleep 1
+echo "0 1000000 1000000" > /proc/$unshared_pid/uid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to uid_map"
+fi
+echo "0 1000000 1000000" > /proc/$unshared_pid/gid_map
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Failed to write to gid_map"
+fi
+
+NSENTER="nsenter -t $unshared_pid --all -S 0 -G 0"
+
+log_must zfs zone /proc/$unshared_pid/ns/user "$TESTPOOL/userns"
+log_must $NSENTER zfs mount "$TESTPOOL/userns"
+log_must $NSENTER chmod 777 $WORKDIR
+
+$NSENTER idmap_util -c $WORKDIR
+if [ "$?" -ne "0" ]; then
+ log_unsupported "Idmapped mount not supported in a user namespace"
+fi
+
+log_must $NSENTER idmap_util -m b:0:10000:100000 $WORKDIR $IDMAPDIR
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups touch $IDMAPDIR/file
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups mkdir $IDMAPDIR/folder
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups ln -s file $IDMAPDIR/file-soft
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups ln $IDMAPDIR/file $IDMAPDIR/file-hard
+
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups cp -p $IDMAPDIR/file $IDMAPDIR/folder/file-p
+log_must $NSENTER setpriv --reuid 11000 --regid 11000 --clear-groups cp $IDMAPDIR/file $IDMAPDIR/folder/file
+
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file)"
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder)"
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file-soft)"
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/file-hard)"
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder/file-p)"
+log_must test "1000 1000" = "$($NSENTER stat -c '%u %g' $WORKDIR/folder/file)"
+
+log_must $NSENTER umount $IDMAPDIR
+log_must $NSENTER umount $WORKDIR
+
+log_must zfs unzone /proc/$unshared_pid/ns/user "$TESTPOOL/userns"
+log_must kill -TERM $unshared_pid
+unset unshared_pid
+log_must zfs set zoned=off "$TESTPOOL/userns"
+log_must zfs mount "$TESTPOOL/userns"
+
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file)"
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder)"
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file-soft)"
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/file-hard)"
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder/file-p)"
+log_must test "1001000 1001000" = "$(stat -c '%u %g' $WORKDIR/folder/file)"
+
+log_pass "Testing idmapped mount in a user ns is successful."
+
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib
new file mode 100644
index 000000000000..980845ca209c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/idmap_mount_common.kshlib
@@ -0,0 +1,23 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/idmap_mount/idmap_mount.cfg
diff --git a/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh b/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh
new file mode 100755
index 000000000000..90a14f12058f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/idmap_mount/setup.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+# unable to do idmapped mount in a local zone
+verify_runnable "global"
+
+DISK=${DISKS%% *}
+default_setup $DISK
+
diff --git a/tests/zfs-tests/tests/functional/inheritance/README.config b/tests/zfs-tests/tests/functional/inheritance/README.config
index 607f10a554ec..95fd363bac4f 100644
--- a/tests/zfs-tests/tests/functional/inheritance/README.config
+++ b/tests/zfs-tests/tests/functional/inheritance/README.config
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/README.state b/tests/zfs-tests/tests/functional/inheritance/README.state
index c1d3cc05d603..2fbd103f178e 100644
--- a/tests/zfs-tests/tests/functional/inheritance/README.state
+++ b/tests/zfs-tests/tests/functional/inheritance/README.state
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh b/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh
index daac5c18a345..7fa851fc0ef6 100755
--- a/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config001.cfg b/tests/zfs-tests/tests/functional/inheritance/config001.cfg
index 23616cbf3b7f..23819eb7ff8b 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config001.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config001.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config002.cfg b/tests/zfs-tests/tests/functional/inheritance/config002.cfg
index 31294110f6ad..09f6bb3535cb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config002.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config002.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config003.cfg b/tests/zfs-tests/tests/functional/inheritance/config003.cfg
index 57a73b95d433..99c5f9f3e0d4 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config003.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config003.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config004.cfg b/tests/zfs-tests/tests/functional/inheritance/config004.cfg
index 1052526379f0..196683d53d53 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config004.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config004.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config005.cfg b/tests/zfs-tests/tests/functional/inheritance/config005.cfg
index d15beb2c4ca8..27f49c54e77f 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config005.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config005.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config006.cfg b/tests/zfs-tests/tests/functional/inheritance/config006.cfg
index a059d17978f7..3cb630b931bb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config006.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config006.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config007.cfg b/tests/zfs-tests/tests/functional/inheritance/config007.cfg
index b416c9f17d20..8a7b47c1a93a 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config007.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config007.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config008.cfg b/tests/zfs-tests/tests/functional/inheritance/config008.cfg
index 4f7e7b0ef7f8..c8105f9e47a6 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config008.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config008.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config009.cfg b/tests/zfs-tests/tests/functional/inheritance/config009.cfg
index 4f7e7b0ef7f8..c8105f9e47a6 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config009.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config009.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config010.cfg b/tests/zfs-tests/tests/functional/inheritance/config010.cfg
index 4f7e7b0ef7f8..c8105f9e47a6 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config010.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config010.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config011.cfg b/tests/zfs-tests/tests/functional/inheritance/config011.cfg
index 57a73b95d433..99c5f9f3e0d4 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config011.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config011.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config012.cfg b/tests/zfs-tests/tests/functional/inheritance/config012.cfg
index 57a73b95d433..99c5f9f3e0d4 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config012.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config012.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config013.cfg b/tests/zfs-tests/tests/functional/inheritance/config013.cfg
index 1052526379f0..196683d53d53 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config013.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config013.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config014.cfg b/tests/zfs-tests/tests/functional/inheritance/config014.cfg
index 1052526379f0..196683d53d53 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config014.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config014.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config015.cfg b/tests/zfs-tests/tests/functional/inheritance/config015.cfg
index 31294110f6ad..09f6bb3535cb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config015.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config015.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config016.cfg b/tests/zfs-tests/tests/functional/inheritance/config016.cfg
index 31294110f6ad..09f6bb3535cb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config016.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config016.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config017.cfg b/tests/zfs-tests/tests/functional/inheritance/config017.cfg
index d15beb2c4ca8..27f49c54e77f 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config017.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config017.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config018.cfg b/tests/zfs-tests/tests/functional/inheritance/config018.cfg
index d15beb2c4ca8..27f49c54e77f 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config018.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config018.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config019.cfg b/tests/zfs-tests/tests/functional/inheritance/config019.cfg
index 23616cbf3b7f..23819eb7ff8b 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config019.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config019.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config020.cfg b/tests/zfs-tests/tests/functional/inheritance/config020.cfg
index 23616cbf3b7f..23819eb7ff8b 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config020.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config020.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config021.cfg b/tests/zfs-tests/tests/functional/inheritance/config021.cfg
index a059d17978f7..3cb630b931bb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config021.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config021.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config022.cfg b/tests/zfs-tests/tests/functional/inheritance/config022.cfg
index a059d17978f7..3cb630b931bb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config022.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config022.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config023.cfg b/tests/zfs-tests/tests/functional/inheritance/config023.cfg
index b416c9f17d20..8a7b47c1a93a 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config023.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config023.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/config024.cfg b/tests/zfs-tests/tests/functional/inheritance/config024.cfg
index b416c9f17d20..8a7b47c1a93a 100644
--- a/tests/zfs-tests/tests/functional/inheritance/config024.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/config024.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib b/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib
index a485d0521d1f..8967a0fbc128 100644
--- a/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib
+++ b/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
index 4dfc3a8986a3..1f203e1dc551 100755
--- a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -26,6 +26,7 @@
#
# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
#
. $STF_SUITE/include/libtest.shlib
@@ -332,7 +333,7 @@ function scan_state { #state-file
log_note "No operation specified"
else
export __ZFS_POOL_RESTRICT="TESTPOOL"
- log_must zfs unmount -a
+ log_must_busy zfs unmount -a
unset __ZFS_POOL_RESTRICT
for p in ${prop[i]} ${prop[((i+1))]}; do
@@ -376,7 +377,8 @@ set -A prop "checksum" "" \
"sharenfs" "" \
"recordsize" "recsize" \
"snapdir" "" \
- "readonly" ""
+ "readonly" "" \
+ "redundant_metadata" ""
#
# Note except for the mountpoint default value (which is handled in
@@ -387,12 +389,14 @@ set -A prop "checksum" "" \
set -A def_val "on" "on" "on" \
"off" "" \
"hidden" \
- "off"
+ "off" \
+ "all"
set -A local_val "off" "off" "off" \
"on" "" \
"visible" \
- "off"
+ "off" \
+ "none"
#
# Add system specific values
diff --git a/tests/zfs-tests/tests/functional/inheritance/state001.cfg b/tests/zfs-tests/tests/functional/inheritance/state001.cfg
index afaf3cccfe14..4fbdcd6e212b 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state001.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state001.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state002.cfg b/tests/zfs-tests/tests/functional/inheritance/state002.cfg
index 5b2f2d2dd98a..f368be370c24 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state002.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state002.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state003.cfg b/tests/zfs-tests/tests/functional/inheritance/state003.cfg
index 5780065ace88..06b092dd3800 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state003.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state003.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state004.cfg b/tests/zfs-tests/tests/functional/inheritance/state004.cfg
index e62979a04b7d..e679e449d850 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state004.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state004.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state005.cfg b/tests/zfs-tests/tests/functional/inheritance/state005.cfg
index 097459ffedb9..da7a4f9d4e86 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state005.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state005.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state006.cfg b/tests/zfs-tests/tests/functional/inheritance/state006.cfg
index 9863b298fe35..93d90c86cbbb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state006.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state006.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state007.cfg b/tests/zfs-tests/tests/functional/inheritance/state007.cfg
index 731ec95a250b..871287b15878 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state007.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state007.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state008.cfg b/tests/zfs-tests/tests/functional/inheritance/state008.cfg
index 7385c98c3c07..4b1cfbd09cbb 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state008.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state008.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state009.cfg b/tests/zfs-tests/tests/functional/inheritance/state009.cfg
index 3fb2841a2cc1..19ee507ef80b 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state009.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state009.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state010.cfg b/tests/zfs-tests/tests/functional/inheritance/state010.cfg
index 4c51e808b1fa..57c29d6e3e04 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state010.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state010.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state011.cfg b/tests/zfs-tests/tests/functional/inheritance/state011.cfg
index f6e791ee73c1..5eb33af00b31 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state011.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state011.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state012.cfg b/tests/zfs-tests/tests/functional/inheritance/state012.cfg
index 47898244b025..afe1d0d947fe 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state012.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state012.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state013.cfg b/tests/zfs-tests/tests/functional/inheritance/state013.cfg
index ae5919292623..49f2c242cb76 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state013.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state013.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state014.cfg b/tests/zfs-tests/tests/functional/inheritance/state014.cfg
index 3770c5093e52..e6418e3e5a80 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state014.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state014.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state015.cfg b/tests/zfs-tests/tests/functional/inheritance/state015.cfg
index fb1fc3907b76..c8228f080925 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state015.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state015.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state016.cfg b/tests/zfs-tests/tests/functional/inheritance/state016.cfg
index f17154c74519..c830287d2a76 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state016.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state016.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state017.cfg b/tests/zfs-tests/tests/functional/inheritance/state017.cfg
index a993eed5f78c..09d061340af3 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state017.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state017.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state018.cfg b/tests/zfs-tests/tests/functional/inheritance/state018.cfg
index 6fd08c6fb8b1..f718c83395d6 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state018.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state018.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state019.cfg b/tests/zfs-tests/tests/functional/inheritance/state019.cfg
index 67b488f84a09..484e9e02c680 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state019.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state019.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state020.cfg b/tests/zfs-tests/tests/functional/inheritance/state020.cfg
index df8ba7dd5246..5a4ec6a6f7e6 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state020.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state020.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state021.cfg b/tests/zfs-tests/tests/functional/inheritance/state021.cfg
index f61472eff197..231530a14776 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state021.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state021.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state022.cfg b/tests/zfs-tests/tests/functional/inheritance/state022.cfg
index 22462f97839a..990215766aad 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state022.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state022.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state023.cfg b/tests/zfs-tests/tests/functional/inheritance/state023.cfg
index 8219a2abf3c3..4f9091c67908 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state023.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state023.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state024.cfg b/tests/zfs-tests/tests/functional/inheritance/state024.cfg
index 848ae1437d06..cd67aaf6728f 100644
--- a/tests/zfs-tests/tests/functional/inheritance/state024.cfg
+++ b/tests/zfs-tests/tests/functional/inheritance/state024.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse.cfg b/tests/zfs-tests/tests/functional/inuse/inuse.cfg
index 631ace7ab795..2514f89e78e5 100644
--- a/tests/zfs-tests/tests/functional/inuse/inuse.cfg
+++ b/tests/zfs-tests/tests/functional/inuse/inuse.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh
index 25a807025c87..17e1169175e7 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh
index 8c984df3089e..385b88bdc6b6 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh
index 8e051d8b6f73..054c6e5ac8bd 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh
index afe30d059997..f50fd2ff91de 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh
index 2222721afd8d..0d2c2ded0260 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh
index 775f1af63bf1..d3e580a6f533 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh
index d60ebcee1554..68bf19f0abce 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh
index 54d201ad6291..64fe05b422dd 100755
--- a/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/inuse/setup.ksh b/tests/zfs-tests/tests/functional/inuse/setup.ksh
index 962a0c98dc7e..14cdb6798a9f 100755
--- a/tests/zfs-tests/tests/functional/inuse/setup.ksh
+++ b/tests/zfs-tests/tests/functional/inuse/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/cleanup.ksh b/tests/zfs-tests/tests/functional/io/cleanup.ksh
index 0031a26c3cec..5bd79c0070fa 100755
--- a/tests/zfs-tests/tests/functional/io/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/io/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/io_uring.ksh b/tests/zfs-tests/tests/functional/io/io_uring.ksh
index 1ee5cee52227..2fa146556358 100755
--- a/tests/zfs-tests/tests/functional/io/io_uring.ksh
+++ b/tests/zfs-tests/tests/functional/io/io_uring.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -40,10 +40,17 @@
verify_runnable "global"
-if [[ $(linux_version) -lt $(linux_version "5.1") ]]; then
+if ! $(grep -q "CONFIG_IO_URING=y" /boot/config-$(uname -r)); then
log_unsupported "Requires io_uring support"
fi
+if [ -e /etc/os-release ] ; then
+ source /etc/os-release
+ if [ -n "$REDHAT_SUPPORT_PRODUCT_VERSION" ] && ((floor($REDHAT_SUPPORT_PRODUCT_VERSION) == 9)) ; then
+ log_unsupported "Disabled on CentOS 9, fails with 'Operation not permitted'"
+ fi
+fi
+
fio --ioengine=io_uring --parse-only || log_unsupported "fio io_uring support required"
function cleanup
diff --git a/tests/zfs-tests/tests/functional/io/libaio.ksh b/tests/zfs-tests/tests/functional/io/libaio.ksh
index ef100209beac..242b2ca8de30 100755
--- a/tests/zfs-tests/tests/functional/io/libaio.ksh
+++ b/tests/zfs-tests/tests/functional/io/libaio.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/mmap.ksh b/tests/zfs-tests/tests/functional/io/mmap.ksh
index 742c1f08f1c7..112267ee20d8 100755
--- a/tests/zfs-tests/tests/functional/io/mmap.ksh
+++ b/tests/zfs-tests/tests/functional/io/mmap.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/posixaio.ksh b/tests/zfs-tests/tests/functional/io/posixaio.ksh
index c720aef9535f..52331027cdd2 100755
--- a/tests/zfs-tests/tests/functional/io/posixaio.ksh
+++ b/tests/zfs-tests/tests/functional/io/posixaio.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/psync.ksh b/tests/zfs-tests/tests/functional/io/psync.ksh
index 8feb87d93a7c..5227fcbdd449 100755
--- a/tests/zfs-tests/tests/functional/io/psync.ksh
+++ b/tests/zfs-tests/tests/functional/io/psync.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/setup.ksh b/tests/zfs-tests/tests/functional/io/setup.ksh
index ff72fc3db7c0..82aaf5bc91b5 100755
--- a/tests/zfs-tests/tests/functional/io/setup.ksh
+++ b/tests/zfs-tests/tests/functional/io/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/io/sync.ksh b/tests/zfs-tests/tests/functional/io/sync.ksh
index aaaa126efb1f..76248a38a519 100755
--- a/tests/zfs-tests/tests/functional/io/sync.ksh
+++ b/tests/zfs-tests/tests/functional/io/sync.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/l2arc/l2arc_mfuonly_pos.ksh b/tests/zfs-tests/tests/functional/l2arc/l2arc_mfuonly_pos.ksh
index f2bada0ebbec..89ab940334ee 100755
--- a/tests/zfs-tests/tests/functional/l2arc/l2arc_mfuonly_pos.ksh
+++ b/tests/zfs-tests/tests/functional/l2arc/l2arc_mfuonly_pos.ksh
@@ -80,7 +80,7 @@ log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
-log_must zpool import -d $VDIR $TESTPOOL
+log_must zpool import -N -d $VDIR $TESTPOOL
# Regardless of l2arc_noprefetch, some MFU buffers might be evicted
# from ARC, accessed later on as prefetches and transition to MRU as
diff --git a/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh b/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh
index 6f7b9aff7c38..a9968723c3ca 100755
--- a/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh
@@ -27,15 +27,14 @@
#
# STRATEGY:
# 1. Create pool with a cache device.
-# 2. Export and re-import pool without writing any data.
-# 3. Create a random file in that pool and random read for 10 sec.
-# 4. Export pool.
-# 5. Read the amount of log blocks written from the header of the
+# 2. Create a random file in that pool and random read for 10 sec.
+# 3. Export pool.
+# 4. Read the amount of log blocks written from the header of the
# L2ARC device.
-# 6. Import pool.
-# 7. Read the amount of log blocks rebuilt in arcstats and compare to
+# 5. Import pool.
+# 6. Read the amount of log blocks rebuilt in arcstats and compare to
# (5).
-# 8. Check if the labels of the L2ARC device are intact.
+# 7. Check if the labels of the L2ARC device are intact.
#
# * We can predict the minimum bytes of L2ARC restored if we subtract
# from the effective size of the cache device the bytes l2arc_evict()
@@ -77,10 +76,8 @@ export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
-log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
-
-log_must zpool export $TESTPOOL
-log_must zpool import -d $VDIR $TESTPOOL
+log_must zpool create -f -o ashift=12 $TESTPOOL $VDEV
+log_must zpool add $TESTPOOL cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
diff --git a/tests/zfs-tests/tests/functional/large_files/cleanup.ksh b/tests/zfs-tests/tests/functional/large_files/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/large_files/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/large_files/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh b/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh
index f59603724e76..aebc8b2647d5 100755
--- a/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh b/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh
index 255a8f8b5ad6..e0014d64350c 100755
--- a/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/large_files/setup.ksh b/tests/zfs-tests/tests/functional/large_files/setup.ksh
index 3a45ec8d510d..d617f361b24d 100755
--- a/tests/zfs-tests/tests/functional/large_files/setup.ksh
+++ b/tests/zfs-tests/tests/functional/large_files/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg b/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg
index 13c157789dd7..9306c799ec54 100644
--- a/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg
+++ b/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh b/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh
index 7955478502d1..85f25c7618c6 100755
--- a/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh b/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/libzfs/many_fds.c b/tests/zfs-tests/tests/functional/libzfs/many_fds.c
index 34029e0e32d0..6e0b1fd4b4aa 100644
--- a/tests/zfs-tests/tests/functional/libzfs/many_fds.c
+++ b/tests/zfs-tests/tests/functional/libzfs/many_fds.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
diff --git a/tests/zfs-tests/tests/functional/libzfs/setup.ksh b/tests/zfs-tests/tests/functional/libzfs/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/libzfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/libzfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/link_count/cleanup.ksh b/tests/zfs-tests/tests/functional/link_count/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/link_count/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/link_count/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh b/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh
index 3ab3fbef8df8..d3020c99c95c 100755
--- a/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh
+++ b/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/link_count/setup.ksh b/tests/zfs-tests/tests/functional/link_count/setup.ksh
index d275e063b13a..76aa23035dd9 100755
--- a/tests/zfs-tests/tests/functional/link_count/setup.ksh
+++ b/tests/zfs-tests/tests/functional/link_count/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/cleanup.ksh b/tests/zfs-tests/tests/functional/migration/cleanup.ksh
index 79676d79e6fd..c9f1833be10c 100755
--- a/tests/zfs-tests/tests/functional/migration/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/migration/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration.cfg b/tests/zfs-tests/tests/functional/migration/migration.cfg
index 308891b86d01..7d606f6d9a12 100644
--- a/tests/zfs-tests/tests/functional/migration/migration.cfg
+++ b/tests/zfs-tests/tests/functional/migration/migration.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration.kshlib b/tests/zfs-tests/tests/functional/migration/migration.kshlib
index 0362f0644f6f..7078f93a559b 100644
--- a/tests/zfs-tests/tests/functional/migration/migration.kshlib
+++ b/tests/zfs-tests/tests/functional/migration/migration.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh
index 3a4a4b7f8f74..8e0cdf8034d9 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh
index a522174f11aa..fe8aee004b93 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh
index c83883d356c3..3d9ba5691d59 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh
index 5a4375410e65..c3b7b73b7e50 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh
index f282c37b7a1c..c48c8d6bc57f 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh
index a2ebd1f3f2c8..893a9bc50fc5 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh
index 40839ecc00a5..80b7749d6805 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh
index af60e4bc1f4e..5fdcc5f90c55 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh
index e24cfdc96db1..c91946067ef2 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh
index f090fed3d83c..62ccccb1613c 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh
index 4293c8d8bdc2..9718fefb406d 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh
index 675b4a159b68..243136e768bd 100755
--- a/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -55,7 +55,7 @@ log_assert "Migrating test file from $NEWFS_DEFAULT_FS fs to ZFS fs using cp"
log_onexit cleanup
-log_mustprepare $DNAME "cp $BNAME $NONZFS_TESTDIR/cp$$.cp"
-log_mustmigrate $TESTDIR $SUMA $SUMB "cp $NONZFS_TESTDIR/cp$$.cp $BNAME"
+log_must prepare $DNAME "cp $BNAME $NONZFS_TESTDIR/cp$$.cp"
+log_must migrate $TESTDIR $SUMA $SUMB "cp $NONZFS_TESTDIR/cp$$.cp $BNAME"
log_pass "Successfully migrated test file from $NEWFS_DEFAULT_FS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/setup.ksh b/tests/zfs-tests/tests/functional/migration/setup.ksh
index 4992f954eeee..5aa4d058ce5d 100755
--- a/tests/zfs-tests/tests/functional/migration/setup.ksh
+++ b/tests/zfs-tests/tests/functional/migration/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/cleanup.ksh b/tests/zfs-tests/tests/functional/mmap/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/mmap/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap.cfg b/tests/zfs-tests/tests/functional/mmap/mmap.cfg
index 1501c0463015..a331c5b2aa4f 100644
--- a/tests/zfs-tests/tests/functional/mmap/mmap.cfg
+++ b/tests/zfs-tests/tests/functional/mmap/mmap.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh
index 031d90c3838b..b9e9a8a3c138 100755
--- a/tests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_mixed.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_mixed.ksh
new file mode 100755
index 000000000000..6c8246d48acf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_mixed.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmap/mmap.cfg
+
+#
+# DESCRIPTION:
+# Verify mixed buffered and mmap IO.
+#
+# STRATEGY:
+# 1. Create an empty file.
+# 2. Start a background buffered read/write fio to the file.
+# 3. Start a background mmap read/write fio to the file.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "$tmp_file"
+}
+
+log_assert "Verify mixed buffered and mmap IO"
+
+log_onexit cleanup
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+tmp_file=$mntpnt/file
+bs=$((128 * 1024))
+blocks=64
+size=$((bs * blocks))
+runtime=60
+
+log_must dd if=/dev/zero of=$tmp_file bs=$bs count=$blocks
+
+# Buffered IO writes
+log_must eval "fio --filename=$tmp_file --name=buffer-write \
+ --rw=randwrite --size=$size --bs=$bs --direct=0 --numjobs=1 \
+ --ioengine=sync --fallocate=none --group_reporting --minimal \
+ --runtime=$runtime --time_based --norandommap &"
+
+# Buffered IO reads
+log_must eval "fio --filename=$tmp_file --name=buffer-read \
+ --rw=randread --size=$size --bs=$bs --direct=0 --numjobs=1 \
+ --ioengine=sync --fallocate=none --group_reporting --minimal \
+ --runtime=$runtime --time_based --norandommap &"
+
+# mmap IO writes
+log_must eval "fio --filename=$tmp_file --name=mmap-write \
+ --rw=randwrite --size=$size --bs=$bs --numjobs=1 \
+ --ioengine=mmap --fallocate=none --group_reporting --minimal \
+ --runtime=$runtime --time_based --norandommap &"
+
+# mmap IO reads
+log_must eval "fio --filename=$tmp_file --name=mmap-read \
+ --rw=randread --size=$size --bs=$bs --numjobs=1 \
+ --ioengine=mmap --fallocate=none --group_reporting --minimal \
+ --runtime=$runtime --time_based --norandommap &"
+
+log_must wait
+
+log_pass "Verfied mixed buffered and mmap IO"
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh
index 470f10d937bc..acef0676f5cb 100755
--- a/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_seek_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_seek_001_pos.ksh
index 6188549ad8d2..c09746b4b66a 100755
--- a/tests/zfs-tests/tests/functional/mmap/mmap_seek_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_seek_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh
index 2f4257993d4a..9de0471a9b69 100755
--- a/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmap/setup.ksh b/tests/zfs-tests/tests/functional/mmap/setup.ksh
index d275e063b13a..76aa23035dd9 100755
--- a/tests/zfs-tests/tests/functional/mmap/setup.ksh
+++ b/tests/zfs-tests/tests/functional/mmap/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp.kshlib b/tests/zfs-tests/tests/functional/mmp/mmp.kshlib
index 9dd6f4d53f4a..5071830c489a 100644
--- a/tests/zfs-tests/tests/functional/mmp/mmp.kshlib
+++ b/tests/zfs-tests/tests/functional/mmp/mmp.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_write_slow_disk.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_write_slow_disk.ksh
new file mode 100755
index 000000000000..8b118684aa7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_write_slow_disk.ksh
@@ -0,0 +1,97 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2024, Klara Inc
+#
+
+# DESCRIPTION:
+# Verify that long VDEV probes do not cause MMP checks to suspend pool
+# Note: without PR-15839 fix, this test will suspend the pool.
+#
+# A device that is returning unexpected errors will trigger a vdev_probe.
+# When the device additionally has slow response times, the probe can hold
+# the spa config lock as a writer for a long period of time such that the
+# mmp uberblock updates stall when trying to acquire the spa config lock.
+#
+# STRATEGY:
+# 1. Create a pool with multiple leaf vdevs
+# 2. Enable multihost and multihost_history
+# 3. Delay for MMP writes to occur
+# 4. Verify that a long VDEV probe didn't cause MMP check to suspend pool
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+
+ if [[ $(zpool list -H -o health $MMP_POOL) == "SUSPENDED" ]]; then
+ log_must zpool clear $MMP_POOL
+ zpool get state $MMP_POOL $MMP_DIR/file.3
+ zpool events | grep ".fs.zfs." | grep -v "history_event"
+ fi
+
+ poolexists $MMP_POOL && destroy_pool $MMP_POOL
+ log_must rm -r $MMP_DIR
+ log_must mmp_clear_hostid
+}
+
+log_assert "A long VDEV probe doesn't cause a MMP check suspend"
+log_onexit cleanup
+
+MMP_HISTORY_URL=/proc/spl/kstat/zfs/$MMP_POOL/multihost
+
+# Create a multiple drive pool
+log_must zpool events -c
+log_must mkdir -p $MMP_DIR
+log_must truncate -s 128M $MMP_DIR/file.{0,1,2,3,4,5}
+log_must zpool create -f $MMP_POOL \
+ mirror $MMP_DIR/file.{0,1,2} \
+ mirror $MMP_DIR/file.{3,4,5}
+
+# Enable MMP
+log_must mmp_set_hostid $HOSTID1
+log_must zpool set multihost=on $MMP_POOL
+clear_mmp_history
+
+# Inject vdev write error along with a delay
+log_must zinject -f 33 -e io -L pad2 -T write -d $MMP_DIR/file.3 $MMP_POOL
+log_must zinject -f 50 -e io -L uber -T write -d $MMP_DIR/file.3 $MMP_POOL
+log_must zinject -D 2000:4 -T write -d $MMP_DIR/file.3 $MMP_POOL
+
+log_must dd if=/dev/urandom of=/$MMP_POOL/data bs=1M count=5
+sleep 10
+sync_pool $MMP_POOL
+
+# Confirm mmp writes to the non-slow disks have taken place
+for x in {0,1,2,4}; do
+ write_count=$(grep -c file.${x} $MMP_HISTORY_URL)
+ [[ $write_count -gt 0 ]] || log_fail "expecting mmp writes"
+done
+
+# Expect that the pool was not suspended
+log_must check_state $MMP_POOL "" "ONLINE"
+health=$(zpool list -H -o health $MMP_POOL)
+log_note "$MMP_POOL health is $health"
+[[ "$health" == "SUSPENDED" ]] && log_fail "$MMP_POOL $health unexpected"
+
+log_pass "A long VDEV probe doesn't cause a MMP check suspend"
diff --git a/tests/zfs-tests/tests/functional/mount/cleanup.ksh b/tests/zfs-tests/tests/functional/mount/cleanup.ksh
index f20c72841f42..bd6b0e435ed1 100755
--- a/tests/zfs-tests/tests/functional/mount/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/mount/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mount/setup.ksh b/tests/zfs-tests/tests/functional/mount/setup.ksh
index 8e2edcd24f4b..9b3bc37ce6ae 100755
--- a/tests/zfs-tests/tests/functional/mount/setup.ksh
+++ b/tests/zfs-tests/tests/functional/mount/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mount/umount_001.ksh b/tests/zfs-tests/tests/functional/mount/umount_001.ksh
index ec4954569961..9e350de66fa3 100755
--- a/tests/zfs-tests/tests/functional/mount/umount_001.ksh
+++ b/tests/zfs-tests/tests/functional/mount/umount_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh b/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh
index 1c170208b574..882f9955a4c2 100755
--- a/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg b/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg
index fbab8f6dad7b..2ee7c08d3c43 100644
--- a/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh b/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh
index 209c3509a347..fffe8d285654 100755
--- a/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh b/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh
index c20831babfab..7eea345d150e 100755
--- a/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib b/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib
index 26c2e84ce4ed..c3827198a6ef 100644
--- a/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/mv_files/setup.ksh b/tests/zfs-tests/tests/functional/mv_files/setup.ksh
index d459c51e4e57..669a930c6323 100755
--- a/tests/zfs-tests/tests/functional/mv_files/setup.ksh
+++ b/tests/zfs-tests/tests/functional/mv_files/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh b/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh
index c4c369145dfc..8a6521193e66 100755
--- a/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh b/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh
index b576b78c8aa5..84749d60227d 100755
--- a/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/nestedfs/setup.ksh b/tests/zfs-tests/tests/functional/nestedfs/setup.ksh
index 677cb12d79ac..1eeefeaa18c1 100755
--- a/tests/zfs-tests/tests/functional/nestedfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/nestedfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/no_space/cleanup.ksh b/tests/zfs-tests/tests/functional/no_space/cleanup.ksh
index 62b28df8ef5a..d1a731f18372 100755
--- a/tests/zfs-tests/tests/functional/no_space/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/no_space/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc.cfg b/tests/zfs-tests/tests/functional/no_space/enospc.cfg
index 0b8298c03165..e8e6065bbc81 100644
--- a/tests/zfs-tests/tests/functional/no_space/enospc.cfg
+++ b/tests/zfs-tests/tests/functional/no_space/enospc.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh
index 56beb4e71e17..c6d374635c5b 100755
--- a/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh
index 496e2a029c5c..5ac96962546f 100755
--- a/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_ganging.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_ganging.ksh
new file mode 100755
index 000000000000..1d35fba5dbfa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_ganging.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh
+
+#
+# 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
+
+#
+# DESCRIPTION:
+# Exercise gang block IO paths for non-encrypted and encrypted datasets.
+#
+
+verify_runnable "both"
+log_assert "Verify IO when file system is full and ganging."
+
+function cleanup
+{
+ log_must set_tunable64 METASLAB_FORCE_GANGING $metaslab_force_ganging
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+default_setup_noexit $DISKS
+
+typeset metaslab_force_ganging=$(get_tunable METASLAB_FORCE_GANGING)
+shift=$(random_int_between 15 17)
+log_must set_tunable64 METASLAB_FORCE_GANGING $((2**$shift))
+
+keyfile=/$TESTPOOL/keyencfods
+log_must eval "echo 'password' > $keyfile"
+bs=1024k
+count=512
+
+log_must dd if=/dev/urandom of=$TESTDIR/data bs=$bs count=$count
+data_checksum=$(sha256digest $TESTDIR/data)
+
+# Test common large block configuration.
+log_must zfs create -o recordsize=1m -o primarycache=metadata $TESTPOOL/gang
+mntpnt=$(get_prop mountpoint $TESTPOOL/gang)
+
+log_must dd if=$TESTDIR/data of=$mntpnt/file bs=$bs count=$count
+sync_pool $TESTPOOL
+log_must dd if=$mntpnt/file of=$TESTDIR/out bs=$bs count=$count
+out_checksum=$(sha256digest $TESTDIR/out)
+
+if [[ "$data_checksum" != "$out_checksum" ]]; then
+ log_fail "checksum mismatch ($data_checksum != $out_checksum)"
+fi
+
+log_must rm -f $TESTDIR/out
+log_must zfs destroy $TESTPOOL/gang
+
+# Test common large block configuration with encryption.
+log_must zfs create \
+ -o recordsize=1m \
+ -o primarycache=metadata \
+ -o compression=off \
+ -o encryption=on \
+ -o keyformat=passphrase \
+ -o keylocation=file://$keyfile \
+ -o copies=2 \
+ $TESTPOOL/gang
+mntpnt=$(get_prop mountpoint $TESTPOOL/gang)
+
+log_must dd if=$TESTDIR/data of=$mntpnt/file bs=$bs count=$count
+sync_pool $TESTPOOL
+log_must dd if=$mntpnt/file of=$TESTDIR/out bs=$bs count=$count
+out_checksum=$(sha256digest $TESTDIR/out)
+
+if [[ "$data_checksum" != "$out_checksum" ]]; then
+ log_fail "checksum mismatch ($data_checksum != $out_checksum)"
+fi
+
+log_must rm -f $TESTDIR/out
+log_must zfs destroy $TESTPOOL/gang
+
+log_pass "Verified IO when file system is full and ganging."
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_rm.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_rm.ksh
index d0f4ff4a08fe..d9582fbe2a76 100755
--- a/tests/zfs-tests/tests/functional/no_space/enospc_rm.ksh
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_rm.ksh
@@ -17,6 +17,7 @@
#
# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
# Copyright (c) 2022 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2023 Hewlett Packard Enterprise Development LP.
#
. $STF_SUITE/include/libtest.shlib
@@ -51,12 +52,21 @@ log_must zfs create $TESTPOOL/$TESTFS
log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
log_must zfs set compression=off $TESTPOOL/$TESTFS
-log_note "Writing files until ENOSPC."
+log_note "Writing Big(1G) files until ENOSPC."
log_mustnot_expect "No space left on device" fio --name=test \
--fallocate=none --rw=write --bs=1M --size=1G --numjobs=4 \
--sync=1 --directory=$TESTDIR/ --group_reporting
log_must rm $TESTDIR/test.*
log_must test -z "$(ls -A $TESTDIR)"
+sync_pool $TESTPOOL true
+
+log_note "Writing small(10M) files until ENOSPC."
+log_mustnot_expect "No space left on device" fio --name=test \
+ --fallocate=none --rw=write --bs=1M --size=10M --numjobs=200 \
+ --sync=1 --directory=$TESTDIR/ --group_reporting
+
+log_must rm $TESTDIR/test.*
+log_must test -z "$(ls -A $TESTDIR)"
log_pass "All files removed without error"
diff --git a/tests/zfs-tests/tests/functional/no_space/setup.ksh b/tests/zfs-tests/tests/functional/no_space/setup.ksh
index 7ab8f1473d66..458a575ed3c0 100755
--- a/tests/zfs-tests/tests/functional/no_space/setup.ksh
+++ b/tests/zfs-tests/tests/functional/no_space/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib
index 139b4b26e5ed..a6d1eb2c769f 100644
--- a/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib
@@ -57,12 +57,12 @@ function verify_nopwrite
within_percent $origin_used $snap_refer $high || return 1
#
- # The comparisons below should pass regardless of nopwrite. They're
- # here for sanity.
+ # The comparisons below should be within 90% regardless of nopwrite.
+ # They're here for sanity.
#
typeset deadlist=$(zdb -Pddd $clone | awk '/Deadlist:/ {print $2}')
- within_percent $deadlist $clone_written $high || return 1
- within_percent $snap_refer $snap_written $high || return 1
+ within_percent $deadlist $clone_written 90 || return 1
+ within_percent $snap_refer $snap_written 90 || return 1
return 0
}
diff --git a/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh b/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh
index b81a372638e3..a0555aff06c2 100755
--- a/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg b/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg
index 6f1121c5e99e..18f197b54d4a 100644
--- a/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh
index 1d1b1c944cc0..d77103330a30 100755
--- a/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh
index a2427f2e1822..33244024284a 100755
--- a/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh
index e33db28f8ddb..1ff5b544b62c 100755
--- a/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/online_offline/setup.ksh b/tests/zfs-tests/tests/functional/online_offline/setup.ksh
index b1fb6a123897..0327c20a73cc 100755
--- a/tests/zfs-tests/tests/functional/online_offline/setup.ksh
+++ b/tests/zfs-tests/tests/functional/online_offline/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pam/cleanup.ksh b/tests/zfs-tests/tests/functional/pam/cleanup.ksh
index 8ea9c848b0ab..dbcb175ed069 100755
--- a/tests/zfs-tests/tests/functional/pam/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/pam/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -25,5 +25,6 @@
rmconfig
destroy_pool $TESTPOOL
del_user ${username}
+del_user ${username}rec
del_group pamtestgroup
log_must rm -rf "$runstatedir" $TESTDIRS
diff --git a/tests/zfs-tests/tests/functional/pam/pam_basic.ksh b/tests/zfs-tests/tests/functional/pam/pam_basic.ksh
index eab819ab8d24..dc54b2d253f8 100755
--- a/tests/zfs-tests/tests/functional/pam/pam_basic.ksh
+++ b/tests/zfs-tests/tests/functional/pam/pam_basic.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pam/pam_change_unmounted.ksh b/tests/zfs-tests/tests/functional/pam/pam_change_unmounted.ksh
new file mode 100755
index 000000000000..91b202f7609d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/pam_change_unmounted.ksh
@@ -0,0 +1,55 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+if [ -n "$ASAN_OPTIONS" ]; then
+ export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
+fi
+
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+genconfig "homes=$TESTPOOL/pam runstatedir=${runstatedir}"
+
+printf "testpass\nsecondpass\nsecondpass\n" | pamtester -v ${pamservice} ${username} chauthtok
+
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+echo "secondpass" | pamtester ${pamservice} ${username} open_session
+references 1
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+printf "secondpass\ntestpass\ntestpass\n" | pamtester -v ${pamservice} ${username} chauthtok
+
+log_must ismounted "$TESTPOOL/pam/${username}"
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+log_must pamtester ${pamservice} ${username} close_session
+references 0
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+log_pass "done."
diff --git a/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh b/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh
index 29ce437b40ee..011a873e5bfd 100755
--- a/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh
+++ b/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pam/pam_recursive.ksh b/tests/zfs-tests/tests/functional/pam/pam_recursive.ksh
new file mode 100755
index 000000000000..3714b179b852
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/pam_recursive.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+if [ -n "$ASAN_OPTIONS" ]; then
+ export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
+fi
+
+username="${username}rec"
+
+# Set up a deeper hierarchy, a mountpoint that doesn't interfere with other tests,
+# and a user which references that mountpoint
+log_must zfs create "$TESTPOOL/pampam"
+log_must zfs create -o mountpoint="$TESTDIR/rec" "$TESTPOOL/pampam/pam"
+echo "recurpass" | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase \
+ -o keylocation=prompt "$TESTPOOL/pampam/pam/${username}"
+log_must zfs unmount "$TESTPOOL/pampam/pam/${username}"
+log_must zfs unload-key "$TESTPOOL/pampam/pam/${username}"
+log_must add_user pamtestgroup ${username} "$TESTDIR/rec"
+
+function keystatus {
+ log_must [ "$(get_prop keystatus "$TESTPOOL/pampam/pam/${username}")" = "$1" ]
+}
+
+log_mustnot ismounted "$TESTPOOL/pampam/pam/${username}"
+keystatus unavailable
+
+function test_session {
+ echo "recurpass" | pamtester ${pamservice} ${username} open_session
+ references 1
+ log_must ismounted "$TESTPOOL/pampam/pam/${username}"
+ keystatus available
+
+ log_must pamtester ${pamservice} ${username} close_session
+ references 0
+ log_mustnot ismounted "$TESTPOOL/pampam/pam/${username}"
+ keystatus unavailable
+}
+
+genconfig "homes=$TESTPOOL/pampam/pam prop_mountpoint runstatedir=${runstatedir}"
+test_session
+
+genconfig "homes=$TESTPOOL/pampam recursive_homes prop_mountpoint runstatedir=${runstatedir}"
+test_session
+
+genconfig "homes=$TESTPOOL recursive_homes prop_mountpoint runstatedir=${runstatedir}"
+test_session
+
+genconfig "homes=* recursive_homes prop_mountpoint runstatedir=${runstatedir}"
+test_session
+
+log_pass "done."
diff --git a/tests/zfs-tests/tests/functional/pam/pam_short_password.ksh b/tests/zfs-tests/tests/functional/pam/pam_short_password.ksh
index 100f279fffed..079608583a72 100755
--- a/tests/zfs-tests/tests/functional/pam/pam_short_password.ksh
+++ b/tests/zfs-tests/tests/functional/pam/pam_short_password.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -52,7 +52,7 @@ log_must ismounted "$TESTPOOL/pam/${username}"
keystatus available
# Change user and dataset password to short one.
-printf "short\nshort\n" | pamtester ${pamservice} ${username} chauthtok
+printf "testpass\nshort\nshort\n" | pamtester -v ${pamservice} ${username} chauthtok
# Unmount and unload key.
log_must pamtester ${pamservice} ${username} close_session
diff --git a/tests/zfs-tests/tests/functional/pam/setup.ksh b/tests/zfs-tests/tests/functional/pam/setup.ksh
index 82370a211fcd..f08758d2f2dc 100755
--- a/tests/zfs-tests/tests/functional/pam/setup.ksh
+++ b/tests/zfs-tests/tests/functional/pam/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pam/utilities.kshlib.in b/tests/zfs-tests/tests/functional/pam/utilities.kshlib.in
index 29c6ada3dbf3..e118255dbd22 100644
--- a/tests/zfs-tests/tests/functional/pam/utilities.kshlib.in
+++ b/tests/zfs-tests/tests/functional/pam/utilities.kshlib.in
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh
index f970935f5bd0..087aef9027ea 100755
--- a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh
@@ -38,6 +38,8 @@
verify_runnable "global"
+log_unsupported "Skipping, issue https://github.com/openzfs/zfs/issues/12053"
+
function test_cleanup
{
# reset memory limit to 16M
diff --git a/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh b/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh
index 45ef2fd67a96..3695feb94931 100755
--- a/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh b/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh
index 4b6744563d07..2a688b6bfcee 100755
--- a/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh b/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh
index c9777b27e406..05d691313b40 100755
--- a/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh b/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh
index 1f4780ccd387..f759a1099cbc 100755
--- a/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh b/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh
index 15cd446b6ea6..1d7e42fcf394 100755
--- a/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/poolversion/setup.ksh b/tests/zfs-tests/tests/functional/poolversion/setup.ksh
index 660083b9fc00..9532404423d1 100755
--- a/tests/zfs-tests/tests/functional/poolversion/setup.ksh
+++ b/tests/zfs-tests/tests/functional/poolversion/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/privilege/cleanup.ksh b/tests/zfs-tests/tests/functional/privilege/cleanup.ksh
index 99985c670f2f..5acce6dc6555 100755
--- a/tests/zfs-tests/tests/functional/privilege/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/privilege/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh b/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh
index af4f705679a5..5e8b0d401966 100755
--- a/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh b/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh
index ab00e3295250..705c1a60e266 100755
--- a/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/privilege/setup.ksh b/tests/zfs-tests/tests/functional/privilege/setup.ksh
index 9d48d1961a7b..92b08b209a65 100755
--- a/tests/zfs-tests/tests/functional/privilege/setup.ksh
+++ b/tests/zfs-tests/tests/functional/privilege/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/procfs/cleanup.ksh b/tests/zfs-tests/tests/functional/procfs/cleanup.ksh
index 8fe46577e409..b3fb51695a2b 100755
--- a/tests/zfs-tests/tests/functional/procfs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/procfs/pool_state.ksh b/tests/zfs-tests/tests/functional/procfs/pool_state.ksh
index d29bfd806913..bae876379177 100755
--- a/tests/zfs-tests/tests/functional/procfs/pool_state.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/pool_state.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -141,7 +141,11 @@ remove_disk $SDISK
# background since the command will hang when the pool gets suspended. The
# command will resume and exit after we restore the missing disk later on.
zpool scrub $TESTPOOL2 &
-sleep 3 # Give the scrub some time to run before we check if it fails
+# Once we trigger the zpool scrub, all zpool/zfs command gets stuck for 180 seconds.
+# Post 180 seconds zpool/zfs commands gets start executing however few more seconds(10s)
+# it take to update the status.
+# hence sleeping for 200 seconds so that we get the correct status.
+sleep 200 # Give the scrub some time to run before we check if it fails
log_must check_all $TESTPOOL2 "SUSPENDED"
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh
index 18caea3c32cc..8eb35f85da32 100755
--- a/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh
index fcdd54da3591..59052ae05c0d 100755
--- a/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh
index dcc71788682d..be89e3b8c548 100755
--- a/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/procfs/setup.ksh b/tests/zfs-tests/tests/functional/procfs/setup.ksh
index 79fa28f4f1ac..f7d07d5d7211 100755
--- a/tests/zfs-tests/tests/functional/procfs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/procfs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh b/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh
index 0440e3d8af8c..fd04aaabc566 100755
--- a/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh
index 46e79062a0e2..ac5524b49d04 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh
index e382f464046b..ef87a1cb774b 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh
index d6dbaafc217a..93474b53709a 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg b/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg
index 564ab3ef9698..b8a37dbd05bb 100644
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh
index 3f8c3d68ce3e..f365bb9df617 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh
index 66cd1fb9ef71..7a92649ab4ad 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh
index 44a5b09f9001..5468759f7e12 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh
index 7ca81c3fbc81..a7a39f8fe7f7 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh
index 0736648f1ed6..ecd2bb278561 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh
index 73554df6a42a..984f4340d922 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh
index 3572e0118f45..a06551b56c96 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh
index b045b2c5fce3..20b64995f64a 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh
index da44e731a92d..52d896577a98 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib b/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib
index a90e001b2407..eea5b5100501 100644
--- a/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh
index 4005c2a408c6..97cb13b2343a 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh
index 1d48eccf22d0..6ea68ff32188 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh
index 8db5d0d89970..07b899c2ff12 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh
index 51e790348ca6..c928080a36c7 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh
index 0402e345df2a..2e048868fec6 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh
index 9942a88cb347..2494b8f7ef49 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh
index cbc45857f779..ec122301255a 100755
--- a/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/projectquota/setup.ksh b/tests/zfs-tests/tests/functional/projectquota/setup.ksh
index 0402d241b100..873d706afc01 100755
--- a/tests/zfs-tests/tests/functional/projectquota/setup.ksh
+++ b/tests/zfs-tests/tests/functional/projectquota/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in b/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in
index d55c4f3270ae..7fa14161a538 100755
--- a/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in
+++ b/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in
@@ -18,6 +18,8 @@
if [ -n "$ASAN_OPTIONS" ]; then
export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
+ # ASan reports leaks in CPython 3.10
+ ASAN_OPTIONS="$ASAN_OPTIONS:detect_leaks=false"
fi
#
@@ -30,20 +32,6 @@ fi
#
verify_runnable "global"
-
-# Verify that the required dependencies for testing are installed.
-@PYTHON@ -c "import cffi" 2>/dev/null ||
- log_unsupported "python3-cffi not found by Python"
-
-# We don't just try to "import libzfs_core" because we want to skip these tests
-# only if pyzfs was not installed due to missing, build-time, dependencies; if
-# we cannot load "libzfs_core" due to other reasons, for instance an API/ABI
-# mismatch, we want to report it.
-@PYTHON@ -c '
-import pkgutil, sys
-sys.exit(pkgutil.find_loader("libzfs_core") is None)' ||
- log_unsupported "libzfs_core not found by Python"
-
log_assert "Verify the nvlist and libzfs_core Python unittest run successfully"
# log_must buffers stderr, which interacts badly with
diff --git a/tests/zfs-tests/tests/functional/quota/cleanup.ksh b/tests/zfs-tests/tests/functional/quota/cleanup.ksh
index c4c369145dfc..8a6521193e66 100755
--- a/tests/zfs-tests/tests/functional/quota/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/quota/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/quota/quota.cfg b/tests/zfs-tests/tests/functional/quota/quota.cfg
index 5b19f40163de..5cb6ae002dbd 100644
--- a/tests/zfs-tests/tests/functional/quota/quota.cfg
+++ b/tests/zfs-tests/tests/functional/quota/quota.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/quota/quota.kshlib b/tests/zfs-tests/tests/functional/quota/quota.kshlib
index 12e882d47e34..b4cfde020f3f 100644
--- a/tests/zfs-tests/tests/functional/quota/quota.kshlib
+++ b/tests/zfs-tests/tests/functional/quota/quota.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -95,3 +95,10 @@ function exceed_quota
log_fail "Returned error code: $zret. Expected: $EDQUOT."
return 0
}
+
+function reset_quota
+{
+ typeset FILESYSTEM="$1"
+
+ log_must zfs set quota=none $FILESYSTEM
+}
diff --git a/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh
index d6783e9a43ac..f01008a46bb1 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -64,6 +64,8 @@ function cleanup
#
wait_freeing $TESTPOOL
sync_pool $TESTPOOL
+
+ reset_quota $TESTPOOL/$TESTFS
}
log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh
index 2f34072dd151..bea2a5a68691 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -64,6 +64,8 @@ function cleanup
wait_freeing $TESTPOOL
sync_pool $TESTPOOL
+
+ reset_quota $TESTPOOL/$TESTFS
}
log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh
index 6ab25cf2d463..33f6421131fc 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -67,6 +67,8 @@ function cleanup
#
wait_freeing $TESTPOOL
sync_pool $TESTPOOL
+
+ reset_quota $TESTPOOL/$TESTCTR/$TESTFS1
}
log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh
index 373354438925..682d09f080a4 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -65,6 +65,8 @@ function cleanup
wait_freeing $TESTPOOL
sync_pool $TESTPOOL
+
+ reset_quota $TESTPOOL/$TESTCTR/$TESTFS1
}
log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh
index e87139a58f69..9c4db81ca270 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -50,20 +50,19 @@ function cleanup
{
datasetexists $fs_child && destroy_dataset $fs_child
- log_must zfs set quota=$quota_val $fs
+ reset_quota $fs
}
log_onexit cleanup
-log_assert "Verify that quota doesnot inherit its value from parent."
-log_onexit cleanup
+log_assert "Verify that quota does not inherit its value from parent."
fs=$TESTPOOL/$TESTFS
fs_child=$TESTPOOL/$TESTFS/$TESTFS
space_avail=$(get_prop available $fs)
quota_val=$(get_prop quota $fs)
-typeset -i quotasize=$space_avail
+typeset -li quotasize=$space_avail
((quotasize = quotasize * 2 ))
log_must zfs set quota=$quotasize $fs
@@ -72,4 +71,4 @@ quota_space=$(get_prop quota $fs_child)
[[ $quota_space == $quotasize ]] && \
log_fail "The quota of child dataset inherits its value from parent."
-log_pass "quota doesnot inherit its value from parent as expected."
+log_pass "quota does not inherit its value from parent as expected."
diff --git a/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh b/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh
index ca5ea5f82f5a..111d771188e3 100755
--- a/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -50,7 +50,7 @@ log_assert "Verify cannot set quota lower than the space currently in use"
function cleanup
{
- log_must zfs set quota=none $TESTPOOL/$TESTFS
+ reset_quota $TESTPOOL/$TESTFS
}
log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/setup.ksh b/tests/zfs-tests/tests/functional/quota/setup.ksh
index 99a4cb3493ae..8ff0592c7632 100755
--- a/tests/zfs-tests/tests/functional/quota/setup.ksh
+++ b/tests/zfs-tests/tests/functional/quota/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/raidz/cleanup.ksh b/tests/zfs-tests/tests/functional/raidz/cleanup.ksh
index c92c54c270a7..c5bb8f9b4fa2 100755
--- a/tests/zfs-tests/tests/functional/raidz/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/raidz/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh
index 0f88a1a51468..9bd616f3a257 100755
--- a/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh
index e238a881b054..4bd11a94036d 100755
--- a/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -23,19 +23,39 @@
#
# Copyright (c) 2016 by Gvozden Neskovic. All rights reserved.
# Use is subject to license terms.
+# Copyright (c) 2020 by vStack. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
#
# DESCRIPTION:
-# Call the raidz_test tool with -S to test all supported raidz
-# implementations. This options will test several raidz block geometries
+# Call the raidz_test tool with sweep to test all supported raidz
+# implementations. This will test several raidz block geometries
# and several zio parameters that affect raidz block layout. Data
-# reconstruction performs all combinations of failed disks. Wall time
-# is set to 5min, but actual runtime might be longer.
+# reconstruction performs all combinations of failed disks. Wall
+# time is set to 5 min, but actual runtime might be longer.
#
-log_must raidz_test -S -t 300
-
-log_pass "raidz_test parameter sweep test succeeded."
+case $((RANDOM % 3)) in
+ 0)
+ # Basic sweep test
+ log_must raidz_test -S -t 300
+ log_pass "raidz_test parameter sweep test succeeded."
+ ;;
+ 1)
+ # Using expanded raidz map to test all supported raidz
+ # implementations with expanded map and default reflow offset.
+ log_must raidz_test -S -e -t 300
+ log_pass "raidz_test sweep test with expanded map succeeded."
+ ;;
+ 2)
+ # Using expanded raidz map ('-e') to test all supported raidz
+ # implementations with expanded map and zero reflow offset.
+ log_must raidz_test -S -e -r 0 -t 300
+ log_pass "raidz_test sweep test with expanded map succeeded."
+ ;;
+ *)
+ # avoid shellcheck SC2249
+ ;;
+esac
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_001_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_001_pos.ksh
new file mode 100755
index 000000000000..063d7fa735df
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_001_pos.ksh
@@ -0,0 +1,215 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2020 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool attach poolname raidz ...' should attach new device to the pool.
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool
+# 2. For each parity value [1..3]
+# - create raidz pool
+# - fill it with some directories/files
+# - attach device to the raidz pool
+# - verify that device attached and the raidz pool size increase
+# - verify resilver by replacing parity devices
+# - verify resilver by replacing data devices
+# - verify scrub by zeroing parity devices
+# - verify scrub by zeroing data devices
+# - verify the raidz pool
+# - destroy the raidz pool
+
+typeset -r devs=6
+typeset -r dev_size_mb=128
+
+typeset -a disks
+
+prefetch_disable=$(get_tunable PREFETCH_DISABLE)
+
+function cleanup
+{
+ log_pos zpool status $TESTPOOL
+
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 PREFETCH_DISABLE $prefetch_disable
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES 0
+}
+
+function wait_expand_paused
+{
+ oldcopied='0'
+ newcopied='1'
+ while [[ $oldcopied != $newcopied ]]; do
+ oldcopied=$newcopied
+ sleep 2
+ newcopied=$(zpool status $TESTPOOL | \
+ grep 'copied out of' | \
+ awk '{print $1}')
+ log_note "newcopied=$newcopied"
+ done
+ log_note "paused at $newcopied"
+}
+
+function test_resilver # <pool> <parity> <dir>
+{
+ typeset pool=$1
+ typeset nparity=$2
+ typeset dir=$3
+
+ for (( i=0; i<$nparity; i=i+1 )); do
+ log_must zpool offline $pool $dir/dev-$i
+ done
+
+ log_must zpool export $pool
+
+ for (( i=0; i<$nparity; i=i+1 )); do
+ log_must zpool labelclear -f $dir/dev-$i
+ done
+
+ log_must zpool import -o cachefile=none -d $dir $pool
+
+ for (( i=0; i<$nparity; i=i+1 )); do
+ log_must zpool replace -f $pool $dir/dev-$i
+ done
+
+ log_must zpool wait -t resilver $pool
+
+ log_must check_pool_status $pool "errors" "No known data errors"
+
+ log_must zpool clear $pool
+
+ for (( i=$nparity; i<$nparity*2; i=i+1 )); do
+ log_must zpool offline $pool $dir/dev-$i
+ done
+
+ log_must zpool export $pool
+
+ for (( i=$nparity; i<$nparity*2; i=i+1 )); do
+ log_must zpool labelclear -f $dir/dev-$i
+ done
+
+ log_must zpool import -o cachefile=none -d $dir $pool
+
+ for (( i=$nparity; i<$nparity*2; i=i+1 )); do
+ log_must zpool replace -f $pool $dir/dev-$i
+ done
+
+ log_must zpool wait -t resilver $pool
+
+ log_must check_pool_status $pool "errors" "No known data errors"
+
+ log_must zpool clear $pool
+}
+
+function test_scrub # <pool> <parity> <dir>
+{
+ typeset pool=$1
+ typeset nparity=$2
+ typeset dir=$3
+ typeset combrec=$4
+
+ reflow_size=$(get_pool_prop allocated $pool)
+ randbyte=$(( ((RANDOM<<15) + RANDOM) % $reflow_size ))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $randbyte
+ log_must zpool attach $TESTPOOL ${raid}-0 $dir/dev-$devs
+ wait_expand_paused
+
+ log_must zpool export $pool
+
+ # zero out parity disks
+ for (( i=0; i<$nparity; i=i+1 )); do
+ dd conv=notrunc if=/dev/zero of=$dir/dev-$i \
+ bs=1M seek=4 count=$(($dev_size_mb-4))
+ done
+
+ log_must zpool import -o cachefile=none -d $dir $pool
+
+ log_must zpool scrub -w $pool
+ log_must zpool clear $pool
+ log_must zpool export $pool
+
+ # zero out parity count worth of data disks
+ for (( i=$nparity; i<$nparity*2; i=i+1 )); do
+ dd conv=notrunc if=/dev/zero of=$dir/dev-$i \
+ bs=1M seek=4 count=$(($dev_size_mb-4))
+ done
+
+ log_must zpool import -o cachefile=none -d $dir $pool
+
+ log_must zpool scrub -w $pool
+
+ log_must check_pool_status $pool "errors" "No known data errors"
+
+ log_must zpool clear $pool
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES 0
+ log_must zpool wait -t raidz_expand $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 PREFETCH_DISABLE 1
+
+# Disk files which will be used by pool
+for i in {0..$(($devs - 1))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+# Disk file which will be attached
+log_must truncate -s 512M $TEST_BASE_DIR/dev-$devs
+
+nparity=$((RANDOM%(3) + 1))
+raid=raidz$nparity
+dir=$TEST_BASE_DIR
+
+log_must zpool create -f -o cachefile=none $TESTPOOL $raid ${disks[@]}
+log_must zfs set primarycache=metadata $TESTPOOL
+
+log_must zfs create $TESTPOOL/fs
+log_must fill_fs /$TESTPOOL/fs 1 512 100 1024 R
+
+log_must zfs create -o compress=on $TESTPOOL/fs2
+log_must fill_fs /$TESTPOOL/fs2 1 512 100 1024 R
+
+log_must zfs create -o compress=on -o recordsize=8k $TESTPOOL/fs3
+log_must fill_fs /$TESTPOOL/fs3 1 512 100 1024 R
+
+log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+
+test_scrub $TESTPOOL $nparity $dir
+test_resilver $TESTPOOL $nparity $dir
+
+zpool destroy "$TESTPOOL"
+
+log_pass "raidz expansion test succeeded."
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_002_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_002_pos.ksh
new file mode 100755
index 000000000000..004f3d1f9255
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_002_pos.ksh
@@ -0,0 +1,115 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2020 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool attach poolname raidz ...' should attach new devive to the pool.
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool
+# 2. For each parity value [1..3]
+# - create raidz pool with minimum block device files required
+# - for each free test block device
+# - attach to the pool
+# - verify the raidz pool
+# - destroy the raidz pool
+
+typeset -r devs=6
+typeset -r dev_size_mb=512
+
+typeset -a disks
+
+prefetch_disable=$(get_tunable PREFETCH_DISABLE)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 PREFETCH_DISABLE $prefetch_disable
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 PREFETCH_DISABLE 1
+
+# Disk files which will be used by pool
+for i in {0..$(($devs))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+nparity=$((RANDOM%(3) + 1))
+raid=raidz$nparity
+dir=$TEST_BASE_DIR
+pool=$TESTPOOL
+opts="-o cachefile=none"
+
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($nparity+1))]}
+log_must zfs set primarycache=metadata $pool
+
+log_must zfs create $pool/fs
+log_must fill_fs /$pool/fs 1 512 100 1024 R
+
+log_must zfs create -o compress=on $pool/fs2
+log_must fill_fs /$pool/fs2 1 512 100 1024 R
+
+log_must zfs create -o compress=on -o recordsize=8k $pool/fs3
+log_must fill_fs /$pool/fs3 1 512 100 1024 R
+
+typeset pool_size=$(get_pool_prop size $pool)
+
+for disk in ${disks[$(($nparity+2))..$devs]}; do
+ log_must dd if=/dev/urandom of=/${pool}/FILE-$RANDOM bs=1M \
+ count=64
+
+ log_must zpool attach -w $pool ${raid}-0 $disk
+
+ # Wait some time for pool size increase
+ sleep 5
+
+ # Confirm that disk was attached to the pool
+ log_must zpool get -H path $TESTPOOL $disk
+
+ typeset expand_size=$(get_pool_prop size $pool)
+ if [[ "$expand_size" -le "$pool_size" ]]; then
+ log_fail "pool $pool not expanded"
+ fi
+
+ verify_pool $pool
+
+ pool_size=$expand_size
+done
+
+zpool destroy "$pool"
+
+log_pass "raidz expansion test succeeded."
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_neg.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_neg.ksh
new file mode 100755
index 000000000000..4d85c46897b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_neg.ksh
@@ -0,0 +1,102 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2021 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool attach poolname raidz ...' should reject device attach if pool
+# is in checkpointed state. If checkpoint creation requested on
+# expanding pool, the request should be rejected.
+
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool.
+# 2. Create pool and checkpoint it.
+# 3. Try to expand raidz, ensure that request rejected.
+# 4. Recreate the pool.
+# 5. Apply raidz expansion.
+# 6. Ensure, that checkpoint cannot be created.
+
+typeset -r devs=6
+typeset -r dev_size_mb=512
+
+typeset -a disks
+
+prefetch_disable=$(get_tunable PREFETCH_DISABLE)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 PREFETCH_DISABLE $prefetch_disable
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES 0
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 PREFETCH_DISABLE 1
+
+# Disk files which will be used by pool
+for i in {0..$(($devs))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+nparity=1
+raid=raidz$nparity
+pool=$TESTPOOL
+opts="-o cachefile=none"
+
+# case 1: checkpoint exist, try to expand
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($devs-1))]}
+log_must zfs set primarycache=metadata $pool
+log_must zpool checkpoint $pool
+log_mustnot zpool attach $pool ${raid}-0 ${disks[$devs]}
+log_must zpool destroy $pool
+
+#
+# case 2: expansion in progress, try to checkpoint
+#
+# Sets pause point at 25% of allocated space so that we know an
+# expansion is still in progress when we attempt the checkpoint
+#
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($devs-1))]}
+log_must zfs set primarycache=metadata $pool
+log_must zfs create $pool/fs
+log_must fill_fs /$pool/fs 1 512 100 1024 R
+allocated=$(zpool list -Hp -o allocated $pool)
+log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $((allocated / 4))
+log_must zpool attach $pool ${raid}-0 ${disks[$devs]}
+log_mustnot zpool checkpoint $pool
+log_must zpool destroy $pool
+
+log_pass "raidz expansion test succeeded."
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_pos.ksh
new file mode 100755
index 000000000000..712b25261773
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_003_pos.ksh
@@ -0,0 +1,141 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2021 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib
+
+#
+# DESCRIPTION:
+# Check raidz expansion is able to work correctly under i/o load.
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool
+# 2. For each parity value [1..3]
+# - create raidz pool with minimum block device files required
+# - create couple of datasets with different recordsize and fill it
+# - set a max reflow value near pool capacity
+# - wait for reflow to reach this max
+# - verify pool
+# - set reflow bytes to max value to complete the expansion
+
+typeset -r devs=10
+typeset -r dev_size_mb=256
+
+typeset -a disks
+
+embedded_slog_min_ms=$(get_tunable EMBEDDED_SLOG_MIN_MS)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && zpool status -v "$TESTPOOL"
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 EMBEDDED_SLOG_MIN_MS $embedded_slog_min_ms
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES 0
+}
+
+function wait_expand_paused
+{
+ oldcopied='0'
+ newcopied='1'
+ # wait until reflow copied value stops changing
+ while [[ $oldcopied != $newcopied ]]; do
+ oldcopied=$newcopied
+ sleep 1
+ newcopied=$(zpool status $TESTPOOL | \
+ grep 'copied out of' | \
+ awk '{print $1}')
+ done
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 99999
+
+# Disk files which will be used by pool
+for i in {0..$(($devs))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+nparity=$((RANDOM%(3) + 1))
+raid=raidz$nparity
+pool=$TESTPOOL
+opts="-o cachefile=none"
+
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($nparity+1))]}
+
+log_must zfs create -o recordsize=8k $pool/fs
+log_must fill_fs /$pool/fs 1 256 100 1024 R
+
+log_must zfs create -o recordsize=128k $pool/fs2
+log_must fill_fs /$pool/fs2 1 256 100 1024 R
+
+for disk in ${disks[$(($nparity+2))..$devs]}; do
+ log_must mkfile -n 400m /$pool/fs/file
+ log_bkgrnd randwritecomp /$pool/fs/file 250
+ pid0=$!
+
+ # start some random writes in the background during expansion
+ log_must mkfile -n 400m /$pool/fs2/file2
+ log_bkgrnd randwritecomp /$pool/fs2/file2 250
+ pid1=$!
+ sleep 10
+
+ # Pause at half total bytes to be copied for expansion
+ reflow_size=$(get_pool_prop allocated $pool)
+ log_note need to reflow $reflow_size bytes
+ pause=$((reflow_size/2))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $pause
+
+ log_must zpool attach $pool ${raid}-0 $disk
+ wait_expand_paused
+
+ kill_if_running $pid0
+ kill_if_running $pid1
+
+ log_must zpool scrub -w $pool
+
+ log_must check_pool_status $pool "errors" "No known data errors"
+ log_must check_pool_status $pool "scan" "with 0 errors"
+ log_must check_pool_status $pool "scan" "repaired 0B"
+
+ # Set pause past largest possible value for this pool
+ pause=$((devs*dev_size_mb*1024*1024))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $pause
+
+ log_must zpool wait -t raidz_expand $pool
+done
+
+log_must zpool destroy "$pool"
+
+log_pass "raidz expansion test succeeded."
+
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_004_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_004_pos.ksh
new file mode 100755
index 000000000000..2be55dae4254
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_004_pos.ksh
@@ -0,0 +1,121 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2021 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Check device replacement during raidz expansion.
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool
+# 2. For each parity value [1..3]
+# - create raidz pool with minimum block device files required
+# - create couple of datasets with different recordsize and fill it
+# - attach new device to the pool
+# - offline and zero vdevs allowed by parity
+# - wait some time and start offlined vdevs replacement
+# - wait replacement completion and verify pool status
+
+typeset -r devs=10
+typeset -r dev_size_mb=128
+
+typeset -a disks
+
+embedded_slog_min_ms=$(get_tunable EMBEDDED_SLOG_MIN_MS)
+original_scrub_after_expand=$(get_tunable SCRUB_AFTER_EXPAND)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 EMBEDDED_SLOG_MIN_MS $embedded_slog_min_ms
+ log_must set_tunable32 SCRUB_AFTER_EXPAND $original_scrub_after_expand
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 99999
+
+# Disk files which will be used by pool
+for i in {0..$(($devs))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+nparity=$((RANDOM%(3) + 1))
+raid=raidz$nparity
+pool=$TESTPOOL
+opts="-o cachefile=none"
+
+log_must set_tunable32 SCRUB_AFTER_EXPAND 0
+
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($nparity+1))]}
+
+log_must zfs create -o recordsize=8k $pool/fs
+log_must fill_fs /$pool/fs 1 128 100 1024 R
+
+log_must zfs create -o recordsize=128k $pool/fs2
+log_must fill_fs /$pool/fs2 1 128 100 1024 R
+
+for disk in ${disks[$(($nparity+2))..$devs]}; do
+ log_must zpool attach $pool ${raid}-0 $disk
+
+ sleep 10
+
+ for (( i=1; i<=$nparity; i=i+1 )); do
+ log_must zpool offline $pool ${disks[$i]}
+ log_must dd if=/dev/zero of=${disks[$i]} \
+ bs=1024k count=$dev_size_mb conv=notrunc
+ done
+
+ sleep 3
+
+ for (( i=1; i<=$nparity; i=i+1 )); do
+ log_must zpool replace $pool ${disks[$i]}
+ done
+
+ log_must zpool wait -t replace $pool
+ log_must check_pool_status $pool "scan" "with 0 errors"
+
+ log_must zpool wait -t raidz_expand $pool
+
+ log_must zpool clear $pool
+ log_must zpool scrub -w $pool
+
+ log_must zpool status -v
+ log_must check_pool_status $pool "scan" "with 0 errors"
+done
+
+log_must zpool destroy "$pool"
+
+log_pass "raidz expansion test succeeded."
+
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh
new file mode 100755
index 000000000000..56ee3e9be67c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh
@@ -0,0 +1,177 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2021 by vStack. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Check device replacement during raidz expansion using expansion pausing.
+#
+# STRATEGY:
+# 1. Create block device files for the test raidz pool
+# 2. For each parity value [1..3]
+# - create raidz pool with minimum block device files required
+# - create couple of datasets with different recordsize and fill it
+# - set raidz expand maximum reflow bytes
+# - attach new device to the pool
+# - wait for reflow bytes to reach the maximum
+# - offline and zero vdevs allowed by parity
+# - wait some time and start offlined vdevs replacement
+# - wait replacement completion and verify pool status
+# - loop thru vdevs replacing with the max reflow bytes increasing
+# - verify pool
+# - set reflow bytes to max value to complete the expansion
+
+typeset -r devs=10
+typeset -r dev_size_mb=128
+
+typeset -a disks
+
+embedded_slog_min_ms=$(get_tunable EMBEDDED_SLOG_MIN_MS)
+original_scrub_after_expand=$(get_tunable SCRUB_AFTER_EXPAND)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && zpool status -v "$TESTPOOL"
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ log_must set_tunable32 EMBEDDED_SLOG_MIN_MS $embedded_slog_min_ms
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES 0
+ log_must set_tunable32 SCRUB_AFTER_EXPAND $original_scrub_after_expand
+}
+
+function wait_expand_paused
+{
+ oldcopied='0'
+ newcopied='1'
+ while [[ $oldcopied != $newcopied ]]; do
+ oldcopied=$newcopied
+ sleep 1
+ newcopied=$(zpool status $TESTPOOL | \
+ grep 'copied out of' | \
+ awk '{print $1}')
+ done
+}
+
+log_onexit cleanup
+
+function test_replace # <pool> <devices> <parity>
+{
+ pool=${1}
+ devices=${2}
+ nparity=${3}
+ device_count=0
+
+ log_must echo "devices=$devices"
+
+ for dev in ${devices}; do
+ device_count=$((device_count+1))
+ done
+
+ index=$((RANDOM%(device_count-nparity)))
+ for (( j=1; j<=$nparity; j=j+1 )); do
+ log_must zpool offline $pool ${disks[$((index+j))]}
+ log_must dd if=/dev/zero of=${disks[$((index+j))]} \
+ bs=1024k count=$dev_size_mb conv=notrunc
+ done
+
+ for (( j=1; j<=$nparity; j=j+1 )); do
+ log_must zpool replace $pool ${disks[$((index+j))]}
+ done
+
+ log_must zpool wait -t replace $pool
+ log_must check_pool_status $pool "scan" "with 0 errors"
+
+ log_must zpool clear $pool
+ log_must zpool scrub -w $pool
+
+ log_must zpool status -v
+ log_must check_pool_status $pool "scan" "with 0 errors"
+}
+
+log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 99999
+
+# Disk files which will be used by pool
+for i in {0..$(($devs))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+nparity=$((RANDOM%(3) + 1))
+raid=raidz$nparity
+pool=$TESTPOOL
+opts="-o cachefile=none"
+devices=""
+
+log_must set_tunable32 SCRUB_AFTER_EXPAND 0
+
+log_must zpool create -f $opts $pool $raid ${disks[1..$(($nparity+1))]}
+devices="${disks[1..$(($nparity+1))]}"
+
+log_must zfs create -o recordsize=8k $pool/fs
+log_must fill_fs /$pool/fs 1 128 100 1024 R
+
+log_must zfs create -o recordsize=128k $pool/fs2
+log_must fill_fs /$pool/fs2 1 128 100 1024 R
+
+for disk in ${disks[$(($nparity+2))..$devs]}; do
+ # Set pause to some random value near halfway point
+ reflow_size=$(get_pool_prop allocated $pool)
+ pause=$((((RANDOM << 15) + RANDOM) % reflow_size / 2))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $pause
+
+ log_must zpool attach $pool ${raid}-0 $disk
+ devices="$devices $disk"
+
+ wait_expand_paused
+
+ for (( i=0; i<2; i++ )); do
+ test_replace $pool "$devices" $nparity
+
+ # Increase pause by about 25%
+ pause=$((pause + (((RANDOM << 15) + RANDOM) % \
+ reflow_size) / 4))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $pause
+
+ wait_expand_paused
+ done
+
+ # Set pause past largest possible value for this pool
+ pause=$((devs*dev_size_mb*1024*1024))
+ log_must set_tunable64 RAIDZ_EXPAND_MAX_REFLOW_BYTES $pause
+
+ log_must zpool wait -t raidz_expand $pool
+done
+
+log_must zpool destroy "$pool"
+
+log_pass "raidz expansion test succeeded."
+
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_006_neg.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_006_neg.ksh
new file mode 100755
index 000000000000..35ba8bde2392
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_006_neg.ksh
@@ -0,0 +1,78 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by iXsystems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool attach poolname raidz ...' should fail if raidz_expansion
+# feature is not enabled.
+#
+# STRATEGY:
+# 1. Create raidz pool with raidz_expansion feature disabled
+# 2. Attempt to attach a device to the raidz vdev
+# 3. Verify that device attached failed
+# 4. Destroy the raidz pool
+
+typeset -r devs=4
+typeset -r dev_size_mb=128
+typeset -a disks
+
+function cleanup
+{
+ log_pos zpool status "$TESTPOOL"
+
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+}
+
+log_onexit cleanup
+
+for i in {0..$devs}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M "$device"
+ if [[ $i -ne $devs ]]; then
+ disks[${#disks[*]}+1]=$device
+ fi
+done
+
+# create a pool with raidz_expansion feature disabled
+log_must zpool create -f -o cachefile=none -o feature@raidz_expansion=disabled \
+ "$TESTPOOL" raidz1 "${disks[@]}"
+status=$(zpool list -H -o feature@raidz_expansion "$TESTPOOL")
+if [[ "$status" != "disabled" ]]; then
+ log_fail "raidz_expansion feature was not disabled"
+fi
+
+# expecting attach to fail
+log_mustnot_expect "raidz_expansion feature must be enabled" zpool attach -f \
+ "$TESTPOOL" raidz1-0 "$TEST_BASE_DIR/dev-$devs"
+log_must zpool destroy "$TESTPOOL"
+
+log_pass "raidz attach failed with feature disabled as expected"
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_expand_007_neg.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_expand_007_neg.ksh
new file mode 100755
index 000000000000..78294cb9e516
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_expand_007_neg.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2023 by iXsystems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Negative for FreeBSD Only
+#
+# Attempting to expand a RAIDZ should fail if the scratch area on the
+# existing disks contains BTX Server binary (used to boot FreeBSD when
+# using MBR partitions with ZFS).
+#
+# STRATEGY:
+# 1. Create raidz pool
+# 2. Add a BTX header to the reserved boot area
+# 3. Attempt to attach a device to the raidz vdev
+# 4. Verify that device attached failed
+# 5. Destroy the raidz pool
+
+typeset -r devs=4
+typeset -r dev_size_mb=128
+typeset -a disks
+
+function cleanup
+{
+ log_pos zpool status "$TESTPOOL"
+
+ poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ log_must rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+}
+
+log_onexit cleanup
+
+for i in {0..$devs}; do
+ device=$TEST_BASE_DIR/dev-$i
+ # simulate active BTX Server data by inserting a BTX header
+ printf "\xeb\x0e%s\x01\x02\x80" "BTX" | dd of="$device" \
+ bs=512 seek=1024 status=none
+ log_must truncate -s ${dev_size_mb}M "$device"
+ if [[ $i -ne $devs ]]; then
+ disks[${#disks[*]}+1]=$device
+ fi
+done
+
+log_must zpool create -f -o cachefile=none "$TESTPOOL" raidz1 "${disks[@]}"
+
+if is_freebsd; then
+ # expecting attach to fail
+ log_mustnot_expect "the reserved boot area" zpool attach -f \
+ "$TESTPOOL" raidz1-0 "$TEST_BASE_DIR/dev-$devs"
+ log_must zpool destroy "$TESTPOOL"
+ log_pass "raidz attach failed with in-use reserved boot area"
+else
+ # expecting attach to pass everywhere else
+ log_must zpool attach -f "$TESTPOOL" raidz1-0 "$TEST_BASE_DIR/dev-$devs"
+ log_must zpool destroy "$TESTPOOL"
+ log_pass "raidz attach passed with in-use reserved boot area"
+fi
+
diff --git a/tests/zfs-tests/tests/functional/raidz/setup.ksh b/tests/zfs-tests/tests/functional/raidz/setup.ksh
index 4e155d24d544..47821e42915e 100755
--- a/tests/zfs-tests/tests/functional/raidz/setup.ksh
+++ b/tests/zfs-tests/tests/functional/raidz/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh b/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh
index 1a7c142b8551..2c344f0ed3d8 100755
--- a/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg b/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg
index 3b9e1714dfe9..9608b87f107b 100644
--- a/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib b/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib
index a3810d55f97c..cc1cf0411027 100644
--- a/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib
@@ -8,7 +8,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh
index 3386643b295e..f2150be3bc95 100755
--- a/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh
@@ -27,7 +27,6 @@
# second (the last block in the file) is common to them all.
# 2. Verify a redacted stream with a reasonable redaction list length can
# be correctly processed.
-# 3. Verify that if the list is too long, the send fails gracefully.
#
typeset ds_name="many_clones"
@@ -56,13 +55,18 @@ for i in {1..64}; do
log_must zfs snapshot ${clone}$i@snap
done
-# The limit isn't necessarily 32 snapshots. The maximum number of snapshots in
+# The limit isn't necessarily 64 snapshots. The maximum number of snapshots in
# the redacted list is determined in dsl_bookmark_create_redacted_check().
-log_must zfs redact $sendfs@snap book1 $clone{1..32}@snap
+log_must zfs redact $sendfs@snap book1 $clone{1..64}@snap
log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
log_must eval "zfs recv $recvfs <$stream"
compare_files $sendfs $recvfs "f2" "$RANGE8"
-log_mustnot zfs redact $sendfs@snap book2 $clone{1..64}@snap
+rls_value="$(zpool get -H -o value feature@redaction_list_spill $POOL)"
+if [ "$rls_value" = "active" ]; then
+ log_note "redaction_list_spill feature active"
+else
+ log_fail "redaction_list_spill feature not active"
+fi
log_pass "Redacted send can deal with a large redaction list."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/setup.ksh b/tests/zfs-tests/tests/functional/redacted_send/setup.ksh
index 3f537f813db0..6e08bec2e822 100755
--- a/tests/zfs-tests/tests/functional/redacted_send/setup.ksh
+++ b/tests/zfs-tests/tests/functional/redacted_send/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh b/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh
index ba8d980710ee..1c95d752c5a0 100755
--- a/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg b/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg
index 37b93820bc1d..3e7916257ff4 100644
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib b/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
index 78c33d81db26..297c6a073bb9 100644
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -45,28 +45,6 @@ function cleanup
}
#
-# Get random number between min and max number.
-#
-# $1 Minimal value
-# $2 Maximal value
-#
-function random
-{
- typeset -i min=$1
- typeset -i max=$2
- typeset -i value
-
- while true; do
- ((value = RANDOM % (max + 1)))
- if ((value >= min)); then
- break
- fi
- done
-
- echo $value
-}
-
-#
# Get the number of checksum errors for the pool.
#
# $1 Pool
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
index 285318853a9e..8208d2b4a398 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid1.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid1.ksh
index 85d420ab0d3a..a59743592eca 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid1.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid1.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid2.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid2.ksh
index 04f1fdfb150d..48c4a24cb496 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid2.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid2.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid3.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid3.ksh
index d4c823ed9b37..8e1ad237b5a2 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid3.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid3.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
index da2d58eef6f3..110c69159eb1 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
index 8e06db9bad99..b0bb4ef84129 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh
index b7b791b248ee..3410ac018b83 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz.ksh
index a3ea3e53cb75..83cacda84b09 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh
index a73890e4cc05..5700aa440606 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh
index 94b9b8825154..d73d80114b6b 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz3.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz3.ksh
index 0a01c47106b3..9839d9b63145 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz3.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz3.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh
index b2c4a85febef..774226acda96 100755
--- a/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/redundancy/setup.ksh b/tests/zfs-tests/tests/functional/redundancy/setup.ksh
index e2c04fe5cfbd..0ac48c82a810 100755
--- a/tests/zfs-tests/tests/functional/redundancy/setup.ksh
+++ b/tests/zfs-tests/tests/functional/redundancy/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/cleanup.ksh b/tests/zfs-tests/tests/functional/refquota/cleanup.ksh
index ea139ae0395b..2f0a02ed8dd3 100755
--- a/tests/zfs-tests/tests/functional/refquota/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh
index 411fab8459af..6583210ca3ec 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh
index e1d3aa82033c..e2c42529c9d4 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh
index e4def1a0a7b4..7f7c2ba683f1 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh
index 0691c3630931..8051f9af833c 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh
index 13977bc3b48f..cfccff5f1af5 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh
index 39b317512df2..d0d9d12b0813 100755
--- a/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refquota/setup.ksh b/tests/zfs-tests/tests/functional/refquota/setup.ksh
index 48bd314cd2dc..aae97e80f7b3 100755
--- a/tests/zfs-tests/tests/functional/refquota/setup.ksh
+++ b/tests/zfs-tests/tests/functional/refquota/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh b/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh
index ea139ae0395b..2f0a02ed8dd3 100755
--- a/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg b/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg
index 8c892db4a3a2..818e7e8283a2 100644
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh
index 527949f27c10..82904663b668 100755
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh
index 6b096f5d2010..ed45eb782e12 100755
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh
index 3e5a78cf944f..aa910facb984 100755
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh
index 529d918c3695..ec67ccf44057 100755
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh
index 1ccc9828d4f7..e078e76ad698 100755
--- a/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/refreserv/setup.ksh b/tests/zfs-tests/tests/functional/refreserv/setup.ksh
index 48bd314cd2dc..aae97e80f7b3 100755
--- a/tests/zfs-tests/tests/functional/refreserv/setup.ksh
+++ b/tests/zfs-tests/tests/functional/refreserv/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh
index cede81ad60c2..3533c41cac28 100755
--- a/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh
+++ b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh
@@ -15,7 +15,7 @@
#
#
-# Copyright (c) 2019 by Delphix. All rights reserved.
+# Copyright (c) 2019, 2022 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
@@ -24,19 +24,35 @@
default_setup_noexit "$DISKS"
log_onexit default_cleanup_noexit
-BLOCKSIZE=8192
+
+#
+# Randomly pick a device to remove
+#
+DISK_TOKENS=( $DISKS )
+DISK_INDEX_TO_REMOVE=$((RANDOM%${#DISK_TOKENS[@]}))
+DISK_TO_REMOVE=${DISK_TOKENS[${DISK_INDEX_TO_REMOVE}]}
origin="$TESTPOOL/$TESTFS"
log_must zfs set compress=on $origin
log_must zfs set checksum=skein $origin
+log_must zfs set copies=1 $origin
log_must zfs set recordsize=8k $origin
dd if=/dev/urandom of=$TESTDIR/file_8k bs=1024k count=$MEGS oflag=sync \
conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+log_must zfs set copies=3 $origin
+dd if=/dev/urandom of=$TESTDIR/file_8k_copies bs=1024k count=$MEGS oflag=sync \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+
+log_must zfs set copies=1 $origin
log_must zfs set recordsize=128k $origin
dd if=/dev/urandom of=$TESTDIR/file_128k bs=1024k count=$MEGS oflag=sync \
conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+log_must zfs set copies=3 $origin
+dd if=/dev/urandom of=$TESTDIR/file_128k_copies bs=1024k \
+ count=$MEGS oflag=sync conv=notrunc >/dev/null 2>&1 || \
+ log_fail "dd into $TESTDIR/file failed."
zfs snapshot $origin@a || log_fail "zfs snap failed"
log_must zfs clone $origin@a $origin/clone
@@ -44,22 +60,33 @@ log_must zfs clone $origin@a $origin/clone
#
# Verify that nopwrites work prior to removal
#
+log_must zfs set copies=1 $origin/clone
log_must zfs set recordsize=8k $origin/clone
dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \
oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
log_must verify_nopwrite $origin $origin@a $origin/clone
+log_must zfs set copies=3 $origin/clone
+dd if=/$TESTDIR/file_8k_copies of=/$TESTDIR/clone/file_8k_copies bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_must verify_nopwrite $origin $origin@a $origin/clone
+log_must zfs set copies=1 $origin/clone
log_must zfs set recordsize=128k $origin/clone
dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \
oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
log_must verify_nopwrite $origin $origin@a $origin/clone
+log_must zfs set copies=3 $origin/clone
+dd if=/$TESTDIR/file_128k_copies of=/$TESTDIR/clone/file_128k_copies bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_must verify_nopwrite $origin $origin@a $origin/clone
#
# Remove a device before testing nopwrites again
#
-log_must zpool remove $TESTPOOL $REMOVEDISK
+log_note "Removing: $DISK_TO_REMOVE"
+log_must zpool remove $TESTPOOL $DISK_TO_REMOVE
log_must wait_for_removal $TESTPOOL
-log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+log_mustnot vdevs_in_pool $TESTPOOL $DISK_TO_REMOVE
#
# Normally, we expect nopwrites to avoid allocating new blocks, but
@@ -71,17 +98,27 @@ log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
#
# Perform a direct zil nopwrite test
#
+log_must zfs set copies=1 $origin/clone
log_must zfs set recordsize=8k $origin/clone
dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \
oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+log_must zfs set copies=3 $origin/clone
+dd if=/$TESTDIR/file_8k_copies of=/$TESTDIR/clone/file_8k_copies bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
#
# Perform an indirect zil nopwrite test
#
+log_must zfs set copies=1 $origin/clone
log_must zfs set recordsize=128k $origin/clone
dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \
oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+log_must zfs set copies=3 $origin/clone
+dd if=/$TESTDIR/file_128k_copies of=/$TESTDIR/clone/file_128k_copies bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
log_pass "Remove works with nopwrite."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_indirect.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_indirect.ksh
new file mode 100755
index 000000000000..2a7878f4a2d5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_indirect.ksh
@@ -0,0 +1,57 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# 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.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2014, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+
+DISK1="$TMPDIR/dsk1"
+DISK2="$TMPDIR/dsk2"
+DISK3="$TMPDIR/dsk3"
+DISK4="$TMPDIR/dsk4"
+DISKS="$DISK1 $DISK2 $DISK3 $DISK4"
+
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK1
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK2
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK3
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK4
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+}
+
+# Build a zpool with 2 mirror vdevs
+log_must default_setup_noexit "mirror $DISK1 $DISK2 mirror $DISK3 $DISK4"
+log_onexit cleanup
+
+# Remove one of the mirrors
+log_must zpool remove $TESTPOOL mirror-1
+log_must wait_for_removal $TESTPOOL
+
+# Attempt to add a single-device vdev, shouldn't work
+log_mustnot zpool add $TESTPOOL $DISK3
+
+# Force it, should work
+log_must zpool add -f $TESTPOOL $DISK3
+
+log_pass "Prevented from adding a non-mirror vdev on a mirrored zpool w/ indirect vdevs"
diff --git a/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh b/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh
index 06335b70360a..a62479f2a1e4 100755
--- a/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh
+++ b/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh
@@ -49,7 +49,8 @@ log_mustnot zpool remove $TESTPOOL $DISK2
log_must wait_for_removal $TESTPOOL
# Add back the first disk.
-log_must zpool add $TESTPOOL $DISK1
+# We use -f as we're adding a single vdev to zpool with only mirrors.
+log_must zpool add -f $TESTPOOL $DISK1
# Now attempt to remove the mirror.
log_must zpool remove $TESTPOOL mirror-1
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh b/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh b/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh
index 938a7d391ab5..10e4be0e2581 100755
--- a/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh b/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh
index fc5cec3063a6..b756d4e76c83 100755
--- a/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_004_pos.ksh b/tests/zfs-tests/tests/functional/renameat2/cleanup.ksh
index 6cd2bf7c9f60..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/raidz/raidz_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/renameat2/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -21,21 +21,14 @@
#
#
-# Copyright (c) 2020 by vStack. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
#
-. $STF_SUITE/include/libtest.shlib
-
#
-# DESCRIPTION:
-# Call the raidz_test tool with -S and -e to test all supported raidz
-# implementations with expanded map and zero reflow offset.
-# This options will test several raidz block geometries and several zio
-# parameters that affect raidz block layout. Data reconstruction performs
-# all combinations of failed disks. Wall time is set to 5min, but actual
-# runtime might be longer.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
-log_must raidz_test -S -e -r 0 -t 60
+. $STF_SUITE/include/libtest.shlib
-log_pass "raidz_test parameter sweep test with expanded map succeeded."
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/renameat2/renameat2_exchange.ksh b/tests/zfs-tests/tests/functional/renameat2/renameat2_exchange.ksh
new file mode 100755
index 000000000000..b9d5d6498bc5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/renameat2/renameat2_exchange.ksh
@@ -0,0 +1,61 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
+# Copyright (C) 2019 SUSE LLC
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm -rf $TESTDIR/*
+}
+
+log_assert "ZFS supports RENAME_EXCHANGE."
+log_onexit cleanup
+
+cd $TESTDIR
+echo "foo" > foo
+echo "bar" > bar
+
+# Self-exchange is a no-op.
+log_must renameat2 -x foo foo
+log_must grep '^foo$' foo
+
+# Basic exchange.
+log_must renameat2 -x foo bar
+log_must grep '^bar$' foo
+log_must grep '^foo$' bar
+
+# And exchange back.
+log_must renameat2 -x foo bar
+log_must grep '^foo$' foo
+log_must grep '^bar$' bar
+
+# Exchange with a bad path should fail.
+log_mustnot renameat2 -x bar baz
+
+log_pass "ZFS supports RENAME_EXCHANGE as expected."
diff --git a/tests/zfs-tests/tests/functional/renameat2/renameat2_noreplace.ksh b/tests/zfs-tests/tests/functional/renameat2/renameat2_noreplace.ksh
new file mode 100755
index 000000000000..c8ce12b1ca82
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/renameat2/renameat2_noreplace.ksh
@@ -0,0 +1,51 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
+# Copyright (C) 2019 SUSE LLC
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm -rf $TESTDIR/*
+}
+
+log_assert "ZFS supports RENAME_NOREPLACE."
+log_onexit cleanup
+
+cd $TESTDIR
+touch foo bar
+
+# Clobbers should always fail.
+log_mustnot renameat2 -n foo foo
+log_mustnot renameat2 -n foo bar
+log_mustnot renameat2 -n bar foo
+
+# Regular renames should succeed.
+log_must renameat2 -n bar baz
+
+log_pass "ZFS supports RENAME_NOREPLACE as expected."
diff --git a/tests/zfs-tests/tests/functional/renameat2/renameat2_whiteout.ksh b/tests/zfs-tests/tests/functional/renameat2/renameat2_whiteout.ksh
new file mode 100755
index 000000000000..7e7a3ba5efeb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/renameat2/renameat2_whiteout.ksh
@@ -0,0 +1,50 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
+# Copyright (C) 2019 SUSE LLC
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm -rf $TESTDIR/*
+}
+
+log_assert "ZFS supports RENAME_WHITEOUT."
+log_onexit cleanup
+
+cd $TESTDIR
+echo "whiteout" > whiteout
+
+# Straight-forward rename-with-whiteout.
+log_must renameat2 -w whiteout new
+# Check new file.
+log_must grep '^whiteout$' new
+# Check that the whiteout is actually a {0,0} char device.
+log_must grep '^character special file:0:0$' <<<"$(stat -c '%F:%t:%T' whiteout)"
+
+log_pass "ZFS supports RENAME_WHITEOUT as expected."
diff --git a/tests/zfs-tests/tests/functional/renameat2/setup.ksh b/tests/zfs-tests/tests/functional/renameat2/setup.ksh
new file mode 100755
index 000000000000..9b34b18cd5cd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/renameat2/setup.ksh
@@ -0,0 +1,37 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
+# Copyright (C) 2019 SUSE LLC
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+if ! is_linux ; then
+ log_unsupported "renameat2 is linux-only"
+elif ! renameat2 -C ; then
+ log_unsupported "renameat2 not supported on this (pre-3.15) linux kernel"
+fi
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh b/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh
index 384a588064b1..8b4cb9da2d23 100755
--- a/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh b/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh
index d855ad928b60..724a7865fe69 100755
--- a/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/cleanup.ksh b/tests/zfs-tests/tests/functional/replacement/cleanup.ksh
index b81a372638e3..a0555aff06c2 100755
--- a/tests/zfs-tests/tests/functional/replacement/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/detach.ksh b/tests/zfs-tests/tests/functional/replacement/detach.ksh
index 8c8eb1e88331..c563a015ad9a 100755
--- a/tests/zfs-tests/tests/functional/replacement/detach.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/detach.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh b/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh
index 19823de1240d..ea1fabdbbeb9 100755
--- a/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh b/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh
index f25e8f548b72..bdca3c772584 100755
--- a/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/replacement.cfg b/tests/zfs-tests/tests/functional/replacement/replacement.cfg
index 271317b1c970..9e82a4ccd502 100644
--- a/tests/zfs-tests/tests/functional/replacement/replacement.cfg
+++ b/tests/zfs-tests/tests/functional/replacement/replacement.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/replacement/setup.ksh b/tests/zfs-tests/tests/functional/replacement/setup.ksh
index b1fb6a123897..0327c20a73cc 100755
--- a/tests/zfs-tests/tests/functional/replacement/setup.ksh
+++ b/tests/zfs-tests/tests/functional/replacement/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/cleanup.ksh b/tests/zfs-tests/tests/functional/reservation/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/reservation/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation.cfg b/tests/zfs-tests/tests/functional/reservation/reservation.cfg
index b4f9af938623..18d0ead30d64 100644
--- a/tests/zfs-tests/tests/functional/reservation/reservation.cfg
+++ b/tests/zfs-tests/tests/functional/reservation/reservation.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation.shlib b/tests/zfs-tests/tests/functional/reservation/reservation.shlib
index 9bac794a9784..911c3a908a17 100644
--- a/tests/zfs-tests/tests/functional/reservation/reservation.shlib
+++ b/tests/zfs-tests/tests/functional/reservation/reservation.shlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh
index 4f151ef15c1d..dbe4890be86c 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh
index e0fed6389c35..eca3f5936580 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh
index ee303b53bedd..a6e701dcf381 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh
index eb606a762432..2b52cd6a07d9 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh
index 535d652dafab..e6cfa88990ac 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh
index da0d36a35d3c..ef7b554de1ef 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh
index a1fffd362427..d3db1c7cfbeb 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh
index cfc30f47421b..2c7c0c04014b 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh
index a639abf8960a..7fd19ef50b12 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh
index f3a64a0bea8c..c575dc7c3156 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh
index a6abe9db6a13..d3fcc24bc49d 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh
index 5ab0952b1910..77bf8beb0b92 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh
index 786d5d4d3008..7ef2b61e3c8b 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh
index 3b7f384da365..eeefe182798a 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh
index 7067a7810590..2b9d3f98694b 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh
index 82bbcde4a3b7..84a80e34323e 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh
index bb3af67d24d3..486ad397ca13 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh
index 1f92c8898562..717c8371ff19 100755
--- a/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/reservation/setup.ksh b/tests/zfs-tests/tests/functional/reservation/setup.ksh
index 731aa6a30680..6b93b4a7e310 100755
--- a/tests/zfs-tests/tests/functional/reservation/setup.ksh
+++ b/tests/zfs-tests/tests/functional/reservation/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh b/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh
index 8f043259fb91..c51a3f27bddc 100755
--- a/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh
index 0d592ad33e58..c6c3bf8a52b1 100755
--- a/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh
index 3bb5d12edddf..6dbbc7da39ef 100755
--- a/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh
index e4d4268cc08e..a336e6bbb33f 100755
--- a/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rootpool/setup.ksh b/tests/zfs-tests/tests/functional/rootpool/setup.ksh
index d81b3dfbdd40..049bdf066aeb 100755
--- a/tests/zfs-tests/tests/functional/rootpool/setup.ksh
+++ b/tests/zfs-tests/tests/functional/rootpool/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/cleanup.ksh b/tests/zfs-tests/tests/functional/rsend/cleanup.ksh
index 063fe9dd1f61..9a6ad98b3fde 100755
--- a/tests/zfs-tests/tests/functional/rsend/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend.cfg b/tests/zfs-tests/tests/functional/rsend/rsend.cfg
index 99e87d9369ed..9e3422ecad67 100644
--- a/tests/zfs-tests/tests/functional/rsend/rsend.cfg
+++ b/tests/zfs-tests/tests/functional/rsend/rsend.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend.kshlib b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib
index 06886131cf83..26e7c2cc25bc 100644
--- a/tests/zfs-tests/tests/functional/rsend/rsend.kshlib
+++ b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh
index 3864d8a7d1bd..b73c27656437 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh
index f2c1e03937e2..111d00eeb63a 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh
index 2ace6737b14e..fa4479c666d9 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh
index c0b36b2329e7..522662076d2c 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh
index 4d156690e38a..2c1ba0c1644a 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh
index 8c598f4ec29c..5216016e6b71 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh
index 29e9f1859579..499caff9a71a 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh
index 8e1821d88a68..fab0a7d9ec7c 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh
index 5712cb513401..fc5a582f881e 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -45,13 +45,16 @@
verify_runnable "global"
+BPOOL=bpool_test
+SPOOL=spool_test
+
function cleanup
{
- if datasetexists bpool ; then
- log_must_busy zpool destroy -f bpool
+ if datasetexists $BPOOL ; then
+ log_must_busy zpool destroy -f $BPOOL
fi
- if datasetexists spool ; then
- log_must_busy zpool destroy -f spool
+ if datasetexists $SPOOL ; then
+ log_must_busy zpool destroy -f $SPOOL
fi
}
@@ -60,33 +63,33 @@ log_onexit cleanup
log_must mkfile $MINVDEVSIZE $TESTDIR/bfile
log_must mkfile $SPA_MINDEVSIZE $TESTDIR/sfile
-log_must zpool create -O compression=off bpool $TESTDIR/bfile
-log_must zpool create -O compression=off spool $TESTDIR/sfile
+log_must zpool create -O compression=off $BPOOL $TESTDIR/bfile
+log_must zpool create -O compression=off $SPOOL $TESTDIR/sfile
#
# Test out of space on sub-filesystem
#
-log_must zfs create bpool/fs
-log_must mkfile 30M /bpool/fs/file
+log_must zfs create $BPOOL/fs
+log_must mkfile 30M /$BPOOL/fs/file
-log_must zfs snapshot bpool/fs@snap
-log_must eval "zfs send -R bpool/fs@snap > $BACKDIR/fs-R"
-log_mustnot eval "zfs receive -d -F spool < $BACKDIR/fs-R"
+log_must zfs snapshot $BPOOL/fs@snap
+log_must eval "zfs send -R $BPOOL/fs@snap > $BACKDIR/fs-R"
+log_mustnot eval "zfs receive -d -F $SPOOL < $BACKDIR/fs-R"
-log_must datasetnonexists spool/fs
-log_must ismounted spool
+log_must datasetnonexists $SPOOL/fs
+log_must ismounted $SPOOL
#
# Test out of space on top filesystem
#
-log_must mv /bpool/fs/file /bpool
-log_must_busy zfs destroy -rf bpool/fs
+log_must mv /$BPOOL/fs/file /$BPOOL
+log_must_busy zfs destroy -rf $BPOOL/fs
-log_must zfs snapshot bpool@snap
-log_must eval "zfs send -R bpool@snap > $BACKDIR/bpool-R"
-log_mustnot eval "zfs receive -d -F spool < $BACKDIR/bpool-R"
+log_must zfs snapshot $BPOOL@snap
+log_must eval "zfs send -R $BPOOL@snap > $BACKDIR/bpool-R"
+log_mustnot eval "zfs receive -d -F $SPOOL < $BACKDIR/bpool-R"
-log_must datasetnonexists spool/fs
-log_must ismounted spool
+log_must datasetnonexists $SPOOL/fs
+log_must ismounted $SPOOL
log_pass "zfs receive can handle out of space correctly."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh
index e76f5c5c8620..a9a7d53819d8 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh
index 88f79f3e921a..113ef4f6dc85 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh
index 0608598b8333..0fa40f40bed5 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh
index 110e56144674..e06e0f3e5e53 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_025_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_025_pos.ksh
index 99254cccdbcb..95ec9875737e 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_025_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_025_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_026_neg.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_026_neg.ksh
index 5248008a18c5..504e5fba811d 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_026_neg.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_026_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_027_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_027_pos.ksh
index 645685e690b4..d575ac2676bb 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_027_pos.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_027_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_028_neg.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_028_neg.ksh
index e9186d79344f..a6a1cbfc8ee8 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_028_neg.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_028_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_029_neg.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_029_neg.ksh
index 7c3a96b71285..28d3826cef60 100755
--- a/tests/zfs-tests/tests/functional/rsend/rsend_029_neg.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_029_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_030_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_030_pos.ksh
new file mode 100755
index 000000000000..a683f5befa3d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_030_pos.ksh
@@ -0,0 +1,66 @@
+#!/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) 2022 by Nutanix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of full ZFS send/receive on existing dataset
+#
+# Strategy:
+# 1. Start a full ZFS send with redirect output to a file
+# 2. Mess up the contents of the stream state file on disk
+# 3. Try ZFS receive, which should fail with a checksum mismatch error
+# 4. ZFS send to the stream state file again using the receive_resume_token
+# 5. Verify ZFS receive without "-F" option (force recvflag) fails.
+# 6. Verify ZFS receive with "-F" option completes successfully.
+# 7. Repeat steps on an incremental ZFS send. It should complete
+# successfully without "-F" option.
+#
+
+verify_runnable "both"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_assert "Verify resumability of full ZFS send/receive on existing dataset"
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+
+# Full send/recv on existing dataset
+log_must zfs create -o readonly=on $recvfs
+log_must eval "zfs send -c -v $sendfs@a >/$streamfs/1"
+mess_send_file /$streamfs/1
+log_mustnot eval "zfs recv -suvF $recvfs </$streamfs/1"
+token=$(get_prop receive_resume_token $recvfs)
+log_must eval "zfs send -t $token >/$streamfs/2"
+log_mustnot eval "zfs recv -suv $recvfs </$streamfs/2"
+log_must eval "zfs recv -suvF $recvfs </$streamfs/2"
+file_check $sendfs $recvfs
+
+# Incremental send/recv
+log_must eval "zfs send -c -v -i @a $sendfs@b >/$streamfs/3"
+mess_send_file /$streamfs/3
+log_mustnot eval "zfs recv -suvF $recvfs </$streamfs/3"
+token=$(get_prop receive_resume_token $recvfs)
+log_must eval "zfs send -t $token >/$streamfs/4"
+log_must eval "zfs recv -suv $recvfs </$streamfs/4"
+file_check $sendfs $recvfs
+
+log_pass "Verify resumability of full ZFS send/receive on existing dataset"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_031_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_031_pos.ksh
new file mode 100755
index 000000000000..119da7150c36
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_031_pos.ksh
@@ -0,0 +1,63 @@
+#!/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) 2023 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify recursive incremental sends missing snapshots behave correctly.
+#
+# Strategy:
+# 1. Create snapshots on source filesystem.
+# 2. Recursively send snapshots.
+# 3. Delete snapshot on source filesystem
+# 4. Perform incremental recursive send.
+# 5. Verify matching snapshot lists.
+#
+
+verify_runnable "both"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+
+function cleanup {
+ rm $BACKDIR/stream1
+ rm $BACKDIR/stream2
+ zfs destroy -r $sendfs
+ zfs destroy -r $recvfs
+}
+
+log_assert "Verify recursive incremental sends missing snapshots behave correctly."
+log_onexit cleanup
+
+log_must zfs create $sendfs
+log_must zfs snapshot $sendfs@A
+log_must zfs snapshot $sendfs@B
+log_must zfs snapshot $sendfs@C
+log_must eval "zfs send -Rpv $sendfs@C > $BACKDIR/stream1"
+log_must eval "zfs receive -F $recvfs < $BACKDIR/stream1"
+log_must zfs list $sendfs@C
+
+log_must zfs destroy $sendfs@C
+log_must zfs snapshot $sendfs@D
+log_must zfs snapshot $sendfs@E
+log_must eval "zfs send -Rpv -I $sendfs@A $sendfs@E > $BACKDIR/stream2"
+log_must eval "zfs receive -Fv $recvfs < $BACKDIR/stream2"
+log_must zfs list $sendfs@D
+log_must zfs list $sendfs@E
+log_mustnot zfs list $sendfs@C
+log_pass "Verify recursive incremental sends missing snapshots behave correctly."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh
index 988ed91b9918..1bf234823459 100755
--- a/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh
@@ -29,6 +29,7 @@
function cleanup
{
+ rm $BACKDIR/copy
log_must_busy zfs destroy -r $vol
cleanup_pool $POOL2
}
@@ -60,7 +61,9 @@ log_must eval "zfs recv -d $POOL2 <$BACKDIR/full"
verify_stream_size $BACKDIR/full $vol
verify_stream_size $BACKDIR/full $vol2
-md5=$(dd if=$voldev2 bs=1024k count=$megs 2>/dev/null | md5digest)
+block_device_wait $voldev2
+log_must dd if=$voldev2 of=$BACKDIR/copy bs=1024k count=$megs
+md5=$(md5digest $BACKDIR/copy)
[[ $md5 = $md5_1 ]] || log_fail "md5 mismatch: $md5 != $md5_1"
# Repeat, for an incremental send
@@ -72,7 +75,9 @@ log_must eval "zfs recv -d $POOL2 <$BACKDIR/inc"
verify_stream_size $BACKDIR/inc $vol 90 $vol@snap
verify_stream_size $BACKDIR/inc $vol2 90 $vol2@snap
-md5=$(dd skip=$megs if=$voldev2 bs=1024k count=$megs 2>/dev/null | md5digest)
+block_device_wait $voldev2
+log_must dd skip=$megs if=$voldev2 of=$BACKDIR/copy bs=1024k count=$megs
+md5=$(md5digest $BACKDIR/copy)
[[ $md5 = $md5_2 ]] || log_fail "md5 mismatch: $md5 != $md5_2"
log_pass "Verify compressed send works with volumes"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_zstream_recompress.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_zstream_recompress.ksh
new file mode 100755
index 000000000000..dd2a7d02a261
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_zstream_recompress.ksh
@@ -0,0 +1,58 @@
+#!/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) 2022 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/math.shlib
+
+#
+# Description:
+# Verify compression features show up in zstream dump
+#
+# Strategy:
+# 1. Create a compressed send stream
+# 2. Recompress the stream with a different algorithm
+# 3. Verify it can be received correctly
+# 4. Verify the contents match the original filesystem
+# 5. Create an uncompressed send stream
+# 6. Compress the send stream
+# 7. Verify that the stream is smaller when compressed
+#
+
+verify_runnable "both"
+
+log_assert "Verify zstream recompress correctly modifies send streams."
+log_onexit cleanup_pool $POOL2
+
+typeset sendfs=$POOL2/fs
+typeset recvfs=$POOL2/fs2
+
+log_must zfs create -o compress=lz4 $sendfs
+typeset dir=$(get_prop mountpoint $sendfs)
+write_compressible $dir 16m
+log_must zfs snapshot $sendfs@snap
+
+log_must eval "zfs send -c $sendfs@snap | zstream recompress gzip-1 | zfs recv $recvfs"
+typeset recvdir=$(get_prop mountpoint $recvfs)
+log_must diff -r $dir $recvdir
+
+log_must eval "zfs send $sendfs@snap >$BACKDIR/uncompressed"
+log_must zstream recompress gzip-1 <$BACKDIR/uncompressed >$BACKDIR/compressed
+typeset uncomp_size=$(wc -c $BACKDIR/uncompressed | awk '{print $1}')
+typeset comp_size=$(wc -c $BACKDIR/compressed | awk '{print $1}')
+[[ "$uncomp_size" -gt "$comp_size" ]] || log_fail "recompressed stream was not smaller"
+
+log_pass "zstream recompress correctly modifies send streams."
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_freeobjects.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_freeobjects.ksh
new file mode 100755
index 000000000000..92451bd1ab6f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_freeobjects.ksh
@@ -0,0 +1,87 @@
+#!/bin/ksh
+
+#
+# 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) 2017 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2023 by Findity AB
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that receiving a raw encrypted stream, with a FREEOBJECTS
+# removing all existing objects in a block followed by an OBJECT write
+# to the same block, does not result in a panic.
+#
+# Strategy:
+# 1. Create a new encrypted filesystem
+# 2. Create file f1 as the first object in some block (here object 128)
+# 3. Take snapshot A
+# 4. Create file f2 as the second object in the same block (here object 129)
+# 5. Delete f1
+# 6. Take snapshot B
+# 7. Receive a full raw encrypted send of A
+# 8. Receive an incremental raw send of B
+#
+verify_runnable "both"
+
+function create_object_with_num
+{
+ file=$1
+ num=$2
+
+ tries=100
+ for ((i=0; i<$tries; i++)); do
+ touch $file
+ onum=$(ls -li $file | awk '{print $1}')
+
+ if [[ $onum -ne $num ]] ; then
+ rm -f $file
+ else
+ break
+ fi
+ done
+ if [[ $i -eq $tries ]]; then
+ log_fail "Failed to create object with number $num"
+ fi
+}
+
+log_assert "FREEOBJECTS followed by OBJECT in encrypted stream does not crash"
+
+sendds=sendencfods
+recvds=recvencfods
+keyfile=/$POOL/keyencfods
+f1=/$POOL/$sendds/f1
+f2=/$POOL/$sendds/f2
+
+log_must eval "echo 'password' > $keyfile"
+
+#
+# xattr=sa and dnodesize=legacy for sequential object numbers, see
+# note in send_freeobjects.ksh.
+#
+log_must zfs create -o xattr=sa -o dnodesize=legacy -o encryption=on \
+ -o keyformat=passphrase -o keylocation=file://$keyfile $POOL/$sendds
+
+create_object_with_num $f1 128
+log_must zfs snap $POOL/$sendds@A
+create_object_with_num $f2 129
+log_must rm $f1
+log_must zfs snap $POOL/$sendds@B
+
+log_must eval "zfs send -w $POOL/$sendds@A | zfs recv $POOL/$recvds"
+log_must eval "zfs send -w -i $POOL/$sendds@A $POOL/$sendds@B |" \
+ "zfs recv $POOL/$recvds"
+
+log_pass "FREEOBJECTS followed by OBJECT in encrypted stream did not crash"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh
new file mode 100755
index 000000000000..491ad55db411
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_incremental.ksh
@@ -0,0 +1,93 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Incrementally receiving a snapshot to an encrypted filesystem succeeds.
+#
+# Strategy:
+# 1) Create a pool and an encrypted fs
+# 2) Create some files and snapshots
+# 3) Send the first snapshot to a second encrypted as well as an
+# unencrypted fs.
+# 4) Incrementally send the second snapshot to the unencrypted fs.
+# 5) Rollback the second encrypted fs to the first snapshot.
+# 6) Incrementally send the second snapshot from the unencrypted to the
+# second encrypted fs.
+# 7) Incrementally send the third snapshot from the first encrypted to the
+# unencrypted fs.
+# 8) Incrementally send the third snapshot from the unencrypted to the second
+# encrypted fs.
+#
+
+verify_runnable "both"
+
+log_assert "Incrementally receiving a snapshot to an encrypted filesystem succeeds"
+
+function cleanup
+{
+ destroy_pool pool_lb
+ log_must rm -f $TESTDIR/vdev_a
+}
+
+log_onexit cleanup
+
+typeset passphrase="password"
+typeset passphrase2="password2"
+
+typeset file="/pool_lb/encryptme/$TESTFILE0"
+typeset file1="/pool_lb/encryptme/$TESTFILE1"
+typeset file2="/pool_lb/encryptme/$TESTFILE2"
+
+# Create pool
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f pool_lb $TESTDIR/vdev_a
+log_must eval "echo $passphrase > /pool_lb/pwd"
+log_must eval "echo $passphrase2 > /pool_lb/pwd2"
+
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///pool_lb/pwd pool_lb/encryptme
+log_must dd if=/dev/urandom of=$file bs=1024 count=1024
+log_must zfs snapshot pool_lb/encryptme@snap1
+log_must dd if=/dev/urandom of=$file1 bs=1024 count=1024
+log_must zfs snapshot pool_lb/encryptme@snap2
+log_must dd if=/dev/urandom of=$file2 bs=1024 count=1024
+log_must zfs snapshot pool_lb/encryptme@snap3
+log_must eval "zfs send -Lc pool_lb/encryptme@snap1 | zfs recv \
+ -o encryption=on -o keyformat=passphrase -o keylocation=file:///pool_lb/pwd2 \
+ pool_lb/encrypttwo"
+log_must eval "zfs send -Lc pool_lb/encryptme@snap1 | zfs recv \
+ pool_lb/unencryptme"
+log_must eval "zfs send -Lc -i pool_lb/encryptme@{snap1,snap2} | zfs recv \
+ pool_lb/unencryptme"
+log_must zfs rollback pool_lb/encrypttwo@snap1
+log_must eval "zfs send -Lc -i pool_lb/unencryptme@{snap1,snap2} | zfs recv \
+ pool_lb/encrypttwo"
+log_must eval "zfs send -Lc -i pool_lb/encryptme@{snap2,snap3} | zfs recv \
+ pool_lb/unencryptme"
+log_must eval "zfs send -Lc -i pool_lb/unencryptme@{snap2,snap3} | zfs recv \
+ -F pool_lb/encrypttwo"
+
+log_pass "Incrementally receiving a snapshot to an encrypted filesystem succeeds"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
index 793904db91ca..c0c7b682def9 100755
--- a/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
@@ -133,6 +133,14 @@ recv_cksum=$(md5digest /$ds/$TESTFILE0)
log_must test "$recv_cksum" == "$cksum"
log_must zfs destroy -r $ds
+# Test that we can override sharesmb property for encrypted raw stream.
+log_note "Must be able to override sharesmb property for encrypted raw stream"
+ds=$TESTPOOL/recv
+log_must eval "zfs send -w $esnap > $sendfile"
+log_must eval "zfs recv -o sharesmb=on $ds < $sendfile"
+log_must test "$(get_prop 'sharesmb' $ds)" == "on"
+log_must zfs destroy -r $ds
+
# Test that we can override encryption properties on a properties stream
# of an unencrypted dataset, turning it into an encryption root.
log_note "Must be able to receive stream with props as encryption root"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh b/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh
index 1dfa97e77358..6754fb0f44bb 100755
--- a/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/rsend/send_raw_ashift.ksh b/tests/zfs-tests/tests/functional/rsend/send_raw_ashift.ksh
index 3cea334495d9..f238c361134f 100755
--- a/tests/zfs-tests/tests/functional/rsend/send_raw_ashift.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/send_raw_ashift.ksh
@@ -37,6 +37,10 @@ verify_runnable "both"
log_assert "Verify raw sending to pools with greater ashift succeeds"
+if is_freebsd; then
+ log_unsupported "Runs too long on FreeBSD 14 (Issue #14961)"
+fi
+
function cleanup
{
rm -f $BACKDIR/fs@*
diff --git a/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh
new file mode 100755
index 000000000000..48a76fca63e1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh
@@ -0,0 +1,78 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2022, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Receiving a snapshot with large blocks and raw sending it succeeds.
+#
+# Strategy:
+# 1) Create a set of files each containing some file data in an
+# encrypted filesystem with recordsize=1m.
+# 2) Snapshot and send with large_blocks enabled to a new filesystem.
+# 3) Raw send to a file. If the large_blocks feature is not activated
+# in the filesystem created in (2) the raw send will fail.
+#
+
+verify_runnable "both"
+
+log_assert "Receiving and raw sending a snapshot with large blocks succeeds"
+
+backup=$TEST_BASE_DIR/backup
+raw_backup=$TEST_BASE_DIR/raw_backup
+
+function cleanup
+{
+ log_must rm -f $backup $raw_backup $ibackup $unc_backup
+ destroy_pool pool_lb
+ log_must rm -f $TESTDIR/vdev_a
+}
+
+log_onexit cleanup
+
+typeset passphrase="password"
+typeset file="/pool_lb/fs/$TESTFILE0"
+
+# Create pool
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+log_must zpool create -f -o feature@large_blocks=enabled pool_lb $TESTDIR/vdev_a
+
+log_must eval "echo $passphrase > /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/rsend/setup.ksh b/tests/zfs-tests/tests/functional/rsend/setup.ksh
index dbf4eecede88..5632df3da7f0 100755
--- a/tests/zfs-tests/tests/functional/rsend/setup.ksh
+++ b/tests/zfs-tests/tests/functional/rsend/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh
index 92e58996ab62..4854a318dc08 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg b/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg
index 01c90e58f51b..9c027fd2013f 100644
--- a/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh
index cce59737255c..a65375022c78 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh
index d1fb9d2f174c..a2e32e7ca03f 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh
index fa6c3c2f575f..b68e354a3fd2 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh
index 3139b047bb6f..c21c226b9c0c 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
index 4e434ae0b600..72a9dbd4f1ac 100644
--- a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh
index 94b995db53ed..0bed5df6fd7e 100755
--- a/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/simd/simd_supported.ksh b/tests/zfs-tests/tests/functional/simd/simd_supported.ksh
index 1c89824e02fd..79bacc2b8d1e 100755
--- a/tests/zfs-tests/tests/functional/simd/simd_supported.ksh
+++ b/tests/zfs-tests/tests/functional/simd/simd_supported.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/cleanup.ksh b/tests/zfs-tests/tests/functional/slog/cleanup.ksh
index 92bc4aa59d8f..53b5f4c4ab87 100755
--- a/tests/zfs-tests/tests/functional/slog/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/slog/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/setup.ksh b/tests/zfs-tests/tests/functional/slog/setup.ksh
index 4278fc69786d..02f05cc568ec 100755
--- a/tests/zfs-tests/tests/functional/slog/setup.ksh
+++ b/tests/zfs-tests/tests/functional/slog/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog.cfg b/tests/zfs-tests/tests/functional/slog/slog.cfg
index d0d25fde151e..ef32d2fb57ff 100644
--- a/tests/zfs-tests/tests/functional/slog/slog.cfg
+++ b/tests/zfs-tests/tests/functional/slog/slog.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog.kshlib b/tests/zfs-tests/tests/functional/slog/slog.kshlib
index 8bc34d0dac32..98863d6c9882 100644
--- a/tests/zfs-tests/tests/functional/slog/slog.kshlib
+++ b/tests/zfs-tests/tests/functional/slog/slog.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh
index a4c35ed9e98e..112d0192f136 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh
index 91904aa612d1..17fb1f6a4841 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh
index 0b4d6ede3e13..678802e99ad2 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh
index 10f28dcc000b..7c29e2c05ce0 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh
index 4836f6f27937..2dad806033fc 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh
index 24143196fd2e..3804c3896da7 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh
index 27ac38606c29..ff54cd781781 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh
index 54587a0c61a7..8f95c6fe3cae 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh
index 222f71a99928..395706b58519 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh
index edd9abea0930..800e6cc054cf 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh
index 3bebc8201713..9953fa55d2d4 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh
index 8d6fb2bffb7f..f1434e10c357 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh
index 89b3aeb4034c..b412b310f5b2 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh
index 9d9bcf885d50..8f1502c71564 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_016_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_016_pos.ksh
index 75f78c800a7c..b69c0c58e38d 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_016_pos.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_016_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh
index 0b78a9645a60..8f3585a5997f 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -175,6 +175,29 @@ log_must ln /$TESTPOOL/$TESTFS/link_and_unlink \
/$TESTPOOL/$TESTFS/link_and_unlink.link
log_must rm /$TESTPOOL/$TESTFS/link_and_unlink.link
+# We can't test RENAME_* flags without renameat2(2) support.
+if ! is_linux ; then
+ log_note "renameat2 is linux-only"
+elif ! renameat2 -C ; then
+ log_note "renameat2 not supported on this (pre-3.15) linux kernel"
+else
+ # TX_RENAME_EXCHANGE
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-a bs=1k count=1
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-b bs=1k count=1
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-c bs=1k count=1
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-d bs=1k count=1
+ # rotate the files around
+ log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{a,b}
+ log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{b,c}
+ log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{c,a}
+ # exchange same path
+ log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{d,d}
+
+ # TX_RENAME_WHITEOUT
+ log_must mkfile 1k /$TESTPOOL/$TESTFS/whiteout
+ log_must renameat2 -w /$TESTPOOL/$TESTFS/whiteout{,-moved}
+fi
+
#
# 4. Copy TESTFS to temporary location (TESTDIR/copy)
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh
index 50ccc6089322..a62d229d5057 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh
index 35cb4b696965..e99d40570c39 100755
--- a/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh b/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh
index 530a785330dc..4ff6739098a8 100755
--- a/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh
index 819e263b1c5b..697f8f83aa09 100755
--- a/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh
index 38db22fdfe17..79b00bd3c1b5 100755
--- a/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh
index 571065fdd69b..842d469695e3 100755
--- a/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh
index e707640acd14..3cbc6694ee0c 100755
--- a/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/setup.ksh b/tests/zfs-tests/tests/functional/snapshot/setup.ksh
index a73d1aff3c53..17d09fa9c196 100755
--- a/tests/zfs-tests/tests/functional/snapshot/setup.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg b/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg
index 265903fe1469..69b4f3a06fd5 100644
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh
index 9a677b036ead..0724216ee561 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh
index a3ed1b548210..d9e44d332e05 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh
index a1357b1551e6..96f7dac0beec 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh
index 683afb5e1a3f..3725de0c1ec6 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh
index a5667badf53a..127b73143893 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh
index 2130ff8901cd..e34a50941470 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh
index bcca2a04a7c4..3f7029f581e7 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh
index 560e846cee9d..299424fc9573 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh
index 1ee7e33c2ac2..ccc0857b077b 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh
index 128b443c6fc9..4aca2854a7d9 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh
index 7fa7aec22d6f..2d5f63b6237c 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh
index 92db9b53a7b8..d2671787975b 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh
index 27408222c80e..a071759beca6 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh
index 55188960b7e3..9c7e64ab6cf0 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh
index 5a4d2ccaf62e..4fdbfce55063 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh
index b66023cc85e6..6058ec1cfe70 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh
index 6e5b8973cf4f..dc234636ec6a 100755
--- a/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh
new file mode 100755
index 000000000000..e9a2fbe5c595
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh
@@ -0,0 +1,127 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2022 iXsystems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify the functionality of snapshots_changed property
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Verify snapshots_changed property is NULL
+# 3. Create a filesystem
+# 4. Verify snapshots_changed property is NULL
+# 5. Create snapshots for all filesystems
+# 6. Verify snapshots_changed property shows correct time
+# 7. Unmount all filesystems
+# 8. Create a snapshot while unmounted
+# 9. Verify snapshots_changed
+# 10. Mount the filsystems
+# 11. Verify snapshots_changed
+# 12. Destroy the snapshots
+# 13. Verify snapshots_changed
+#
+
+function cleanup
+{
+ create_pool $TESTPOOL $DISKS
+}
+
+verify_runnable "both"
+
+log_assert "Verify snapshots_changed property"
+
+log_onexit cleanup
+
+snap_testpool="$TESTPOOL@v1"
+snap_testfsv1="$TESTPOOL/$TESTFS@v1"
+snap_testfsv2="$TESTPOOL/$TESTFS@v2"
+snapdir=".zfs/snapshot"
+
+# Create filesystems and check snapshots_changed is NULL
+create_pool $TESTPOOL $DISKS
+snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
+log_must eval "[[ $snap_changed_testpool == - ]]"
+tpool_snapdir=$(get_prop mountpoint $TESTPOOL)/$snapdir
+log_must eval "[[ $(stat_mtime $tpool_snapdir) == 0 ]]"
+
+log_must zfs create $TESTPOOL/$TESTFS
+snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
+log_must eval "[[ $snap_changed_testfs == - ]]"
+tfs_snapdir=$(get_prop mountpoint $TESTPOOL/$TESTFS)/$snapdir
+log_must eval "[[ $(stat_mtime $tfs_snapdir) == 0 ]]"
+
+# Create snapshots for filesystems and check snapshots_changed reports correct time
+curr_time=$(date '+%s')
+log_must zfs snapshot $snap_testpool
+snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
+log_must eval "[[ $snap_changed_testpool -ge $curr_time ]]"
+log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
+
+curr_time=$(date '+%s')
+log_must zfs snapshot $snap_testfsv1
+snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
+log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
+log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
+
+# Unmount the filesystems and check snapshots_changed has correct value after unmount
+log_must zfs unmount $TESTPOOL/$TESTFS
+log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) == $snap_changed_testfs ]]"
+
+# Create snapshot while unmounted
+curr_time=$(date '+%s')
+log_must zfs snapshot $snap_testfsv2
+snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
+log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
+
+log_must zfs unmount $TESTPOOL
+log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL) == $snap_changed_testpool ]]"
+
+# Mount back the filesystems and check snapshots_changed still has correct value
+log_must zfs mount $TESTPOOL
+log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL) == $snap_changed_testpool ]]"
+log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
+
+log_must zfs mount $TESTPOOL/$TESTFS
+log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) == $snap_changed_testfs ]]"
+log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
+
+# Destroy the snapshots and check snapshots_changed shows correct time
+curr_time=$(date '+%s')
+log_must zfs destroy $snap_testfsv1
+snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
+log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
+log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
+
+curr_time=$(date '+%s')
+log_must zfs destroy $snap_testpool
+snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
+log_must eval "[[ $snap_changed_testpool -ge $curr_time ]]"
+log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
+
+log_pass "snapshots_changed property behaves correctly"
diff --git a/tests/zfs-tests/tests/functional/snapused/cleanup.ksh b/tests/zfs-tests/tests/functional/snapused/cleanup.ksh
index 2f536ca588ed..557bfeb213dd 100755
--- a/tests/zfs-tests/tests/functional/snapused/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/setup.ksh b/tests/zfs-tests/tests/functional/snapused/setup.ksh
index dfe8696add67..c1e02d843a32 100755
--- a/tests/zfs-tests/tests/functional/snapused/setup.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused.kshlib b/tests/zfs-tests/tests/functional/snapused/snapused.kshlib
index d7d05bfeef1f..043f54d54fd2 100644
--- a/tests/zfs-tests/tests/functional/snapused/snapused.kshlib
+++ b/tests/zfs-tests/tests/functional/snapused/snapused.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh
index c1277f2b4e2f..6d33f32d6875 100755
--- a/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh
index a41ca1d70f19..c78e7cde39b7 100755
--- a/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh
index ff54cbaa1aec..940dc0e7bfc5 100755
--- a/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh
index 8fb8b6be5b47..d5f97168bd3c 100755
--- a/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh
index 9d21e1d23d87..fbf7165e7734 100755
--- a/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/sparse/cleanup.ksh b/tests/zfs-tests/tests/functional/sparse/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/sparse/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/sparse/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/sparse/setup.ksh b/tests/zfs-tests/tests/functional/sparse/setup.ksh
index 3a45ec8d510d..d617f361b24d 100755
--- a/tests/zfs-tests/tests/functional/sparse/setup.ksh
+++ b/tests/zfs-tests/tests/functional/sparse/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/sparse/sparse.cfg b/tests/zfs-tests/tests/functional/sparse/sparse.cfg
index b7e403bce5f1..970dd25177ea 100644
--- a/tests/zfs-tests/tests/functional/sparse/sparse.cfg
+++ b/tests/zfs-tests/tests/functional/sparse/sparse.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh b/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh
index 6ad252adf325..3e25af39c08a 100755
--- a/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/stat/cleanup.ksh b/tests/zfs-tests/tests/functional/stat/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/stat/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/stat/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/stat/setup.ksh b/tests/zfs-tests/tests/functional/stat/setup.ksh
index 4fc55cd47803..bc74ee62e075 100755
--- a/tests/zfs-tests/tests/functional/stat/setup.ksh
+++ b/tests/zfs-tests/tests/functional/stat/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/stat/stat_001_pos.ksh b/tests/zfs-tests/tests/functional/stat/stat_001_pos.ksh
index e6f9775f4b8e..e167526f4c3d 100755
--- a/tests/zfs-tests/tests/functional/stat/stat_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/stat/stat_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/cleanup.ksh b/tests/zfs-tests/tests/functional/suid/cleanup.ksh
index 6e41e02faf58..b1aa351587f1 100755
--- a/tests/zfs-tests/tests/functional/suid/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/suid/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/setup.ksh b/tests/zfs-tests/tests/functional/suid/setup.ksh
index d04d5568c003..96e891a5ba1d 100755
--- a/tests/zfs-tests/tests/functional/suid/setup.ksh
+++ b/tests/zfs-tests/tests/functional/suid/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
index 907c94e3fd9c..984dda6a0208 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
index 4554bc3c00a4..41367e0b136d 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
index 541e1125d539..77d092227ab1 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
index 57361d2e39a9..51f6775c003f 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh
index 8843e67da24b..1d7407000ebf 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh b/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh
index 3166bd6ec16e..42fe70042d6a 100755
--- a/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/tmpfile/setup.ksh b/tests/zfs-tests/tests/functional/tmpfile/setup.ksh
index bc00a2a22c5a..2b38556c9a78 100755
--- a/tests/zfs-tests/tests/functional/tmpfile/setup.ksh
+++ b/tests/zfs-tests/tests/functional/tmpfile/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c
index 424231d112b2..906b81b4d9b3 100644
--- a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c
@@ -46,7 +46,6 @@ main(void)
int i, fd;
char spath[1024], dpath[1024];
const char *penv[] = {"TESTDIR", "TESTFILE0"};
- struct stat sbuf;
(void) fprintf(stdout, "Verify O_TMPFILE file can be linked.\n");
@@ -73,12 +72,10 @@ main(void)
run("export");
run("import");
- if (stat(dpath, &sbuf) < 0) {
- perror("stat");
- unlink(dpath);
+ if (unlink(dpath) == -1) {
+ perror("unlink");
exit(5);
}
- unlink(dpath);
return (0);
}
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c
index 893d2639ae64..8f936d36de1f 100644
--- a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -37,18 +37,18 @@
/*
* DESCRIPTION:
- * Verify stat(2) for O_TMPFILE file considers umask.
+ * Verify fstat(2) for O_TMPFILE file considers umask.
*
* STRATEGY:
* 1. open(2) with O_TMPFILE.
* 2. linkat(2).
- * 3. fstat(2)/stat(2) and verify .st_mode value.
+ * 3. fstat(2) and verify .st_mode value.
*/
static void
test_stat_mode(mode_t mask)
{
- struct stat st, fst;
+ struct stat fst;
int i, fd;
char spath[1024], dpath[1024];
const char *penv[] = {"TESTDIR", "TESTFILE0"};
@@ -68,7 +68,7 @@ test_stat_mode(mode_t mask)
err(2, "open(%s)", penv[0]);
if (fstat(fd, &fst) == -1)
- err(3, "open");
+ err(3, "fstat(%s)", penv[0]);
snprintf(spath, sizeof (spath), "/proc/self/fd/%d", fd);
snprintf(dpath, sizeof (dpath), "%s/%s", penv[0], penv[1]);
@@ -78,19 +78,23 @@ test_stat_mode(mode_t mask)
err(4, "linkat");
close(fd);
- if (stat(dpath, &st) == -1)
- err(5, "stat");
- unlink(dpath);
-
- /* Verify fstat(2) result */
+ /* Verify fstat(2) result at old path */
mode = fst.st_mode & 0777;
if (mode != masked)
- errx(6, "fstat(2) %o != %o\n", mode, masked);
+ errx(5, "fstat(2) %o != %o\n", mode, masked);
+
+ fd = open(dpath, O_RDWR);
+ if (fd == -1)
+ err(6, "open(%s)", dpath);
- /* Verify stat(2) result */
- mode = st.st_mode & 0777;
+ if (fstat(fd, &fst) == -1)
+ err(7, "fstat(%s)", dpath);
+
+ /* Verify fstat(2) result at new path */
+ mode = fst.st_mode & 0777;
if (mode != masked)
- errx(7, "stat(2) %o != %o\n", mode, masked);
+ errx(8, "fstat(2) %o != %o\n", mode, masked);
+ close(fd);
}
int
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh
index 924b56935def..4dba4616e947 100755
--- a/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh
@@ -57,7 +57,7 @@ log_onexit cleanup
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
# Reduced TRIM_TXG_BATCH to make trimming more frequent.
typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
@@ -95,6 +95,7 @@ for type in "" "mirror" "raidz2" "draid"; do
# Fill the pool, verify the vdevs are no longer sparse.
file_write -o create -f /$TESTPOOL/file -b 1048576 -c $fill_mb -d R
+ sync_pool $TESTPOOL
verify_vdevs "-ge" "$VDEV_MAX_MB" $VDEVS
# Remove the file, wait for trim, verify the vdevs are now sparse.
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh
index e25390339b6c..e139809105df 100755
--- a/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh
@@ -54,7 +54,7 @@ log_onexit cleanup
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
# Reduced TRIM_TXG_BATCH to make trimming more frequent.
typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh
index ae7ad8d73dd8..53de485b1a8e 100755
--- a/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh
@@ -55,7 +55,7 @@ log_onexit cleanup
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
# Reduced TRIM_TXG_BATCH to make trimming more frequent.
typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
diff --git a/tests/zfs-tests/tests/functional/trim/trim.cfg b/tests/zfs-tests/tests/functional/trim/trim.cfg
index 91adb7624326..02dc77ab57e7 100644
--- a/tests/zfs-tests/tests/functional/trim/trim.cfg
+++ b/tests/zfs-tests/tests/functional/trim/trim.cfg
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/trim/trim_config.ksh b/tests/zfs-tests/tests/functional/trim/trim_config.ksh
index 9a6e19e1c042..c08b5edb5698 100755
--- a/tests/zfs-tests/tests/functional/trim/trim_config.ksh
+++ b/tests/zfs-tests/tests/functional/trim/trim_config.ksh
@@ -57,7 +57,7 @@ log_onexit cleanup
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
# Reduced TRIM_TXG_BATCH to make trimming more frequent.
typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
@@ -94,6 +94,7 @@ for type in "" "mirror" "raidz2" "draid"; do
# Fill the pool, verify the vdevs are no longer sparse.
file_write -o create -f /$TESTPOOL/file -b 1048576 -c $fill_mb -d R
+ sync_pool $TESTPOOL
verify_vdevs "-ge" "$VDEV_MAX_MB" $VDEVS
# Remove the file, issue trim, verify the vdevs are now sparse.
diff --git a/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh
index 2dff0924f7b1..c67697521ce8 100755
--- a/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh
+++ b/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh
@@ -54,7 +54,7 @@ log_onexit cleanup
# Minimum trim size is decreased to verify all trim sizes.
typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
-log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 512
# Reduced TRIM_TXG_BATCH to make trimming more frequent.
typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
diff --git a/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh b/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh
index 0bbd08acdd3f..a93d0b3cc803 100755
--- a/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh
+++ b/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh
@@ -67,7 +67,7 @@ typeset VDEV_MIN_MB=$((MINVDEVSIZE * 0.30 / 1024 / 1024))
log_must zpool create -f $TESTPOOL $TRIM_VDEV1 cache $TRIM_VDEV2
verify_vdevs "-le" "$VDEV_MIN_MB" $TRIM_VDEV2
-typeset fill_mb=$(( floor(2 * MINVDEVSIZE) ))
+typeset fill_mb=$(( floor(3 * MINVDEVSIZE) ))
export DIRECTORY=/$TESTPOOL
export NUMJOBS=1
export FILE_SIZE=${fill_mb}
diff --git a/tests/zfs-tests/tests/functional/truncate/cleanup.ksh b/tests/zfs-tests/tests/functional/truncate/cleanup.ksh
index 9756c0fab805..68b56287ed2b 100755
--- a/tests/zfs-tests/tests/functional/truncate/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/truncate/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/truncate/setup.ksh b/tests/zfs-tests/tests/functional/truncate/setup.ksh
index 863492db531d..570c94570ef9 100755
--- a/tests/zfs-tests/tests/functional/truncate/setup.ksh
+++ b/tests/zfs-tests/tests/functional/truncate/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate.cfg b/tests/zfs-tests/tests/functional/truncate/truncate.cfg
index d852ee63abb5..aca91cda9c64 100644
--- a/tests/zfs-tests/tests/functional/truncate/truncate.cfg
+++ b/tests/zfs-tests/tests/functional/truncate/truncate.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh b/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh
index 1ae2d74e0d4e..19bf0343e32d 100755
--- a/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh b/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh
index cff740e5fbba..17cde7b698ba 100755
--- a/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh
index 1f0c9b63d9f1..5cb5fae1f1a3 100755
--- a/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/upgrade/setup.ksh b/tests/zfs-tests/tests/functional/upgrade/setup.ksh
index c25d25df6b9e..09fb2fbfe9a3 100755
--- a/tests/zfs-tests/tests/functional/upgrade/setup.ksh
+++ b/tests/zfs-tests/tests/functional/upgrade/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib b/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib
index 6ffd85b5b1b6..3e1886428620 100644
--- a/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh b/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh
index 88d09759bfee..2ad37e06a5f1 100755
--- a/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh b/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh
index b437a0cdfa3d..d4ad8df85242 100755
--- a/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
index 61caf3910042..4895aa23ee4a 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/user_namespace/setup.ksh b/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
index 354cc9a6b17d..bf6bc8399fd1 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
index 9e55398e239c..ca94fc4a7ea0 100644
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
index 39aad91d0c61..d79828a36e9e 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_002.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_002.ksh
index a5f76014ab85..cfc478cd3592 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_002.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_002.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -85,7 +85,7 @@ fi
list="$($NSENTER zfs list -r -H -o name | tr '\n' ' ')"
log_must test -z "$list"
log_must zfs zone $proc_ns $TESTPOOL/userns
-proc_ns_added="$ns"
+proc_ns_added="$proc_ns"
# 2. 'zfs list'
list="$($NSENTER zfs list -r -H -o name $TESTPOOL | tr '\n' ' ')"
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_003.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_003.ksh
index 20a7f6677d20..6a746c6d33f6 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_003.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_003.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -88,7 +88,7 @@ list="$($NSENTER zfs list -r -H -o name | tr '\n' ' ')"
log_must test -z "$list"
log_must zfs zone $proc_ns $TESTPOOL/userns
log_must zfs zone $proc_ns $TESTPOOL/otheruserns
-proc_ns_added="$ns"
+proc_ns_added="$proc_ns"
# 2. 'zfs list'
list="$($NSENTER zfs list -r -H -o name $TESTPOOL | tr '\n' ' ')"
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_004.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_004.ksh
index 6edb0413c98a..e6ad25f23f93 100755
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_004.ksh
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_004.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -44,8 +44,6 @@ user_ns_cleanup() {
log_must zfs destroy -r "$TESTPOOL/userns"
}
-log_onexit user_ns_cleanup
-
log_assert "Check zfs zone command handling of non-namespace files"
# Pass if user namespaces are not supported.
@@ -54,6 +52,8 @@ if [ "$?" -ne "0" ]; then
log_unsupported "Failed to create user namespace"
fi
+log_onexit user_ns_cleanup
+
# Create the baseline datasets.
log_must zfs create -o zoned=on "$TESTPOOL/userns"
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
index 8577294d0eaa..e9f1d7c5bd5e 100644
--- a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
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
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/userquota/cleanup.ksh b/tests/zfs-tests/tests/functional/userquota/cleanup.ksh
index 5c8229b1874f..8af203eabde5 100755
--- a/tests/zfs-tests/tests/functional/userquota/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh
index b2c48a6424c4..d6e01fa5c6ea 100755
--- a/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh
index 3e9262831229..1885986aecc7 100755
--- a/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh
index 6d7f5bad3f35..111187057b83 100755
--- a/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/setup.ksh b/tests/zfs-tests/tests/functional/userquota/setup.ksh
index 29cbbeb660d0..79507504711c 100755
--- a/tests/zfs-tests/tests/functional/userquota/setup.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota.cfg b/tests/zfs-tests/tests/functional/userquota/userquota.cfg
index 893428deaf0a..75ecdc309fe8 100644
--- a/tests/zfs-tests/tests/functional/userquota/userquota.cfg
+++ b/tests/zfs-tests/tests/functional/userquota/userquota.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh
index dd8f6d3552bb..dcd4d5d76ded 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh
index 4e13691dac43..9df0dd539a38 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh
index c4ac15c0dfe4..99b99874edfa 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh
index 896645f7ca0d..f7b87de2093b 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh
index b8e956164f73..bcdd12021fa7 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh
index 1c2509c83705..422702cccbe1 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh
index 61cfb4661567..ccf4035f87f8 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh
index c9404cd2868f..368399aec50c 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh
index b6f2727806c4..541a6318430a 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh
index 20c9c56ba5ef..e025802196f6 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh
index 8917b3be2865..63b4a491758a 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh
index 12e023134d81..b6d24f6ed75e 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh
index 84f2386af5b8..6938fcc5a032 100755
--- a/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib b/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib
index 40f9184c5254..6599d89973f7 100644
--- a/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh
index 137dd68662cc..4f38744a686a 100755
--- a/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh
index 0821bd075f60..e4889e5e4ee9 100755
--- a/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh
index de7c117af3ab..1d36d515b56e 100755
--- a/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
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"
diff --git a/tests/zfs-tests/tests/functional/vdev_disk/.gitignore b/tests/zfs-tests/tests/functional/vdev_disk/.gitignore
new file mode 100644
index 000000000000..27653e5924fc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_disk/.gitignore
@@ -0,0 +1 @@
+page_alignment
diff --git a/tests/zfs-tests/tests/functional/vdev_disk/page_alignment.c b/tests/zfs-tests/tests/functional/vdev_disk/page_alignment.c
new file mode 100644
index 000000000000..5c6d28eb2c44
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_disk/page_alignment.c
@@ -0,0 +1,413 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2023, 2024, Klara Inc.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/param.h>
+#include <stdlib.h>
+
+/*
+ * This tests the vdev_disk page alignment check callback
+ * vdev_disk_check_pages_cb(). For now, this test includes a copy of that
+ * function from module/os/linux/zfs/vdev_disk.c. If you change it here,
+ * remember to change it there too, and add tests data here to validate the
+ * change you're making.
+ */
+
+struct page;
+
+typedef struct {
+ uint32_t bmask;
+ uint32_t npages;
+ uint32_t end;
+} vdev_disk_check_pages_t;
+
+static int
+vdev_disk_check_pages_cb(struct page *page, size_t off, size_t len, void *priv)
+{
+ (void) page;
+ vdev_disk_check_pages_t *s = priv;
+
+ /*
+ * If we didn't finish on a block size boundary last time, then there
+ * would be a gap if we tried to use this ABD as-is, so abort.
+ */
+ if (s->end != 0)
+ return (1);
+
+ /*
+ * Note if we're taking less than a full block, so we can check it
+ * above on the next call.
+ */
+ s->end = (off+len) & s->bmask;
+
+ /* All blocks after the first must start on a block size boundary. */
+ if (s->npages != 0 && (off & s->bmask) != 0)
+ return (1);
+
+ s->npages++;
+ return (0);
+}
+
+typedef struct {
+ /* test name */
+ const char *name;
+
+ /* blocks size mask */
+ uint32_t mask;
+
+ /* amount of data to take */
+ size_t size;
+
+ /* [start offset in page, len to end of page or size] */
+ size_t pages[16][2];
+} page_test_t;
+
+static const page_test_t valid_tests[] = {
+ /* 512B block tests */
+ {
+ "512B blocks, 4K single page",
+ 0x1ff, 0x1000, {
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "512B blocks, 1K at start of page",
+ 0x1ff, 0x400, {
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "512B blocks, 1K at end of page",
+ 0x1ff, 0x400, {
+ { 0x0c00, 0x0400 },
+ },
+ }, {
+ "512B blocks, 1K within page, 512B start offset",
+ 0x1ff, 0x400, {
+ { 0x0200, 0x0e00 },
+ },
+ }, {
+ "512B blocks, 8K across 2x4K pages",
+ 0x1ff, 0x2000, {
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "512B blocks, 4K across two pages, 2K start offset",
+ 0x1ff, 0x1000, {
+ { 0x0800, 0x0800 },
+ { 0x0, 0x0800 },
+ },
+ }, {
+ "512B blocks, 16K across 5x4K pages, 512B start offset",
+ 0x1ff, 0x4000, {
+ { 0x0200, 0x0e00 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0200 },
+ },
+ }, {
+ "512B blocks, 64K data, 8x8K compound pages",
+ 0x1ff, 0x10000, {
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ },
+ }, {
+ "512B blocks, 64K data, 9x8K compound pages, 512B start offset",
+ 0x1ff, 0x10000, {
+ { 0x0200, 0x1e00 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x0200 },
+ },
+ }, {
+ "512B blocks, 64K data, 2x16K compound pages, 8x4K pages",
+ 0x1ff, 0x10000, {
+ { 0x0, 0x8000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "512B blocks, 64K data, mixed 4K/8K/16K pages",
+ 0x1ff, 0x10000, {
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ },
+ }, {
+ "512B blocks, 64K data, mixed 4K/8K/16K pages, 1K start offset",
+ 0x1ff, 0x10000, {
+ { 0x0400, 0x0c00 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0400 },
+ },
+ },
+
+ /* 4K block tests */
+ {
+ "4K blocks, 4K single page",
+ 0xfff, 0x1000, {
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "4K blocks, 1K at start of page",
+ 0xfff, 0x400, {
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "4K blocks, 1K at end of page",
+ 0xfff, 0x400, {
+ { 0x0c00, 0x0400 },
+ },
+ }, {
+ "4K blocks, 1K within page, 512B start offset",
+ 0xfff, 0x400, {
+ { 0x0200, 0x0e00 },
+ },
+ }, {
+ "4K blocks, 8K across 2x4K pages",
+ 0xfff, 0x2000, {
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "4K blocks, 4K across two pages, 2K start offset",
+ 0xfff, 0x1000, {
+ { 0x0800, 0x0800 },
+ { 0x0, 0x0800 },
+ },
+ }, {
+ "4K blocks, 16K across 5x4K pages, 512B start offset",
+ 0xfff, 0x4000, {
+ { 0x0200, 0x0e00 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0200 },
+ },
+ }, {
+ "4K blocks, 64K data, 8x8K compound pages",
+ 0xfff, 0x10000, {
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ },
+ }, {
+ "4K blocks, 64K data, 9x8K compound pages, 512B start offset",
+ 0xfff, 0x10000, {
+ { 0x0200, 0x1e00 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x0200 },
+ },
+ }, {
+ "4K blocks, 64K data, 2x16K compound pages, 8x4K pages",
+ 0xfff, 0x10000, {
+ { 0x0, 0x8000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ },
+ }, {
+ "4K blocks, 64K data, mixed 4K/8K/16K pages",
+ 0xfff, 0x10000, {
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ },
+ }, {
+ "4K blocks, 64K data, mixed 4K/8K/16K pages, 1K start offset",
+ 0xfff, 0x10000, {
+ { 0x0400, 0x0c00 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x2000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x8000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0400 },
+ },
+ },
+
+ { 0 },
+};
+
+static const page_test_t invalid_tests[] = {
+ {
+ "512B blocks, 16K data, 512 leader (gang block simulation)",
+ 0x1ff, 0x8000, {
+ { 0x0, 0x0200 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0c00 },
+ },
+ }, {
+ "4K blocks, 32K data, 2 incompatible spans "
+ "(gang abd simulation)",
+ 0xfff, 0x8000, {
+ { 0x0800, 0x0800 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0800 },
+ { 0x0800, 0x0800 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x1000 },
+ { 0x0, 0x0800 },
+ },
+ },
+ { 0 },
+};
+
+static bool
+run_test(const page_test_t *test, bool verbose)
+{
+ size_t rem = test->size;
+
+ vdev_disk_check_pages_t s = {
+ .bmask = 0xfff,
+ .npages = 0,
+ .end = 0,
+ };
+
+ for (int i = 0; test->pages[i][1] > 0; i++) {
+ size_t off = test->pages[i][0];
+ size_t len = test->pages[i][1];
+
+ size_t take = MIN(rem, len);
+
+ if (verbose)
+ printf(" page %d [off %lx len %lx], "
+ "rem %lx, take %lx\n",
+ i, off, len, rem, take);
+
+ if (vdev_disk_check_pages_cb(NULL, off, take, &s)) {
+ if (verbose)
+ printf(" ABORT: misalignment detected, "
+ "rem %lx\n", rem);
+ return (false);
+ }
+
+ rem -= take;
+ if (rem == 0)
+ break;
+ }
+
+ if (rem > 0) {
+ if (verbose)
+ printf(" ABORT: ran out of pages, rem %lx\n", rem);
+ return (false);
+ }
+
+ return (true);
+}
+
+static void
+run_test_set(const page_test_t *tests, bool want, int *ntests, int *npassed)
+{
+ for (const page_test_t *test = &tests[0]; test->name; test++) {
+ bool pass = (run_test(test, false) == want);
+ if (pass) {
+ printf("%s: PASS\n", test->name);
+ (*npassed)++;
+ } else {
+ printf("%s: FAIL [expected %s, got %s]\n", test->name,
+ want ? "VALID" : "INVALID",
+ want ? "INVALID" : "VALID");
+ run_test(test, true);
+ }
+ (*ntests)++;
+ }
+}
+
+int main(void) {
+ int ntests = 0, npassed = 0;
+
+ run_test_set(valid_tests, true, &ntests, &npassed);
+ run_test_set(invalid_tests, false, &ntests, &npassed);
+
+ printf("\n%d/%d tests passed\n", npassed, ntests);
+
+ return (ntests == npassed ? 0 : 1);
+}
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib
index ad5bd9e7f81b..c68a5b2c4c83 100644
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib
@@ -34,6 +34,10 @@ function get_top_vd_zap # dsk conf
{
get_conf_section "$1" "$2" | awk '/com.delphix:vdev_zap_top: [0-9]+/ {print $2}'
}
+function get_root_vd_zap # conf
+{
+ awk '/com.klarasystems:vdev_zap_root: [0-9]+/ {print $2}' "$1"
+}
function assert_has_sentinel # conf
{
@@ -54,6 +58,15 @@ function assert_zap_common # pool vd lvl zapobj
fi
}
+function assert_root_zap # pool conf
+{
+ typeset pool=$1
+ typeset conf=$2
+
+ root_zap=$(get_root_vd_zap $conf)
+ assert_zap_common $pool "root vdev" "root" $root_zap
+}
+
function assert_top_zap # pool vd conf
{
typeset pool=$1
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh
index b67cc6d973e6..bdc8dcd468ae 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh
@@ -21,7 +21,7 @@
#
# Strategy:
# 1. Create a pool with one disk.
-# 2. Verify that the disk has a top and leaf ZAP in its config and the MOS.
+# 2. Verify that the disk has a root, top and leaf ZAP in its config and the MOS.
#
. $STF_SUITE/include/libtest.shlib
@@ -35,6 +35,7 @@ log_must zpool create -f $TESTPOOL $DISK
conf="$TESTDIR/vz001"
log_must eval "zdb -PC $TESTPOOL > $conf"
+assert_root_zap $TESTPOOL "$conf"
assert_top_zap $TESTPOOL $DISK "$conf"
assert_leaf_zap $TESTPOOL $DISK "$conf"
assert_has_sentinel "$conf"
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh
index c571973b080b..35c4f64fa463 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh
@@ -36,6 +36,7 @@ conf="$TESTDIR/vz002"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
for DISK in $DISKS; do
assert_top_zap $TESTPOOL $DISK "$conf"
assert_leaf_zap $TESTPOOL $DISK "$conf"
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh
index 015729576a7d..bb6875c339c3 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh
@@ -37,6 +37,7 @@ conf="$TESTDIR/vz003"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
assert_top_zap $TESTPOOL "type: 'mirror'" "$conf"
for DISK in $DISKS; do
assert_leaf_zap $TESTPOOL $DISK "$conf"
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh
index 3d0f55d5a9a7..e82e398c6d27 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh
@@ -40,6 +40,7 @@ log_must zpool create -f $TESTPOOL $DISK
conf="$TESTDIR/vz004"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
orig_top=$(get_top_vd_zap $DISK $conf)
orig_leaf=$(get_leaf_vd_zap $DISK $conf)
assert_zap_common $TESTPOOL $DISK "top" $orig_top
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh
index 1d82218bf283..4b9b45e149d7 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh
@@ -37,6 +37,7 @@ log_must zpool create -f $TESTPOOL $DISK
conf="$TESTDIR/vz005"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
orig_top=$(get_top_vd_zap $DISK $conf)
orig_leaf=$(get_leaf_vd_zap $DISK $conf)
assert_zap_common $TESTPOOL $DISK "top" $orig_top
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh
index ce94336c7c5d..2ac493b8b0d2 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh
@@ -39,6 +39,7 @@ conf="$TESTDIR/vz006"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
orig_top=$(get_top_vd_zap ${DISK_ARR[1]} $conf)
assert_zap_common $TESTPOOL ${DISK_ARR[1]} "top" $orig_top
assert_leaf_zap $TESTPOOL ${DISK_ARR[1]} "$conf"
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh
index c7f12c633706..c7a4a62de436 100755
--- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh
@@ -39,6 +39,7 @@ conf="$TESTDIR/vz007"
log_must eval "zdb -PC $TESTPOOL > $conf"
assert_has_sentinel "$conf"
+assert_root_zap $TESTPOOL "$conf"
orig_top=$(get_top_vd_zap "type: 'mirror'" $conf)
orig_leaf0=$(get_leaf_vd_zap ${DISK_ARR[0]} $conf)
orig_leaf1=$(get_leaf_vd_zap ${DISK_ARR[1]} $conf)
diff --git a/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh b/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh
index aa032084cdce..760356108f58 100755
--- a/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/write_dirs/setup.ksh b/tests/zfs-tests/tests/functional/write_dirs/setup.ksh
index c89cb8678c6a..a74087f9f505 100755
--- a/tests/zfs-tests/tests/functional/write_dirs/setup.ksh
+++ b/tests/zfs-tests/tests/functional/write_dirs/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh
index f7519eb6dd3b..3b6801288593 100755
--- a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh
index 07387017fa08..fc7dac0a6085 100755
--- a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/cleanup.ksh b/tests/zfs-tests/tests/functional/xattr/cleanup.ksh
index 625718cfeac8..83837aebe473 100755
--- a/tests/zfs-tests/tests/functional/xattr/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/setup.ksh b/tests/zfs-tests/tests/functional/xattr/setup.ksh
index 4f0fb1abf493..e7c1f64c5f32 100755
--- a/tests/zfs-tests/tests/functional/xattr/setup.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr.cfg b/tests/zfs-tests/tests/functional/xattr/xattr.cfg
index d61fc46cb08c..9b4c0ef9ca0e 100644
--- a/tests/zfs-tests/tests/functional/xattr/xattr.cfg
+++ b/tests/zfs-tests/tests/functional/xattr/xattr.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh
index ffb700438528..ab61211d9fd2 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh
index 4393774cb1ad..c60be2217dae 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
index 852bffc7a173..6c8b895f841f 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh
index 2ed040d864c4..cd7840843971 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh
index e5fbe6f18b50..80470e8735b7 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh
index 56f29c88d8eb..138302d970c3 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh
index 5189b627271a..3a6897312651 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh
index 099a61010afd..bf05c681f4eb 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh
index c9d636ecbca3..ae8cb599d9da 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh
index 41c7054f23d7..f0bb9f6dd29a 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh
index 7d7827e135ea..0cb2f8ac5111 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh
index f5c0ab0c22d0..14f109b32bd5 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh
index a5a43ff1083c..5420d1943106 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib b/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib
index 5ff2b489024c..b50f21c13827 100644
--- a/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_compat.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_compat.ksh
index 2f74ffe358b8..c153fb3813d6 100755
--- a/tests/zfs-tests/tests/functional/xattr/xattr_compat.ksh
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_compat.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zap_shrink/cleanup.ksh b/tests/zfs-tests/tests/functional/zap_shrink/cleanup.ksh
new file mode 100755
index 000000000000..42fe70042d6a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zap_shrink/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/zap_shrink/setup.ksh b/tests/zfs-tests/tests/functional/zap_shrink/setup.ksh
new file mode 100755
index 000000000000..b756d4e76c83
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zap_shrink/setup.ksh
@@ -0,0 +1,35 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/zap_shrink/zap_shrink_001_pos.ksh b/tests/zfs-tests/tests/functional/zap_shrink/zap_shrink_001_pos.ksh
new file mode 100755
index 000000000000..4dbf579b8ac7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zap_shrink/zap_shrink_001_pos.ksh
@@ -0,0 +1,81 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2024, Klara Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Create a large number of files in a directory. Then remove all files and
+# check that the directory zap was shrunk. Use zdb to check that the zap object
+# contains only one leaf block using zdb.
+#
+
+verify_runnable "global"
+
+DIR=largedir
+
+NR_FILES=100000
+BATCH=1000
+CWD=$PWD
+
+log_assert "Create a large number of files ($NR_FILES) in a directory. " \
+ "Make sure that the directory ZAP object was shrunk."
+
+log_must mkdir $TESTDIR/$DIR
+
+cd $TESTDIR/$DIR
+# In order to prevent arguments overflowing, create NR_FILES in BATCH at once.
+for i in $(seq $(($NR_FILES/$BATCH))); do
+ touch $(seq $((($i-1)*$BATCH+1)) $(($i*$BATCH)));
+done
+cd $CWD
+
+log_must test $NR_FILES -eq $(ls -U $TESTDIR/$DIR | wc -l)
+
+# remove all files in $DIR directory
+cd $TESTDIR/$DIR
+for i in $(seq $(($NR_FILES/$BATCH))); do
+ rm $(seq $((($i-1)*$BATCH+1)) $(($i*$BATCH)))
+done
+cd $CWD
+sync_pool $TESTPOOL
+
+log_must test 0 -eq $(ls -U $TESTDIR/$DIR | wc -l)
+
+# check whether zap_shrink works
+zapobj=$(zdb -v -O $TESTPOOL/$TESTFS $DIR)
+nleafs=$(echo "$zapobj" | grep "Leaf blocks:" | awk -F\: '{print($2);}')
+log_must test 1 -eq $nleafs
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+# check whether zap_shrink works
+zapobj=$(zdb -v -O $TESTPOOL/$TESTFS $DIR)
+nleafs=$(echo "$zapobj" | grep "Leaf blocks:" | awk -F\: '{print($2);}')
+log_must test 1 -eq $nleafs
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol.cfg b/tests/zfs-tests/tests/functional/zvol/zvol.cfg
index fb2a0385a24c..65ad02ddb76f 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol.cfg
+++ b/tests/zfs-tests/tests/functional/zvol/zvol.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh
index c9250d4e53e9..6488ad63e6f0 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh
index dcdfc86d4e7b..49603d15be9c 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
index 92650c5e050e..bbafacff72a8 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh
index f19fa9df3bf4..47a5eb9277f4 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh
index 79836c2e5d18..29af4a43ff78 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh
index c24933df2fbc..14da78868cc4 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg
index 92650c5e050e..bbafacff72a8 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh
index 847443ac0e95..1bc76517eaef 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh
index 7b8749751b05..22152e2ae1d8 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh
index 779a0baaa091..fa588c6b5f8d 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib b/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib
index c04559fe337b..29ac84d6d151 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh
index 7714530ff4cb..c6296275503c 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh
index 6b2cc821792c..e08f058fb2d6 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh
index 25325ddda694..6a9d2d685668 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh
index 16ff1f5f87db..5b89eb7806b9 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh
index 2b8e5099312b..c7db9ed14a5f 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh
index 0f8dbb1bcfff..c335b869f9bf 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh
index b4a6f1248579..456008ded021 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh
index 08726a7c37e6..62f4adf64235 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
index da8a494b4a64..93355d0b3ded 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh
index e44107030f3c..619d8d0e8f07 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -45,6 +45,15 @@ fi
if ! is_linux ; then
log_unsupported "Only linux supports dd with oflag=dsync for FUA writes"
+else
+ if [[ $(linux_version) -gt $(linux_version "6.2") ]]; then
+ log_unsupported "Disabled while issue #14872 is being worked"
+ fi
+
+ # Disabled for the CentOS 9 kernel
+ if [[ $(linux_version) -eq $(linux_version "5.14") ]]; then
+ log_unsupported "Disabled while issue #14872 is being worked"
+ fi
fi
typeset datafile1="$(mktemp zvol_misc_fua1.XXXXXX)"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh
index 9d3fb05da4b0..1fc2d2780b1c 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_trim.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_trim.ksh
index 2e417a0e6676..c0b191aafd45 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_trim.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_trim.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -44,6 +44,15 @@
verify_runnable "global"
if is_linux ; then
+ if [[ $(linux_version) -gt $(linux_version "6.2") ]]; then
+ log_unsupported "Disabled while issue #14872 is being worked"
+ fi
+
+ # Disabled for the CentOS 9 kernel
+ if [[ $(linux_version) -eq $(linux_version "5.14") ]]; then
+ log_unsupported "Disabled while issue #14872 is being worked"
+ fi
+
# We need '--force' here since the prior tests may leave a filesystem
# on the zvol, and blkdiscard will see that filesystem and print a
# warning unless you force it.
@@ -83,6 +92,7 @@ function do_test {
# Write to zvol
log_must dd if=$datafile1 of=$zvolpath conv=fsync
+ sync_pool
# Record how much space we've used (should be 5MB, with 128k
# of tolerance).
@@ -122,14 +132,13 @@ log_must zfs set compression=off $TESTPOOL/$TESTVOL
# Remove old data from previous tests
log_must $trimcmd $zvolpath
-
set_blk_mq 1
-log_must zpool export $TESTPOOL
+log_must_busy zpool export $TESTPOOL
log_must zpool import $TESTPOOL
do_test
set_blk_mq 0
-log_must zpool export $TESTPOOL
+log_must_busy zpool export $TESTPOOL
log_must zpool import $TESTPOOL
do_test
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh
index af808dc30764..05287674da66 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh
index a393606d0fa9..16b22150b3e8 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_stress/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_stress/cleanup.ksh
index b81a372638e3..a0555aff06c2 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_stress/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_stress/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_stress/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_stress/setup.ksh
index 9e70fc47b89b..2abf3411fd07 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_stress/setup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_stress/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_stress/zvol_stress.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_stress/zvol_stress.ksh
index c1aadcac3bf5..3431d33d97d0 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_stress/zvol_stress.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_stress/zvol_stress.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
@@ -151,6 +151,7 @@ for DISK in $DISKS ; do
log_must zinject -d $DISK -f 10 -e io -T write $TESTPOOL
done
log_must dd if=/dev/zero of=$ZVOL_DEVDIR/$TESTPOOL/testvol1 bs=512 count=50
+sync_pool $TESTPOOL
log_must zinject -c all
# We should see write errors
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh
index f1457b72199e..0befaf15ef8e 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh
index 6c6ca2b3b6f8..b837211aaebd 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg
index b6501da9c5c7..b25ce80c20d5 100644
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg
@@ -6,7 +6,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh
index 854859aa6f1b..3f4cb928529e 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh
index 6106f7ee7d33..8e4a983c7cf3 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh
index 588663dba278..8a58a1f4be60 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh
index 83bf465b633a..a4f24bf5b807 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh
index b22bfdb16507..021c0e3c2761 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh
index 5788a8643487..4a519e6b7547 100755
--- a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh
@@ -7,7 +7,7 @@
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
+# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
diff --git a/tests/zfs-tests/tests/perf/perf.shlib b/tests/zfs-tests/tests/perf/perf.shlib
index 27c40bd52946..5555e910d722 100644
--- a/tests/zfs-tests/tests/perf/perf.shlib
+++ b/tests/zfs-tests/tests/perf/perf.shlib
@@ -485,7 +485,6 @@ function get_system_config
printf " \"tunables\": {\n" >>$config
for tunable in \
zfs_arc_max \
- zfs_arc_meta_limit \
zfs_arc_sys_free \
zfs_dirty_data_max \
zfs_flags \
diff --git a/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh b/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh
index 3a358774f565..e0626c0b42f3 100755
--- a/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh
+++ b/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh
@@ -60,7 +60,7 @@ export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
# Variables specific to this test for use by fio.
export PERF_NTHREADS=${PERF_NTHREADS:-'32 64'}
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
-export PERF_IOSIZES='' # bssplit used instead
+export PERF_IOSIZES='bssplit' # bssplit used instead of fixed sizes
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
# Layout the files to be used by the readwrite tests. Create as many files
diff --git a/udev/zvol_id.c b/udev/zvol_id.c
index ea38ac8cdf38..609349594767 100644
--- a/udev/zvol_id.c
+++ b/udev/zvol_id.c
@@ -6,7 +6,7 @@
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
@@ -51,7 +51,7 @@ const char *__asan_default_options(void) {
int
main(int argc, const char *const *argv)
{
- if (argc != 2) {
+ if (argc != 2 || strncmp(argv[1], "/dev/zd", 7) != 0) {
fprintf(stderr, "usage: %s /dev/zdX\n", argv[0]);
return (1);
}
@@ -72,9 +72,10 @@ main(int argc, const char *const *argv)
return (1);
}
- unsigned int dev_part = minor(sb.st_rdev) % ZVOL_MINORS;
- if (dev_part != 0)
- sprintf(zvol_name + strlen(zvol_name), "-part%u", dev_part);
+ const char *dev_part = strrchr(dev_name, 'p');
+ if (dev_part != NULL) {
+ sprintf(zvol_name + strlen(zvol_name), "-part%s", dev_part + 1);
+ }
for (size_t i = 0; i < strlen(zvol_name); ++i)
if (isblank(zvol_name[i]))