imago/qcow2/
mod.rs

1//! Qcow2 implementation.
2
3mod allocation;
4mod builder;
5mod cache;
6mod compressed;
7mod cow;
8mod io_func;
9mod mappings;
10mod metadata;
11mod preallocation;
12#[cfg(feature = "sync-wrappers")]
13mod sync_wrappers;
14mod types;
15
16use crate::async_lru_cache::AsyncLruCache;
17use crate::format::builder::{FormatCreateBuilder, FormatDriverBuilder};
18use crate::format::drivers::FormatDriverInstance;
19use crate::format::gate::{ImplicitOpenGate, PermissiveImplicitOpenGate};
20use crate::format::wrapped::WrappedFormat;
21use crate::format::{Format, PreallocateMode};
22use crate::io_buffers::IoVectorMut;
23use crate::misc_helpers::{invalid_data, ResultErrorContext};
24use crate::raw::Raw;
25use crate::{storage, FormatAccess, ShallowMapping, Storage, StorageExt, StorageOpenOptions};
26use allocation::Allocator;
27use async_trait::async_trait;
28pub use builder::{Qcow2CreateBuilder, Qcow2OpenBuilder};
29use cache::L2CacheBackend;
30use mappings::FixedMapping;
31use metadata::*;
32use std::fmt::{self, Debug, Display, Formatter};
33use std::ops::Range;
34use std::path::Path;
35use std::sync::Arc;
36use std::{cmp, io};
37use tokio::sync::{Mutex, RwLock};
38use types::*;
39
40/// Access qcow2 images.
41///
42/// Allows access to qcow2 images (v2 and v3), referencing the following objects:
43/// - Metadata storage object: The image file itself
44/// - Data file (storage object): May be the image file itself, or an external data file
45/// - Backing image `WrappedFormat<S>`: A backing disk image in any format
46#[must_use = "qcow2 images must be flushed before closing"]
47pub struct Qcow2<S: Storage + 'static, F: WrappedFormat<S> + 'static = FormatAccess<S>> {
48    /// Image file (which contains the qcow2 metadata).
49    metadata: Arc<S>,
50
51    /// Whether this image may be modified.
52    writable: bool,
53
54    /// Whether the user explicitly assigned a data file storage object (or `None`).
55    storage_set: bool,
56    /// Data file storage object; will use `metadata` if `None`.
57    storage: Option<S>,
58    /// Whether the user explicitly assigned a backing file (or `None`).
59    backing_set: bool,
60    /// Backing image.
61    backing: Option<F>,
62    /// Base options to be used for implicitly opened storage objects.
63    storage_open_options: StorageOpenOptions,
64
65    /// Qcow2 header.
66    header: Arc<Header>,
67    /// L1 table.
68    l1_table: RwLock<L1Table>,
69
70    /// L2 table cache.
71    l2_cache: AsyncLruCache<HostCluster, L2Table, L2CacheBackend<S>>,
72
73    /// Allocates clusters.
74    ///
75    /// Is `None` for read-only images.
76    allocator: Option<Mutex<Allocator<S>>>,
77}
78
79impl<S: Storage + 'static, F: WrappedFormat<S> + 'static> Qcow2<S, F> {
80    /// Create a new [`FormatDriverBuilder`] instance for the given image.
81    pub fn builder(image: S) -> Qcow2OpenBuilder<S, F> {
82        Qcow2OpenBuilder::new(image)
83    }
84
85    /// Create a new [`FormatDriverBuilder`] instance for an image under the given path.
86    pub fn builder_path<P: AsRef<Path>>(image_path: P) -> Qcow2OpenBuilder<S, F> {
87        Qcow2OpenBuilder::new_path(image_path)
88    }
89
90    /// Create a new [`FormatCreateBuilder`] instance to format the given file.
91    pub fn create_builder(image: S) -> Qcow2CreateBuilder<S, F> {
92        Qcow2CreateBuilder::<S, F>::new(image)
93    }
94
95    /// Internal implementation for opening a qcow2 image.
96    ///
97    /// Does not open external dependencies.
98    async fn do_open(
99        metadata: S,
100        writable: bool,
101        storage_open_options: StorageOpenOptions,
102    ) -> io::Result<Self> {
103        let header = Arc::new(Header::load(&metadata, writable).await?);
104
105        let cb = header.cluster_bits();
106        let l1_offset = header.l1_table_offset();
107        let l1_cluster = l1_offset
108            .checked_cluster(cb)
109            .ok_or_else(|| invalid_data("Unaligned L1 table: {l1_offset}"))?;
110
111        let l1_table =
112            L1Table::load(&metadata, &header, l1_cluster, header.l1_table_entries()).await?;
113
114        let metadata = Arc::new(metadata);
115
116        let allocator = if writable {
117            let allocator = Allocator::new(Arc::clone(&metadata), Arc::clone(&header)).await?;
118            Some(Mutex::new(allocator))
119        } else {
120            None
121        };
122
123        let l2_cache_backend = L2CacheBackend::new(Arc::clone(&metadata), Arc::clone(&header));
124        let l2_cache = AsyncLruCache::new(l2_cache_backend, 128);
125
126        Ok(Qcow2 {
127            metadata,
128
129            writable,
130
131            storage_set: false,
132            storage: None,
133            backing_set: false,
134            backing: None,
135            storage_open_options,
136
137            header,
138            l1_table: RwLock::new(l1_table),
139
140            l2_cache,
141            allocator,
142        })
143    }
144
145    /// Opens a qcow2 file.
146    ///
147    /// `metadata` is the file containing the qcow2 metadata.  If `writable` is not set, no
148    /// modifications are permitted.
149    ///
150    /// This will not open any other storage objects needed, i.e. no backing image, no external
151    /// data file.  If you want to handle those manually, check whether an external data file is
152    /// needed via [`Qcow2::requires_external_data_file()`], and, if necessary, assign one via
153    /// [`Qcow2::set_data_file()`]; and assign a backing image via [`Qcow2::set_backing()`].
154    ///
155    /// If you want to use the implicit references given in the image header, use
156    /// [`Qcow2::open_implicit_dependencies()`].
157    pub async fn open_image(metadata: S, writable: bool) -> io::Result<Self> {
158        Self::do_open(metadata, writable, StorageOpenOptions::new()).await
159    }
160
161    /// Open a qcow2 file at the given path.
162    ///
163    /// Open the file as a storage object via [`Storage::open()`], with write access if specified,
164    /// then pass that object to [`Qcow2::open_image()`].
165    ///
166    /// This will not open any other storage objects needed, i.e. no backing image, no external
167    /// data file.  If you want to handle those manually, check whether an external data file is
168    /// needed via [`Qcow2::requires_external_data_file()`], and, if necessary, assign one via
169    /// [`Qcow2::set_data_file()`]; and assign a backing image via [`Qcow2::set_backing()`].
170    ///
171    /// If you want to use the implicit references given in the image header, use
172    /// [`Qcow2::open_implicit_dependencies()`].
173    pub async fn open_path<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
174        let storage_opts = StorageOpenOptions::new().write(writable).filename(path);
175        let metadata = S::open(storage_opts).await?;
176        Self::do_open(metadata, writable, StorageOpenOptions::new()).await
177    }
178
179    /// Does this qcow2 image require an external data file?
180    ///
181    /// Conversely, if this is `false`, this image must not use an external data file.
182    pub fn requires_external_data_file(&self) -> bool {
183        self.header.external_data_file()
184    }
185
186    /// External data file filename given in the image header.
187    ///
188    /// Note that even if an image requires an external data file, the header may not contain its
189    /// filename.  In this case, an external data file must be set explicitly via
190    /// [`Qcow2::set_data_file()`].
191    pub fn implicit_external_data_file(&self) -> Option<&String> {
192        self.header.external_data_filename()
193    }
194
195    /// Backing image filename given in the image header.
196    pub fn implicit_backing_file(&self) -> Option<&String> {
197        self.header.backing_filename()
198    }
199
200    /// Backing image format given in the image header.
201    ///
202    /// If this is `None`, the backing image’s format should be probed.  Note that this may be
203    /// dangerous if guests have write access to the backing file: Given a raw image, a guest can
204    /// write a qcow2 header into it, resulting in the image being opened as qcow2 the next time,
205    /// allowing the guest to read arbitrary files (e.g. by setting them as backing files).
206    pub fn implicit_backing_format(&self) -> Option<&String> {
207        self.header.backing_format()
208    }
209
210    /// Assign the data file.
211    ///
212    /// `None` means using the same data storage for both metadata and data, which should be used
213    /// if [`Qcow2::requires_external_data_file()`] is `false`.
214    pub fn set_data_file(&mut self, file: Option<S>) {
215        self.storage = file;
216        self.storage_set = true;
217    }
218
219    /// Assign a backing image.
220    ///
221    /// `None` means no backing image, i.e. reading from unallocated areas will produce zeroes.
222    pub fn set_backing(&mut self, backing: Option<F>) {
223        self.backing = backing;
224        self.backing_set = true;
225    }
226
227    /// Get the data storage object.
228    ///
229    /// If we have an external data file, return that.  Otherwise, return the image (metadata)
230    /// file.
231    fn storage(&self) -> &S {
232        self.storage.as_ref().unwrap_or(&self.metadata)
233    }
234
235    /// Return the image’s implicit data file (as given in the image header).
236    async fn open_implicit_data_file<G: ImplicitOpenGate<S>>(
237        &self,
238        gate: &mut G,
239    ) -> io::Result<Option<S>> {
240        if !self.header.external_data_file() {
241            return Ok(None);
242        }
243
244        let Some(filename) = self.header.external_data_filename() else {
245            return Err(io::Error::other(
246                "Image requires external data file, but no filename given",
247            ));
248        };
249
250        let absolute = self
251            .metadata
252            .resolve_relative_path(filename)
253            .err_context(|| format!("Cannot resolve external data file name {filename}"))?;
254
255        let opts = self
256            .storage_open_options
257            .clone()
258            .write(true)
259            .filename(absolute.clone());
260
261        let file = gate
262            .open_storage(opts)
263            .await
264            .err_context(|| format!("External data file {absolute:?}"))?;
265        Ok(Some(file))
266    }
267
268    /// Wrap `file` in the `Raw` format.  Helper for [`Qcow2::implicit_backing_file()`].
269    async fn open_raw_backing_file<G: ImplicitOpenGate<S>>(
270        &self,
271        file: S,
272        gate: &mut G,
273    ) -> io::Result<F> {
274        let opts = Raw::builder(file).storage_open_options(self.storage_open_options.clone());
275        let raw = gate.open_format(opts).await?;
276        Ok(F::wrap(FormatAccess::new(raw)))
277    }
278
279    /// Wrap `file` in the `Qcow2` format.  Helper for [`Qcow2::implicit_backing_file()`].
280    async fn open_qcow2_backing_file<G: ImplicitOpenGate<S>>(
281        &self,
282        file: S,
283        gate: &mut G,
284    ) -> io::Result<F> {
285        let opts =
286            Qcow2::<S>::builder(file).storage_open_options(self.storage_open_options.clone());
287        // Recursive, so needs to be boxed
288        let qcow2 = Box::pin(gate.open_format(opts)).await?;
289        Ok(F::wrap(FormatAccess::new(qcow2)))
290    }
291
292    /// Return the image’s implicit backing image (as given in the image header).
293    ///
294    /// Anything opened will be passed through `gate`.
295    async fn open_implicit_backing_file<G: ImplicitOpenGate<S>>(
296        &self,
297        gate: &mut G,
298    ) -> io::Result<Option<F>> {
299        let Some(filename) = self.header.backing_filename() else {
300            return Ok(None);
301        };
302
303        let absolute = self
304            .metadata
305            .resolve_relative_path(filename)
306            .err_context(|| format!("Cannot resolve backing file name {filename}"))?;
307
308        let file_opts = self
309            .storage_open_options
310            .clone()
311            .filename(absolute.clone())
312            .write(false);
313
314        let file = gate
315            .open_storage(file_opts)
316            .await
317            .err_context(|| format!("Backing file {absolute:?}"))?;
318
319        let result = match self.header.backing_format().map(|f| f.as_str()) {
320            Some("qcow2") => self.open_qcow2_backing_file(file, gate).await.map(Some),
321            Some("raw") | Some("file") => self.open_raw_backing_file(file, gate).await.map(Some),
322
323            Some(fmt) => Err(io::Error::other(format!("Unknown backing format {fmt}"))),
324
325            // Reasonably safe: The backing image is supposed to be read-only.  We could run into
326            // trouble if a guest is on a raw image, which is then snapshotted, and now we see a
327            // qcow2 image; but let’s rely on such images always having a backing format set.
328            None => match unsafe { Self::probe(&file) }.await {
329                Ok(true) => self.open_qcow2_backing_file(file, gate).await.map(Some),
330                Ok(false) => self.open_raw_backing_file(file, gate).await.map(Some),
331                Err(err) => Err(err),
332            },
333        };
334
335        result.err_context(|| format!("Backing file {absolute:?}"))
336    }
337
338    /// Open all implicit dependencies.
339    ///
340    /// Qcow2 images have dependencies:
341    /// - The metadata file, which is the image file itself.
342    /// - The data file, which may be the same as the metadata file, or may be an external data
343    ///   file.
344    /// - A backing disk image in any format.
345    ///
346    /// All of this can be set explicitly:
347    /// - The metadata file is always given explicitly to [`Qcow2::open_image()`].
348    /// - The data file can be set via [`Qcow2::set_data_file()`].
349    /// - The backing image can be set via [`Qcow2::set_backing()`].
350    ///
351    /// But the image header can also provide “default” references to the data file and a backing
352    /// image, which we call *implicit* dependencies.  This function opens all such implicit
353    /// dependencies if they have not been overridden with prior calls to
354    /// [`Qcow2::set_data_file()`] or [`Qcow2::set_backing()`], respectively.
355    ///
356    /// Any image or file is opened through `gate`.
357    pub async fn open_implicit_dependencies_gated<G: ImplicitOpenGate<S>>(
358        &mut self,
359        mut gate: G,
360    ) -> io::Result<()> {
361        if !self.storage_set {
362            self.storage = self.open_implicit_data_file(&mut gate).await?;
363            self.storage_set = true;
364        }
365
366        if !self.backing_set {
367            self.backing = self.open_implicit_backing_file(&mut gate).await?;
368            self.backing_set = true;
369        }
370
371        Ok(())
372    }
373
374    /// Open all implicit dependencies, ungated.
375    ///
376    /// Same as [`Qcow2::open_implicit_dependencies_gated`], but does not perform any gating on
377    /// implicitly opened images/files.
378    ///
379    /// See the cautionary notes on [`PermissiveImplicitOpenGate`] on
380    /// [`FormatDriverInstance::probe()`] on why this may be dangerous.
381    pub async fn open_implicit_dependencies(&mut self) -> io::Result<()> {
382        self.open_implicit_dependencies_gated(PermissiveImplicitOpenGate::default())
383            .await
384    }
385
386    /// Require write access, i.e. return an error for read-only images.
387    fn need_writable(&self) -> io::Result<()> {
388        self.writable
389            .then_some(())
390            .ok_or_else(|| io::Error::other("Image is read-only"))
391    }
392
393    /// Check whether `length + offset` is within the disk size.
394    fn check_disk_bounds<D: Display>(&self, length: u64, offset: u64, req: D) -> io::Result<()> {
395        let size = self.header.size();
396        let length_until_eof = size.saturating_sub(offset);
397        if length_until_eof >= length {
398            Ok(())
399        } else {
400            Err(io::Error::new(
401                io::ErrorKind::UnexpectedEof,
402                format!("Cannot {req} beyond the disk size ({length} + {offset} > {size}"),
403            ))
404        }
405    }
406}
407
408#[async_trait(?Send)]
409impl<S: Storage, F: WrappedFormat<S>> FormatDriverInstance for Qcow2<S, F> {
410    type Storage = S;
411
412    fn format(&self) -> Format {
413        Format::Qcow2
414    }
415
416    async unsafe fn probe(metadata: &S) -> io::Result<bool>
417    where
418        Self: Sized,
419    {
420        let mut magic_version = [0u8; 8];
421        metadata.read(&mut magic_version[..], 0).await?;
422
423        let magic = u32::from_be_bytes((&magic_version[..4]).try_into().unwrap());
424        let version = u32::from_be_bytes((&magic_version[4..]).try_into().unwrap());
425        Ok(magic == MAGIC && (version == 2 || (version == 3)))
426    }
427
428    fn size(&self) -> u64 {
429        self.header.size()
430    }
431
432    fn zero_granularity(&self) -> Option<u64> {
433        self.header.require_version(3).ok()?;
434        Some(self.header.cluster_size() as u64)
435    }
436
437    fn collect_storage_dependencies(&self) -> Vec<&S> {
438        let mut v = self
439            .backing
440            .as_ref()
441            .map(|b| b.inner().collect_storage_dependencies())
442            .unwrap_or_default();
443
444        v.push(&self.metadata);
445        if let Some(storage) = self.storage.as_ref() {
446            v.push(storage);
447        }
448
449        v
450    }
451
452    fn writable(&self) -> bool {
453        self.writable
454    }
455
456    async fn get_mapping<'a>(
457        &'a self,
458        offset: u64,
459        max_length: u64,
460    ) -> io::Result<(ShallowMapping<'a, S>, u64)> {
461        let length_until_eof = match self.header.size().checked_sub(offset) {
462            None | Some(0) => return Ok((ShallowMapping::Eof {}, 0)),
463            Some(length) => length,
464        };
465
466        let max_length = cmp::min(max_length, length_until_eof);
467        let offset = GuestOffset(offset);
468        self.do_get_mapping(offset, max_length).await
469    }
470
471    async fn ensure_data_mapping<'a>(
472        &'a self,
473        offset: u64,
474        length: u64,
475        overwrite: bool,
476    ) -> io::Result<(&'a S, u64, u64)> {
477        self.check_disk_bounds(offset, length, "allocate")?;
478
479        if length == 0 {
480            return Ok((self.storage(), 0, 0));
481        }
482
483        self.need_writable()?;
484        let offset = GuestOffset(offset);
485        self.do_ensure_data_mapping(offset, length, overwrite).await
486    }
487
488    async fn ensure_zero_mapping(&self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
489        self.need_writable()?;
490        self.check_disk_bounds(offset, length, "write")?;
491
492        self.ensure_fixed_mapping(
493            GuestOffset(offset),
494            length,
495            FixedMapping::ZeroRetainAllocation,
496        )
497        .await
498        .map(|(ofs, len)| (ofs.0, len))
499    }
500
501    async fn discard_to_zero(&mut self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
502        self.need_writable()?;
503        self.check_disk_bounds(offset, length, "discard")?;
504
505        // Safe to discard: We have a mutable `self` reference
506        // Note this will return an `Unsupported` error for v2 images.  That’s OK, safely
507        // discarding on them is a hairy affair, and they are really outdated by now.
508        self.ensure_fixed_mapping(GuestOffset(offset), length, FixedMapping::ZeroDiscard)
509            .await
510            .map(|(ofs, len)| (ofs.0, len))
511    }
512
513    async fn discard_to_any(&mut self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
514        self.discard_to_zero(offset, length).await
515    }
516
517    async fn discard_to_backing(&mut self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
518        self.need_writable()?;
519        self.check_disk_bounds(offset, length, "discard")?;
520
521        // Safe to discard: We have a mutable `self` reference
522        self.ensure_fixed_mapping(GuestOffset(offset), length, FixedMapping::FullDiscard)
523            .await
524            .map(|(ofs, len)| (ofs.0, len))
525    }
526
527    async fn readv_special(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
528        let offset = GuestOffset(offset);
529        self.do_readv_special(bufv, offset).await
530    }
531
532    async fn flush(&self) -> io::Result<()> {
533        self.l2_cache.flush().await?;
534        if let Some(allocator) = self.allocator.as_ref() {
535            allocator.lock().await.flush_rb_cache().await?;
536        }
537
538        self.metadata.flush().await?;
539        if let Some(storage) = self.storage.as_ref() {
540            storage.flush().await?;
541        }
542        // Backing file is read-only, so need not be flushed from us.
543        Ok(())
544    }
545
546    async fn sync(&self) -> io::Result<()> {
547        self.metadata.sync().await?;
548        if let Some(storage) = self.storage.as_ref() {
549            storage.sync().await?;
550        }
551        // Backing file is read-only, so need not be synced from us.
552        Ok(())
553    }
554
555    async unsafe fn invalidate_cache(&self) -> io::Result<()> {
556        // Safe: Caller says we should do this
557        unsafe { self.l2_cache.invalidate() }.await?;
558        if let Some(allocator) = self.allocator.as_ref() {
559            let allocator = allocator.lock().await;
560            // Safe: Caller says we should do this
561            unsafe { allocator.invalidate_rb_cache() }.await?;
562        }
563
564        // Safe: Caller says we should do this
565        unsafe { self.metadata.invalidate_cache() }.await?;
566        if let Some(storage) = self.storage.as_ref() {
567            // Safe: Caller says we should do this
568            unsafe { storage.invalidate_cache() }.await?;
569        }
570        if let Some(backing) = self.backing.as_ref() {
571            // Safe: Caller says we should do this
572            unsafe { backing.inner().invalidate_cache() }.await?;
573        }
574
575        // TODO: Ideally we would reload the whole image header, but that would require putting it
576        // in a lock.  We probably do not want to put things like cluster_bits behind a lock.  For
577        // the time being, all we need to reload are things that are mutable at runtime anyway
578        // (because the source instance would not have been able to change other things), so just
579        // reload the L1 and refcount table positions.
580        let new_header = Header::load(self.metadata.as_ref(), false).await?;
581        self.header.update(&new_header)?;
582
583        if let Some(allocator) = self.allocator.as_ref() {
584            *allocator.lock().await =
585                Allocator::new(Arc::clone(&self.metadata), Arc::clone(&self.header)).await?;
586        }
587
588        // Alignment checked in `load()`
589        let l1_cluster = self
590            .header
591            .l1_table_offset()
592            .cluster(self.header.cluster_bits());
593
594        *self.l1_table.write().await = L1Table::load(
595            self.metadata.as_ref(),
596            &self.header,
597            l1_cluster,
598            self.header.l1_table_entries(),
599        )
600        .await?;
601
602        Ok(())
603    }
604
605    async fn resize_grow(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
606        self.need_writable()?;
607
608        let old_size = self.size();
609        let grown_length = new_size.saturating_sub(old_size);
610        if grown_length == 0 {
611            return Ok(()); // only grow, else do nothing
612        }
613
614        if let Some(data_file) = self.storage.as_ref() {
615            // Options that allocate data mappings in qcow2 will resize the data file via
616            // `preallocate()` or `preallocate_write_data()`.  Those that don’t won’t, so they need
617            // to be handled here.
618            match prealloc_mode {
619                PreallocateMode::None => {
620                    data_file
621                        .resize(new_size, storage::PreallocateMode::None)
622                        .await?;
623                }
624                PreallocateMode::Zero => {
625                    data_file
626                        .resize(new_size, storage::PreallocateMode::Zero)
627                        .await?;
628                }
629                PreallocateMode::FormatAllocate
630                | PreallocateMode::FullAllocate
631                | PreallocateMode::WriteData => (),
632            }
633        }
634
635        // QEMU requires the L1 table to at least match the image’s size.
636        // On that note, note that this would make an L1 state’s data visible to the guest (and
637        // also effectively invalidate it, because it is no longer L1 state, but just data), but
638        // QEMU does not care either.  (We could see whether there are allocated clusters after the
639        // image end to find out.)
640        {
641            let l1_locked = self.l1_table.write().await;
642            let l1_index =
643                GuestOffset(new_size.saturating_sub(1)).l1_index(self.header.cluster_bits());
644            let _l1_locked = self.grow_l1_table(l1_locked, l1_index).await?;
645        }
646
647        // Grow before preallocating (so we can preallocate)
648        self.header.set_size(new_size);
649
650        match prealloc_mode {
651            PreallocateMode::None => Ok(()),
652            PreallocateMode::Zero => self.preallocate_zero(old_size, grown_length).await,
653            PreallocateMode::FormatAllocate => {
654                self.preallocate(old_size, grown_length, storage::PreallocateMode::Zero)
655                    .await
656            }
657            PreallocateMode::FullAllocate => {
658                self.preallocate(old_size, grown_length, storage::PreallocateMode::Allocate)
659                    .await
660            }
661            PreallocateMode::WriteData => self.preallocate_write_data(old_size, grown_length).await,
662        }
663        .inspect_err(|_| {
664            // Better reset to old size then
665            self.header.set_size(old_size)
666        })?;
667
668        // Do this last because we may not be able to undo it
669        self.header
670            .write_size(self.metadata.as_ref())
671            .await
672            .inspect_err(|_| {
673                // Reset to old size
674                self.header.set_size(old_size)
675            })
676    }
677
678    async fn resize_shrink(&mut self, new_size: u64) -> io::Result<()> {
679        self.need_writable()?;
680
681        let old_size = self.size();
682        if new_size >= old_size {
683            return Ok(()); // only shrink, else do nothing
684        }
685
686        if let Some(data_file) = self.storage.as_ref() {
687            data_file
688                .resize(new_size, storage::PreallocateMode::None)
689                .await?;
690        }
691
692        let mut offset = new_size;
693        while offset < old_size {
694            match self.discard_to_backing(offset, old_size - offset).await {
695                Ok((_, 0)) => break, // cannot discard tail
696                Ok((dofs, dlen)) => offset = dofs + dlen,
697                // Basically ignore errors, but stop trying to discard
698                Err(_) => break,
699            }
700        }
701
702        // Shrink after discarding (so we can discard)
703        self.header.set_size(new_size);
704
705        // Do this last because we may not be able to undo it
706        self.header
707            .write_size(self.metadata.as_ref())
708            .await
709            .inspect_err(|_| {
710                // Reset to old size
711                self.header.set_size(old_size);
712            })
713    }
714}
715
716impl<S: Storage + 'static, F: WrappedFormat<S>> Debug for Qcow2<S, F> {
717    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
718        f.debug_struct("Qcow2")
719            .field("metadata", &self.metadata)
720            .field("storage_set", &self.storage_set)
721            .field("storage", &self.storage)
722            .field("backing_set", &self.backing_set)
723            .field("backing", &self.backing)
724            .finish()
725    }
726}
727
728impl<S: Storage + 'static, F: WrappedFormat<S>> Display for Qcow2<S, F> {
729    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
730        write!(f, "qcow2[{}]", self.metadata)
731    }
732}