Description:
After copying or transforming a file, `ndbxfrm` calls the destination
transform close, destination `fsync`, and destination OS close functions, but
discards all three return values. If streaming and source finalization have
succeeded, the command returns the earlier zero result even when destination
finalization fails.
This was reproduced by returning EIO only from the first `fsync()` whose file
descriptor resolved to the exact destination path. The injector printed a
marker proving that the failure was delivered. `ndbxfrm` nevertheless exited
with status 0 and retained the destination file.
How to repeat:
Create a disposable directory, copy the attached injector into it, and compile
the path-restricted fault library:
```bash
mkdir /tmp/my44-repro
cp /path/to/ndbxfrm_fsync_fault.c /tmp/my44-repro/
cd /tmp/my44-repro
gcc -shared -fPIC -O2 -Wall -Wextra -Werror \
ndbxfrm_fsync_fault.c -ldl -o ndbxfrm_fsync_fault.so
```
Use a source-built MySQL/NDB 8.4.11 `ndbxfrm`. The control and fault runs use
separate, previously nonexistent output paths:
```bash
NDBXFRM=/path/to/mysql-build/runtime_output_directory/ndbxfrm
printf 'ndbxfrm destination fsync reproducer\n' > plain.txt
"$NDBXFRM" --no-defaults \
--encrypt-password=repro-only --encrypt-kdf-iter-count=1 \
--encrypt-cipher=1 --encrypt-block-size=0 --file-block-size=512 \
plain.txt control.ndbxfrm
echo "control_exit=$?"
export LD_PRELOAD="$PWD/ndbxfrm_fsync_fault.so"
export NDBXFRM_FAULT_TARGET="$PWD/fsync-eio.ndbxfrm"
"$NDBXFRM" --no-defaults \
--encrypt-password=repro-only --encrypt-kdf-iter-count=1 \
--encrypt-cipher=1 --encrypt-block-size=0 --file-block-size=512 \
plain.txt "$NDBXFRM_FAULT_TARGET"
echo "fault_exit=$?"
test -f "$NDBXFRM_FAULT_TARGET" && echo 'fault_output_retained=yes'
```
The interposer delegates every other `fsync` call. It activates once, only
when `/proc/self/fd/FD` exactly equals `NDBXFRM_FAULT_TARGET`.
## Actual result
The observed fault output was:
```text
NDBXFRM_FAULT_INJECTED fsync fd=4 path=/tmp/my44-repro/fsync-eio.ndbxfrm errno=EIO
fault_exit=0
fault_output_retained=yes
```
The control also returned 0 but printed no injection marker. The fault output
happened to remain readable from the page cache; that does not make the failed
durability operation successful. This reproduction proves false success after
EIO, not visible corruption in this particular run.
## Expected result
If destination transform close, `fsync`, or OS close fails, `ndbxfrm` should:
1. print an error identifying destination finalization;
2. return a nonzero exit status; and
3. remove the incomplete output, or clearly preserve it only as an invalid
artifact that automation cannot mistake for success.