refactor(fileio): move zstd window diagnostic policy to Rust

Project the zstd window-too-large diagnostic inputs into Rust so Rust owns
error filtering and the concrete-versus-unsupported guidance choice. C keeps
frame-header parsing, window-log extraction, and the exact display text behind
a callback, preserving the existing diagnostics and fallback behavior.

All heavy verification was run serially with a 40 GiB virtual-memory cap and
one build job.

Test Plan:
- git diff --cached --check
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets (790 passed)
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets (184 passed)
- ulimit -v 41943040; cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check
- ulimit -v 41943040; make -j1 (clean after C90 declaration cleanup)
- ulimit -v 41943040; make -j1 -C tests test (passed; the later cleanup only moved a declaration before statements)
This commit is contained in:
2026-07-20 08:21:27 +02:00
parent 69425cb8a4
commit 675c3fc307
2 changed files with 345 additions and 20 deletions
+103 -20
View File
@@ -3755,6 +3755,83 @@ static int FIO_passThrough(dRess_t *ress)
return FIO_rust_passThrough(ress->readCtx, ress->writeCtx);
}
enum {
FIO_RUST_ZSTD_ERROR_HELP_WINDOW_SIZE = 0,
FIO_RUST_ZSTD_ERROR_HELP_WINDOW_GUIDANCE = 1,
FIO_RUST_ZSTD_ERROR_HELP_UNSUPPORTED_WINDOW_LOG = 2
};
typedef void (*FIO_rust_zstdErrorHelpDisplayFn)(
void* callbackContext,
int diagnostic,
const char* srcFileName,
unsigned long long windowSize,
unsigned windowLog,
unsigned windowMB,
unsigned memLimit);
typedef struct {
void* callbackContext;
const char* srcFileName;
unsigned long long windowSize;
size_t headerError;
unsigned windowLog;
unsigned memLimit;
int errorCode;
FIO_rust_zstdErrorHelpDisplayFn display;
} FIO_rust_zstdErrorHelpState;
typedef char FIO_rust_zstd_error_help_state_layout[
(offsetof(FIO_rust_zstdErrorHelpState, callbackContext) == 0
&& offsetof(FIO_rust_zstdErrorHelpState, srcFileName)
== sizeof(void*)
&& offsetof(FIO_rust_zstdErrorHelpState, windowSize)
== 2 * sizeof(void*)
&& offsetof(FIO_rust_zstdErrorHelpState, headerError)
== offsetof(FIO_rust_zstdErrorHelpState, windowSize)
+ sizeof(unsigned long long)
&& offsetof(FIO_rust_zstdErrorHelpState, windowLog)
== offsetof(FIO_rust_zstdErrorHelpState, headerError)
+ sizeof(size_t)
&& offsetof(FIO_rust_zstdErrorHelpState, memLimit)
== offsetof(FIO_rust_zstdErrorHelpState, windowLog)
+ sizeof(unsigned)
&& offsetof(FIO_rust_zstdErrorHelpState, errorCode)
== offsetof(FIO_rust_zstdErrorHelpState, memLimit)
+ sizeof(unsigned)
&& offsetof(FIO_rust_zstdErrorHelpState, display)
== ((offsetof(FIO_rust_zstdErrorHelpState, errorCode)
+ sizeof(int) + sizeof(void*) - 1)
/ sizeof(void*)) * sizeof(void*)
&& sizeof(FIO_rust_zstdErrorHelpState)
== offsetof(FIO_rust_zstdErrorHelpState, display)
+ sizeof(void*)
&& sizeof(FIO_rust_zstdErrorHelpDisplayFn) == sizeof(void*))
? 1 : -1];
void FIO_rust_zstdErrorHelp(const FIO_rust_zstdErrorHelpState* state);
static void FIO_rust_zstdErrorHelp_display(
void* callbackContext,
int diagnostic,
const char* srcFileName,
unsigned long long windowSize,
unsigned windowLog,
unsigned windowMB,
unsigned memLimit)
{
(void)callbackContext;
if (diagnostic == FIO_RUST_ZSTD_ERROR_HELP_WINDOW_SIZE) {
DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u \n",
srcFileName, windowSize, memLimit);
return;
}
if (diagnostic == FIO_RUST_ZSTD_ERROR_HELP_WINDOW_GUIDANCE) {
DISPLAYLEVEL(1, "%s : Use --long=%u or --memory=%uMB \n",
srcFileName, windowLog, windowMB);
return;
}
assert(diagnostic == FIO_RUST_ZSTD_ERROR_HELP_UNSUPPORTED_WINDOW_LOG);
DISPLAYLEVEL(1, "%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported \n",
srcFileName, ZSTD_WINDOWLOG_MAX);
}
/* FIO_zstdErrorHelp() :
* detailed error message when requested window size is too large */
static void
@@ -3764,28 +3841,34 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs,
const char* srcFileName)
{
ZSTD_FrameHeader header;
int const errorCode = (int)ZSTD_getErrorCode(err);
size_t headerError = 1;
unsigned long long windowSize = 0;
unsigned windowLog = 0;
unsigned memLimit = 0;
FIO_rust_zstdErrorHelpState state = { 0 };
/* Help message only for one specific error */
if (ZSTD_getErrorCode(err) != ZSTD_error_frameParameter_windowTooLarge)
return;
if (errorCode == ZSTD_error_frameParameter_windowTooLarge) {
/* Keep codec/header parsing and the private read-pool layout in C. */
headerError = ZSTD_getFrameHeader(
&header, ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded);
if (headerError == 0) {
windowSize = header.windowSize;
windowLog = FIO_highbit64(windowSize)
+ ((windowSize & (windowSize - 1)) != 0);
memLimit = prefs->memLimit;
}
}
/* Try to decode the frame header */
err = ZSTD_getFrameHeader(&header, ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded);
if (err == 0) {
unsigned long long const windowSize = header.windowSize;
unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0);
assert(prefs->memLimit > 0);
DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u \n",
srcFileName, windowSize, prefs->memLimit);
if (windowLog <= ZSTD_WINDOWLOG_MAX) {
unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0));
assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */
DISPLAYLEVEL(1, "%s : Use --long=%u or --memory=%uMB \n",
srcFileName, windowLog, windowMB);
return;
} }
DISPLAYLEVEL(1, "%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported \n",
srcFileName, ZSTD_WINDOWLOG_MAX);
state.callbackContext = NULL;
state.srcFileName = srcFileName;
state.windowSize = windowSize;
state.headerError = headerError;
state.windowLog = windowLog;
state.memLimit = memLimit;
state.errorCode = errorCode;
state.display = FIO_rust_zstdErrorHelp_display;
FIO_rust_zstdErrorHelp(&state);
}
/** FIO_decompressFrame() :