1mod 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::MetadataCaches;
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#[must_use = "qcow2 images must be flushed before closing"]
47pub struct Qcow2<S: Storage + 'static, F: WrappedFormat<S> + 'static = FormatAccess<S>> {
48 metadata: Arc<S>,
50
51 writable: bool,
53
54 storage_set: bool,
56 storage: Option<S>,
58 backing_set: bool,
60 backing: Option<F>,
62 storage_open_options: StorageOpenOptions,
64
65 header: Arc<Header>,
67 l1_table: RwLock<L1Table>,
69
70 caches: Arc<MetadataCaches<S>>,
72
73 allocator: Option<Mutex<Allocator<S>>>,
77}
78
79impl<S: Storage + 'static, F: WrappedFormat<S> + 'static> Qcow2<S, F> {
80 pub fn builder(image: S) -> Qcow2OpenBuilder<S, F> {
82 Qcow2OpenBuilder::new(image)
83 }
84
85 pub fn builder_path<P: AsRef<Path>>(image_path: P) -> Qcow2OpenBuilder<S, F> {
87 Qcow2OpenBuilder::new_path(image_path)
88 }
89
90 pub fn create_builder(image: S) -> Qcow2CreateBuilder<S, F> {
92 Qcow2CreateBuilder::<S, F>::new(image)
93 }
94
95 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 let caches = Arc::new(MetadataCaches::new(&metadata, &header, 128, 32));
116
117 let allocator = if writable {
118 let allocator = Allocator::new(
119 Arc::clone(&metadata),
120 Arc::clone(&header),
121 Arc::clone(&caches),
122 )
123 .await?;
124 Some(Mutex::new(allocator))
125 } else {
126 None
127 };
128
129 Ok(Qcow2 {
130 metadata,
131
132 writable,
133
134 storage_set: false,
135 storage: None,
136 backing_set: false,
137 backing: None,
138 storage_open_options,
139
140 header,
141 l1_table: RwLock::new(l1_table),
142
143 caches,
144 allocator,
145 })
146 }
147
148 pub async fn open_image(metadata: S, writable: bool) -> io::Result<Self> {
161 Self::do_open(metadata, writable, StorageOpenOptions::new()).await
162 }
163
164 pub async fn open_path<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
177 let storage_opts = StorageOpenOptions::new().write(writable).filename(path);
178 let metadata = S::open(storage_opts).await?;
179 Self::do_open(metadata, writable, StorageOpenOptions::new()).await
180 }
181
182 pub fn requires_external_data_file(&self) -> bool {
186 self.header.external_data_file()
187 }
188
189 pub fn implicit_external_data_file(&self) -> Option<&String> {
195 self.header.external_data_filename()
196 }
197
198 pub fn implicit_backing_file(&self) -> Option<&String> {
200 self.header.backing_filename()
201 }
202
203 pub fn implicit_backing_format(&self) -> Option<&String> {
210 self.header.backing_format()
211 }
212
213 pub fn set_data_file(&mut self, file: Option<S>) {
218 self.storage = file;
219 self.storage_set = true;
220 }
221
222 pub fn set_backing(&mut self, backing: Option<F>) {
226 self.backing = backing;
227 self.backing_set = true;
228 }
229
230 fn storage(&self) -> &S {
235 self.storage.as_ref().unwrap_or(&self.metadata)
236 }
237
238 async fn open_implicit_data_file<G: ImplicitOpenGate<S>>(
240 &self,
241 gate: &mut G,
242 ) -> io::Result<Option<S>> {
243 if !self.header.external_data_file() {
244 return Ok(None);
245 }
246
247 let Some(filename) = self.header.external_data_filename() else {
248 return Err(io::Error::other(
249 "Image requires external data file, but no filename given",
250 ));
251 };
252
253 let absolute = self
254 .metadata
255 .resolve_relative_path(filename)
256 .err_context(|| format!("Cannot resolve external data file name {filename}"))?;
257
258 let opts = self
259 .storage_open_options
260 .clone()
261 .write(true)
262 .filename(absolute.clone());
263
264 let file = gate
265 .open_storage(opts)
266 .await
267 .err_context(|| format!("External data file {absolute:?}"))?;
268 Ok(Some(file))
269 }
270
271 async fn open_raw_backing_file<G: ImplicitOpenGate<S>>(
273 &self,
274 file: S,
275 gate: &mut G,
276 ) -> io::Result<F> {
277 let opts = Raw::builder(file).storage_open_options(self.storage_open_options.clone());
278 let raw = gate.open_format(opts).await?;
279 Ok(F::wrap(raw))
280 }
281
282 async fn open_qcow2_backing_file<G: ImplicitOpenGate<S>>(
284 &self,
285 file: S,
286 gate: &mut G,
287 ) -> io::Result<F> {
288 let opts =
289 Qcow2::<S>::builder(file).storage_open_options(self.storage_open_options.clone());
290 let qcow2 = Box::pin(gate.open_format(opts)).await?;
292 Ok(F::wrap(qcow2))
293 }
294
295 async fn open_implicit_backing_file<G: ImplicitOpenGate<S>>(
299 &self,
300 gate: &mut G,
301 ) -> io::Result<Option<F>> {
302 let Some(filename) = self.header.backing_filename() else {
303 return Ok(None);
304 };
305
306 let absolute = self
307 .metadata
308 .resolve_relative_path(filename)
309 .err_context(|| format!("Cannot resolve backing file name {filename}"))?;
310
311 let file_opts = self
312 .storage_open_options
313 .clone()
314 .filename(absolute.clone())
315 .write(false);
316
317 let file = gate
318 .open_storage(file_opts)
319 .await
320 .err_context(|| format!("Backing file {absolute:?}"))?;
321
322 let result = match self.header.backing_format().map(|f| f.as_str()) {
323 Some("qcow2") => self.open_qcow2_backing_file(file, gate).await.map(Some),
324 Some("raw") | Some("file") => self.open_raw_backing_file(file, gate).await.map(Some),
325
326 Some(fmt) => Err(io::Error::other(format!("Unknown backing format {fmt}"))),
327
328 None => match unsafe { Self::probe(&file) }.await {
332 Ok(true) => self.open_qcow2_backing_file(file, gate).await.map(Some),
333 Ok(false) => self.open_raw_backing_file(file, gate).await.map(Some),
334 Err(err) => Err(err),
335 },
336 };
337
338 result.err_context(|| format!("Backing file {absolute:?}"))
339 }
340
341 pub async fn open_implicit_dependencies_gated<G: ImplicitOpenGate<S>>(
361 &mut self,
362 mut gate: G,
363 ) -> io::Result<()> {
364 if !self.storage_set {
365 self.storage = self.open_implicit_data_file(&mut gate).await?;
366 self.storage_set = true;
367 }
368
369 if !self.backing_set {
370 self.backing = self.open_implicit_backing_file(&mut gate).await?;
371 self.backing_set = true;
372 }
373
374 Ok(())
375 }
376
377 pub async fn open_implicit_dependencies(&mut self) -> io::Result<()> {
385 self.open_implicit_dependencies_gated(PermissiveImplicitOpenGate::default())
386 .await
387 }
388
389 fn need_writable(&self) -> io::Result<()> {
391 self.writable
392 .then_some(())
393 .ok_or_else(|| io::Error::other("Image is read-only"))
394 }
395
396 fn check_disk_bounds<D: Display>(&self, length: u64, offset: u64, req: D) -> io::Result<()> {
398 let size = self.header.size();
399 let length_until_eof = size.saturating_sub(offset);
400 if length_until_eof >= length {
401 Ok(())
402 } else {
403 Err(io::Error::new(
404 io::ErrorKind::UnexpectedEof,
405 format!("Cannot {req} beyond the disk size ({length} + {offset} > {size}"),
406 ))
407 }
408 }
409
410 fn check_valid_preallocation(
414 prealloc_mode: PreallocateMode,
415 with_backing: bool,
416 ) -> io::Result<()> {
417 if !with_backing {
418 return Ok(());
419 }
420
421 match prealloc_mode {
422 PreallocateMode::None | PreallocateMode::Zero => Ok(()),
423
424 PreallocateMode::FormatAllocate
425 | PreallocateMode::FullAllocate
426 | PreallocateMode::WriteData => Err(io::Error::new(
427 io::ErrorKind::Unsupported,
428 "Preallocation is not yet supported for images with a backing file",
429 )),
430 }
431 }
432}
433
434#[async_trait(?Send)]
435impl<S: Storage, F: WrappedFormat<S>> FormatDriverInstance for Qcow2<S, F> {
436 type Storage = S;
437
438 fn format(&self) -> Format {
439 Format::Qcow2
440 }
441
442 async unsafe fn probe(metadata: &S) -> io::Result<bool>
443 where
444 Self: Sized,
445 {
446 let mut magic_version = [0u8; 8];
447 metadata.read(&mut magic_version[..], 0).await?;
448
449 let magic = u32::from_be_bytes((&magic_version[..4]).try_into().unwrap());
450 let version = u32::from_be_bytes((&magic_version[4..]).try_into().unwrap());
451 Ok(magic == MAGIC && (version == 2 || (version == 3)))
452 }
453
454 fn size(&self) -> u64 {
455 self.header.size()
456 }
457
458 fn zero_granularity(&self) -> Option<u64> {
459 self.header.require_version(3).ok()?;
460 Some(self.header.cluster_size() as u64)
461 }
462
463 fn collect_storage_dependencies(&self) -> Vec<&S> {
464 let mut v = self
465 .backing
466 .as_ref()
467 .map(|b| b.inner().collect_storage_dependencies())
468 .unwrap_or_default();
469
470 v.push(&self.metadata);
471 if let Some(storage) = self.storage.as_ref() {
472 v.push(storage);
473 }
474
475 v
476 }
477
478 fn writable(&self) -> bool {
479 self.writable
480 }
481
482 async fn get_mapping<'a>(
483 &'a self,
484 offset: u64,
485 max_length: u64,
486 ) -> io::Result<(ShallowMapping<'a, S>, u64)> {
487 let length_until_eof = match self.header.size().checked_sub(offset) {
488 None | Some(0) => return Ok((ShallowMapping::Eof {}, 0)),
489 Some(length) => length,
490 };
491
492 let max_length = cmp::min(max_length, length_until_eof);
493 let offset = GuestOffset(offset);
494 self.do_get_mapping(offset, max_length).await
495 }
496
497 async fn ensure_data_mapping<'a>(
498 &'a self,
499 offset: u64,
500 length: u64,
501 overwrite: bool,
502 ) -> io::Result<(&'a S, u64, u64)> {
503 self.check_disk_bounds(offset, length, "allocate")?;
504
505 if length == 0 {
506 return Ok((self.storage(), 0, 0));
507 }
508
509 self.need_writable()?;
510 let offset = GuestOffset(offset);
511 self.do_ensure_data_mapping(offset, length, overwrite, false)
512 .await
513 }
514
515 async fn ensure_zero_mapping(&self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
516 self.need_writable()?;
517 self.check_disk_bounds(offset, length, "write")?;
518
519 self.ensure_fixed_mapping(
520 GuestOffset(offset),
521 length,
522 FixedMapping::ZeroRetainAllocation,
523 )
524 .await
525 .map(|(ofs, len)| (ofs.0, len))
526 }
527
528 async unsafe fn discard_to_zero_unsafe(
529 &self,
530 offset: u64,
531 length: u64,
532 ) -> io::Result<(u64, u64)> {
533 self.need_writable()?;
534 self.check_disk_bounds(offset, length, "discard")?;
535
536 self.ensure_fixed_mapping(GuestOffset(offset), length, FixedMapping::ZeroDiscard)
540 .await
541 .map(|(ofs, len)| (ofs.0, len))
542 }
543
544 async unsafe fn discard_to_any_unsafe(
545 &self,
546 offset: u64,
547 length: u64,
548 ) -> io::Result<(u64, u64)> {
549 unsafe { self.discard_to_zero_unsafe(offset, length).await }
551 }
552
553 async unsafe fn discard_to_backing_unsafe(
554 &self,
555 offset: u64,
556 length: u64,
557 ) -> io::Result<(u64, u64)> {
558 self.need_writable()?;
559 self.check_disk_bounds(offset, length, "discard")?;
560
561 self.ensure_fixed_mapping(GuestOffset(offset), length, FixedMapping::FullDiscard)
563 .await
564 .map(|(ofs, len)| (ofs.0, len))
565 }
566
567 async fn readv_special(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
568 let offset = GuestOffset(offset);
569 self.do_readv_special(bufv, offset).await
570 }
571
572 async fn flush(&self) -> io::Result<()> {
573 self.caches.flush_all().await?;
574 self.metadata.flush().await?;
575 if let Some(storage) = self.storage.as_ref() {
576 storage.flush().await?;
577 }
578 Ok(())
580 }
581
582 async fn sync(&self) -> io::Result<()> {
583 self.metadata.sync().await?;
584 if let Some(storage) = self.storage.as_ref() {
585 storage.sync().await?;
586 }
587 Ok(())
589 }
590
591 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
592 unsafe { self.caches.invalidate_l2() }.await?;
594 if let Some(allocator) = self.allocator.as_ref() {
595 let allocator = allocator.lock().await;
596 unsafe { allocator.invalidate_rb_cache() }.await?;
598 }
599
600 unsafe { self.metadata.invalidate_cache() }.await?;
602 if let Some(storage) = self.storage.as_ref() {
603 unsafe { storage.invalidate_cache() }.await?;
605 }
606 if let Some(backing) = self.backing.as_ref() {
607 unsafe { backing.inner().invalidate_cache() }.await?;
609 }
610
611 let new_header = Header::load(self.metadata.as_ref(), false).await?;
617 self.header.update(&new_header)?;
618
619 if let Some(allocator) = self.allocator.as_ref() {
620 *allocator.lock().await = Allocator::new(
621 Arc::clone(&self.metadata),
622 Arc::clone(&self.header),
623 Arc::clone(&self.caches),
624 )
625 .await?;
626 }
627
628 let l1_cluster = self
630 .header
631 .l1_table_offset()
632 .cluster(self.header.cluster_bits());
633
634 *self.l1_table.write().await = L1Table::load(
635 self.metadata.as_ref(),
636 &self.header,
637 l1_cluster,
638 self.header.l1_table_entries(),
639 )
640 .await?;
641
642 Ok(())
643 }
644
645 async fn resize_grow(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
646 self.need_writable()?;
647
648 let old_size = self.size();
649 let grown_length = new_size.saturating_sub(old_size);
650 if grown_length == 0 {
651 return Ok(()); }
653
654 Self::check_valid_preallocation(prealloc_mode, self.backing.is_some())?;
655
656 if let Some(data_file) = self.storage.as_ref() {
657 match prealloc_mode {
660 PreallocateMode::None => {
661 data_file
662 .resize(new_size, storage::PreallocateMode::None)
663 .await?;
664 }
665 PreallocateMode::Zero => {
666 data_file
667 .resize(new_size, storage::PreallocateMode::Zero)
668 .await?;
669 }
670 PreallocateMode::FormatAllocate
671 | PreallocateMode::FullAllocate
672 | PreallocateMode::WriteData => (),
673 }
674 }
675
676 {
682 let l1_locked = self.l1_table.write().await;
683 let l1_index =
684 GuestOffset(new_size.saturating_sub(1)).l1_index(self.header.cluster_bits());
685 let _l1_locked = self.grow_l1_table(l1_locked, l1_index).await?;
686 }
687
688 match prealloc_mode {
690 PreallocateMode::None => (),
691 PreallocateMode::Zero => self.preallocate_zero(old_size, grown_length).await?,
692 PreallocateMode::FormatAllocate => {
693 self.preallocate(old_size, grown_length, storage::PreallocateMode::Zero)
694 .await?;
695 }
696 PreallocateMode::FullAllocate => {
697 self.preallocate(old_size, grown_length, storage::PreallocateMode::Allocate)
698 .await?;
699 }
700 PreallocateMode::WriteData => {
701 self.preallocate(old_size, grown_length, storage::PreallocateMode::WriteData)
702 .await?
703 }
704 }
705
706 self.header.set_size(new_size);
710 self.header
711 .write_size(self.metadata.as_ref())
712 .await
713 .inspect_err(|_| {
714 self.header.set_size(old_size)
716 })
717 }
718
719 async fn resize_shrink(&mut self, new_size: u64) -> io::Result<()> {
720 self.need_writable()?;
721
722 let old_size = self.size();
723 if new_size >= old_size {
724 return Ok(()); }
726
727 if let Some(data_file) = self.storage.as_ref() {
728 data_file
729 .resize(new_size, storage::PreallocateMode::None)
730 .await?;
731 }
732
733 let mut offset = new_size;
734 while offset < old_size {
735 match self.discard_to_backing(offset, old_size - offset).await {
736 Ok((_, 0)) => break, Ok((dofs, dlen)) => offset = dofs + dlen,
738 Err(_) => break,
740 }
741 }
742
743 self.header.set_size(new_size);
745
746 self.header
748 .write_size(self.metadata.as_ref())
749 .await
750 .inspect_err(|_| {
751 self.header.set_size(old_size);
753 })
754 }
755}
756
757impl<S: Storage + 'static, F: WrappedFormat<S>> Debug for Qcow2<S, F> {
758 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
759 f.debug_struct("Qcow2")
760 .field("metadata", &self.metadata)
761 .field("storage_set", &self.storage_set)
762 .field("storage", &self.storage)
763 .field("backing_set", &self.backing_set)
764 .field("backing", &self.backing)
765 .finish()
766 }
767}
768
769impl<S: Storage + 'static, F: WrappedFormat<S>> Display for Qcow2<S, F> {
770 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
771 write!(f, "qcow2[{}]", self.metadata)
772 }
773}