update
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# Pre10 Batch C: BSD Decompressor Request Dispatch
|
||||
|
||||
Status: **STATIC PASS; RUNTIME NOT RUN**
|
||||
|
||||
This batch aligns the BSD decompressor boundary with the Linux source shape
|
||||
where the responsibility is equivalent. It keeps the FreeBSD implementation
|
||||
synchronous and contiguous-buffer based. No page, folio, bio, workqueue,
|
||||
XArray, shrinker, or asynchronous decompression abstraction was added.
|
||||
|
||||
## Baseline and Scope
|
||||
|
||||
The implementation starts from Pre10 commit `d3c1cb90` and preserves Batch A,
|
||||
Batch B, and the documented `insmntque()` lifecycle issue. The source changes
|
||||
are limited to:
|
||||
|
||||
```text
|
||||
repo-pre-10/src/internal.h
|
||||
repo-pre-10/src/decompressor.c
|
||||
repo-pre-10/src/lz4.c
|
||||
repo-pre-10/src/decompressor_lzma.c
|
||||
repo-pre-10/src/decompressor_deflate.c
|
||||
repo-pre-10/src/decompressor_zstd.c
|
||||
```
|
||||
|
||||
`zdata.c` was inspected but did not need a mechanical edit: its existing call
|
||||
to `z_erofs_decompress()` remains the sole dispatcher call, and its buffer
|
||||
release and decoded LZMA extent-cache publication remain unchanged.
|
||||
|
||||
## Request Contract
|
||||
|
||||
The new request is stack-owned by `z_erofs_decompress()` and is valid only for
|
||||
the synchronous callback invocation:
|
||||
|
||||
```c
|
||||
struct z_erofs_decompress_req {
|
||||
struct erofs_mount *em;
|
||||
const struct erofs_map_blocks *map;
|
||||
const void *in;
|
||||
size_t inputsize;
|
||||
void *out;
|
||||
size_t outputsize;
|
||||
bool partial_decoding;
|
||||
};
|
||||
```
|
||||
|
||||
Field mapping is direct:
|
||||
|
||||
| Request field | Previous source | Ownership |
|
||||
| --- | --- | --- |
|
||||
| `em` | `em` / codec configuration arguments | Borrowed mount, never retained |
|
||||
| `map` | `map` and its algorithm/offset fields | Borrowed mapping, never retained |
|
||||
| `in` | `src` after padding removal | Borrowed compressed buffer |
|
||||
| `inputsize` | `srclen` after padding removal | Value copy |
|
||||
| `out` | `dst` | Borrowed decoded buffer |
|
||||
| `outputsize` | `dstlen` | Value copy |
|
||||
| `partial_decoding` | `partial` | Value copy |
|
||||
|
||||
The request does not own either data buffer. `zdata.c` continues to release
|
||||
the compressed buffer with `erofs_brelse()`, and continues to free or publish
|
||||
the decoded allocation after the callback returns.
|
||||
|
||||
The descriptor callback is intentionally synchronous:
|
||||
|
||||
```c
|
||||
struct z_erofs_decompressor {
|
||||
const char *name;
|
||||
int (*config)(struct erofs_mount *,
|
||||
const struct erofs_super_block *, const void *, size_t);
|
||||
int (*decompress)(const struct z_erofs_decompress_req *);
|
||||
};
|
||||
```
|
||||
|
||||
The configuration callback receives the superblock argument because the LZ4
|
||||
legacy configuration path uses it. The other codec configuration callbacks
|
||||
retain their previous inputs and explicitly ignore that additional argument.
|
||||
|
||||
## Descriptor Coverage
|
||||
|
||||
`decompressor.c` contains one static array indexed by the on-disk algorithm
|
||||
number. The entries are:
|
||||
|
||||
```text
|
||||
0 LZ4 config + z_erofs_lz4_decompress
|
||||
1 LZMA config + z_erofs_lzma_decompress
|
||||
2 DEFLATE config + z_erofs_deflate_decompress
|
||||
3 ZSTD config + z_erofs_zstd_decompress
|
||||
4 SHIFTED plain transform callback
|
||||
5 INTERLACED plain transform callback
|
||||
```
|
||||
|
||||
The first four entries cover every real EROFS compression algorithm currently
|
||||
defined by `erofs_fs.h`. The two runtime-only entries cover the existing plain
|
||||
mapping forms. No duplicate backend entry point or compatibility wrapper is
|
||||
present.
|
||||
|
||||
Configuration parsing preserves the old ordering:
|
||||
|
||||
1. Read the configuration record and its payload.
|
||||
2. Return the read error immediately if either read fails.
|
||||
3. Select the descriptor and invoke its configuration callback.
|
||||
4. Release the payload with `erofs_brelse()`.
|
||||
5. Return the callback's original error unchanged.
|
||||
|
||||
This retains the existing I/O-error priority. Unknown on-disk algorithm bits
|
||||
are rejected before configuration reads by the existing
|
||||
`Z_EROFS_ALL_COMPR_ALGS` mask check. A supported algorithm whose configuration
|
||||
is unavailable returns `EOPNOTSUPP` from its existing callback. In particular,
|
||||
the no-`ZSTDIO` build still emits the existing mount error and returns
|
||||
`EOPNOTSUPP`.
|
||||
|
||||
## Decode and Error Semantics
|
||||
|
||||
The old and new paths have the following equivalent behavior:
|
||||
|
||||
| Condition | Result before Batch C | Result after Batch C |
|
||||
| --- | --- | --- |
|
||||
| Shifted/interlaced output larger than input | `EINTEGRITY` | `EINTEGRITY` |
|
||||
| Shifted/interlaced transform success | `0` | `0` |
|
||||
| Invalid algorithm format | `EOPNOTSUPP` | `EOPNOTSUPP` |
|
||||
| Required zero-padding absent | `EINTEGRITY` | `EINTEGRITY` |
|
||||
| LZMA dictionary not configured | `EINTEGRITY` | `EINTEGRITY` |
|
||||
| Backend success | `0` | `0` |
|
||||
| Any backend failure | `EIO` | `EIO` |
|
||||
|
||||
Padding removal remains in the dispatcher and is performed before the backend
|
||||
request is updated. The LZ4 zero-padding exception remains unchanged. The LZMA
|
||||
dictionary check remains before callback dispatch. Backend-specific checks are
|
||||
unchanged apart from reading their previous parameters from the request or
|
||||
mount configuration:
|
||||
|
||||
- LZ4 preserves literal/match bounds, overlap copying, partial completion,
|
||||
and trailing-zero validation.
|
||||
- MicroLZMA preserves input/output size limits, dictionary selection, decoder
|
||||
shutdown, full-stream consumption, and partial output acceptance.
|
||||
- DEFLATE preserves window validation, `inflateEnd()`, no-progress detection,
|
||||
output completion, and full-stream input consumption.
|
||||
- ZSTD preserves window selection, decoder destruction on every initialized
|
||||
path, no-progress detection, output completion, and full-stream consumption.
|
||||
|
||||
## Consumer and Symbol Proof
|
||||
|
||||
Before the change, repository searches found exactly one in-tree consumer of
|
||||
each old backend symbol: the switch in `decompressor.c`. The only consumer of
|
||||
`z_erofs_decompress()` is `zdata.c`. After the change:
|
||||
|
||||
```text
|
||||
old lz4_decompress 0 definitions/references
|
||||
old lzma_decompress 0 definitions/references
|
||||
old deflate_decompress 0 definitions/references
|
||||
old zstd_decompress 0 definitions/references
|
||||
|
||||
new LZ4 backend one definition, one descriptor reference, one prototype
|
||||
new LZMA backend one definition, one descriptor reference, one prototype
|
||||
new DEFLATE backend one definition, one descriptor reference, one prototype
|
||||
new ZSTD backend two definitions for #ifdef/#else, one descriptor reference,
|
||||
one prototype
|
||||
```
|
||||
|
||||
The two ZSTD definitions are mutually exclusive build branches, not duplicate
|
||||
runtime implementations. No old-name wrapper was retained because no real
|
||||
consumer remains.
|
||||
|
||||
## Cache and Ownership Review
|
||||
|
||||
The Pre9 decoded LZMA cache policy is untouched. The request callback returns
|
||||
before the cache code runs, so the following remain owned by `zdata.c`:
|
||||
|
||||
- compressed-buffer release;
|
||||
- decoded allocation cleanup on failure;
|
||||
- decoded extent publication;
|
||||
- duplicate-cache replacement and old-entry freeing;
|
||||
- one-entry-per-mount bound and cache lock lifecycle.
|
||||
|
||||
No callback stores the request pointer or either borrowed buffer after return.
|
||||
|
||||
## Static Checks
|
||||
|
||||
The following checks were run before this report was written:
|
||||
|
||||
```sh
|
||||
git diff --check
|
||||
git diff --name-only | sort
|
||||
grep -RInE '(^|[^_])(lz4_decompress|lzma_decompress|deflate_decompress|zstd_decompress)\\(' repo-pre-10/src
|
||||
grep -RInE 'z_erofs_(lz4|lzma|deflate|zstd)_decompress' repo-pre-10/src
|
||||
grep -RInE '\\b(page|folio|bio|workqueue|xarray|shrinker)\\b' \\
|
||||
repo-pre-10/src/internal.h repo-pre-10/src/decompressor.c \\
|
||||
repo-pre-10/src/lz4.c repo-pre-10/src/decompressor_lzma.c \\
|
||||
repo-pre-10/src/decompressor_deflate.c repo-pre-10/src/decompressor_zstd.c \\
|
||||
repo-pre-10/src/zdata.c
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
- `git diff --check`: PASS.
|
||||
- Changed paths: only the six allowed source files: PASS.
|
||||
- Old backend symbol search: no matches: PASS.
|
||||
- New backend definitions and descriptor references: PASS.
|
||||
- Forbidden Linux memory-model concepts in the changed codec boundary: no
|
||||
matches: PASS.
|
||||
- Descriptor entries: six unique designated entries covering algorithms 0-5:
|
||||
PASS.
|
||||
- `zdata.c` cache and ownership diff: unchanged: PASS.
|
||||
|
||||
The host is not a FreeBSD build environment, so this batch does not claim a
|
||||
KLD build. Per the Pre10 instruction, QEMU smoke testing and the full feature
|
||||
matrix were not run in this batch.
|
||||
|
||||
## Concerns and Deferred Validation
|
||||
|
||||
The primary remaining validation is a FreeBSD guest KLD build followed by the
|
||||
planned Pre10 smoke run. That runtime work is intentionally separate from this
|
||||
static implementation batch. Full feature tests remain outside Pre10.
|
||||
|
||||
The existing `erofs_vget()` `insmntque()` failure-path P1 remains documented
|
||||
in `repo-pre-10/issues/erofs-vget-insmntque-failure-use-after-release.md` and
|
||||
was not changed here.
|
||||
Reference in New Issue
Block a user