OpenZFS/src 75bd31cmodule/zfs arc.c

L2ARC: do not feed a device while its rebuild is pending

l2arc_add_vdev() leaves the device at l2ad_start with l2ad_first set,
marks it l2ad_rebuild, and starts its feed thread.  The rebuild runs
later from the spa async thread and only then restores the geometry the
on-disk header describes.

A feed in that window writes at l2ad_start believing the device is
empty, and its headers go on the head of l2ad_buflist while the rebuild
appends the restored ones at the tail.  l2arc_evict() walks that list
from the tail and stops at the first header outside the range it is
clearing, so once list position stops tracking device offset the walk
exits early, headers the hand is about to overwrite are never destroyed,
and the writes that replace them charge the space twice.  vs_alloc
passes vs_space and zpool(8) reports 16.0E free.

l2arc_dev_invalid() rejected a device with l2ad_rebuild or l2ad_trim_all
set until b525525b4 made the feed threads per-device; neither flag has
had a reader since.  Restore the test, after SCL_L2ARC is taken so it

    [7 lines not shown]
DeltaFile
+5-0module/zfs/arc.c
+5-01 files

OpenZFS/src 7853c27include/sys zio.h, module/zfs vdev_raidz.c vdev_draid.c

ZIO: Batch lightweight ZIOs

This further develops concept of ZIO batching from #18921, extending
it from the leaf vdev layer up the stack.  Now it covers the case of
I/O scheduler enabled, not covered before.  I/O aggregation of the
scheduler can complete several ZIOs at once, creating opportunity
for batching.

This change allows ZIO pipeline stages to return more than one ZIO,
chaining them via the field added in previous commit, renaming it
to more generic io_exec_next.  To identify ZIOs to batch, this change
introduces a new ZIO flag ZIO_FLAG_LIGHTWEIGHT, set for members of
a batch.  So once zio_done() or possibly other stage handlers return
a list of ZIOs, zio_execute() has now ability to decide which of them
to execute itself, and which to dispatch to taskqueues as before.

With this change my tests of 32KB block writes to 3x 5-wide NVMe RAIDZ1
on 64-core system with scheduler=on show throughput increase from
15.0GiB/s to 16.1GiB/s, while the taskqueue lock contention is

    [12 lines not shown]
DeltaFile
+259-113module/zfs/zio.c
+4-3include/sys/zio.h
+2-4module/zfs/vdev_mirror.c
+3-1module/zfs/vdev_queue.c
+1-2module/zfs/vdev_raidz.c
+1-2module/zfs/vdev_draid.c
+270-1256 files

OpenZFS/src 6a320c9config kernel-vfs-fop-flags.m4, module/os/linux/zfs zpl_file.c

Linux: Wire RWF_DONTCACHE and POSIX_FADV_NOREUSE

Wire both to Uncached I/O, since that is what they mean -- the data
will not be accessed again after the operation. It allows us to both
reduce ARC/dbuf cache trashing and avoid extra memory copies to/from
scattered and unmapped ARC buffers.

Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: George Melikov <mail at gmelikov.ru>
Signed-off-by: Alexander Motin <alexander.motin at TrueNAS.com>
Closes #19054
DeltaFile
+184-0tests/zfs-tests/cmd/file/file_uncached.c
+103-0tests/zfs-tests/tests/functional/uncached/uncached_noreuse.ksh
+100-0tests/zfs-tests/tests/functional/uncached/uncached_dontcache.ksh
+37-0module/os/linux/zfs/zpl_file.c
+28-0config/kernel-vfs-fop-flags.m4
+20-0tests/zfs-tests/tests/functional/uncached/setup.ksh
+472-013 files not shown
+528-419 files

OpenZFS/src cb333betests/zfs-tests/tests/functional/compression compress_004_pos.ksh, tests/zfs-tests/tests/functional/zstream zstream_raw_001_pos.ksh

ZTS: resolve two possible divide by zero errors in tests

Resolve two divide by zero errors observed by the CI. Change 
how random picking to ensure no divide by zero, and also keep 
same semantics.

Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: George Melikov <mail at gmelikov.ru>
Signed-off-by: tiehexue <tiehexue at hotmail.com>
Closes #19078
DeltaFile
+7-2tests/zfs-tests/tests/functional/zstream/zstream_raw_001_pos.ksh
+6-1tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh
+13-32 files

OpenZFS/src ba464dftests/zfs-tests/tests/functional/mmp mmp_write_uberblocks.ksh mmp_write_distribution.ksh

ZTS: do not leave a suspended pool behind in the mmp tests

The mmp tests destroy their pool from cleanup through

    datasetexists $TESTPOOL && destroy_pool $TESTPOOL

and datasetexists() asks zfs, which cannot open a pool whose I/O is
suspended:

    # zfs get name msus
    cannot open 'msus': pool I/O is currently suspended

MMP suspends the pool by itself once its writes have not succeeded for
long enough, which is exactly the state a failing mmp test tends to
leave behind, so the guard says the pool is gone, cleanup destroys
nothing, and the pool stays imported.  Every mmp test that runs after
it then fails on its own zpool create:

    /dev/loop0 is part of active pool 'testpool'

    [31 lines not shown]
DeltaFile
+21-3tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh
+2-1tests/zfs-tests/tests/functional/mmp/mmp_write_uberblocks.ksh
+2-1tests/zfs-tests/tests/functional/mmp/mmp_write_distribution.ksh
+2-1tests/zfs-tests/tests/functional/mmp/mmp_on_zdb.ksh
+2-1tests/zfs-tests/tests/functional/mmp/mmp_on_thread.ksh
+2-1tests/zfs-tests/tests/functional/mmp/mmp_on_off.ksh
+31-82 files not shown
+34-108 files

OpenZFS/src 0e2c0f9tests/zfs-tests/cmd mmap_sync.c

ZTS: judge mmap_sync by a concurrent fsync, not by a fixed bound

mmap_sync fails whenever one msync() takes longer than two seconds,
and in CI it does, on machines that are merely loaded:

    slow msync: 2318.177000 ms
    slow msync: 4043.686000 ms

The bound was raised once already, in c4d1a19b3 ("ZTS: increase
timeout of mmap_sync_001_pos"), and the ctime_001_pos failure fixed in
8486ea36f shows the same CI stalling a creat() for twelve seconds, so
no fixed bound is going to hold there.

An msync() goes through zpl_fsync(): since a18c9edda ("Linux: sync:
remove async/sync accounting") it writes the dirty pages out with
zfs_putpage() and ends in zil_commit(), and it never waits for page
writeback.  So what the bound really measures is the ZIL commit, which
is the disk.  Sampling the kernel stacks of mmap_sync under an IO load
in a VM confirms it: the time goes into zil_commit_impl() waiting for

    [28 lines not shown]
DeltaFile
+200-36tests/zfs-tests/cmd/mmap_sync.c
+200-361 files

OpenZFS/src e08bc29module/zfs dmu_recv.c, tests/runfiles common.run

Skip interior dnode slots when receiving DRR_FREEOBJECTS

receive_freeobjects() looks up every object of the record with
dmu_object_info() and fails the receive on any error but ENOENT.  An
interior slot of a multi-slot dnode answers EEXIST, and that is the
errno zfs receive then reports as "destination already exists".  This
is how ZTS send_realloc_files fails in CI:

    cannot restore to testpool/newfs at snap3: destination already exists

The sender emits such a record whenever a multi-slot dnode was freed
and a smaller one was later allocated on one of its interior slots: it
frees the leading slots, claims the new object and frees the trailing
slots as three separate records, e.g. for an 8-slot dnode at 10:

    FREEOBJECTS firstobj = 10 numobjs = 3
    OBJECT object = 13 ... dn_slots = 1
    FREEOBJECTS firstobj = 14 numobjs = 4


    [24 lines not shown]
DeltaFile
+116-0tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_interior.ksh
+10-1module/zfs/dmu_recv.c
+2-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+129-24 files

OpenZFS/src 09e7e73tests/zfs-tests/tests/functional/l2arc l2arc_multidev_scaling_pos.ksh

ZTS: fill the ARC before l2arc_multidev_scaling_pos measures it

The test sets l2arc_write_max to 4MB/s, starts a background dd and then
requires that L2ARC wrote at least 80% of 4MB/s per device over a fixed
window.  What that window measures, though, is not the rate limit but
how fast the dd manages to feed the ARC: a feed thread writes what it
finds on the eviction lists and goes back to sleep, so with a writer
that cannot keep ahead of it the phase falls short of the bound through
no fault of the code under test.

In CI on Linux it fails both ways, on unrelated branches:

    NOTE: Single-device writes: 19MB (expected ~48MB)
    Single-device writes 19MB below minimum 38MB

    NOTE: Dual-device writes: 26MB (expected ~96MB)
    Dual-device writes 26MB below minimum 76MB

while passing runs on the same days report 72MB and 158MB for those very

    [45 lines not shown]
DeltaFile
+86-73tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_scaling_pos.ksh
+86-731 files

OpenZFS/src 92a3904include/sys dsl_scan.h, module/zfs dsl_scan.c spa.c

Wait for the txg that finished a scan to sync

dsl_scan_done() marks the scan DSS_FINISHED in syncing context, and
right before that it asks vdev_dtl_reassess() to update the DTLs and
dirty the config, which the same txg writes out later in its
spa_sync().  spa_activity_in_progress() looks at the state alone:

    scanning = (scn->scn_phys.scn_state == DSS_SCANNING);
    ...
    *in_progress = (scanning && !paused && ...);

so "zpool wait -t resilver" and "zpool wait -t scrub" return while the
labels of that txg are still being written; spa_vdev_resilver_done()
notifies the waiters from the async thread, which can run before the
sync ends, so a waiter is not even guaranteed to sleep.

A command issued right after the wait then reads a pool whose labels
are mid-rewrite.  ZTS vdev_zaps_004_pos fails on this: it runs "zdb
-PC" straight after "zpool wait -t resilver" and the pool fails to

    [28 lines not shown]
DeltaFile
+21-2module/zfs/spa.c
+7-0module/zfs/dsl_scan.c
+6-0include/sys/dsl_scan.h
+34-23 files

OpenZFS/src 1ebc6f5cmd/zdb zdb.c

zdb: do not adopt an unreferenced spa when the pool fails to open

When spa_open_rewind() fails, zdb looks the pool up in the namespace
to see whether it only failed for a missing log device, and it does
so into the global spa:

    if ((spa = spa_lookup(target)) != NULL &&
        spa->spa_log_state == SPA_LOG_MISSING) {

spa_lookup() takes no reference, and the open that just failed had
already set spa to NULL.  So whenever the pool is in the namespace
but fails to open for any other reason, zdb goes on to fatal(), and
zdb_exit() then spa_close()s a pool it holds no reference on:

    zdb: can't open 'testpool': Device not configured
    ASSERT at module/zfs/spa_misc.c:1004:spa_close()
    zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref || ...

The pool is in the namespace whenever the cachefile names it, so a

    [13 lines not shown]
DeltaFile
+10-4cmd/zdb/zdb.c
+10-41 files

OpenZFS/src 0ee8ea0include/os/freebsd/spl/sys types32.h, lib/libspl/include/sys types32.h

FreeBSD: use sys/abi_compat.h for time32_t

FreeBSD 14.5 defines time32_t in sys/abi_types.h. The SPL typedef now
duplicates it, which breaks the -std=gnu99 module build on stable/14.
Apply the same change as freebsd-src 87632ddf67b.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Christos Longros <chris.longros at gmail.com>
Closes #19059
DeltaFile
+5-0lib/libspl/include/sys/types32.h
+2-1include/os/freebsd/spl/sys/types32.h
+7-12 files

OpenZFS/src 9e06573.github/workflows README.md zfs-qemu.yml, .github/workflows/scripts qemu-2-start.sh

CI: update the FreeBSD STABLE CI runner to 14.5-STABLE

Update the FreeBSD STABLE CI from 14.4-STABLE to 14.5-STABLE. Update the
README as well.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Christos Longros <chris.longros at gmail.com>
Closes #19058
DeltaFile
+2-2.github/workflows/zfs-qemu.yml
+2-2.github/workflows/scripts/qemu-2-start.sh
+1-1.github/workflows/README.md
+5-53 files

OpenZFS/src e4538b5tests/zfs-tests/tests/functional/device_access device_access_import.ksh setup.ksh

ZTS: tighten the device_access tests

- Wrap the cachefile copy in log_must and require it to be
  non-empty, so the negative import tests cannot pass vacuously
  on a system without /etc/zfs/zpool.cache.
- Make check_vdevs() list only the pool it is passed instead of
  every /dev-backed pool on the host.
- Skip the group with log_unsupported when $DISKS are not real
  block devices, instead of failing.
- Wrap the restore_perms() chmod in log_must.

Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: xfcyhuang <xfcyhuang at aliyun.com>
Closes #19057
DeltaFile
+2-2tests/zfs-tests/tests/functional/device_access/device_access.kshlib
+2-1tests/zfs-tests/tests/functional/device_access/device_access_import.ksh
+3-0tests/zfs-tests/tests/functional/device_access/setup.ksh
+7-33 files

OpenZFS/src 0a25e5ccmd ztest.c

ztest: print the fishing seed with %016llx

printf("%016lx", uint64_t) is undefined on ILP32 where uint64_t
promotes to unsigned long long.  Cast to u_longlong_t and use
%016llx, as is done elsewhere in this file.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Igor Ostapenko <igor.ostapenko at klarasystems.com>
Signed-off-by: xfcyhuang <xfcyhuang at aliyun.com>
Closes #19055
DeltaFile
+10-7cmd/ztest.c
+10-71 files

OpenZFS/src cc22ee2cmd ztest.c

ztest: sleep while waiting for the fishing thread to seed

ztest_thread_create() busy-waits on zs_jumps with an empty loop
body until the newly created fishing thread jumps the shared PRNG
state.  On a single-CPU system, or when the machine is heavily
loaded, the spinning parent can starve the very thread it is
waiting for.  Sleep briefly in the wait loop so the fishing thread
gets a chance to run.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Igor Ostapenko <igor.ostapenko at klarasystems.com>
Signed-off-by: xfcyhuang <xfcyhuang at aliyun.com>
Closes #19055
DeltaFile
+6-1cmd/ztest.c
+6-11 files

OpenZFS/src 69ef525module/zfs dsl_deadlist.c

dsl_deadlist_space_range: use correct tree when summing up space

This was found via code inspection: space_range uses dl_cache for
determining the starting point, and then uses dl_tree for the loop.
This works accidentally only because the tree and cache structs have
the same fields (specifically, node and mintxg) at the same offsets.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Mark Musante <mmusante at wasabi.com>
Closes #19053
DeltaFile
+2-2module/zfs/dsl_deadlist.c
+2-21 files

OpenZFS/src 39764ebmodule/zfs dmu.c

Fix double free when cloning a block with a pending free

dmu_read_l0_bps() captures the source block pointers for a clone
without consulting dnode_block_freed(). A block whose free is recorded
but not yet synced still has a valid on-disk pointer, so the clone
registers a BRT reference to a block about to be returned to the
allocator, and it is freed twice. On a debug build this trips the
metaslab double-free verifier; on a release build the space map is
silently corrupted.

Check for a pending free and return EAGAIN, as dbuf_read_hole() already
does for buffered reads. zfs_clone_range() waits a TXG and retries, by
which point the block reads as a hole.

Two cases need more than the plain check. A hole has nothing to free,
so guard with !BP_IS_HOLE(bp), otherwise a hole inside a pending free
range fails a FICLONE that master cloned. When the head dirty record
already overrode the BP, only frees after the override count against
it, so use dnode_block_freed_after(); dbuf_free_range() leaves the

    [12 lines not shown]
DeltaFile
+38-0module/zfs/dmu.c
+38-01 files

OpenZFS/src 33ae06binclude/sys zio.h, man/man4 zfs.4

ZIO: Batch vdev children completions

A vdev child ZIO's life after return from the block layer is three cheap
pipeline stages, yet each child costs its own taskq dispatch and context
switch to get there, only to decrement the parent's child count and die.
Even with increased number of taskqueues this can create a huge lock
contention and scheduler overheads, especially on large systems.

To avoid that extra cost collect the leaf children of a RAIDZ, dRAID or
mirror parents as they come back, and only once the last one is in,
process all of their completions, followed by the parent's one, all on
a single thread.

This optimization is mutually exclusive with I/O scheduler, since
delayed completions there may lead to a deadlock, but for that case I
have somewhat alike optimization idea later.

With this change my tests of 32KB block writes to 3x 5-wide NVMe RAIDZ1
on 64-core system show throughput increase from 13 GiB/s to 17 GiB/s,

    [4 lines not shown]
DeltaFile
+215-4module/zfs/zio.c
+21-4module/zfs/vdev_queue.c
+19-0include/sys/zio.h
+10-0module/zfs/vdev_mirror.c
+6-0man/man4/zfs.4
+3-0module/zfs/vdev_raidz.c
+274-82 files not shown
+277-88 files

OpenZFS/src 154290ctests/runfiles common.run, tests/zfs-tests/tests Makefile.am

zfs-tests: add zhack mos leak/reclaim coverage

- Add a new cli_root zhack test for the mos leak/scan/reclaim flow.
- Verify dry-run leak/reclaim do not change reclaimable leak counts.
- Verify write-mode leak adds the expected reclaimable clone and
  space map objects, and write-mode reclaim removes them.
- Verify reclaim idempotency by running write reclaim twice and
  asserting the second pass reports "nothing to reclaim".
- Export/import the pool around write-mode operations to match the
  zhack mos command import requirements.
- Register the new test in tests/zfs-tests/tests/Makefile.am and
  tests/runfiles/common.run.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Martin Minkus <martin.minkus at gmail.com>
Closes #18907
DeltaFile
+197-0tests/zfs-tests/tests/functional/cli_root/zhack/zhack_mos_scan_reclaim.ksh
+2-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+200-13 files

OpenZFS/src e74cde0cmd zhack.c, man/man1 zhack.1

zhack: add mos leak subcommand for local repro

- Add `zhack mos leak` to create synthetic leaked MOS objects for
  testing scan/reclaim behavior on disposable pools, mirroring the
  existing `zhack metaslab leak`.
- Support `-c` and `-s` counts for leaked DSL clone maps and
  leaked SPA space maps, with dry-run default and `-w` apply.
- Print the created object IDs so test scripts can assert expected
  candidates and post-reclaim cleanup.
- Document the new subcommand in zhack.1.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Martin Minkus <martin.minkus at gmail.com>
Closes #18907
DeltaFile
+154-1cmd/zhack.c
+24-0man/man1/zhack.1
+178-12 files

OpenZFS/src fe95257cmd zhack.c, man/man1 zhack.1

zhack: add mos scan/reclaim for leaked MOS objects

- Add `zhack mos scan` to enumerate reclaim candidates for
  unreferenced empty DSL clone maps and zeroed space maps.
- Add `zhack mos reclaim` with dry-run by default; `-w` applies
  frees in sync context using `zap_destroy` and `space_map_free_obj`.
- Enable readable spacemaps during readonly analysis to avoid
  false positives when counting referenced metaslab space maps.
- Document the new subcommands in zhack.1.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Martin Minkus <martin.minkus at gmail.com>
Closes #18907
DeltaFile
+501-1cmd/zhack.c
+32-1man/man1/zhack.1
+533-22 files

OpenZFS/src ba524e0cmd/zpool zpool_main.c

zpool: things get messy with 0 columns

zpool iostat with terminal reporting 0 columns will print out
a very long line. Use columns 80 when query reports 0.

Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Toomas Soome <tsoome at me.com>
Closes #19051
DeltaFile
+1-1cmd/zpool/zpool_main.c
+1-11 files

OpenZFS/src 5880127tests/zfs-tests/tests/functional/mmp mmp_concurrent_import.ksh

ZTS: wait for the zhack pids mmp_concurrent_import started

verify_zhack() looks up the processes to wait for by name:

    ZHACKPIDS=$(pgrep zhack)
    for pid in $ZHACKPIDS; do
            wait $pid

so it only waits for the zhacks that pgrep happens to see.  One that has
not reached its exec() yet is still named after the shell that forked
it, and one that has already exited is gone; either way the test
continues while a zhack may still hold the pool imported, and the
import_activity_check() that follows then finds activity where it
requires mmp_result: 0.  A zhack missed this way is also not counted,
so IMPORT_COUNT can silently disagree with what actually happened.

A CI run failed this way.  Two zhacks were started, only one was
reported, the other was still running at the end and was killed by
cleanup:

    [21 lines not shown]
DeltaFile
+22-12tests/zfs-tests/tests/functional/mmp/mmp_concurrent_import.ksh
+22-121 files

OpenZFS/src 7b119detests/zfs-tests/tests/functional/alloc_class alloc_class_016_pos.ksh

ZTS: let the zvol settle before alloc_class_016_pos destroys the pool

The test writes 10M to a zvol and then destroys the pool a few tens of
milliseconds later:

    cannot destroy 'testpool': pool is busy
    ERROR: zpool destroy -f testpool exited 1

Closing the zvol makes the kernel emit a change uevent, udev opens the
device to scan it, and a destroy issued while that scan is in flight
gets EBUSY.  The test already waits for udev after creating the volume
but not after writing to it, and it destroys the pool with log_must
rather than log_must_busy.

Wait for udev again after the write, and destroy the pool the way
destroy_pool() does, retrying while it reports "busy".

Verified in a VM.  The race does not reproduce on an idle machine, so
udev was imitated by holding the zvol open for three seconds before the

    [7 lines not shown]
DeltaFile
+5-1tests/zfs-tests/tests/functional/alloc_class/alloc_class_016_pos.ksh
+5-11 files

OpenZFS/src fd639b0include/sys dsl_bookmark.h, module/zfs dsl_bookmark.c zcp_synctask.c

zcp: support bookmarks in zfs.sync.destroy

Teach the channel-program synctask destroy path to recognize bookmark
targets and route them through the existing bookmark-destroy
implementation. This enables zfs.sync.destroy() to remove bookmarks from
Lua channel programs, matching the behavior already available for
datasets and snapshots. A functional regression test was added to cover
bookmark destruction from a channel program.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
Closes #18992
DeltaFile
+45-0tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_bookmark.ksh
+22-2module/zfs/zcp_synctask.c
+2-8module/zfs/dsl_bookmark.c
+9-0include/sys/dsl_bookmark.h
+2-1tests/runfiles/sanity.run
+2-1tests/runfiles/common.run
+82-121 files not shown
+83-127 files

OpenZFS/src f7b10b6module/os/linux/zfs zfs_uio.c, module/zfs zfs_vnops.c

Revert "Linux: avoid prefaulting under the ZFS range lock"

This reverts commit 43bb1614d50fee71b8ada14ca7b3a0d968a26263.

Signed-off-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Issue #18872
Issue #19046
DeltaFile
+40-26module/zfs/zfs_vnops.c
+2-11module/os/linux/zfs/zfs_uio.c
+42-372 files

OpenZFS/src aa26ca6module/zfs vdev_removal.c

Do not complete a device removal that hit IO errors

spa_vdev_remove_thread() checks vca_read_error_bytes and
vca_write_error_bytes at the end of each metaslab it copies and sets
svr_thread_exit, so that the removal is cancelled instead of completed.
Both counters are incremented from the copy zio callbacks in
spa_vdev_copy_segment_read_done() and
spa_vdev_copy_segment_write_done(), so the errors of the segments
copied last can arrive after that check has already run.  The loop then
ends with svr_thread_exit still B_FALSE and the thread calls
vdev_remove_complete(), dropping the vdev even though part of its data
was never written to the new location.

Write errors are the way to hit this.  A write error is only known once
the write completes, while a read error is recorded before the write it
feeds is even issued, so read errors are almost always seen in time.
With enough data to copy, the errors of one metaslab are noticed while
the next one is being copied, which is why this mostly goes unnoticed;
it is the errors of the metaslab copied last that are missed.

    [15 lines not shown]
DeltaFile
+14-0module/zfs/vdev_removal.c
+14-01 files

OpenZFS/src 1660786.github/workflows zfs-qemu.yml

Increasing ZTS timeout as some PRs exceed the limit

Follow up work to better balance the work between the available
CI VMs is being evaluated to speed things up, but for the moment
increase the limit to prevent these timeout failures.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: tiehexue <tiehexue at hotmail.com>
Closes #18997
DeltaFile
+1-1.github/workflows/zfs-qemu.yml
+1-11 files

OpenZFS/src 8e5bb1dmodule/zfs vdev_trim.c vdev_initialize.c

Wait for the initialize and trim threads to exit

An initializing thread marks the vdev VDEV_INITIALIZE_COMPLETE, drops
vdev_initialize_lock, syncs out the new state with txg_wait_synced()
and only then clears vdev_initialize_thread.  spa_vdev_activity_in_
progress_impl() looks at the state alone:

    boolean_t in_progress = (activity == ZPOOL_WAIT_INITIALIZE) ?
        (vd->vdev_initialize_state == VDEV_INITIALIZE_ACTIVE) :
        (vd->vdev_trim_state == VDEV_TRIM_ACTIVE);

so "zpool wait -t initialize" and "zpool initialize -w" return while
the thread is still in that txg wait.  A command issued right after
them then hits the vdev_initialize_thread != NULL checks in
spa_vdev_initialize_impl() and fails with EBUSY, both for uninit and
for starting another initialization:

    cannot initialize '/var/tmp/zpool_disk2.dat': currently initializing


    [16 lines not shown]
DeltaFile
+11-2module/zfs/spa.c
+1-0module/zfs/vdev_trim.c
+1-0module/zfs/vdev_initialize.c
+13-23 files

OpenZFS/src 489ea64tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: cover change-key on a dataset whose key does not match its root

An incremental raw receive onto a dataset that was rewrapped locally
with 'zfs change-key -i' leaves it pointing at the local encryption root
while carrying the sending root's key material.  Until the previous
commit, running 'zfs change-key' on such a dataset, or on its encryption
root, panicked in syncing context.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Michael Heller <75820586+mkhllr at users.noreply.github.com>
Closes #17425
Closes #18969
DeltaFile
+76-0tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_mismatch.ksh
+1-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+78-13 files