OpenZFS/src a941881 — module/zfs vdev_rebuild.c

vdev_rebuild: wait for the syncing txg before rebuilding a metaslab

Before a sequential rebuild reads a metaslab, it disables allocations
from it and waits for pending allocations to sync. Later passes of the
syncing txg can still rewrite blocks born in that txg in place: a
rewrite allocates nothing, and the first pass has already moved their
allocations to the space map. A rebuild read which overlaps such a
rewrite sees some columns before it and some after. dRAID then finds
the row's parity inconsistent and withholds its repair, and a read
which completes before the rewrite can write the old block over the new
one on the device being rebuilt.

Wait for the txg that is syncing when the metaslab is disabled. No later
txg can allocate from it, so none can rewrite its blocks in place.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Andriy Tkachuk <atkachuk at wasabi.com>
Signed-off-by: Kamil Monicz <kamil at monicz.dev>
Closes #19198
DeltaFile
+8-5module/zfs/vdev_rebuild.c
+8-51 files

OpenZFS/src 602c474 — include/sys metaslab.h, module/zfs zio.c metaslab.c

Report EIO when no vdev can take a Direct I/O write

A Direct I/O write to a pool whose vdevs have all stopped taking
writes fails with ENOSPC. The same write done buffered fails at fsync
with EIO. fstests generic/271, 272 and 278 grep xfs_io's output for
"error", and "No space left on device" does not contain it.

metaslab_group_allocatable() skips a vdev that vdev_allocatable() says
cannot be written. When it skips every vdev in the class, the
allocation fails with ENOSPC, the only error that path returns.

Add metaslab_class_unwritable(), which reports whether a class has
vdevs and none of them is allocatable. When an allocation for a
ZIO_FLAG_CANFAIL zio fails with ENOSPC and its class is unwritable,
report EIO instead. A full pool keeps ENOSPC while any of its vdevs
can still be written, a degraded one included.

The allocator still returns ENOSPC to its callers, because the class
fallback and the gang retry in zio_dva_allocate() depend on it. The

    [24 lines not shown]
DeltaFile
+90-0tests/zfs-tests/tests/functional/failmode/failmode_dio_unwritable.ksh
+26-0module/zfs/metaslab.c
+16-2module/zfs/zio.c
+1-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+1-0include/sys/metaslab.h
+135-36 files

OpenZFS/src 21df1e4 — module/zfs vdev_raidz.c

raidz: resilver every child a block born before an expansion spans

vdev_raidz_need_resilver() assumes that a block spans its sectors
plus one row of parity over consecutive children.  A block born
before a RAID-Z expansion keeps its logical width and is laid out in
rows of that width, each with its own parity columns, so it spans
s + p * howmany(s, width - p) children.  Once the vdev has been
expanded more than once, this can exceed s + p while staying below
the vdev's width, and when the rows past the first end on a child
whose DTL is dirty, the resilver skips the block and leaves that
child without its sectors.  A later scrub repairs them, but a second
failure in the same row before that leaves the row one column short
of what its parity can rebuild.

Count the columns of every row, from the logical width of the block's
birth txg.  The count is unchanged for a block of the vdev's width,
which needs one row whenever the count is below the vdev's width.
The lookup takes vd_expand_lock, so it comes after the DTL check and
after the one-row test, which already settles most blocks.

    [5 lines not shown]
DeltaFile
+14-1module/zfs/vdev_raidz.c
+14-11 files

OpenZFS/src b5efb27 — tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: resilver a RAID-Z vdev expanded more than once

A block born before a RAID-Z expansion keeps the logical width it was
written with, so after the vdev has been expanded more than once it
is laid out over more rows than a block of the vdev's width, each row
with its own parity columns, and spans more consecutive children than
its sectors plus one row of parity.  No test resilvers such a block.

raidz_expand_010_pos writes 16K blocks on a four-wide RAIDZ1, a
five-wide RAIDZ2 and a six-wide RAIDZ3, expands each vdev twice, then
replaces each child in turn and requires the scrub that follows each
resilver to find nothing to repair.

Reviewed-by: Alexander Motin <alexander.motin at TrueNAS.com>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Tigerblue77 <37409593+tigerblue77 at users.noreply.github.com>
Closes #19395
DeltaFile
+117-0tests/zfs-tests/tests/functional/raidz/raidz_expand_010_pos.ksh
+2-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+120-13 files

OpenZFS/src f61e029 — include/sys spa.h, module/zfs zio_checksum.c zio.c

zio: find large gang headers while the pool is loading

zio_gang_tree_assemble() and zio_checksum_error() size gang headers
with spa_feature_is_active(dynamic_gang_header).  During import the
MOS is read before spa_ld_check_features() loads the feature
refcounts, so the feature looks inactive: a ganged MOS block with a
large (ashift-sized) header is read as a 512-byte one, fails its
checksum, and the fallback only tries large-to-small.  Every txg the
import tries fails the same way, so a pool that ganged MOS blocks
after the feature went active can't be imported.

Add spa_dynamic_gang_header(), which while the pool is loading also
checks the label's features_for_read, where dynamic_gang_header is
listed when active, and use it for both decisions.

This makes gang_blocks/gang_blocks_dyn_header_import pass.

Reviewed-by: Paul Dagnelie <paul.dagnelie at klarasystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>

    [3 lines not shown]
DeltaFile
+17-0module/zfs/spa_misc.c
+9-0module/zfs/zfeature.c
+1-2module/zfs/zio.c
+1-1module/zfs/zio_checksum.c
+1-0include/sys/spa.h
+29-35 files

OpenZFS/src b9b544f — tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: test importing a pool with large gang headers in its MOS

gang_blocks_dyn_header_pos checks that large gang headers are written,
but never re-imports the pool.  Add a test that forces ganging on an
ashift=12 pool until dynamic_gang_header is active and MOS blocks have
been ganged, then exports and imports the pool and scrubs it.

Reviewed-by: Paul Dagnelie <paul.dagnelie at klarasystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Issue #19189
Closes #19314
DeltaFile
+91-0tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_import.ksh
+3-2tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+95-23 files

OpenZFS/src cd1b094 — module/zfs arc.c, tests/zfs-tests/tests/functional/cli_root/zfs_rewrite zfs_rewrite_physical.ksh

Accept the dedup NOP of zfs rewrite -P in arc_write_done()

A physical rewrite (zfs rewrite -P) of a dedup block that the DDT still
holds unchanged becomes a NOP in zio_ddt_write(), which sets
ZIO_FLAG_NOPWRITE so that the block pointer and its accounting are
kept, as for a nopwrite.  arc_write_done() asserts that a write with
that flag has zp_nopwrite set, but dmu_write_policy() turns nopwrite
off whenever dedup is on.  When the header of the block is still in
the ARC, a debug build therefore panics in arc_write_done() with
"VERIFY(zio->io_prop.zp_nopwrite) failed", and the pool hangs: the
first zfs rewrite -P -r of a dedup=on dataset holding a file and a
copy of it did so on master.  Builds without assertions are not
affected.

Accept the flag for a physical rewrite of a dedup block as well, and
rewrite a deduplicated file and its copy twice with -P in
zfs_rewrite_physical.

Reviewed-by: Alexander Motin <alexander.motin at TrueNAS.com>

    [2 lines not shown]
DeltaFile
+19-0tests/zfs-tests/tests/functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh
+7-2module/zfs/arc.c
+26-22 files

OpenZFS/src 83f7e0e — module/zfs vdev_initialize.c vdev_trim.c

Translate initialize and TRIM ranges under the config lock

vdev_initialize_thread() and vdev_trim_thread() drop SCL_CONFIG
before they disable and load each metaslab, then walk its
ms_allocatable tree through vdev_xlate_walk() before they take the
lock again.  vdev_xlate() climbs vdev_parent up to the top-level
vdev, so that walk reads the vdev tree without the lock protecting it.

spa_vdev_detach() takes SCL_ALL as writer, unlinks the leaf with
vdev_remove_child(), which clears its vdev_parent, and sets
vdev_detached.  The leaf's initialize and TRIM threads are only
stopped afterwards, in spa_vdev_config_exit(), once the lock has been
dropped.  A thread inside the walk then passes the NULL parent to
vdev_xlate().  ztest hit this as a SIGSEGV in vdev_xlate() called
from vdev_initialize_thread() while the same leaf was being detached.
Detaching the leaf's sibling, which frees the parent mirror, races
with the walk in the same way.

Take SCL_CONFIG as reader again once the metaslab is disabled, and

    [9 lines not shown]
DeltaFile
+13-1module/zfs/vdev_trim.c
+13-0module/zfs/vdev_initialize.c
+26-12 files

OpenZFS/src 000b4c4 — module/zfs ddt.c

ddt: prune only entries unchanged since the prune walk

The prune walk reads candidates from the stored unique class, which
lags the dedup log. The prune's sync task then skips a candidate only
if it is live or was loaded from the log. If the log is flushed between
the walk and the sync task, a candidate that has gained a reference is
found in the stored duplicate class and cleared anyway. Freeing either
reference afterwards frees the block while the other still uses it,
and the space can be reallocated under it.

Prune a candidate only if its reloaded entry still matches what the
walk read. Releases since 2.3.0 also skip a candidate found in the log
during the walk, but that lookup is unsynchronized and separate from
the read of the stored entry, so a flush between the two still lets the
candidate through: the lookup narrows the race without closing it.
Since fd1ae59c7 (#18889) removed the lookup, which was unsafe outside
txg sync, an entry already in the log when the walk reads it is pruned
as well.


    [2 lines not shown]
DeltaFile
+8-1module/zfs/ddt.c
+8-11 files

OpenZFS/src 326fd64 — tests/zfs-tests/tests/functional/cli_root/zpool_get zpool_get_006_pos.ksh

ZTS: read zpool_get_006_pos class properties together

zpool_get_006_pos checks that the space properties of each allocation
class agree with each other, for example that used is not larger than
allocated. It read each property with a separate zpool get.

Three sections of the test write with sync=always and do not wait for
the pool to sync before the checks. The space counters only change when
a transaction group syncs, and this can happen between two of the zpool
get calls. The values then come from different points in time, and the
check fails. With kmemleak enabled, each zpool get takes longer, and the
test failed in about a third of the runs.

Read all properties of a class with a single zpool get. It returns all
values from the same ioctl, so they agree with each other.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Alexander Moch <mail at alexmoch.com>
Closes #19401
DeltaFile
+38-54tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh
+38-541 files

OpenZFS/src 1dbc2d5 — tests/runfiles common.run, tests/test-runner/bin zts-report.py.in

ZTS: run zfs_get_009_pos under kmemleak without CPU mitigations

zfs_get_009_pos skips itself when kmemleak is enabled, because it runs
too slowly. Most of the slowdown comes from CPU mitigations: with
mitigations=off, it takes at most about 10 minutes under kmemleak.

Add has_mitigations, and skip the test only when both kmemleak and CPU
mitigations are enabled. Raise the timeout of the zfs_get tests to 900
seconds, so that slower runners can still finish it. Keep expecting a
SKIP in zts-report for systems that still skip it.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Alexander Moch <mail at alexmoch.com>
Closes #19382
DeltaFile
+9-0tests/zfs-tests/include/libtest.shlib
+7-0tests/test-runner/bin/zts-report.py.in
+3-2tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
+1-0tests/runfiles/common.run
+20-24 files

OpenZFS/src 34cf366 — .github/workflows zloop.yml zfs-qemu.yml

CI: Cancel outdated push runs on the same branch

Push events have no head_ref, so the run_id fallback puts every push
in a separate concurrency group. Use the pushed ref to group runs from
the same branch and let cancel-in-progress stop outdated runs.

Keep the existing grouping for PRs and independent manual runs.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: George Melikov <mail at gmelikov.ru>
Closes #19412
DeltaFile
+3-1.github/workflows/zloop.yml
+3-1.github/workflows/zfs-qemu.yml
+3-1.github/workflows/zfs-precheck.yml
+3-1.github/workflows/zfs-arm.yml
+3-1.github/workflows/unit-tests.yml
+3-1.github/workflows/smatch.yml
+18-62 files not shown
+24-88 files

OpenZFS/src ab178c3 — . AGENTS.md

docs: Add fork CI and PR submission guidance for agents

Wait for successful fork CI on the final PR head before opening an
upstream PR so supported workflows can reuse its results. Limit new
upstream PRs to five per day unless agreed with maintainers in advance.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: George Melikov <mail at gmelikov.ru>
Closes #19412
DeltaFile
+5-0AGENTS.md
+5-01 files

OpenZFS/src 3acfee1 — .github/workflows unit-tests.yml checkstyle.yaml, .github/workflows/scripts reuse-qemu.py reuse-ci.py

CI: Extend fork result reuse and honor requested reruns

Extend QEMU result reuse to zloop, unit tests, ARM builds and
checkstyle. Use one helper with workflow file, runner, job name and
required step profiles. Require successful lint and ABI checks for
checkstyle, and exclude manual ARM runs with custom GCC inputs.

Reuse fork results only on the first workflow attempt. Requested reruns
execute in the base repository. Ignore cached Setup outputs on selective
QEMU matrix reruns and collect their new artifacts and summaries.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: George Melikov <mail at gmelikov.ru>
Closes #19412
DeltaFile
+122-0.github/workflows/scripts/reuse-ci.py
+0-101.github/workflows/scripts/reuse-qemu.py
+29-6.github/workflows/zloop.yml
+31-0.github/workflows/README.md
+24-0.github/workflows/checkstyle.yaml
+21-0.github/workflows/unit-tests.yml
+227-1072 files not shown
+260-1128 files

OpenZFS/src 22013c3 — module/zfs zio.c

zio: free the gang header ABD when its read fails

zio_gang_tree_assemble() wraps the gang header buffer in an ABD with
abd_get_from_buf().  zio_gang_tree_assemble_done() frees it, but only
when the read succeeded: on an error it returns first and the abd_t is
never freed.  Each failed gang header read, whether from a checksum
or an I/O error, leaks one.

A pool whose MOS has large gang headers that can not be read while
the pool is loading (#19189) shows it.  On a debug kernel, the failed
imports of such a pool left six abd_t objects behind and "rmmod zfs"
then panicked on
VERIFY3U(percpu_counter_sum(&skc->skc_linux_alloc), ==, 0).  valgrind
on a failed "zdb -e" of the same kind of pool reports the abd_t
allocated by abd_get_from_buf() in zio_gang_tree_assemble() as
definitely lost.

Free the ABD on the error path as well.  Nothing else owns it: the
gang tree only frees the header buffer, and the other gang callbacks

    [5 lines not shown]
DeltaFile
+4-1module/zfs/zio.c
+4-11 files

OpenZFS/src b4167b6 — module/zfs zil.c

ZIL: zero the header bp in zil_crash() only if lwbs own it

zil_crash() zeroes the syncing header's zh_log because the lwbs it
takes over include the block zh_log points to, and zil_clean() frees
them. When it takes no lwbs, nothing frees that block. Since 5d1ed14b3
zil_create() can crash the ZIL before it has an lwb, while it waits for
a pending zil_destroy(). zil_replay() does a keep_first destroy at
every mount of a file system whose ZIL needs no replay, and the
destroy's sync keeps the block that zh_log points to at that time:
after the zeroing, none. The pool then leaks the kept log block, which
zdb -b reports after the pool resumes.

Leave zh_log alone when there are no lwbs to free. The header still
owns the block, and the next zil_create() reuses it.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19320
DeltaFile
+7-3module/zfs/zil.c
+7-31 files

OpenZFS/src 1893e35 — tests/runfiles linux.run, tests/zfs-tests/tests Makefile.am

ZTS: suspend the pool while zil_create() waits for a destroy

zil_replay() at mount destroys a ZIL that needs no replay but keeps its
first log block, which the header still points to until the destroy
syncs. If the pool suspends while an fsync() waits in zil_create() for
that txg, zil_crash() zeroes the header and the kept block is never
freed. Mount with txgs held back, pull the disk under an fsync(), and
check with zdb that no space leaked after the pool resumes.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19320
DeltaFile
+100-0tests/zfs-tests/tests/functional/fault/suspend_zil_keep_first.ksh
+1-0tests/zfs-tests/tests/Makefile.am
+1-0tests/runfiles/linux.run
+102-03 files

OpenZFS/src 44ceb65 — cmd/zdb zdb.h zdb_il.c, tests/runfiles common.run

zdb: print TX_SETSAXATTR values as text

zil_prt_rec_setsaxattr() printed each byte of an xattr value with
"%c" and no trailing newline. Values often contain non-printable
bytes; SELinux labels end in a NUL. So "zdb -ivvvvv" output had NUL
bytes in it (GNU grep then treats it as binary and stops printing
matches) and the next line was glued onto the XAT_VALUE line.

Move the value printing from dump_znode_sa_xattr() into a helper,
dump_xattr_value(), and use it for TX_SETSAXATTR records too, followed
by a newline. As before for SA xattrs, a value is printed as is if
every byte is printable; otherwise, or with -P, every byte is printed
as an octal \ooo escape. "zdb -dddd" output is unchanged.

Add zdb_il_saxattr to check this.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Matthew Ahrens <matt at mahrens.org>
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
Closes #19361
DeltaFile
+88-0tests/zfs-tests/tests/functional/cli_root/zdb/zdb_il_saxattr.ksh
+25-16cmd/zdb/zdb.c
+3-5cmd/zdb/zdb_il.c
+2-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+1-0cmd/zdb/zdb.h
+120-226 files

OpenZFS/src f66613f — .github/workflows README.md zfs-qemu.yml, .github/workflows/scripts qemu-9-summary-page.sh reuse-qemu.py

CI: Reuse successful QEMU jobs from forks

Find completed push runs for the exact PR head SHA and reuse successful
per-OS QEMU jobs from the source fork. Preserve upstream check names and
link to the original logs, while running missing results normally.

Require successful build, test and summary steps, and limit results to
completed runs from the last seven days. Reuse is available for all
forks without additional repository configuration. CI file comparison
is deferred so the introducing PR can exercise reuse.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Tony Hutter <hutter2 at llnl.gov>
Signed-off-by: George Melikov <mail at gmelikov.ru>
Closes #19394
DeltaFile
+101-0.github/workflows/scripts/reuse-qemu.py
+44-4.github/workflows/zfs-qemu.yml
+27-0.github/workflows/README.md
+1-0.github/workflows/scripts/qemu-9-summary-page.sh
+173-44 files

OpenZFS/src 63c423a — man/man8 zpool-attach.8 zfs-rewrite.8, tests/runfiles common.run

ZTS: test zfs rewrite on an expanded RAID-Z vdev

After a RAID-Z expansion, a block keeps the width of the vdev at its
birth, and with it its data-to-parity ratio. zfs rewrite writes it
again at the width of the expanded vdev, but nothing tests that: the
raidz_expand_* tests never call it, and the zfs_rewrite* tests run on a
single disk. The zpool-attach(8) and zfs-rewrite(8) man pages do not
refer to each other either.

Add raidz_expand_rewrite. It writes a 128K, a 16K and a 4K block to a
5-wide RAID-Z2 with ashift=12 and expands it to 6 wide, checking the
allocated sizes with zdb. Rewritten while the expansion is paused, the
blocks move but keep their sizes (0x36000, 0x9000 and 0x3000), as the
new width only applies to blocks born after the expansion has
completed. Rewritten after it, they are allocated 0x30000, 0x6000 and
0x3000: the 4K block is the same at both widths. Blocks that are
already in the dedup table are found again and stay where they are. The
data is then compared and the pool scrubbed.


    [6 lines not shown]
DeltaFile
+175-0tests/zfs-tests/tests/functional/raidz/raidz_expand_rewrite.ksh
+8-1man/man8/zfs-rewrite.8
+2-1tests/runfiles/common.run
+3-0man/man8/zpool-attach.8
+1-0tests/zfs-tests/tests/Makefile.am
+189-25 files

OpenZFS/src 8b11b98 — lib/libzutil zutil_import.c

libzutil: prefer devices of the same pool when fixing up paths

Vdev guids survive 'zpool reguid', so a stale copy of a device, such
as a cloned VM disk taken before the reguid, has the same vdev guid
and path in its label as the device of the reguided pool.  fix_paths()
picks the device for a leaf by vdev guid alone, preferring the path in
the config, so the old pool's config is pointed at the new pool's
device: 'zpool import' lists the pool twice, both times with the new
guid and the same device, and the stale copy is never shown.

Record each label's pool guid with its name and prefer devices of the
pool being assembled.  Fall back to any device with the vdev guid, as
before, for labels left with different pool guids by an interrupted
reguid.

This makes cli_root/zpool_import/zpool_import_reguid_stale pass.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>

    [2 lines not shown]
DeltaFile
+67-40lib/libzutil/zutil_import.c
+67-401 files

OpenZFS/src 8f71869 — tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: test import listing of a stale device after reguid

Create a pool on a file vdev, copy the file aside, reguid the pool,
and put the copy back.  The copy has the old pool guid but the same
vdev guid and path in its label.  'zpool import -d' must list both
pools, with the copy as the old one, and importing the old guid must
give the old pool.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Issue #16989
Closes #19316
DeltaFile
+77-0tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_reguid_stale.ksh
+1-0tests/zfs-tests/tests/Makefile.am
+1-0tests/runfiles/common.run
+79-03 files

OpenZFS/src 23feecb — lib/libzfs_core libzfs_core.c, man/man8 zfs-program.8

zfs_ioctl: allow read-only channel programs on read-only pools

The channel program ioctl is registered with POOL_CHECK_READONLY, so
the dispatcher rejects every program on a pool imported read-only
before the handler can look at the "sync" flag. That check predates
open-context channel programs and is only needed for programs that
run as a sync task: a read-only pool has no sync thread, so the task
would never complete. A read-only program never assigns a transaction
and cannot call into zfs.sync, so refusing it only stops
"zfs program -n" from inspecting a pool imported read-only, which is
exactly when such inspection is most useful.

Drop POOL_CHECK_READONLY from the registration and have the handler
return EROFS itself when the sync flag is set, which is also the
default when the flag is absent. Sync-context programs behave as
before, while open-context programs now run on read-only pools.
History logging already skips pools that are not writeable. The only
visible difference for sync programs is that invalid limits are now
reported as EINVAL ahead of EROFS.

    [7 lines not shown]
DeltaFile
+15-1module/zfs/zfs_ioctl.c
+10-2lib/libzfs_core/libzfs_core.c
+3-0man/man8/zfs-program.8
+28-33 files

OpenZFS/src 176329b — tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: run channel programs on a read-only pool

Check that on a pool imported read-only, zfs program -n runs a
read-only channel program, while a channel program in syncing context
fails with "pool is read-only" and changes nothing.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19315
DeltaFile
+68-0tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.readonly_pool.ksh
+1-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+70-13 files

OpenZFS/src f452d10 — cmd/zpool zpool_main.c Makefile.am, cmd/zpool/zpool.d phy_link phy_errors

zpool: Add 'zpool status -c phy' for SAS PHY stats

Add a number of SAS PHY stats to the 'zpool status -c' scripts.  This
can be useful for identifying flaky SAS connections.

Also, widen the 'zpool status -c' help column to accommodate
longer names.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Tony Hutter <hutter2 at llnl.gov>
Closes #19238
DeltaFile
+99-0cmd/zpool/zpool.d/phy
+26-0cmd/zpool/Makefile.am
+1-1cmd/zpool/zpool_main.c
+1-0cmd/zpool/zpool.d/phy_link
+1-0cmd/zpool/zpool.d/phy_errors
+1-0cmd/zpool/zpool.d/phy_invalid_dword_count
+129-19 files not shown
+138-115 files

OpenZFS/src 465d86a — tests/zfs-tests/callbacks zfs_failsafe.ksh

ZTS: find zinject in zfs_failsafe when it is not installed

When the test runner kills a test, it runs callbacks/zfs_failsafe as
root through "sudo -E", like the tests themselves. sudo replaces PATH
with its secure_path. The tests set it back from STF_PATH in
libtest.shlib, but zfs_failsafe.ksh does not source it, so when the
suite runs from a build tree with no OpenZFS installed, the callback
fails with "zinject: not found" and leaves in place the faults it is
there to clear.

Set PATH from STF_PATH, as libtest.shlib does.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Tigerblue77 <37409593+tigerblue77 at users.noreply.github.com>
Closes #19380
DeltaFile
+6-0tests/zfs-tests/callbacks/zfs_failsafe.ksh
+6-01 files

OpenZFS/src c4da9f8 — module/nvpair fnvpair.c

build: Fix uninitialized errors in 'make rpm-utils'

Fix 'make rpm-utils' error on Fedora 42:

  CCLD     libzfs_core.la
tests/unit/test_nvpair.c: In function 'test_nv_fnvpair_value':
tests/unit/test_nvpair.c:1713:9: error: 'rv' may be used uninitialized
 1713 |     unit_str_eq(fnvpair_value_string(fnvlist_lookup_nvpair ...
      |     ^
module/nvpair/fnvpair.c:575:21: note: 'rv' was declared here
  575 |     const char *rv;
      |                 ^

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Tony Hutter <hutter2 at llnl.gov>
Closes #19386
DeltaFile
+37-37module/nvpair/fnvpair.c
+37-371 files

OpenZFS/src daab476 — module/zfs zio.c

zio: Remove the priority match assertion when joining a batch

zio_change_priority() may upgrade an in-flight read tree at any time,
so a child created from the parent's stale priority can legitimately
disagree with the parent and with its peers.  Priority steers the
batch's taskq choice only for ZIO_PRIORITY_SYNC_WRITE, which no member
can reach.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed-by: Rob Norris <rob.norris at truenas.com>
Signed-off-by: Alexander Motin <alexander.motin at truenas.com>
Closes #19360
Closes #18921
Closes #19381
DeltaFile
+3-3module/zfs/zio.c
+3-31 files

OpenZFS/src 9e8e7a9 — module/zfs metaslab.c

metaslab: don't gang every block on a degraded single-disk vdev

metaslab_group_allocatable() skips a top-level vdev that is a single
disk below VDEV_STATE_HEALTHY for the first copy of a block, so that a
healthy vdev is used instead. Since be5c6d965 the allocator no longer
retries with try_hard before ganging, so when every vdev in the class
is skipped this way, e.g. on a pool with one disk that ZED degraded
for checksum errors, every block larger than spa_min_alloc becomes a
gang block. The gang header and members are allocated with try_hard,
so they land on the same degraded vdev: the guard keeps nothing off
it, but the blocks take more space, more I/O to read, and some boot
loaders can't read them. This lasts until zpool clear.

Retry with try_hard when a normal-class allocation fails after
skipping an unhealthy vdev. Normal is the class the special and dedup
classes fall back to, so failing there only leads to ganging. In the
special and dedup classes the block still falls back to the next
class as before.


    [5 lines not shown]
DeltaFile
+13-5module/zfs/metaslab.c
+13-51 files

OpenZFS/src be3407c — tests/runfiles common.run, tests/zfs-tests/tests Makefile.am

ZTS: gang blocks on a degraded single-disk vdev

Add gang_blocks_degraded_vdev: a pool whose only top-level vdev is a
single disk marked DEGRADED (zinject -A degrade) must still write
128K blocks without ganging them, and a pool with a second, healthy
single-disk vdev must put the blocks on the healthy one.

On master every L0 and L1 block of the file is a gang block.

Reviewed-by: Brian Behlendorf <behlendorf1 at llnl.gov>
Signed-off-by: Will Rouesnel <wrouesnel at wrouesnel.com>
Closes #19351
DeltaFile
+99-0tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_degraded_vdev.ksh
+1-1tests/runfiles/common.run
+1-0tests/zfs-tests/tests/Makefile.am
+101-13 files