unit/nvpair: verify complete copied results
Read the copied string from the destination list rather than the source.
Require both pair iterators to reach the end when comparing a duplicate.
The current loop accepts a copy truncated after its first pair.
Check that duplication preserves the list's uniqueness flags as well as
its entries. Distinct input names otherwise hide a changed list mode.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19455
unit: exercise the selected nvlist and normalization modes
The byte and uint8 cases ignore their uniqueness parameters, and the
pair-lookup case always constructs an NV_UNIQUE_NAME list. Use the
selected fixtures and check ENOTSUP for pair lookup in the other modes.
Select NFKD in the compatibility-decomposition test, which currently
passes NFKC and repeats the composition mode instead.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19455
unit: check fixture setup and output cleanup results
Check the fat-ZAP upgrade operations and memory-stream closes directly,
so their failures cannot be hidden by later assertions on the contents.
Reject a failure to disable core dumps in the btree death-test child
with a nonzero exit. An assertion there would produce the same SIGABRT
that the test expects from the btree operation.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Rob Norris <rob.norris at truenas.com>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19467
libspl: keep native backtraces usable under Valgrind
Native unwinding inspects register snapshots and probes process memory.
Memcheck can report these operations while handling an assertion,
obscuring the failure that triggered the backtrace.
Disable Valgrind error reporting on the calling thread while generating
the native backtrace, then restore the previous reporting state. Keep
the native registers, symbolization and caller-selected descriptor,
including stderr redirected after Valgrind starts. Detect the optional
client-request headers during userspace configuration.
This scope also hides genuine errors encountered while unwinding.
Add destination tests for redirected stderr and custom descriptors.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19459
build: generate zfs_gitrev.h before building the kernel modules
module/Makefile lists modules and gitrev as two prerequisites of all,
with nothing that orders them. Under make -j the kernel build can then
compile spa_history.c or spl-proc.c before zfs_gitrev.h exists. Seen
with make -j24 -l25:
spa_history.c:32:10: fatal error: 'zfs_gitrev.h' file not found
Make modules-Linux and modules-FreeBSD depend on gitrev instead.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Alexander Moch <mail at alexmoch.com>
Closes #19535
test-runner: write the kmemleak report into the log
When kmemleak reports objects after a test, the test runner marks the
test as failed and writes the report to a kmemleak file in the test's
output directory, but not to the log. The CI's Test Summary and job
summary take a failed test's output from the log, so the report only
shows up in the downloaded archive.
Also write the report into the log, after the test's own output, with
each line prefixed "kmemleak:". The kmemleak file is unchanged.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Alexander Moch <mail at alexmoch.com>
Closes #19472
ZTS: select failed tests from current runner logs
The rerun filters only recognize unprefixed, unlabelled result lines.
Current timestamps and platform identifiers prevent failures from
being selected, so automatic retries can report success without
rerunning a failed test.
Parse the emitted result headers and retain group identifiers when
matching failures. Match resolved directories first, with relative
runfile group paths allowing reruns after the suite moves. Absolute
groups and standalone tests keep exact path matching.
Let the runner parse retry records after the wrapper filters eligible
test names, retaining older log support.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Tigerblue77 <37409593+tigerblue77 at users.noreply.github.com>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19437
zio_crypt_os: add Linux kernel crypto API backend
Implement the zio_crypt_os platform interface using the Linux kernel
crypto API. This provides hardware-accelerated encryption on platforms
where the ICP has none, most notably ARM.
The kernel exports these symbols GPL-only by default, so configure
selects this backend only when the kernel exports them with a license
compatible with the module's and the AEAD and hash cores (CRYPTO_AEAD2
and CRYPTO_HASH2) are enabled. A builtin build is not subject to export
licensing, but then needs those cores to be builtin as well. Otherwise
the ICP backend is used. Only the selected backend is compiled.
The backend looks up its algorithms by name at key load time, so it
declares a soft dependency on the modules providing them for initrd
builders to include.
Finally, since crypto accelerators may DMA write to keydata and
hmac_keydata, dsl_crypto_key_sync() will now put these on the heap
[6 lines not shown]
zstream: read BLKSSZGET into an int in zstream raw
The BLKSSZGET ioctl stores an int, but zstream raw passed a pointer to
the uint64_t volume.sectorsize. On little-endian systems this happens
to work because the upper half was already zero, but on big-endian
systems the sector size ends up in the upper 32 bits (512 << 32, or
2 TiB). free_blocks() then rounds the start of a freed range up to
2 TiB and writes zeros from the start of the range towards it. On any
smaller device that write fails with ENOSPC at the end of the device,
so zstream raw exits at the first FREE record with a nonzero offset,
after zeroing from that offset to the end of the device. Every zvol
stream has such a record before its data (the free past the end of the
volume), so zstream raw could not apply a zvol stream to a block
device on big-endian systems at all.
Read the value into an int and assign it.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19324
zpool: compare special and dedup vdevs only with normal vdevs
Since 1d9c32c16 a special or dedup vdev may be more redundant than the
normal vdevs, but get_replication() still compared each special or dedup
vdev with the previous special or dedup vdev. A pool with a 3-way
special mirror and a 2-way dedup mirror on 2-way mirror normal vdevs,
each of which is individually acceptable, was therefore reported as
inconsistent. check_replication() skips all checks for an inconsistent
pool, so a later non-redundant addition was accepted without -f:
zpool create tank mirror f1 f2 special mirror f3 f4 f5
zpool add tank dedup mirror f6 f7 # accepted
zpool add tank f8 # accepted without -f
At the same time, creating the same layout in one step was rejected:
zpool create tank mirror f1 f2 special mirror f3 f4 f5 \
dedup mirror f6 f7 # rejected
[14 lines not shown]
ZTS: test replication checks with mixed special and dedup
Add alloc_class_018_pos. It creates a 2-way mirror pool with a 3-way
special mirror and a 2-way dedup mirror, both in one step and with
'zpool add', and checks that adding a single disk to it is refused
without -f. It also checks that a less redundant dedup device is
rejected when added together with a more redundant special device.
This currently fails: creating the pool in one step is rejected as an
inconsistent replication level, while building it with 'zpool add'
succeeds and the pool is then considered inconsistent, so the single
disk is accepted without -f. The fix follows in the next commit.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19288
libspl/membar: silence GCC warnings with ThreadSanitizer
ThreadSanitizer (TSan) does not currently have any support for fences.
GCC will throw an error when trying to emit a fence with
-fsanitize=thread enabled. Silence that warning.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19505
libspl/atomic: remove membar_enter/membar_exit
Not used anywhere, and not implemented for kernel SPLs.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19505
ZTS: pass only numbers to return
ksh93u+m 1.0 (533ab5f932, 2026-10-22) rejects a non-numeric argument to
return with "bad number" and exit status 128. The Alpine CI runners
build ksh from the head of that branch, so since then
zpool_prefetch_001_pos (return true) and zinject_counts (return [[ ...
]]) fail there on every run.
Older versions silently treated those arguments as 0, so
check_count_freq() in zinject_counts never failed: its equality test was
also malformed ([[ $match -eq 0 $inject ]]), and the object injection
case read /tank/file instead of the test pool's file, so it never
matched the rule. Use the [[ ]] result as the status, compare the
injection count with the match count, and read the right file.
zed_stop() returned "" on FreeBSD; return 0.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19530
dsl_deadlist_open(): clean up on error
Since c33a55b0c2, dsl_deadlist_open() can fail, but when
dmu_bonus_hold() fails it leaves dl_os set. dsl_deadlist_is_open()
then returns true, and the error paths of dsl_dataset_hold_obj() and
dsl_dir_hold_obj() call dsl_deadlist_close(), which does
dmu_buf_rele(NULL). For a livelist, dsl_dir_livelist_close() also
destroys dd_pending_allocs and dd_pending_frees, which were never
created. Importing a pool with a damaged deadlist object can thus
crash the kernel (#17809).
Make dsl_deadlist_open() set dl_os, dl_object and dl_lock only once
it has succeeded, also for an old-format deadlist whose bpobj_open()
fails, so that a failed open leaves the deadlist not open. Likewise
initialize bpo_lock only once bpobj_open() has succeeded.
Add a test that damages the MOS dnode block holding a snapshot's
deadlist object and holds that snapshot.
[5 lines not shown]
zoned_uid: preserve global-only zoning property checks (#19521)
The UID-based property policy returns before the global-zone check for
zoned. A namespace owner with delegated zoned permission can change it
through ZFS_IOC_SET_PROP, although the CLI rejects the request.
Check both zoning properties before choosing the UID or regular policy.
Use dsl_deleg_access() instead of repeating its dataset-hold sequence,
retaining the delegation-disabled rejection.
Grant zoned permission in the existing negative test so absence of the
grant does not hide the property restriction.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19521
metaslab: don't modify ms_weight when verifying it
metaslab_verify_weight_and_frag() (enabled by ZFS_DEBUG_METASLAB_VERIFY,
which is set by default on debug builds) recomputes a metaslab's weight
to check it against the cached value. To do so it temporarily set
msp->ms_weight to 0, called metaslab_weight() and then stored the
result (OR'ed with the original active bits) back into ms_weight, all
while holding only ms_lock.
It is called from metaslab_flush() in syncing context, which can run
concurrently with open-context allocations (e.g. the device removal
thread in spa_vdev_copy_segment(), or ZIL writes). Those read
ms_weight of the group's active metaslabs while holding only mg_lock,
and so could observe the transient zero weight and trip
ASSERT(msp->ms_weight & METASLAB_ACTIVE_MASK)
in metaslab_group_alloc(). We hit this in the zpool_labelclear_removed
ZTS test. ms_weight is also the sort key of the metaslab group's AVL
[17 lines not shown]
ZTS: test allocations during metaslab weight verification
metaslab_verify_weight_and_frag() (ZFS_DEBUG_METASLAB_VERIFY, on by
default in debug builds) temporarily sets ms_weight to 0 while holding
only ms_lock. An open-context allocation such as a ZIL write looks at
its allocator's active metaslab under mg_lock alone, so if it lands in
that window it trips
ASSERT(msp->ms_weight & METASLAB_ACTIVE_MASK)
in metaslab_group_alloc(). The window is short, so this has only been
seen as an occasional ZTS failure.
Add a test-only module parameter, metaslab_verify_weight_delay_ms,
which delays the verification of active metaslabs and notes it in the
debug log, and a test that uses it: log_spacemap_verify_weight forces a
flush of all metaslabs with `zpool condense -t log_spacemap` and issues
a ZIL write to the log device's active metaslab while it is being
verified. Without a fix this fails the assertion above.
[5 lines not shown]
abi: updates for removed atomic_* and member_* exports
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19518
config: test for atomic intrinsics and -latomic
Test for 64-bit atomic support in the compiler, either directly or via
-latomic. If required, -latomic is added to the global LIBS, and all
programs will be linked against it.
The previous version of this check tried to compile lib/libspl/atomic.c
directly. That's now gone so this needed an update anyway.
All GCC and Clang that have C11 support have these intrinsics, and use
them to implement stdatomic and _Atomic. However, they are not part of
any standard, and a C11 compiler is not required to implement them.
It's extremely unlikely that we'll ever encounter this situation, but if
we do this check will fail, and we can implement atomics some other way.
libatomic is a GCC implementation detail, so there's no guarantee that a
non-GCC compiler that doesn't implement atomic intrinsics internally
will necessarily supply a libatomic that does, but that's the common
method when it is necessary. Again, if a compiler implements it support
[25 lines not shown]
libspl/atomic: extend generators for pointer variants
Use selector macros to handle void as a void* parameter and void**
target as necessary. This lets us generate the pointer variants from the
same implementations rather than repeating ourselves.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19518
libspl/atomic: use intrinsics for load/store
Volatile accesses are ordered within the same thread (C11 §5.1.2.3),
however they are not atomic (concurrent read & write is a data race) and
are not barriers against non-volatile accesses (C11 §5.1.2.4).
They also aren't easily interceptable by static analysis or sanitizer
tools, because they're a special language feature, rather than just
another intrinsic.
Let's just sidestep all of this, and use atomic intrinsics for load and
store. In production builds they will decompose to the same assembly
instructions anyway, and for anything else they're much easier to work
with.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19518
libspl/atomic: lift implementation into header as inlines
Best of both worlds - compiler can aggressively inline the intrinsic,
but they're also named so can be #define'd over, seen in the debugger on
low-optimisation builds, etc.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19518
libspl: move atomic.h to sys/atomic.h
Matches the kernel SPLs.
Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Rob Norris <rob.norris at truenas.com>
Closes #19518
vdev: atomically account checkpoint space during parallel load
Each vdev_load task adds its checkpoint space to the same pool-wide
sci_dspace counter. Plain updates can lose contributions from other
vdevs loading concurrently. Use atomic addition during load and
atomic subtraction when tearing down a loaded checkpoint space map.
The other updates of the counter, in metaslab_sync() and in the
checkpoint discard callback, are not known to race, but use the same
atomic helpers so that every update of the field is consistent.
This addresses a candidate cause of the sci_dspace verification
failure in #12053; that failure has not been reproduced locally.
Sponsored-by: TAKT (ABX DEVELOPMENT LLP)
Reviewed-by: Alexander Motin <alexander.motin at TrueNAS.com>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Dmitry R <rdmitry0911 at gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
[2 lines not shown]
Fix dbuf dirty record traversal locking
free_verify() and dmu_buf_set_crypt_params() should hold ->db_mtx
before dbuf_find_dirty_eq(), otherwise it can race with an open
contexts dbuf_free_range().
Assert the lock is held in dbuf_find_dirty_lte() which also covers
dbuf_find_dirty_eq() to prevent future omissions.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Rick Galliher <kcid at kcid.io>
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
Closes #19503
raidz: compute the aggregate copy offset before adding it
vdev_raidz_io_done() found a column's data in an aggregate read buffer
with physbuf + rc_offset - prc_offset. That adds the column's device
offset to the pointer before taking off the aggregate's, so the
intermediate pointer is far outside the buffer, which is undefined.
macOS arm64e kexts are built with pointer arithmetic checks that poison
a result whose top bits differ from the base pointer. Once a child
offset was large enough to wrap the kernel heap address, the
intermediate pointer was poisoned and the memcpy() in
abd_copy_from_buf() took a data abort on a non-canonical address.
Subtract the two offsets first so only the in-bounds result is formed.
Reviewed-by: Matthew Ahrens <matt at mahrens.org>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Signed-off-by: Joergen Lundman <lundman at lundman.net>
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
Closes #19506
ZIL replay of an indirect write leaks later writes in the same block
Consider three sequential writes to a file, A, B and C, where A is
logged WR_INDIRECT and C is to a different part of the same block in
the same txg, and then an fsync(). If we crash during the fsync(),
after we come back up we may see writes A and C but not B. While
POSIX doesn't specify anything before the fsync() completes, ZFS
intends to preserve ordering in as many cases as possible.
The problem occurs because when ZIL replay applies a WR_INDIRECT
record, it restores the entire on-disk block, not just the range that
the user wrote. The on-disk block holds whatever the dbuf contained
when the log was committed, including later writes in the same txg.
So after a crash, replay can bring back writes whose own log records
were never written, out of order with the rest of the log. Also, a
whole-block write into a file's last, partial block grows the file to
the block boundary.
Whole-block replay was added (with TX_WRITE2) to recover the data of a
[61 lines not shown]
unit: zfs_file tests shouldn't use libzpool
The zfs_file unit tests shouldn't link against all of libzpool.
Only the zfs_file_os.c source is needed, add it to the SOURCES
and replace libzpool.la with libspl.la in LDADD.
Additionally, to avoid having to pull in libzutil() solely for
zfs_basename() drop the call and do the strrchr() directly.
Reviewed-by: Kamil Monicz <kamil at monicz.dev>
Reviewed-by: Rob Norris <rob.norris at truenas.com>
Signed-off-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Closes #19522
CI: run unit tests with ASan and UBSan
Enable the existing sanitizer options for the userspace unit-test job,
covering the test implementations and their linked libraries. Enable
UBSan stack traces so reports identify the failing code.
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19457