Refuse snapshot rollback up front when newer snapshots are blocked
## Problem
Rolling a dataset back to an older snapshot crashed with a raw traceback whenever a newer snapshot had a dependent clone. Two separate failures were in play: `clone_rsrc.destroy()` does not exist on any pylibzfs resource type, so it raised `AttributeError`, which is not a `RuntimeError` and so escaped both surrounding handlers; and `lzc.destroy_snapshots()` raises `ZFSCoreException`, a sibling of `ZFSException` rather than a subclass, so the handler wrapping it never fired. There was also no pre-flight of any kind, so nothing could refuse cleanly — and because destroy failures were silently swallowed and the loop continued, a failed destroy left the rollback to fail later with a message telling the user to pass a flag they had already passed.
## Solution
- **Destroy clones through the handle.** `tls.lzh.destroy_resource(name=...)` replaces the non-existent resource-level `destroy()`, matching how the destroy path already does it.
- **Catch both exception families.** `lzc.destroy_snapshots()` failures are now caught alongside `ZFSException` and converted, rather than escaping as a raw traceback.
- **Refuse before destroying anything.** A new pre-flight walks the whole dataset set — including the full `recursive_rollback` tree, before the fan-out loop rather than inside it — and collects every blocker it can see: dependent clones when `recursive_clones` is not set, holds in all cases, and clones that cannot be destroyed non-recursively because they have children or snapshots of their own. Previously a blocker on a child was discovered only after the parent had been irreversibly rolled back. This is fail-first, not atomic: a clone or hold created between the pre-flight and the destroy still fails mid-loop, and only a concurrently pruned snapshot (ENOENT) is tolerated.
- **Typed errors at both boundaries.** Blockers raise `ZFSRollbackBlockedException`, mapped to `EBUSY` with a message naming each blocking snapshot and what blocks it. `pool.snapshot.rollback` had no exception mapping at all and leaked every impl failure as an untyped traceback; it now mirrors `zfs.resource.snapshot.rollback`.
- **`force` now means how forcefully, not whether.** Clones are always unmounted before destroy, since `zfs_destroy()` does not unmount and a mounted clone could never be destroyed otherwise; `force` selects a forced unmount, matching the `zfs destroy` CLI. Unmount no longer requests a key unload, matching what the CLI's rollback path does.
Adds unit coverage for each defect and the pre-flight, plus integration coverage for clone-present, nested-clone, hold-present, and cross-dataset cases. `pool.snapshot.rollback` had no api2 coverage before this.
Newer bookmarks remain unhandled: pylibzfs exposes no bookmark primitives, so a newer bookmark still fails the rollback with an empty conflict list. That needs a pylibzfs change first and is tracked separately.
[mlir:bazel] Expose "expsensive pattern API checks" as build flag. (#216673)
This PR exposes the `MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS`
definition as a build flag in the Bazel build. This makes it more easy
to run these expensive checks as a CI task. The new flag can be used as
follows:
```
bazelisk build \
--@llvm-project//mlir:enable_expensive_pattern_api_checks \
${BUILD_TARGETS}
```
Signed-off-by: Ingo Müller <ingomueller at google.com>
[mlir] Remove dead declaration populateSparseTensorRewriting (#216942)
The corresponding function definition was removed on July 15, 2022 in
commit 28ebb0b61d110e4b108fc1ebcbc43d50fff8f087.
Refuse snapshot rollback up front when newer snapshots are blocked
## Problem
Rolling a dataset back to an older snapshot crashed with a raw traceback whenever a newer snapshot had a dependent clone. Two separate failures were in play: `clone_rsrc.destroy()` does not exist on any pylibzfs resource type, so it raised `AttributeError`, which is not a `RuntimeError` and so escaped both surrounding handlers; and `lzc.destroy_snapshots()` raises `ZFSCoreException`, a sibling of `ZFSException` rather than a subclass, so the handler wrapping it never fired. There was also no pre-flight of any kind, so nothing could refuse cleanly — and because destroy failures were silently swallowed and the loop continued, a failed destroy left the rollback to fail later with a message telling the user to pass a flag they had already passed.
## Solution
- **Destroy clones through the handle.** `tls.lzh.destroy_resource(name=...)` replaces the non-existent resource-level `destroy()`, matching how the destroy path already does it.
- **Catch both exception families.** `lzc.destroy_snapshots()` failures are now caught alongside `ZFSException` and converted, rather than escaping as a raw traceback.
- **Refuse before destroying anything.** A new pre-flight walks the whole dataset set — including the full `recursive_rollback` tree, before the fan-out loop rather than inside it — and collects every blocker it can see: dependent clones when `recursive_clones` is not set, holds in all cases, and clones that cannot be destroyed non-recursively because they have children or snapshots of their own. Previously a blocker on a child was discovered only after the parent had been irreversibly rolled back. This is fail-first, not atomic: a clone or hold created between the pre-flight and the destroy still fails mid-loop, and only a concurrently pruned snapshot (ENOENT) is tolerated.
- **Typed errors at both boundaries.** Blockers raise `ZFSRollbackBlockedException`, mapped to `EBUSY` with a message naming each blocking snapshot and what blocks it. `pool.snapshot.rollback` had no exception mapping at all and leaked every impl failure as an untyped traceback; it now mirrors `zfs.resource.snapshot.rollback`.
- **`force` now means how forcefully, not whether.** Clones are always unmounted before destroy, since `zfs_destroy()` does not unmount and a mounted clone could never be destroyed otherwise; `force` selects a forced unmount, matching the `zfs destroy` CLI. Unmount no longer requests a key unload, matching what the CLI's rollback path does.
Adds unit coverage for each defect and the pre-flight, plus integration coverage for clone-present, nested-clone, hold-present, and cross-dataset cases. `pool.snapshot.rollback` had no api2 coverage before this.
Newer bookmarks remain unhandled: pylibzfs exposes no bookmark primitives, so a newer bookmark still fails the rollback with an empty conflict list. That needs a pylibzfs change first and is tracked separately.
Mk/Scripts/qa.sh: Filter baselibs() input to improve performance
After the baselibs() fix in f0f863b1a2d6, readelf is executed for each
result from find(1). There are two concerns with this fix:
1. -exec readelf -d {} \; drops the filename from the error messages
readelf prints "File: <name>" headers only when it is supplied with two
or more files, and baselibs() uses ${file} from those headers. So, the
two err() messages in baselibs() will break.
This is moot for now, though, because nothing in the ports tree can
trigger these errors. Those base soname versions for libarchive and
libedit are long gone.
2. Performance hit with one readelf execution per staged file
The costs are high for ports that stage many files. For
emulators/linux_base-rl9, the find returns over 30k hits that the while
[12 lines not shown]
ipfilter: Fix checksum update for NAT_DIVERTOUT
When taking a snapshot of the before ip_len (s1) for comparison with the
after-translated ip_len (s2), we must convert it from network to host
byte order before we can use it. Add the missing ntohs() call.
PR: 296944
MFC after: 3 days
[SCEV] Make operand use flags part of expression's identity. (#216604)
Update hashing for SCEVNodes to include the use-specific operand flags.
This makes sure expression with different operand flags distinct. Going
forward, this ensures that various maps that cache SCEV expressions
handle use-specific operands correctly.
PR: https://github.com/llvm/llvm-project/pull/216604
[PromoteMemToReg] Insert store undef when removing lifetime markers (#191909)
The `lifetime.start` and `lifetime.end` can help avoid the creation of
spurious phi-node.
For example, when a local struct/array is declared in a loop, Clang
will generate a `alloca` outside the loop (required) and annotate
the loop body with `lifetime.start` and `lifetime.end` to remember
that there are no loop-carried live values. It is currently mostly
used by stack coloring, but we can use it to improve SSA too.
In particular, `sroa` and `mem2reg` did not leverage those lifetime
informations and will sometimes create spurious phi-nodes that
are not always cleaned-up later on (see unit test).
As `mem2reg` simply deletes the lifetime intrinsic before promoting
to SSA, it forgets the lifetime information completely. We improve this
by inserting a `store undef` in place of each
`lifetime.start`/`lifetime.end`
[5 lines not shown]
security/wpa_supplicant*: Fix EAPOL_TEST build for non-standard SSL_DEFAULT
The post-build target does not have the same environment variables setup
as the do-build target. This results in the eapol_test binary getting
compiled against the headers of the TLS library specified in
SSL_DEFAULT, but getting linked against the TLS library from the base
system regardless of SSL_DEFAULT, causing build failures when
SSL_DEFAULT is set to a different TLS library/version than the on from
the base system.
Fix this by not using the post-build target to build the eapol_test
binary, but instead conditionally add the eapol_test target to
TARGET_ALL if the EAPOL_TEST option is enabled for the port.
Signed-off-by: Pascal Ernster <git at hardfalcon.net>
[AMDGPU] Fix miscompile folding math calls with poison/undef vector lanes (#216971)
A poison or undef lane made evaluateCall ConstantDataVector cast fail,
and evaluateScalarMathFunc silently treated the missing operand as 0.0,
producing wrong results instead of bailing out
[AMDGPU] Fix miscompile from stale value cache in LowerBufferFatPointers (#216962)
ConvertedForStore cached a p7->int conversion per Value across the whole
function, so a second store of the same fat pointer in a non-dominating
block reused an instruction from the first block, breaking dominance
[AMDGPU] Fix crash folding cos/sin table lookups on poison/undef vector lanes (#216972)
TDOFold cast the lane directly to ConstantFP, which aborts under
assertions when a lane is poison or undef instead of a table lookup
failure