Skip to main content

imago/qcow2/
mod.rs

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