u-boot: v2026.01: fix BTRFS zstd decompression failure (error 70)#9651
u-boot: v2026.01: fix BTRFS zstd decompression failure (error 70)#9651iav wants to merge 1 commit intoarmbian:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughReplaces BTRFS zstd decompression to use libzstd decompression-context APIs, detect exact zstd frame compressed/content sizes, strip BTRFS sector padding, optionally allocate temporary output/workspace buffers, perform decompression via a dctx, and return -1 on errors. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant decompress_zstd
participant Allocator
participant libzstd
Caller->>decompress_zstd: call(ibuf, clen, dbuf, dlen)
decompress_zstd->>libzstd: zstd_find_frame_compressed_size(ibuf, clen)
libzstd-->>decompress_zstd: frame_compressed_size / error
decompress_zstd->>decompress_zstd: adjust clen (strip padding)
decompress_zstd->>libzstd: ZSTD_getFrameContentSize(ibuf)
libzstd-->>decompress_zstd: frame_decompressed_size
alt frame_decompressed_size known and > dlen
decompress_zstd->>Allocator: malloc(temp_out, frame_decompressed_size)
Allocator-->>decompress_zstd: temp_out / NULL
end
decompress_zstd->>Allocator: malloc(workspace, zstd_dctx_workspace_bound())
Allocator-->>decompress_zstd: workspace / NULL
decompress_zstd->>libzstd: zstd_init_dctx(workspace)
libzstd-->>decompress_zstd: dctx / error
decompress_zstd->>libzstd: zstd_decompress_dctx(dctx, ibuf, clen, outbuf, outlen)
libzstd-->>decompress_zstd: success / error
alt success and temp_out used
decompress_zstd->>Allocator: memcpy(dbuf, temp_out, dlen)
decompress_zstd->>Allocator: free(temp_out)
end
decompress_zstd->>Allocator: free(workspace)
decompress_zstd-->>Caller: return dlen or -1
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch (1)
79-81: Consider size_t truncation on 32-bit platforms.
fcsisunsigned long longbutmalloc()takessize_t. On 32-bit systems wheresize_tis 32 bits, values > 4GB would truncate. While unlikely for BTRFS extents in practice (typical max extent size is 128MB), a defensive check could prevent unexpected behavior:🛡️ Optional: Add size overflow check
if (fcs != ZSTD_CONTENTSIZE_ERROR && fcs != ZSTD_CONTENTSIZE_UNKNOWN && fcs > dlen) { + if (fcs > SIZE_MAX) + return -1; tmp = malloc(fcs); if (!tmp) return -1;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch` around lines 79 - 81, The allocation uses malloc(tmp = malloc(fcs)) where fcs is an unsigned long long and malloc takes size_t, so on 32-bit platforms fcs may truncate; add a defensive size overflow check before calling malloc: verify fcs <= (size_t)-1 (or SIZE_MAX) and fail fast (return -1) if it exceeds, then cast fcs to size_t when calling malloc for tmp; reference symbols: fcs, tmp, malloc().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch`:
- Around line 79-81: The allocation uses malloc(tmp = malloc(fcs)) where fcs is
an unsigned long long and malloc takes size_t, so on 32-bit platforms fcs may
truncate; add a defensive size overflow check before calling malloc: verify fcs
<= (size_t)-1 (or SIZE_MAX) and fail fast (return -1) if it exceeds, then cast
fcs to size_t when calling malloc for tmp; reference symbols: fcs, tmp,
malloc().
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 011b3518-0333-4433-a861-0fed3835b12a
📒 Files selected for processing (1)
patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch
b4c330a to
2e91b75
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch`:
- Around line 53-56: The out_len variable is declared as u32 which can truncate
64-bit frame sizes (fcs); change its type to size_t (e.g., replace "u32 out_len
= dlen;" with "size_t out_len = dlen;") and update any subsequent assignments
from fcs (e.g., when doing "out_len = fcs;") to use size_t (cast if necessary:
"out_len = (size_t)fcs;") so the decompression call receives the full 64-bit
capacity; ensure any other uses of out_len match size_t semantics.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 222d1f07-33d1-4207-b8e2-441e709bf5c9
📒 Files selected for processing (1)
patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch
patch/u-boot/v2026.01/board_helios64/general-fix-btrfs-zstd-decompression.patch
Outdated
Show resolved
Hide resolved
U-Boot's generic zstd_decompress() wrapper fails when used by BTRFS due to two sector-alignment mismatches: 1. Compressed extents are stored padded to sector boundaries (4096), but zstd_decompress_dctx() rejects trailing data after the frame. 2. BTRFS compresses in sector-sized blocks, so the zstd frame content size may exceed ram_bytes. When the output buffer is sized to ram_bytes, zstd_decompress_dctx() returns dstSize_tooSmall (error 70). Symptoms on zstd-compressed BTRFS partition: zstd_decompress: failed to decompress: 70 BTRFS: An error occurred while reading file /boot/boot.scr Fix by calling zstd_decompress_dctx() directly with: - zstd_find_frame_compressed_size() to strip sector padding from input - ZSTD_getFrameContentSize() to allocate a larger output buffer when the frame decompresses beyond the caller's buffer size Tested on Helios64 (RK3399) booting from BTRFS+zstd SD card.
2e91b75 to
c644580
Compare
Summary
zstd_decompress()wrapper inlib/zstd/zstd.cfails for BTRFS extents due to two sector-alignment mismatcheszstd_decompress_dctx()directly withzstd_find_frame_compressed_size()to strip input padding andZSTD_getFrameContentSize()to handle output buffer size mismatchRoot cause
Sector-aligned compressed size: BTRFS stores compressed extents padded to sector boundaries (4096 bytes).
zstd_decompress_dctx()rejects trailing data after the zstd frame, breaking regular (non-inline) extents.Sector-aligned decompressed size: BTRFS compresses in sector-sized blocks, so the zstd frame content size may exceed
ram_bytesfrom extent metadata (e.g. a 3906-byte file is compressed as a 4096-byte block).zstd_decompress_dctx()returnsZSTD_error_dstSize_tooSmall(error 70) for inline extents.Symptoms:
Testing done
🤖 Generated with Claude Code
Summary by CodeRabbit