Skip to main content

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