Skip to content

feat(disk/qcow): support compressed qcow2 clusters (zlib + zstd) with…#3

Open
lateautumn233 wants to merge 1 commit into
Droid-VM:droidvmfrom
lateautumn233:feat-qcow-compressed
Open

feat(disk/qcow): support compressed qcow2 clusters (zlib + zstd) with…#3
lateautumn233 wants to merge 1 commit into
Droid-VM:droidvmfrom
lateautumn233:feat-qcow-compressed

Conversation

@lateautumn233

Copy link
Copy Markdown
Contributor

… COW writes

Add read and copy-on-write support for compressed qcow2 clusters. Compressed clusters are decompressed on read and rewritten as plain clusters on write, so images produced by qemu-img convert -c can be used and modified.

  • Decode both compression types: zlib (raw DEFLATE via flate2's zlib-rs backend) and zstd (C libzstd via the zstd crate). Enable the qcow feature's new flate2/zstd deps in Cargo.toml and wire libflate2/libzstd_rust into disk/Android.bp.
  • Validate the incompatible-features header: tolerate the dirty and compression bits, reject corrupt/external-data-file/extended-L2 and any unknown bit, and require the compression bit to agree with the compression-type field.
  • Add a 2 MiB LRU cache of decompressed clusters and parallelize multi-cluster compressed reads across worker threads (single-cluster reads decode inline).
  • Fix COPIED-flag corruption: write_pointer_table no longer ORs OFLAG_COPIED (bit 63) onto compressed L2 entries (bit 62), which the qcow2 spec forbids, and strips any stray bit-63 left by prior writes. This stops qemu-img check from reporting "OFLAG_COPIED must never be set for compressed" on written images.

We don't accept any GitHub pull requests to crosvm. We use
Chromium Gerrit for the code review process. See
the contribution guide for the details.

… COW writes

Add read and copy-on-write support for compressed qcow2 clusters. Compressed
clusters are decompressed on read and rewritten as plain clusters on write,
so images produced by `qemu-img convert -c` can be used and modified.

- Decode both compression types: zlib (raw DEFLATE via flate2's zlib-rs
  backend) and zstd (C libzstd via the zstd crate). Enable the `qcow` feature's
  new flate2/zstd deps in Cargo.toml and wire libflate2/libzstd_rust into
  disk/Android.bp.
- Validate the incompatible-features header: tolerate the dirty and compression
  bits, reject corrupt/external-data-file/extended-L2 and any unknown bit, and
  require the compression bit to agree with the compression-type field.
- Add a 2 MiB LRU cache of decompressed clusters and parallelize multi-cluster
  compressed reads across worker threads (single-cluster reads decode inline).
- Fix COPIED-flag corruption: write_pointer_table no longer ORs OFLAG_COPIED
  (bit 63) onto compressed L2 entries (bit 62), which the qcow2 spec forbids,
  and strips any stray bit-63 left by prior writes. This stops `qemu-img check`
  from reporting "OFLAG_COPIED must never be set for compressed" on written
  images.
@lateautumn233 lateautumn233 marked this pull request as ready for review July 6, 2026 13:46
Copilot AI review requested due to automatic review settings July 6, 2026 13:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds qcow2 compressed-cluster support to the disk crate’s qcow implementation so images created with qemu-img convert -c can be read and modified. The PR extends header validation, introduces decompression (zlib + zstd) with caching/parallel decode, and updates refcount/COW logic to correctly handle compressed L2 entries (including preventing forbidden OFLAG_COPIED on compressed entries).

Changes:

  • Add decoding for qcow2 compressed clusters (zlib raw DEFLATE + zstd) with an LRU cache and parallel multi-cluster decode.
  • Validate qcow2 incompatible-features bits and compression-type consistency; reject unsupported incompatible bits/types.
  • Fix pointer-table writeback to avoid propagating OFLAG_COPIED onto compressed L2 entries and reclaim freed compressed storage safely.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
disk/src/qcow/qcow_raw_file.rs Adjust pointer-table writeback to preserve compressed descriptors and strip forbidden/copied bits.
disk/src/qcow/mod.rs Implement compressed-cluster read/COW-write paths, caching/prefetch, header validation, and refcount handling updates.
disk/Cargo.toml Enable qcow feature to pull in flate2 (zlib-rs backend) and zstd dependencies.
disk/Android.bp Wire flate2/zstd Rust libs and enable required features for Android builds.
Cargo.lock Lockfile update for new/updated dependencies (flate2/zlib-rs, zstd, etc.).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread disk/src/qcow/mod.rs
Comment on lines +311 to +314
fn decompress_zstd_cluster(compressed: &[u8], out: &mut [u8]) -> std::io::Result<()> {
let decoder = zstd::stream::read::Decoder::with_buffer(compressed)?;
read_fill(&mut decoder.single_frame(), out)
}
Comment thread disk/src/qcow/mod.rs
Comment on lines +1419 to +1423
entry if entry & COMPRESSED_FLAG != 0 => {
// Copy-on-write from a compressed cluster: decompress it into a freshly allocated
// uncompressed cluster and repoint the L2 entry there (clearing the compressed
// descriptor), unless the caller overwrites the whole cluster — then hand out a
// zeroed cluster and skip the decompression. Fill the new cluster before
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants