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::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#[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 l2_cache: AsyncLruCache<HostCluster, L2Table, L2CacheBackend<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
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 pub async fn open_image(metadata: S, writable: bool) -> io::Result<Self> {
158 Self::do_open(metadata, writable, StorageOpenOptions::new()).await
159 }
160
161 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 pub fn requires_external_data_file(&self) -> bool {
183 self.header.external_data_file()
184 }
185
186 pub fn implicit_external_data_file(&self) -> Option<&String> {
192 self.header.external_data_filename()
193 }
194
195 pub fn implicit_backing_file(&self) -> Option<&String> {
197 self.header.backing_filename()
198 }
199
200 pub fn implicit_backing_format(&self) -> Option<&String> {
207 self.header.backing_format()
208 }
209
210 pub fn set_data_file(&mut self, file: Option<S>) {
215 self.storage = file;
216 self.storage_set = true;
217 }
218
219 pub fn set_backing(&mut self, backing: Option<F>) {
223 self.backing = backing;
224 self.backing_set = true;
225 }
226
227 fn storage(&self) -> &S {
232 self.storage.as_ref().unwrap_or(&self.metadata)
233 }
234
235 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 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 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 let qcow2 = Box::pin(gate.open_format(opts)).await?;
289 Ok(F::wrap(FormatAccess::new(qcow2)))
290 }
291
292 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 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 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 pub async fn open_implicit_dependencies(&mut self) -> io::Result<()> {
382 self.open_implicit_dependencies_gated(PermissiveImplicitOpenGate::default())
383 .await
384 }
385
386 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 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 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 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 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 Ok(())
553 }
554
555 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
556 unsafe { self.l2_cache.invalidate() }.await?;
558 if let Some(allocator) = self.allocator.as_ref() {
559 let allocator = allocator.lock().await;
560 unsafe { allocator.invalidate_rb_cache() }.await?;
562 }
563
564 unsafe { self.metadata.invalidate_cache() }.await?;
566 if let Some(storage) = self.storage.as_ref() {
567 unsafe { storage.invalidate_cache() }.await?;
569 }
570 if let Some(backing) = self.backing.as_ref() {
571 unsafe { backing.inner().invalidate_cache() }.await?;
573 }
574
575 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 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(()); }
613
614 if let Some(data_file) = self.storage.as_ref() {
615 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 {
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 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 self.header.set_size(old_size)
666 })?;
667
668 self.header
670 .write_size(self.metadata.as_ref())
671 .await
672 .inspect_err(|_| {
673 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(()); }
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, Ok((dofs, dlen)) => offset = dofs + dlen,
697 Err(_) => break,
699 }
700 }
701
702 self.header.set_size(new_size);
704
705 self.header
707 .write_size(self.metadata.as_ref())
708 .await
709 .inspect_err(|_| {
710 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}