• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 mod qcow_raw_file;
6 mod refcount;
7 mod vec_cache;
8 
9 use base::{
10     error, open_file, AsRawDescriptor, AsRawDescriptors, FileAllocate, FileReadWriteAtVolatile,
11     FileSetLen, FileSync, PunchHole, RawDescriptor, WriteZeroesAt,
12 };
13 use data_model::{VolatileMemory, VolatileSlice};
14 use libc::{EINVAL, ENOSPC, ENOTSUP};
15 use remain::sorted;
16 use thiserror::Error;
17 
18 use std::cmp::{max, min};
19 use std::fs::{File, OpenOptions};
20 use std::io::{self, Read, Seek, SeekFrom, Write};
21 use std::mem::size_of;
22 use std::path::Path;
23 use std::str;
24 
25 use crate::qcow::qcow_raw_file::QcowRawFile;
26 use crate::qcow::refcount::RefCount;
27 use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache};
28 use crate::{create_disk_file, DiskFile, DiskGetLen};
29 
30 #[sorted]
31 #[derive(Error, Debug)]
32 pub enum Error {
33     #[error("backing file io error: {0}")]
34     BackingFileIo(io::Error),
35     #[error("backing file open error: {0}")]
36     BackingFileOpen(Box<crate::Error>),
37     #[error("backing file name is too long: {0} bytes over")]
38     BackingFileTooLong(usize),
39     #[error("compressed blocks not supported")]
40     CompressedBlocksNotSupported,
41     #[error("failed to evict cache: {0}")]
42     EvictingCache(io::Error),
43     #[error("file larger than max of {}: {0}", MAX_QCOW_FILE_SIZE)]
44     FileTooBig(u64),
45     #[error("failed to get file size: {0}")]
46     GettingFileSize(io::Error),
47     #[error("failed to get refcount: {0}")]
48     GettingRefcount(refcount::Error),
49     #[error("failed to parse filename: {0}")]
50     InvalidBackingFileName(str::Utf8Error),
51     #[error("invalid cluster index")]
52     InvalidClusterIndex,
53     #[error("invalid cluster size")]
54     InvalidClusterSize,
55     #[error("invalid index")]
56     InvalidIndex,
57     #[error("invalid L1 table offset")]
58     InvalidL1TableOffset,
59     #[error("invalid L1 table size {0}")]
60     InvalidL1TableSize(u32),
61     #[error("invalid magic")]
62     InvalidMagic,
63     #[error("invalid offset")]
64     InvalidOffset(u64),
65     #[error("invalid refcount table offset")]
66     InvalidRefcountTableOffset,
67     #[error("invalid refcount table size: {0}")]
68     InvalidRefcountTableSize(u64),
69     #[error("no free clusters")]
70     NoFreeClusters,
71     #[error("no refcount clusters")]
72     NoRefcountClusters,
73     #[error("not enough space for refcounts")]
74     NotEnoughSpaceForRefcounts,
75     #[error("failed to open file: {0}")]
76     OpeningFile(io::Error),
77     #[error("failed to open file: {0}")]
78     ReadingHeader(io::Error),
79     #[error("failed to read pointers: {0}")]
80     ReadingPointers(io::Error),
81     #[error("failed to read ref count block: {0}")]
82     ReadingRefCountBlock(refcount::Error),
83     #[error("failed to read ref counts: {0}")]
84     ReadingRefCounts(io::Error),
85     #[error("failed to rebuild ref counts: {0}")]
86     RebuildingRefCounts(io::Error),
87     #[error("refcount table offset past file end")]
88     RefcountTableOffEnd,
89     #[error("too many clusters specified for refcount table")]
90     RefcountTableTooLarge,
91     #[error("failed to seek file: {0}")]
92     SeekingFile(io::Error),
93     #[error("failed to set refcount refcount: {0}")]
94     SettingRefcountRefcount(io::Error),
95     #[error("size too small for number of clusters")]
96     SizeTooSmallForNumberOfClusters,
97     #[error("l1 entry table too large: {0}")]
98     TooManyL1Entries(u64),
99     #[error("ref count table too large: {0}")]
100     TooManyRefcounts(u64),
101     #[error("unsupported refcount order")]
102     UnsupportedRefcountOrder,
103     #[error("unsupported version: {0}")]
104     UnsupportedVersion(u32),
105     #[error("failed to write header: {0}")]
106     WritingHeader(io::Error),
107 }
108 
109 pub type Result<T> = std::result::Result<T, Error>;
110 
111 // Maximum data size supported.
112 const MAX_QCOW_FILE_SIZE: u64 = 0x01 << 44; // 16 TB.
113 
114 // QCOW magic constant that starts the header.
115 pub const QCOW_MAGIC: u32 = 0x5146_49fb;
116 // Default to a cluster size of 2^DEFAULT_CLUSTER_BITS
117 const DEFAULT_CLUSTER_BITS: u32 = 16;
118 // Limit clusters to reasonable sizes. Choose the same limits as qemu. Making the clusters smaller
119 // increases the amount of overhead for book keeping.
120 const MIN_CLUSTER_BITS: u32 = 9;
121 const MAX_CLUSTER_BITS: u32 = 21;
122 // The L1 and RefCount table are kept in RAM, only handle files that require less than 35M entries.
123 // This easily covers 1 TB files. When support for bigger files is needed the assumptions made to
124 // keep these tables in RAM needs to be thrown out.
125 const MAX_RAM_POINTER_TABLE_SIZE: u64 = 35_000_000;
126 // Only support 2 byte refcounts, 2^refcount_order bits.
127 const DEFAULT_REFCOUNT_ORDER: u32 = 4;
128 
129 const V3_BARE_HEADER_SIZE: u32 = 104;
130 
131 // bits 0-8 and 56-63 are reserved.
132 const L1_TABLE_OFFSET_MASK: u64 = 0x00ff_ffff_ffff_fe00;
133 const L2_TABLE_OFFSET_MASK: u64 = 0x00ff_ffff_ffff_fe00;
134 // Flags
135 const COMPRESSED_FLAG: u64 = 1 << 62;
136 const CLUSTER_USED_FLAG: u64 = 1 << 63;
137 const COMPATIBLE_FEATURES_LAZY_REFCOUNTS: u64 = 1 << 0;
138 
139 // The format supports a "header extension area", that crosvm does not use.
140 const QCOW_EMPTY_HEADER_EXTENSION_SIZE: u32 = 8;
141 
142 // Defined by the specification
143 const MAX_BACKING_FILE_SIZE: u32 = 1023;
144 
145 /// Contains the information from the header of a qcow file.
146 #[derive(Clone, Debug)]
147 pub struct QcowHeader {
148     pub magic: u32,
149     pub version: u32,
150 
151     pub backing_file_offset: u64,
152     pub backing_file_size: u32,
153 
154     pub cluster_bits: u32,
155     pub size: u64,
156     pub crypt_method: u32,
157 
158     pub l1_size: u32,
159     pub l1_table_offset: u64,
160 
161     pub refcount_table_offset: u64,
162     pub refcount_table_clusters: u32,
163 
164     pub nb_snapshots: u32,
165     pub snapshots_offset: u64,
166 
167     // v3 entries
168     pub incompatible_features: u64,
169     pub compatible_features: u64,
170     pub autoclear_features: u64,
171     pub refcount_order: u32,
172     pub header_size: u32,
173 
174     // Post-header entries
175     pub backing_file_path: Option<String>,
176 }
177 
178 // Reads the next u16 from the file.
read_u16_from_file(mut f: &File) -> Result<u16>179 fn read_u16_from_file(mut f: &File) -> Result<u16> {
180     let mut value = [0u8; 2];
181     (&mut f)
182         .read_exact(&mut value)
183         .map_err(Error::ReadingHeader)?;
184     Ok(u16::from_be_bytes(value))
185 }
186 
187 // Reads the next u32 from the file.
read_u32_from_file(mut f: &File) -> Result<u32>188 fn read_u32_from_file(mut f: &File) -> Result<u32> {
189     let mut value = [0u8; 4];
190     (&mut f)
191         .read_exact(&mut value)
192         .map_err(Error::ReadingHeader)?;
193     Ok(u32::from_be_bytes(value))
194 }
195 
196 // Reads the next u64 from the file.
read_u64_from_file(mut f: &File) -> Result<u64>197 fn read_u64_from_file(mut f: &File) -> Result<u64> {
198     let mut value = [0u8; 8];
199     (&mut f)
200         .read_exact(&mut value)
201         .map_err(Error::ReadingHeader)?;
202     Ok(u64::from_be_bytes(value))
203 }
204 
205 impl QcowHeader {
206     /// Creates a QcowHeader from a reference to a file.
new(f: &mut File) -> Result<QcowHeader>207     pub fn new(f: &mut File) -> Result<QcowHeader> {
208         f.seek(SeekFrom::Start(0)).map_err(Error::ReadingHeader)?;
209 
210         let magic = read_u32_from_file(f)?;
211         if magic != QCOW_MAGIC {
212             return Err(Error::InvalidMagic);
213         }
214 
215         let mut header = QcowHeader {
216             magic,
217             version: read_u32_from_file(f)?,
218             backing_file_offset: read_u64_from_file(f)?,
219             backing_file_size: read_u32_from_file(f)?,
220             cluster_bits: read_u32_from_file(f)?,
221             size: read_u64_from_file(f)?,
222             crypt_method: read_u32_from_file(f)?,
223             l1_size: read_u32_from_file(f)?,
224             l1_table_offset: read_u64_from_file(f)?,
225             refcount_table_offset: read_u64_from_file(f)?,
226             refcount_table_clusters: read_u32_from_file(f)?,
227             nb_snapshots: read_u32_from_file(f)?,
228             snapshots_offset: read_u64_from_file(f)?,
229             incompatible_features: read_u64_from_file(f)?,
230             compatible_features: read_u64_from_file(f)?,
231             autoclear_features: read_u64_from_file(f)?,
232             refcount_order: read_u32_from_file(f)?,
233             header_size: read_u32_from_file(f)?,
234             backing_file_path: None,
235         };
236         if header.backing_file_size > MAX_BACKING_FILE_SIZE {
237             return Err(Error::BackingFileTooLong(header.backing_file_size as usize));
238         }
239         if header.backing_file_offset != 0 {
240             f.seek(SeekFrom::Start(header.backing_file_offset))
241                 .map_err(Error::ReadingHeader)?;
242             let mut backing_file_name_bytes = vec![0u8; header.backing_file_size as usize];
243             f.read_exact(&mut backing_file_name_bytes)
244                 .map_err(Error::ReadingHeader)?;
245             header.backing_file_path = Some(
246                 String::from_utf8(backing_file_name_bytes)
247                     .map_err(|err| Error::InvalidBackingFileName(err.utf8_error()))?,
248             );
249         }
250         Ok(header)
251     }
252 
create_for_size_and_path(size: u64, backing_file: Option<&str>) -> Result<QcowHeader>253     pub fn create_for_size_and_path(size: u64, backing_file: Option<&str>) -> Result<QcowHeader> {
254         let cluster_bits: u32 = DEFAULT_CLUSTER_BITS;
255         let cluster_size: u32 = 0x01 << cluster_bits;
256         let max_length: usize =
257             (cluster_size - V3_BARE_HEADER_SIZE - QCOW_EMPTY_HEADER_EXTENSION_SIZE) as usize;
258         if let Some(path) = backing_file {
259             if path.len() > max_length {
260                 return Err(Error::BackingFileTooLong(path.len() - max_length));
261             }
262         }
263         // L2 blocks are always one cluster long. They contain cluster_size/sizeof(u64) addresses.
264         let l2_size: u32 = cluster_size / size_of::<u64>() as u32;
265         let num_clusters: u32 = div_round_up_u64(size, u64::from(cluster_size)) as u32;
266         let num_l2_clusters: u32 = div_round_up_u32(num_clusters, l2_size);
267         let l1_clusters: u32 = div_round_up_u32(num_l2_clusters, cluster_size);
268         let header_clusters = div_round_up_u32(size_of::<QcowHeader>() as u32, cluster_size);
269         Ok(QcowHeader {
270             magic: QCOW_MAGIC,
271             version: 3,
272             backing_file_offset: (if backing_file.is_none() {
273                 0
274             } else {
275                 V3_BARE_HEADER_SIZE + QCOW_EMPTY_HEADER_EXTENSION_SIZE
276             }) as u64,
277             backing_file_size: backing_file.map_or(0, |x| x.len()) as u32,
278             cluster_bits: DEFAULT_CLUSTER_BITS,
279             size,
280             crypt_method: 0,
281             l1_size: num_l2_clusters,
282             l1_table_offset: u64::from(cluster_size),
283             // The refcount table is after l1 + header.
284             refcount_table_offset: u64::from(cluster_size * (l1_clusters + 1)),
285             refcount_table_clusters: {
286                 // Pre-allocate enough clusters for the entire refcount table as it must be
287                 // continuous in the file. Allocate enough space to refcount all clusters, including
288                 // the refcount clusters.
289                 let max_refcount_clusters = max_refcount_clusters(
290                     DEFAULT_REFCOUNT_ORDER,
291                     cluster_size,
292                     num_clusters + l1_clusters + num_l2_clusters + header_clusters,
293                 ) as u32;
294                 // The refcount table needs to store the offset of each refcount cluster.
295                 div_round_up_u32(
296                     max_refcount_clusters * size_of::<u64>() as u32,
297                     cluster_size,
298                 )
299             },
300             nb_snapshots: 0,
301             snapshots_offset: 0,
302             incompatible_features: 0,
303             compatible_features: 0,
304             autoclear_features: 0,
305             refcount_order: DEFAULT_REFCOUNT_ORDER,
306             header_size: V3_BARE_HEADER_SIZE,
307             backing_file_path: backing_file.map(String::from),
308         })
309     }
310 
311     /// Write the header to `file`.
write_to<F: Write + Seek>(&self, file: &mut F) -> Result<()>312     pub fn write_to<F: Write + Seek>(&self, file: &mut F) -> Result<()> {
313         // Writes the next u32 to the file.
314         fn write_u32_to_file<F: Write>(f: &mut F, value: u32) -> Result<()> {
315             f.write_all(&value.to_be_bytes())
316                 .map_err(Error::WritingHeader)
317         }
318 
319         // Writes the next u64 to the file.
320         fn write_u64_to_file<F: Write>(f: &mut F, value: u64) -> Result<()> {
321             f.write_all(&value.to_be_bytes())
322                 .map_err(Error::WritingHeader)
323         }
324 
325         write_u32_to_file(file, self.magic)?;
326         write_u32_to_file(file, self.version)?;
327         write_u64_to_file(file, self.backing_file_offset)?;
328         write_u32_to_file(file, self.backing_file_size)?;
329         write_u32_to_file(file, self.cluster_bits)?;
330         write_u64_to_file(file, self.size)?;
331         write_u32_to_file(file, self.crypt_method)?;
332         write_u32_to_file(file, self.l1_size)?;
333         write_u64_to_file(file, self.l1_table_offset)?;
334         write_u64_to_file(file, self.refcount_table_offset)?;
335         write_u32_to_file(file, self.refcount_table_clusters)?;
336         write_u32_to_file(file, self.nb_snapshots)?;
337         write_u64_to_file(file, self.snapshots_offset)?;
338         write_u64_to_file(file, self.incompatible_features)?;
339         write_u64_to_file(file, self.compatible_features)?;
340         write_u64_to_file(file, self.autoclear_features)?;
341         write_u32_to_file(file, self.refcount_order)?;
342         write_u32_to_file(file, self.header_size)?;
343         write_u32_to_file(file, 0)?; // header extension type: end of header extension area
344         write_u32_to_file(file, 0)?; // length of header extension data: 0
345         if let Some(backing_file_path) = self.backing_file_path.as_ref() {
346             write!(file, "{}", backing_file_path).map_err(Error::WritingHeader)?;
347         }
348 
349         // Set the file length by seeking and writing a zero to the last byte. This avoids needing
350         // a `File` instead of anything that implements seek as the `file` argument.
351         // Zeros out the l1 and refcount table clusters.
352         let cluster_size = 0x01u64 << self.cluster_bits;
353         let refcount_blocks_size = u64::from(self.refcount_table_clusters) * cluster_size;
354         file.seek(SeekFrom::Start(
355             self.refcount_table_offset + refcount_blocks_size - 2,
356         ))
357         .map_err(Error::WritingHeader)?;
358         file.write(&[0u8]).map_err(Error::WritingHeader)?;
359 
360         Ok(())
361     }
362 }
363 
max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u32) -> u64364 fn max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u32) -> u64 {
365     // Use u64 as the product of the u32 inputs can overflow.
366     let refcount_bytes = (0x01 << refcount_order as u64) / 8;
367     let for_data = div_round_up_u64(num_clusters as u64 * refcount_bytes, cluster_size as u64);
368     let for_refcounts = div_round_up_u64(for_data * refcount_bytes, cluster_size as u64);
369     for_data + for_refcounts
370 }
371 
372 /// Represents a qcow2 file. This is a sparse file format maintained by the qemu project.
373 /// Full documentation of the format can be found in the qemu repository.
374 ///
375 /// # Example
376 ///
377 /// ```
378 /// # use base::FileReadWriteAtVolatile;
379 /// # use data_model::VolatileSlice;
380 /// # use disk::QcowFile;
381 /// # fn test(file: std::fs::File) -> std::io::Result<()> {
382 ///     let mut q = QcowFile::from(file, disk::MAX_NESTING_DEPTH).expect("Can't open qcow file");
383 ///     let mut buf = [0u8; 12];
384 ///     let mut vslice = VolatileSlice::new(&mut buf);
385 ///     q.read_at_volatile(vslice, 10)?;
386 /// #   Ok(())
387 /// # }
388 /// ```
389 #[derive(Debug)]
390 pub struct QcowFile {
391     raw_file: QcowRawFile,
392     header: QcowHeader,
393     l1_table: VecCache<u64>,
394     l2_entries: u64,
395     l2_cache: CacheMap<VecCache<u64>>,
396     refcounts: RefCount,
397     current_offset: u64,
398     unref_clusters: Vec<u64>, // List of freshly unreferenced clusters.
399     // List of unreferenced clusters available to be used. unref clusters become available once the
400     // removal of references to them have been synced to disk.
401     avail_clusters: Vec<u64>,
402     backing_file: Option<Box<dyn DiskFile>>,
403 }
404 
405 impl QcowFile {
406     /// Creates a QcowFile from `file`. File must be a valid qcow2 image.
from(mut file: File, max_nesting_depth: u32) -> Result<QcowFile>407     pub fn from(mut file: File, max_nesting_depth: u32) -> Result<QcowFile> {
408         let header = QcowHeader::new(&mut file)?;
409 
410         // Only v3 files are supported.
411         if header.version != 3 {
412             return Err(Error::UnsupportedVersion(header.version));
413         }
414 
415         // Make sure that the L1 table fits in RAM.
416         if u64::from(header.l1_size) > MAX_RAM_POINTER_TABLE_SIZE {
417             return Err(Error::InvalidL1TableSize(header.l1_size));
418         }
419 
420         let cluster_bits: u32 = header.cluster_bits;
421         if !(MIN_CLUSTER_BITS..=MAX_CLUSTER_BITS).contains(&cluster_bits) {
422             return Err(Error::InvalidClusterSize);
423         }
424         let cluster_size = 0x01u64 << cluster_bits;
425 
426         // Limit the total size of the disk.
427         if header.size > MAX_QCOW_FILE_SIZE {
428             return Err(Error::FileTooBig(header.size));
429         }
430 
431         let backing_file = if let Some(backing_file_path) = header.backing_file_path.as_ref() {
432             let path = backing_file_path.clone();
433             let backing_raw_file = open_file(
434                 Path::new(&path),
435                 OpenOptions::new().read(true), // TODO(b/190435784): Add support for O_DIRECT.
436             )
437             .map_err(|e| Error::BackingFileIo(e.into()))?;
438             let backing_file =
439                 create_disk_file(backing_raw_file, max_nesting_depth, Path::new(&path))
440                     .map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
441             Some(backing_file)
442         } else {
443             None
444         };
445 
446         // Only support two byte refcounts.
447         let refcount_bits: u64 = 0x01u64
448             .checked_shl(header.refcount_order)
449             .ok_or(Error::UnsupportedRefcountOrder)?;
450         if refcount_bits != 16 {
451             return Err(Error::UnsupportedRefcountOrder);
452         }
453         let refcount_bytes = (refcount_bits + 7) / 8;
454 
455         // Need at least one refcount cluster
456         if header.refcount_table_clusters == 0 {
457             return Err(Error::NoRefcountClusters);
458         }
459         offset_is_cluster_boundary(header.l1_table_offset, header.cluster_bits)?;
460         offset_is_cluster_boundary(header.snapshots_offset, header.cluster_bits)?;
461         // refcount table must be a cluster boundary, and within the file's virtual or actual size.
462         offset_is_cluster_boundary(header.refcount_table_offset, header.cluster_bits)?;
463         let file_size = file.metadata().map_err(Error::GettingFileSize)?.len();
464         if header.refcount_table_offset > max(file_size, header.size) {
465             return Err(Error::RefcountTableOffEnd);
466         }
467 
468         // The first cluster should always have a non-zero refcount, so if it is 0,
469         // this is an old file with broken refcounts, which requires a rebuild.
470         let mut refcount_rebuild_required = true;
471         file.seek(SeekFrom::Start(header.refcount_table_offset))
472             .map_err(Error::SeekingFile)?;
473         let first_refblock_addr = read_u64_from_file(&file)?;
474         if first_refblock_addr != 0 {
475             file.seek(SeekFrom::Start(first_refblock_addr))
476                 .map_err(Error::SeekingFile)?;
477             let first_cluster_refcount = read_u16_from_file(&file)?;
478             if first_cluster_refcount != 0 {
479                 refcount_rebuild_required = false;
480             }
481         }
482 
483         if (header.compatible_features & COMPATIBLE_FEATURES_LAZY_REFCOUNTS) != 0 {
484             refcount_rebuild_required = true;
485         }
486 
487         let mut raw_file =
488             QcowRawFile::from(file, cluster_size).ok_or(Error::InvalidClusterSize)?;
489         if refcount_rebuild_required {
490             QcowFile::rebuild_refcounts(&mut raw_file, header.clone())?;
491         }
492 
493         let l2_size = cluster_size / size_of::<u64>() as u64;
494         let num_clusters = div_round_up_u64(header.size, cluster_size);
495         let num_l2_clusters = div_round_up_u64(num_clusters, l2_size);
496         let l1_clusters = div_round_up_u64(num_l2_clusters, cluster_size);
497         let header_clusters = div_round_up_u64(size_of::<QcowHeader>() as u64, cluster_size);
498         if num_l2_clusters > MAX_RAM_POINTER_TABLE_SIZE {
499             return Err(Error::TooManyL1Entries(num_l2_clusters));
500         }
501         let l1_table = VecCache::from_vec(
502             raw_file
503                 .read_pointer_table(
504                     header.l1_table_offset,
505                     num_l2_clusters,
506                     Some(L1_TABLE_OFFSET_MASK),
507                 )
508                 .map_err(Error::ReadingHeader)?,
509         );
510 
511         let num_clusters = div_round_up_u64(header.size, cluster_size);
512         let refcount_clusters = max_refcount_clusters(
513             header.refcount_order,
514             cluster_size as u32,
515             (num_clusters + l1_clusters + num_l2_clusters + header_clusters) as u32,
516         );
517         // Check that the given header doesn't have a suspiciously sized refcount table.
518         if u64::from(header.refcount_table_clusters) > 2 * refcount_clusters {
519             return Err(Error::RefcountTableTooLarge);
520         }
521         if l1_clusters + refcount_clusters > MAX_RAM_POINTER_TABLE_SIZE {
522             return Err(Error::TooManyRefcounts(refcount_clusters));
523         }
524         let refcount_block_entries = cluster_size / refcount_bytes;
525         let refcounts = RefCount::new(
526             &mut raw_file,
527             header.refcount_table_offset,
528             refcount_clusters,
529             refcount_block_entries,
530             cluster_size,
531         )
532         .map_err(Error::ReadingRefCounts)?;
533 
534         let l2_entries = cluster_size / size_of::<u64>() as u64;
535 
536         let mut qcow = QcowFile {
537             raw_file,
538             header,
539             l1_table,
540             l2_entries,
541             l2_cache: CacheMap::new(100),
542             refcounts,
543             current_offset: 0,
544             unref_clusters: Vec::new(),
545             avail_clusters: Vec::new(),
546             backing_file,
547         };
548 
549         // Check that the L1 and refcount tables fit in a 64bit address space.
550         qcow.header
551             .l1_table_offset
552             .checked_add(qcow.l1_address_offset(qcow.virtual_size()))
553             .ok_or(Error::InvalidL1TableOffset)?;
554         qcow.header
555             .refcount_table_offset
556             .checked_add(u64::from(qcow.header.refcount_table_clusters) * cluster_size)
557             .ok_or(Error::InvalidRefcountTableOffset)?;
558 
559         qcow.find_avail_clusters()?;
560 
561         Ok(qcow)
562     }
563 
564     /// Creates a new QcowFile at the given path.
new(file: File, virtual_size: u64) -> Result<QcowFile>565     pub fn new(file: File, virtual_size: u64) -> Result<QcowFile> {
566         let header = QcowHeader::create_for_size_and_path(virtual_size, None)?;
567         QcowFile::new_from_header(file, header, 1)
568     }
569 
570     /// Creates a new QcowFile at the given path.
new_from_backing( file: File, backing_file_name: &str, backing_file_max_nesting_depth: u32, ) -> Result<QcowFile>571     pub fn new_from_backing(
572         file: File,
573         backing_file_name: &str,
574         backing_file_max_nesting_depth: u32,
575     ) -> Result<QcowFile> {
576         let backing_path = Path::new(backing_file_name);
577         let backing_raw_file = open_file(
578             backing_path,
579             OpenOptions::new().read(true), // TODO(b/190435784): add support for O_DIRECT.
580         )
581         .map_err(|e| Error::BackingFileIo(e.into()))?;
582         let backing_file = create_disk_file(
583             backing_raw_file,
584             backing_file_max_nesting_depth,
585             backing_path,
586         )
587         .map_err(|e| Error::BackingFileOpen(Box::new(e)))?;
588         let size = backing_file.get_len().map_err(Error::BackingFileIo)?;
589         let header = QcowHeader::create_for_size_and_path(size, Some(backing_file_name))?;
590         let mut result = QcowFile::new_from_header(file, header, backing_file_max_nesting_depth)?;
591         result.backing_file = Some(backing_file);
592         Ok(result)
593     }
594 
new_from_header( mut file: File, header: QcowHeader, max_nesting_depth: u32, ) -> Result<QcowFile>595     fn new_from_header(
596         mut file: File,
597         header: QcowHeader,
598         max_nesting_depth: u32,
599     ) -> Result<QcowFile> {
600         file.seek(SeekFrom::Start(0)).map_err(Error::SeekingFile)?;
601         header.write_to(&mut file)?;
602 
603         let mut qcow = Self::from(file, max_nesting_depth)?;
604 
605         // Set the refcount for each refcount table cluster.
606         let cluster_size = 0x01u64 << qcow.header.cluster_bits;
607         let refcount_table_base = qcow.header.refcount_table_offset as u64;
608         let end_cluster_addr =
609             refcount_table_base + u64::from(qcow.header.refcount_table_clusters) * cluster_size;
610 
611         let mut cluster_addr = 0;
612         while cluster_addr < end_cluster_addr {
613             let mut unref_clusters = qcow
614                 .set_cluster_refcount(cluster_addr, 1)
615                 .map_err(Error::SettingRefcountRefcount)?;
616             qcow.unref_clusters.append(&mut unref_clusters);
617             cluster_addr += cluster_size;
618         }
619 
620         Ok(qcow)
621     }
622 
set_backing_file(&mut self, backing: Option<Box<dyn DiskFile>>)623     pub fn set_backing_file(&mut self, backing: Option<Box<dyn DiskFile>>) {
624         self.backing_file = backing;
625     }
626 
627     /// Returns the first cluster in the file with a 0 refcount. Used for testing.
first_zero_refcount(&mut self) -> Result<Option<u64>>628     pub fn first_zero_refcount(&mut self) -> Result<Option<u64>> {
629         let file_size = self
630             .raw_file
631             .file_mut()
632             .metadata()
633             .map_err(Error::GettingFileSize)?
634             .len();
635         let cluster_size = 0x01u64 << self.header.cluster_bits;
636 
637         let mut cluster_addr = 0;
638         while cluster_addr < file_size {
639             let cluster_refcount = self
640                 .refcounts
641                 .get_cluster_refcount(&mut self.raw_file, cluster_addr)
642                 .map_err(Error::GettingRefcount)?;
643             if cluster_refcount == 0 {
644                 return Ok(Some(cluster_addr));
645             }
646             cluster_addr += cluster_size;
647         }
648         Ok(None)
649     }
650 
find_avail_clusters(&mut self) -> Result<()>651     fn find_avail_clusters(&mut self) -> Result<()> {
652         let cluster_size = self.raw_file.cluster_size();
653 
654         let file_size = self
655             .raw_file
656             .file_mut()
657             .metadata()
658             .map_err(Error::GettingFileSize)?
659             .len();
660 
661         for i in (0..file_size).step_by(cluster_size as usize) {
662             let refcount = self
663                 .refcounts
664                 .get_cluster_refcount(&mut self.raw_file, i)
665                 .map_err(Error::GettingRefcount)?;
666             if refcount == 0 {
667                 self.avail_clusters.push(i);
668             }
669         }
670 
671         Ok(())
672     }
673 
674     /// Rebuild the reference count tables.
rebuild_refcounts(raw_file: &mut QcowRawFile, header: QcowHeader) -> Result<()>675     fn rebuild_refcounts(raw_file: &mut QcowRawFile, header: QcowHeader) -> Result<()> {
676         fn add_ref(refcounts: &mut [u16], cluster_size: u64, cluster_address: u64) -> Result<()> {
677             let idx = (cluster_address / cluster_size) as usize;
678             if idx >= refcounts.len() {
679                 return Err(Error::InvalidClusterIndex);
680             }
681             refcounts[idx] += 1;
682             Ok(())
683         }
684 
685         // Add a reference to the first cluster (header plus extensions).
686         fn set_header_refcount(refcounts: &mut [u16], cluster_size: u64) -> Result<()> {
687             add_ref(refcounts, cluster_size, 0)
688         }
689 
690         // Add references to the L1 table clusters.
691         fn set_l1_refcounts(
692             refcounts: &mut [u16],
693             header: QcowHeader,
694             cluster_size: u64,
695         ) -> Result<()> {
696             let l1_clusters = div_round_up_u64(header.l1_size as u64, cluster_size);
697             let l1_table_offset = header.l1_table_offset;
698             for i in 0..l1_clusters {
699                 add_ref(refcounts, cluster_size, l1_table_offset + i * cluster_size)?;
700             }
701             Ok(())
702         }
703 
704         // Traverse the L1 and L2 tables to find all reachable data clusters.
705         fn set_data_refcounts(
706             refcounts: &mut [u16],
707             header: QcowHeader,
708             cluster_size: u64,
709             raw_file: &mut QcowRawFile,
710         ) -> Result<()> {
711             let l1_table = raw_file
712                 .read_pointer_table(
713                     header.l1_table_offset,
714                     header.l1_size as u64,
715                     Some(L1_TABLE_OFFSET_MASK),
716                 )
717                 .map_err(Error::ReadingPointers)?;
718             for l1_index in 0..header.l1_size as usize {
719                 let l2_addr_disk = *l1_table.get(l1_index).ok_or(Error::InvalidIndex)?;
720                 if l2_addr_disk != 0 {
721                     // Add a reference to the L2 table cluster itself.
722                     add_ref(refcounts, cluster_size, l2_addr_disk)?;
723 
724                     // Read the L2 table and find all referenced data clusters.
725                     let l2_table = raw_file
726                         .read_pointer_table(
727                             l2_addr_disk,
728                             cluster_size / size_of::<u64>() as u64,
729                             Some(L2_TABLE_OFFSET_MASK),
730                         )
731                         .map_err(Error::ReadingPointers)?;
732                     for data_cluster_addr in l2_table {
733                         if data_cluster_addr != 0 {
734                             add_ref(refcounts, cluster_size, data_cluster_addr)?;
735                         }
736                     }
737                 }
738             }
739 
740             Ok(())
741         }
742 
743         // Add references to the top-level refcount table clusters.
744         fn set_refcount_table_refcounts(
745             refcounts: &mut [u16],
746             header: QcowHeader,
747             cluster_size: u64,
748         ) -> Result<()> {
749             let refcount_table_offset = header.refcount_table_offset;
750             for i in 0..header.refcount_table_clusters as u64 {
751                 add_ref(
752                     refcounts,
753                     cluster_size,
754                     refcount_table_offset + i * cluster_size,
755                 )?;
756             }
757             Ok(())
758         }
759 
760         // Allocate clusters for refblocks.
761         // This needs to be done last so that we have the correct refcounts for all other
762         // clusters.
763         fn alloc_refblocks(
764             refcounts: &mut [u16],
765             cluster_size: u64,
766             refblock_clusters: u64,
767             pointers_per_cluster: u64,
768         ) -> Result<Vec<u64>> {
769             let refcount_table_entries = div_round_up_u64(refblock_clusters, pointers_per_cluster);
770             let mut ref_table = vec![0; refcount_table_entries as usize];
771             let mut first_free_cluster: u64 = 0;
772             for refblock_addr in &mut ref_table {
773                 loop {
774                     if first_free_cluster >= refcounts.len() as u64 {
775                         return Err(Error::NotEnoughSpaceForRefcounts);
776                     }
777                     if refcounts[first_free_cluster as usize] == 0 {
778                         break;
779                     }
780                     first_free_cluster += 1;
781                 }
782 
783                 *refblock_addr = first_free_cluster * cluster_size;
784                 add_ref(refcounts, cluster_size, *refblock_addr)?;
785 
786                 first_free_cluster += 1;
787             }
788 
789             Ok(ref_table)
790         }
791 
792         // Write the updated reference count blocks and reftable.
793         fn write_refblocks(
794             refcounts: &[u16],
795             mut header: QcowHeader,
796             ref_table: &[u64],
797             raw_file: &mut QcowRawFile,
798             refcount_block_entries: u64,
799         ) -> Result<()> {
800             // Rewrite the header with lazy refcounts enabled while we are rebuilding the tables.
801             header.compatible_features |= COMPATIBLE_FEATURES_LAZY_REFCOUNTS;
802             raw_file
803                 .file_mut()
804                 .seek(SeekFrom::Start(0))
805                 .map_err(Error::SeekingFile)?;
806             header.write_to(raw_file.file_mut())?;
807 
808             for (i, refblock_addr) in ref_table.iter().enumerate() {
809                 // Write a block of refcounts to the location indicated by refblock_addr.
810                 let refblock_start = i * (refcount_block_entries as usize);
811                 let refblock_end = min(
812                     refcounts.len(),
813                     refblock_start + refcount_block_entries as usize,
814                 );
815                 let refblock = &refcounts[refblock_start..refblock_end];
816                 raw_file
817                     .write_refcount_block(*refblock_addr, refblock)
818                     .map_err(Error::WritingHeader)?;
819 
820                 // If this is the last (partial) cluster, pad it out to a full refblock cluster.
821                 if refblock.len() < refcount_block_entries as usize {
822                     let refblock_padding =
823                         vec![0u16; refcount_block_entries as usize - refblock.len()];
824                     raw_file
825                         .write_refcount_block(
826                             *refblock_addr + refblock.len() as u64 * 2,
827                             &refblock_padding,
828                         )
829                         .map_err(Error::WritingHeader)?;
830                 }
831             }
832 
833             // Rewrite the top-level refcount table.
834             raw_file
835                 .write_pointer_table(header.refcount_table_offset, ref_table, 0)
836                 .map_err(Error::WritingHeader)?;
837 
838             // Rewrite the header again, now with lazy refcounts disabled.
839             header.compatible_features &= !COMPATIBLE_FEATURES_LAZY_REFCOUNTS;
840             raw_file
841                 .file_mut()
842                 .seek(SeekFrom::Start(0))
843                 .map_err(Error::SeekingFile)?;
844             header.write_to(raw_file.file_mut())?;
845 
846             Ok(())
847         }
848 
849         let cluster_size = raw_file.cluster_size();
850 
851         let file_size = raw_file
852             .file_mut()
853             .metadata()
854             .map_err(Error::GettingFileSize)?
855             .len();
856 
857         let refcount_bits = 1u64 << header.refcount_order;
858         let refcount_bytes = div_round_up_u64(refcount_bits, 8);
859         let refcount_block_entries = cluster_size / refcount_bytes;
860         let pointers_per_cluster = cluster_size / size_of::<u64>() as u64;
861         let data_clusters = div_round_up_u64(header.size, cluster_size);
862         let l2_clusters = div_round_up_u64(data_clusters, pointers_per_cluster);
863         let l1_clusters = div_round_up_u64(l2_clusters, cluster_size);
864         let header_clusters = div_round_up_u64(size_of::<QcowHeader>() as u64, cluster_size);
865         let max_clusters = data_clusters + l2_clusters + l1_clusters + header_clusters;
866         let mut max_valid_cluster_index = max_clusters;
867         let refblock_clusters = div_round_up_u64(max_valid_cluster_index, refcount_block_entries);
868         let reftable_clusters = div_round_up_u64(refblock_clusters, pointers_per_cluster);
869         // Account for refblocks and the ref table size needed to address them.
870         let refblocks_for_refs = div_round_up_u64(
871             refblock_clusters + reftable_clusters,
872             refcount_block_entries,
873         );
874         let reftable_clusters_for_refs =
875             div_round_up_u64(refblocks_for_refs, refcount_block_entries);
876         max_valid_cluster_index += refblock_clusters + reftable_clusters;
877         max_valid_cluster_index += refblocks_for_refs + reftable_clusters_for_refs;
878 
879         if max_valid_cluster_index > MAX_RAM_POINTER_TABLE_SIZE {
880             return Err(Error::InvalidRefcountTableSize(max_valid_cluster_index));
881         }
882 
883         let max_valid_cluster_offset = max_valid_cluster_index * cluster_size;
884         if max_valid_cluster_offset < file_size - cluster_size {
885             return Err(Error::InvalidRefcountTableSize(max_valid_cluster_offset));
886         }
887 
888         let mut refcounts = vec![0; max_valid_cluster_index as usize];
889 
890         // Find all references clusters and rebuild refcounts.
891         set_header_refcount(&mut refcounts, cluster_size)?;
892         set_l1_refcounts(&mut refcounts, header.clone(), cluster_size)?;
893         set_data_refcounts(&mut refcounts, header.clone(), cluster_size, raw_file)?;
894         set_refcount_table_refcounts(&mut refcounts, header.clone(), cluster_size)?;
895 
896         // Allocate clusters to store the new reference count blocks.
897         let ref_table = alloc_refblocks(
898             &mut refcounts,
899             cluster_size,
900             refblock_clusters,
901             pointers_per_cluster,
902         )?;
903 
904         // Write updated reference counts and point the reftable at them.
905         write_refblocks(
906             &refcounts,
907             header,
908             &ref_table,
909             raw_file,
910             refcount_block_entries,
911         )
912     }
913 
914     // Limits the range so that it doesn't exceed the virtual size of the file.
limit_range_file(&self, address: u64, count: usize) -> usize915     fn limit_range_file(&self, address: u64, count: usize) -> usize {
916         if address.checked_add(count as u64).is_none() || address > self.virtual_size() {
917             return 0;
918         }
919         min(count as u64, self.virtual_size() - address) as usize
920     }
921 
922     // Limits the range so that it doesn't overflow the end of a cluster.
limit_range_cluster(&self, address: u64, count: usize) -> usize923     fn limit_range_cluster(&self, address: u64, count: usize) -> usize {
924         let offset: u64 = self.raw_file.cluster_offset(address);
925         let limit = self.raw_file.cluster_size() - offset;
926         min(count as u64, limit) as usize
927     }
928 
929     // Gets the maximum virtual size of this image.
virtual_size(&self) -> u64930     fn virtual_size(&self) -> u64 {
931         self.header.size
932     }
933 
934     // Gets the offset of `address` in the L1 table.
l1_address_offset(&self, address: u64) -> u64935     fn l1_address_offset(&self, address: u64) -> u64 {
936         let l1_index = self.l1_table_index(address);
937         l1_index * size_of::<u64>() as u64
938     }
939 
940     // Gets the offset of `address` in the L1 table.
l1_table_index(&self, address: u64) -> u64941     fn l1_table_index(&self, address: u64) -> u64 {
942         (address / self.raw_file.cluster_size()) / self.l2_entries
943     }
944 
945     // Gets the offset of `address` in the L2 table.
l2_table_index(&self, address: u64) -> u64946     fn l2_table_index(&self, address: u64) -> u64 {
947         (address / self.raw_file.cluster_size()) % self.l2_entries
948     }
949 
950     // Gets the offset of the given guest address in the host file. If L1, L2, or data clusters have
951     // yet to be allocated, return None.
file_offset_read(&mut self, address: u64) -> std::io::Result<Option<u64>>952     fn file_offset_read(&mut self, address: u64) -> std::io::Result<Option<u64>> {
953         if address >= self.virtual_size() as u64 {
954             return Err(std::io::Error::from_raw_os_error(EINVAL));
955         }
956 
957         let l1_index = self.l1_table_index(address) as usize;
958         let l2_addr_disk = *self
959             .l1_table
960             .get(l1_index)
961             .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
962 
963         if l2_addr_disk == 0 {
964             // Reading from an unallocated cluster will return zeros.
965             return Ok(None);
966         }
967 
968         let l2_index = self.l2_table_index(address) as usize;
969 
970         if !self.l2_cache.contains_key(&l1_index) {
971             // Not in the cache.
972             let table =
973                 VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
974 
975             let l1_table = &self.l1_table;
976             let raw_file = &mut self.raw_file;
977             self.l2_cache.insert(l1_index, table, |index, evicted| {
978                 raw_file.write_pointer_table(
979                     l1_table[index],
980                     evicted.get_values(),
981                     CLUSTER_USED_FLAG,
982                 )
983             })?;
984         };
985 
986         let cluster_addr = self.l2_cache.get(&l1_index).unwrap()[l2_index];
987         if cluster_addr == 0 {
988             return Ok(None);
989         }
990         Ok(Some(cluster_addr + self.raw_file.cluster_offset(address)))
991     }
992 
993     // Gets the offset of the given guest address in the host file. If L1, L2, or data clusters need
994     // to be allocated, they will be.
file_offset_write(&mut self, address: u64) -> std::io::Result<u64>995     fn file_offset_write(&mut self, address: u64) -> std::io::Result<u64> {
996         if address >= self.virtual_size() as u64 {
997             return Err(std::io::Error::from_raw_os_error(EINVAL));
998         }
999 
1000         let l1_index = self.l1_table_index(address) as usize;
1001         let l2_addr_disk = *self
1002             .l1_table
1003             .get(l1_index)
1004             .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
1005         let l2_index = self.l2_table_index(address) as usize;
1006 
1007         let mut set_refcounts = Vec::new();
1008 
1009         if !self.l2_cache.contains_key(&l1_index) {
1010             // Not in the cache.
1011             let l2_table = if l2_addr_disk == 0 {
1012                 // Allocate a new cluster to store the L2 table and update the L1 table to point
1013                 // to the new table.
1014                 let new_addr: u64 = self.get_new_cluster(None)?;
1015                 // The cluster refcount starts at one meaning it is used but doesn't need COW.
1016                 set_refcounts.push((new_addr, 1));
1017                 self.l1_table[l1_index] = new_addr;
1018                 VecCache::new(self.l2_entries as usize)
1019             } else {
1020                 VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?)
1021             };
1022             let l1_table = &self.l1_table;
1023             let raw_file = &mut self.raw_file;
1024             self.l2_cache.insert(l1_index, l2_table, |index, evicted| {
1025                 raw_file.write_pointer_table(
1026                     l1_table[index],
1027                     evicted.get_values(),
1028                     CLUSTER_USED_FLAG,
1029                 )
1030             })?;
1031         }
1032 
1033         let cluster_addr = match self.l2_cache.get(&l1_index).unwrap()[l2_index] {
1034             0 => {
1035                 let initial_data = if let Some(backing) = self.backing_file.as_mut() {
1036                     let cluster_size = self.raw_file.cluster_size();
1037                     let cluster_begin = address - (address % cluster_size);
1038                     let mut cluster_data = vec![0u8; cluster_size as usize];
1039                     let volatile_slice = VolatileSlice::new(&mut cluster_data);
1040                     backing.read_exact_at_volatile(volatile_slice, cluster_begin)?;
1041                     Some(cluster_data)
1042                 } else {
1043                     None
1044                 };
1045                 // Need to allocate a data cluster
1046                 let cluster_addr = self.append_data_cluster(initial_data)?;
1047                 self.update_cluster_addr(l1_index, l2_index, cluster_addr, &mut set_refcounts)?;
1048                 cluster_addr
1049             }
1050             a => a,
1051         };
1052 
1053         for (addr, count) in set_refcounts {
1054             let mut newly_unref = self.set_cluster_refcount(addr, count)?;
1055             self.unref_clusters.append(&mut newly_unref);
1056         }
1057 
1058         Ok(cluster_addr + self.raw_file.cluster_offset(address))
1059     }
1060 
1061     // Updates the l1 and l2 tables to point to the new `cluster_addr`.
update_cluster_addr( &mut self, l1_index: usize, l2_index: usize, cluster_addr: u64, set_refcounts: &mut Vec<(u64, u16)>, ) -> io::Result<()>1062     fn update_cluster_addr(
1063         &mut self,
1064         l1_index: usize,
1065         l2_index: usize,
1066         cluster_addr: u64,
1067         set_refcounts: &mut Vec<(u64, u16)>,
1068     ) -> io::Result<()> {
1069         if !self.l2_cache.get(&l1_index).unwrap().dirty() {
1070             // Free the previously used cluster if one exists. Modified tables are always
1071             // witten to new clusters so the L1 table can be committed to disk after they
1072             // are and L1 never points at an invalid table.
1073             // The index must be valid from when it was insterted.
1074             let addr = self.l1_table[l1_index];
1075             if addr != 0 {
1076                 self.unref_clusters.push(addr);
1077                 set_refcounts.push((addr, 0));
1078             }
1079 
1080             // Allocate a new cluster to store the L2 table and update the L1 table to point
1081             // to the new table. The cluster will be written when the cache is flushed, no
1082             // need to copy the data now.
1083             let new_addr: u64 = self.get_new_cluster(None)?;
1084             // The cluster refcount starts at one indicating it is used but doesn't need
1085             // COW.
1086             set_refcounts.push((new_addr, 1));
1087             self.l1_table[l1_index] = new_addr;
1088         }
1089         // 'unwrap' is OK because it was just added.
1090         self.l2_cache.get_mut(&l1_index).unwrap()[l2_index] = cluster_addr;
1091         Ok(())
1092     }
1093 
1094     // Allocate a new cluster and return its offset within the raw file.
get_new_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64>1095     fn get_new_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64> {
1096         // First use a pre allocated cluster if one is available.
1097         if let Some(free_cluster) = self.avail_clusters.pop() {
1098             if let Some(initial_data) = initial_data {
1099                 self.raw_file.write_cluster(free_cluster, initial_data)?;
1100             } else {
1101                 self.raw_file.zero_cluster(free_cluster)?;
1102             }
1103             return Ok(free_cluster);
1104         }
1105 
1106         let max_valid_cluster_offset = self.refcounts.max_valid_cluster_offset();
1107         if let Some(new_cluster) = self.raw_file.add_cluster_end(max_valid_cluster_offset)? {
1108             if let Some(initial_data) = initial_data {
1109                 self.raw_file.write_cluster(new_cluster, initial_data)?;
1110             }
1111             Ok(new_cluster)
1112         } else {
1113             error!("No free clusters in get_new_cluster()");
1114             Err(std::io::Error::from_raw_os_error(ENOSPC))
1115         }
1116     }
1117 
1118     // Allocate and initialize a new data cluster. Returns the offset of the
1119     // cluster in to the file on success.
append_data_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64>1120     fn append_data_cluster(&mut self, initial_data: Option<Vec<u8>>) -> std::io::Result<u64> {
1121         let new_addr: u64 = self.get_new_cluster(initial_data)?;
1122         // The cluster refcount starts at one indicating it is used but doesn't need COW.
1123         let mut newly_unref = self.set_cluster_refcount(new_addr, 1)?;
1124         self.unref_clusters.append(&mut newly_unref);
1125         Ok(new_addr)
1126     }
1127 
1128     // Deallocate the storage for the cluster starting at `address`.
1129     // Any future reads of this cluster will return all zeroes (or the backing file, if in use).
deallocate_cluster(&mut self, address: u64) -> std::io::Result<()>1130     fn deallocate_cluster(&mut self, address: u64) -> std::io::Result<()> {
1131         if address >= self.virtual_size() as u64 {
1132             return Err(std::io::Error::from_raw_os_error(EINVAL));
1133         }
1134 
1135         let l1_index = self.l1_table_index(address) as usize;
1136         let l2_addr_disk = *self
1137             .l1_table
1138             .get(l1_index)
1139             .ok_or_else(|| std::io::Error::from_raw_os_error(EINVAL))?;
1140         let l2_index = self.l2_table_index(address) as usize;
1141 
1142         if l2_addr_disk == 0 {
1143             // The whole L2 table for this address is not allocated yet,
1144             // so the cluster must also be unallocated.
1145             return Ok(());
1146         }
1147 
1148         if !self.l2_cache.contains_key(&l1_index) {
1149             // Not in the cache.
1150             let table =
1151                 VecCache::from_vec(Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk)?);
1152             let l1_table = &self.l1_table;
1153             let raw_file = &mut self.raw_file;
1154             self.l2_cache.insert(l1_index, table, |index, evicted| {
1155                 raw_file.write_pointer_table(
1156                     l1_table[index],
1157                     evicted.get_values(),
1158                     CLUSTER_USED_FLAG,
1159                 )
1160             })?;
1161         }
1162 
1163         let cluster_addr = self.l2_cache.get(&l1_index).unwrap()[l2_index];
1164         if cluster_addr == 0 {
1165             // This cluster is already unallocated; nothing to do.
1166             return Ok(());
1167         }
1168 
1169         // Decrement the refcount.
1170         let refcount = self
1171             .refcounts
1172             .get_cluster_refcount(&mut self.raw_file, cluster_addr)
1173             .map_err(|_| std::io::Error::from_raw_os_error(EINVAL))?;
1174         if refcount == 0 {
1175             return Err(std::io::Error::from_raw_os_error(EINVAL));
1176         }
1177 
1178         let new_refcount = refcount - 1;
1179         let mut newly_unref = self.set_cluster_refcount(cluster_addr, new_refcount)?;
1180         self.unref_clusters.append(&mut newly_unref);
1181 
1182         // Rewrite the L2 entry to remove the cluster mapping.
1183         // unwrap is safe as we just checked/inserted this entry.
1184         self.l2_cache.get_mut(&l1_index).unwrap()[l2_index] = 0;
1185 
1186         if new_refcount == 0 {
1187             let cluster_size = self.raw_file.cluster_size();
1188             // This cluster is no longer in use; deallocate the storage.
1189             // The underlying FS may not support FALLOC_FL_PUNCH_HOLE,
1190             // so don't treat an error as fatal.  Future reads will return zeros anyways.
1191             let _ = self
1192                 .raw_file
1193                 .file_mut()
1194                 .punch_hole(cluster_addr, cluster_size);
1195             self.unref_clusters.push(cluster_addr);
1196         }
1197         Ok(())
1198     }
1199 
1200     // Fill a range of `length` bytes starting at `address` with zeroes.
1201     // Any future reads of this range will return all zeroes.
1202     // If there is no backing file, this will deallocate cluster storage when possible.
zero_bytes(&mut self, address: u64, length: usize) -> std::io::Result<()>1203     fn zero_bytes(&mut self, address: u64, length: usize) -> std::io::Result<()> {
1204         let write_count: usize = self.limit_range_file(address, length);
1205 
1206         let mut nwritten: usize = 0;
1207         while nwritten < write_count {
1208             let curr_addr = address + nwritten as u64;
1209             let count = self.limit_range_cluster(curr_addr, write_count - nwritten);
1210 
1211             if self.backing_file.is_none() && count == self.raw_file.cluster_size() as usize {
1212                 // Full cluster and no backing file in use - deallocate the storage.
1213                 self.deallocate_cluster(curr_addr)?;
1214             } else {
1215                 // Partial cluster - zero out the relevant bytes.
1216                 let offset = if self.backing_file.is_some() {
1217                     // There is a backing file, so we need to allocate a cluster in order to
1218                     // zero out the hole-punched bytes such that the backing file contents do not
1219                     // show through.
1220                     Some(self.file_offset_write(curr_addr)?)
1221                 } else {
1222                     // Any space in unallocated clusters can be left alone, since
1223                     // unallocated clusters already read back as zeroes.
1224                     self.file_offset_read(curr_addr)?
1225                 };
1226                 if let Some(offset) = offset {
1227                     // Partial cluster - zero it out.
1228                     self.raw_file
1229                         .file_mut()
1230                         .write_zeroes_all_at(offset, count)?;
1231                 }
1232             }
1233 
1234             nwritten += count;
1235         }
1236         Ok(())
1237     }
1238 
1239     // Reads an L2 cluster from the disk, returning an error if the file can't be read or if any
1240     // cluster is compressed.
read_l2_cluster(raw_file: &mut QcowRawFile, cluster_addr: u64) -> std::io::Result<Vec<u64>>1241     fn read_l2_cluster(raw_file: &mut QcowRawFile, cluster_addr: u64) -> std::io::Result<Vec<u64>> {
1242         let file_values = raw_file.read_pointer_cluster(cluster_addr, None)?;
1243         if file_values.iter().any(|entry| entry & COMPRESSED_FLAG != 0) {
1244             return Err(std::io::Error::from_raw_os_error(ENOTSUP));
1245         }
1246         Ok(file_values
1247             .iter()
1248             .map(|entry| *entry & L2_TABLE_OFFSET_MASK)
1249             .collect())
1250     }
1251 
1252     // Set the refcount for a cluster with the given address.
1253     // Returns a list of any refblocks that can be reused, this happens when a refblock is moved,
1254     // the old location can be reused.
set_cluster_refcount(&mut self, address: u64, refcount: u16) -> std::io::Result<Vec<u64>>1255     fn set_cluster_refcount(&mut self, address: u64, refcount: u16) -> std::io::Result<Vec<u64>> {
1256         let mut added_clusters = Vec::new();
1257         let mut unref_clusters = Vec::new();
1258         let mut refcount_set = false;
1259         let mut new_cluster = None;
1260 
1261         while !refcount_set {
1262             match self.refcounts.set_cluster_refcount(
1263                 &mut self.raw_file,
1264                 address,
1265                 refcount,
1266                 new_cluster.take(),
1267             ) {
1268                 Ok(None) => {
1269                     refcount_set = true;
1270                 }
1271                 Ok(Some(freed_cluster)) => {
1272                     unref_clusters.push(freed_cluster);
1273                     refcount_set = true;
1274                 }
1275                 Err(refcount::Error::EvictingRefCounts(e)) => {
1276                     return Err(e);
1277                 }
1278                 Err(refcount::Error::InvalidIndex) => {
1279                     return Err(std::io::Error::from_raw_os_error(EINVAL));
1280                 }
1281                 Err(refcount::Error::NeedCluster(addr)) => {
1282                     // Read the address and call set_cluster_refcount again.
1283                     new_cluster = Some((
1284                         addr,
1285                         VecCache::from_vec(self.raw_file.read_refcount_block(addr)?),
1286                     ));
1287                 }
1288                 Err(refcount::Error::NeedNewCluster) => {
1289                     // Allocate the cluster and call set_cluster_refcount again.
1290                     let addr = self.get_new_cluster(None)?;
1291                     added_clusters.push(addr);
1292                     new_cluster = Some((
1293                         addr,
1294                         VecCache::new(self.refcounts.refcounts_per_block() as usize),
1295                     ));
1296                 }
1297                 Err(refcount::Error::ReadingRefCounts(e)) => {
1298                     return Err(e);
1299                 }
1300             }
1301         }
1302 
1303         for addr in added_clusters {
1304             self.set_cluster_refcount(addr, 1)?;
1305         }
1306         Ok(unref_clusters)
1307     }
1308 
sync_caches(&mut self) -> std::io::Result<()>1309     fn sync_caches(&mut self) -> std::io::Result<()> {
1310         // Write out all dirty L2 tables.
1311         for (l1_index, l2_table) in self.l2_cache.iter_mut().filter(|(_k, v)| v.dirty()) {
1312             // The index must be valid from when we insterted it.
1313             let addr = self.l1_table[*l1_index];
1314             if addr != 0 {
1315                 self.raw_file.write_pointer_table(
1316                     addr,
1317                     l2_table.get_values(),
1318                     CLUSTER_USED_FLAG,
1319                 )?;
1320             } else {
1321                 return Err(std::io::Error::from_raw_os_error(EINVAL));
1322             }
1323             l2_table.mark_clean();
1324         }
1325         // Write the modified refcount blocks.
1326         self.refcounts.flush_blocks(&mut self.raw_file)?;
1327         // Make sure metadata(file len) and all data clusters are written.
1328         self.raw_file.file_mut().sync_all()?;
1329 
1330         // Push L1 table and refcount table last as all the clusters they point to are now
1331         // guaranteed to be valid.
1332         let mut sync_required = false;
1333         if self.l1_table.dirty() {
1334             self.raw_file.write_pointer_table(
1335                 self.header.l1_table_offset,
1336                 self.l1_table.get_values(),
1337                 0,
1338             )?;
1339             self.l1_table.mark_clean();
1340             sync_required = true;
1341         }
1342         sync_required |= self.refcounts.flush_table(&mut self.raw_file)?;
1343         if sync_required {
1344             self.raw_file.file_mut().sync_data()?;
1345         }
1346         Ok(())
1347     }
1348 
1349     // Reads `count` bytes starting at `address`, calling `cb` repeatedly with the data source,
1350     // number of bytes read so far, offset to read from, and number of bytes to read from the file
1351     // in that invocation. If None is given to `cb` in place of the backing file, the `cb` should
1352     // infer zeros would have been read.
read_cb<F>(&mut self, address: u64, count: usize, mut cb: F) -> std::io::Result<usize> where F: FnMut(Option<&mut dyn DiskFile>, usize, u64, usize) -> std::io::Result<()>,1353     fn read_cb<F>(&mut self, address: u64, count: usize, mut cb: F) -> std::io::Result<usize>
1354     where
1355         F: FnMut(Option<&mut dyn DiskFile>, usize, u64, usize) -> std::io::Result<()>,
1356     {
1357         let read_count: usize = self.limit_range_file(address, count);
1358 
1359         let mut nread: usize = 0;
1360         while nread < read_count {
1361             let curr_addr = address + nread as u64;
1362             let file_offset = self.file_offset_read(curr_addr)?;
1363             let count = self.limit_range_cluster(curr_addr, read_count - nread);
1364 
1365             if let Some(offset) = file_offset {
1366                 cb(Some(self.raw_file.file_mut()), nread, offset, count)?;
1367             } else if let Some(backing) = self.backing_file.as_mut() {
1368                 cb(Some(backing.as_mut()), nread, curr_addr, count)?;
1369             } else {
1370                 cb(None, nread, 0, count)?;
1371             }
1372 
1373             nread += count;
1374         }
1375         Ok(read_count)
1376     }
1377 
1378     // Writes `count` bytes starting at `address`, calling `cb` repeatedly with the backing file,
1379     // number of bytes written so far, raw file offset, and number of bytes to write to the file in
1380     // that invocation.
write_cb<F>(&mut self, address: u64, count: usize, mut cb: F) -> std::io::Result<usize> where F: FnMut(&mut File, usize, u64, usize) -> std::io::Result<()>,1381     fn write_cb<F>(&mut self, address: u64, count: usize, mut cb: F) -> std::io::Result<usize>
1382     where
1383         F: FnMut(&mut File, usize, u64, usize) -> std::io::Result<()>,
1384     {
1385         let write_count: usize = self.limit_range_file(address, count);
1386 
1387         let mut nwritten: usize = 0;
1388         while nwritten < write_count {
1389             let curr_addr = address + nwritten as u64;
1390             let offset = self.file_offset_write(curr_addr)?;
1391             let count = self.limit_range_cluster(curr_addr, write_count - nwritten);
1392 
1393             if let Err(e) = cb(self.raw_file.file_mut(), nwritten, offset, count) {
1394                 return Err(e);
1395             }
1396 
1397             nwritten += count;
1398         }
1399         Ok(write_count)
1400     }
1401 }
1402 
1403 impl Drop for QcowFile {
drop(&mut self)1404     fn drop(&mut self) {
1405         let _ = self.sync_caches();
1406     }
1407 }
1408 
1409 impl AsRawDescriptors for QcowFile {
as_raw_descriptors(&self) -> Vec<RawDescriptor>1410     fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
1411         let mut descriptors = vec![self.raw_file.file().as_raw_descriptor()];
1412         if let Some(backing) = &self.backing_file {
1413             descriptors.append(&mut backing.as_raw_descriptors());
1414         }
1415         descriptors
1416     }
1417 }
1418 
1419 impl Read for QcowFile {
read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>1420     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1421         let len = buf.len();
1422         let slice = VolatileSlice::new(buf);
1423         let read_count = self.read_cb(
1424             self.current_offset,
1425             len,
1426             |file, already_read, offset, count| {
1427                 let sub_slice = slice.get_slice(already_read, count).unwrap();
1428                 match file {
1429                     Some(f) => f.read_exact_at_volatile(sub_slice, offset),
1430                     None => {
1431                         sub_slice.write_bytes(0);
1432                         Ok(())
1433                     }
1434                 }
1435             },
1436         )?;
1437         self.current_offset += read_count as u64;
1438         Ok(read_count)
1439     }
1440 }
1441 
1442 impl Seek for QcowFile {
seek(&mut self, pos: SeekFrom) -> std::io::Result<u64>1443     fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
1444         let new_offset: Option<u64> = match pos {
1445             SeekFrom::Start(off) => Some(off),
1446             SeekFrom::End(off) => {
1447                 if off < 0 {
1448                     0i64.checked_sub(off)
1449                         .and_then(|increment| self.virtual_size().checked_sub(increment as u64))
1450                 } else {
1451                     self.virtual_size().checked_add(off as u64)
1452                 }
1453             }
1454             SeekFrom::Current(off) => {
1455                 if off < 0 {
1456                     0i64.checked_sub(off)
1457                         .and_then(|increment| self.current_offset.checked_sub(increment as u64))
1458                 } else {
1459                     self.current_offset.checked_add(off as u64)
1460                 }
1461             }
1462         };
1463 
1464         if let Some(o) = new_offset {
1465             if o <= self.virtual_size() {
1466                 self.current_offset = o;
1467                 return Ok(o);
1468             }
1469         }
1470         Err(std::io::Error::from_raw_os_error(EINVAL))
1471     }
1472 }
1473 
1474 impl Write for QcowFile {
write(&mut self, buf: &[u8]) -> std::io::Result<usize>1475     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1476         let write_count = self.write_cb(
1477             self.current_offset,
1478             buf.len(),
1479             |file, offset, raw_offset, count| {
1480                 file.seek(SeekFrom::Start(raw_offset))?;
1481                 file.write_all(&buf[offset..(offset + count)])
1482             },
1483         )?;
1484         self.current_offset += write_count as u64;
1485         Ok(write_count)
1486     }
1487 
flush(&mut self) -> std::io::Result<()>1488     fn flush(&mut self) -> std::io::Result<()> {
1489         self.fsync()
1490     }
1491 }
1492 
1493 impl FileReadWriteAtVolatile for QcowFile {
read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize>1494     fn read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize> {
1495         self.read_cb(offset, slice.size(), |file, read, offset, count| {
1496             let sub_slice = slice.get_slice(read, count).unwrap();
1497             match file {
1498                 Some(f) => f.read_exact_at_volatile(sub_slice, offset),
1499                 None => {
1500                     sub_slice.write_bytes(0);
1501                     Ok(())
1502                 }
1503             }
1504         })
1505     }
1506 
write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize>1507     fn write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> io::Result<usize> {
1508         self.write_cb(offset, slice.size(), |file, offset, raw_offset, count| {
1509             let sub_slice = slice.get_slice(offset, count).unwrap();
1510             file.write_all_at_volatile(sub_slice, raw_offset)
1511         })
1512     }
1513 }
1514 
1515 impl FileSync for QcowFile {
fsync(&mut self) -> std::io::Result<()>1516     fn fsync(&mut self) -> std::io::Result<()> {
1517         self.sync_caches()?;
1518         self.avail_clusters.append(&mut self.unref_clusters);
1519         Ok(())
1520     }
1521 }
1522 
1523 impl FileSetLen for QcowFile {
set_len(&self, _len: u64) -> std::io::Result<()>1524     fn set_len(&self, _len: u64) -> std::io::Result<()> {
1525         Err(std::io::Error::new(
1526             std::io::ErrorKind::Other,
1527             "set_len() not supported for QcowFile",
1528         ))
1529     }
1530 }
1531 
1532 impl DiskGetLen for QcowFile {
get_len(&self) -> io::Result<u64>1533     fn get_len(&self) -> io::Result<u64> {
1534         Ok(self.virtual_size())
1535     }
1536 }
1537 
1538 impl FileAllocate for QcowFile {
allocate(&mut self, offset: u64, len: u64) -> io::Result<()>1539     fn allocate(&mut self, offset: u64, len: u64) -> io::Result<()> {
1540         // Call write_cb with a do-nothing callback, which will have the effect
1541         // of allocating all clusters in the specified range.
1542         self.write_cb(
1543             offset,
1544             len as usize,
1545             |_file, _offset, _raw_offset, _count| Ok(()),
1546         )?;
1547         Ok(())
1548     }
1549 }
1550 
1551 impl PunchHole for QcowFile {
punch_hole(&mut self, offset: u64, length: u64) -> std::io::Result<()>1552     fn punch_hole(&mut self, offset: u64, length: u64) -> std::io::Result<()> {
1553         let mut remaining = length;
1554         let mut offset = offset;
1555         while remaining > 0 {
1556             let chunk_length = min(remaining, std::usize::MAX as u64) as usize;
1557             self.zero_bytes(offset, chunk_length)?;
1558             remaining -= chunk_length as u64;
1559             offset += chunk_length as u64;
1560         }
1561         Ok(())
1562     }
1563 }
1564 
1565 impl WriteZeroesAt for QcowFile {
write_zeroes_at(&mut self, offset: u64, length: usize) -> io::Result<usize>1566     fn write_zeroes_at(&mut self, offset: u64, length: usize) -> io::Result<usize> {
1567         self.punch_hole(offset, length as u64)?;
1568         Ok(length)
1569     }
1570 }
1571 
1572 // Returns an Error if the given offset doesn't align to a cluster boundary.
offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()>1573 fn offset_is_cluster_boundary(offset: u64, cluster_bits: u32) -> Result<()> {
1574     if offset & ((0x01 << cluster_bits) - 1) != 0 {
1575         return Err(Error::InvalidOffset(offset));
1576     }
1577     Ok(())
1578 }
1579 
1580 // Ceiling of the division of `dividend`/`divisor`.
div_round_up_u64(dividend: u64, divisor: u64) -> u641581 fn div_round_up_u64(dividend: u64, divisor: u64) -> u64 {
1582     dividend / divisor + if dividend % divisor != 0 { 1 } else { 0 }
1583 }
1584 
1585 // Ceiling of the division of `dividend`/`divisor`.
div_round_up_u32(dividend: u32, divisor: u32) -> u321586 fn div_round_up_u32(dividend: u32, divisor: u32) -> u32 {
1587     dividend / divisor + if dividend % divisor != 0 { 1 } else { 0 }
1588 }
1589 
1590 #[cfg(test)]
1591 mod tests {
1592     use super::*;
1593     use crate::MAX_NESTING_DEPTH;
1594     use std::fs::OpenOptions;
1595     use std::io::{Read, Seek, SeekFrom, Write};
1596     use tempfile::{tempfile, TempDir};
1597 
valid_header() -> Vec<u8>1598     fn valid_header() -> Vec<u8> {
1599         vec![
1600             0x51u8, 0x46, 0x49, 0xfb, // magic
1601             0x00, 0x00, 0x00, 0x03, // version
1602             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // backing file offset
1603             0x00, 0x00, 0x00, 0x00, // backing file size
1604             0x00, 0x00, 0x00, 0x10, // cluster_bits
1605             0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, // size
1606             0x00, 0x00, 0x00, 0x00, // crypt method
1607             0x00, 0x00, 0x01, 0x00, // L1 size
1608             0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // L1 table offset
1609             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // refcount table offset
1610             0x00, 0x00, 0x00, 0x03, // refcount table clusters
1611             0x00, 0x00, 0x00, 0x00, // nb snapshots
1612             0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // snapshots offset
1613             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // incompatible_features
1614             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compatible_features
1615             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // autoclear_features
1616             0x00, 0x00, 0x00, 0x04, // refcount_order
1617             0x00, 0x00, 0x00, 0x68, // header_length
1618         ]
1619     }
1620 
1621     // Test case found by clusterfuzz to allocate excessive memory.
test_huge_header() -> Vec<u8>1622     fn test_huge_header() -> Vec<u8> {
1623         vec![
1624             0x51, 0x46, 0x49, 0xfb, // magic
1625             0x00, 0x00, 0x00, 0x03, // version
1626             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // backing file offset
1627             0x00, 0x00, 0x00, 0x00, // backing file size
1628             0x00, 0x00, 0x00, 0x09, // cluster_bits
1629             0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // size
1630             0x00, 0x00, 0x00, 0x00, // crypt method
1631             0x00, 0x00, 0x01, 0x00, // L1 size
1632             0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // L1 table offset
1633             0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // refcount table offset
1634             0x00, 0x00, 0x00, 0x03, // refcount table clusters
1635             0x00, 0x00, 0x00, 0x00, // nb snapshots
1636             0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // snapshots offset
1637             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // incompatible_features
1638             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compatible_features
1639             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // autoclear_features
1640             0x00, 0x00, 0x00, 0x04, // refcount_order
1641             0x00, 0x00, 0x00, 0x68, // header_length
1642         ]
1643     }
1644 
basic_file(header: &[u8]) -> File1645     fn basic_file(header: &[u8]) -> File {
1646         let mut disk_file = tempfile().expect("failed to create tempfile");
1647         disk_file.write_all(header).unwrap();
1648         disk_file.set_len(0x8000_0000).unwrap();
1649         disk_file.seek(SeekFrom::Start(0)).unwrap();
1650         disk_file
1651     }
1652 
with_basic_file<F>(header: &[u8], mut testfn: F) where F: FnMut(File),1653     fn with_basic_file<F>(header: &[u8], mut testfn: F)
1654     where
1655         F: FnMut(File),
1656     {
1657         testfn(basic_file(header)); // File closed when the function exits.
1658     }
1659 
with_default_file<F>(file_size: u64, mut testfn: F) where F: FnMut(QcowFile),1660     fn with_default_file<F>(file_size: u64, mut testfn: F)
1661     where
1662         F: FnMut(QcowFile),
1663     {
1664         let file = tempfile().expect("failed to create tempfile");
1665         let qcow_file = QcowFile::new(file, file_size).unwrap();
1666 
1667         testfn(qcow_file); // File closed when the function exits.
1668     }
1669 
1670     // Test helper function to convert a normal slice to a VolatileSlice and write it.
write_all_at(qcow: &mut QcowFile, data: &[u8], offset: u64) -> std::io::Result<()>1671     fn write_all_at(qcow: &mut QcowFile, data: &[u8], offset: u64) -> std::io::Result<()> {
1672         let mut mem = data.to_owned();
1673         let vslice = VolatileSlice::new(&mut mem);
1674         qcow.write_all_at_volatile(vslice, offset)
1675     }
1676 
1677     // Test helper function to read to a VolatileSlice and copy it to a normal slice.
read_exact_at(qcow: &mut QcowFile, data: &mut [u8], offset: u64) -> std::io::Result<()>1678     fn read_exact_at(qcow: &mut QcowFile, data: &mut [u8], offset: u64) -> std::io::Result<()> {
1679         let mut mem = data.to_owned();
1680         let vslice = VolatileSlice::new(&mut mem);
1681         qcow.read_exact_at_volatile(vslice, offset)?;
1682         vslice.copy_to(data);
1683         Ok(())
1684     }
1685 
1686     #[test]
default_header()1687     fn default_header() {
1688         let header = QcowHeader::create_for_size_and_path(0x10_0000, None);
1689         let mut disk_file = tempfile().expect("failed to create tempfile");
1690         header
1691             .expect("Failed to create header.")
1692             .write_to(&mut disk_file)
1693             .expect("Failed to write header to shm.");
1694         disk_file.seek(SeekFrom::Start(0)).unwrap();
1695         QcowFile::from(disk_file, MAX_NESTING_DEPTH)
1696             .expect("Failed to create Qcow from default Header");
1697     }
1698 
1699     #[test]
header_read()1700     fn header_read() {
1701         with_basic_file(&valid_header(), |mut disk_file: File| {
1702             QcowHeader::new(&mut disk_file).expect("Failed to create Header.");
1703         });
1704     }
1705 
1706     #[test]
header_with_backing()1707     fn header_with_backing() {
1708         let header = QcowHeader::create_for_size_and_path(0x10_0000, Some("/my/path/to/a/file"))
1709             .expect("Failed to create header.");
1710         let mut disk_file = tempfile().expect("failed to create tempfile");
1711         header
1712             .write_to(&mut disk_file)
1713             .expect("Failed to write header to shm.");
1714         disk_file.seek(SeekFrom::Start(0)).unwrap();
1715         let read_header = QcowHeader::new(&mut disk_file).expect("Failed to create header.");
1716         assert_eq!(
1717             header.backing_file_path,
1718             Some(String::from("/my/path/to/a/file"))
1719         );
1720         assert_eq!(read_header.backing_file_path, header.backing_file_path);
1721     }
1722 
1723     #[test]
invalid_magic()1724     fn invalid_magic() {
1725         let invalid_header = vec![0x51u8, 0x46, 0x4a, 0xfb];
1726         with_basic_file(&invalid_header, |mut disk_file: File| {
1727             QcowHeader::new(&mut disk_file).expect_err("Invalid header worked.");
1728         });
1729     }
1730 
1731     #[test]
invalid_refcount_order()1732     fn invalid_refcount_order() {
1733         let mut header = valid_header();
1734         header[99] = 2;
1735         with_basic_file(&header, |disk_file: File| {
1736             QcowFile::from(disk_file, MAX_NESTING_DEPTH)
1737                 .expect_err("Invalid refcount order worked.");
1738         });
1739     }
1740 
1741     #[test]
invalid_cluster_bits()1742     fn invalid_cluster_bits() {
1743         let mut header = valid_header();
1744         header[23] = 3;
1745         with_basic_file(&header, |disk_file: File| {
1746             QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect_err("Failed to create file.");
1747         });
1748     }
1749 
1750     #[test]
test_header_huge_file()1751     fn test_header_huge_file() {
1752         let header = test_huge_header();
1753         with_basic_file(&header, |disk_file: File| {
1754             QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect_err("Failed to create file.");
1755         });
1756     }
1757 
1758     #[test]
test_header_excessive_file_size_rejected()1759     fn test_header_excessive_file_size_rejected() {
1760         let mut header = valid_header();
1761         header[24..32].copy_from_slice(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1e]);
1762         with_basic_file(&header, |disk_file: File| {
1763             QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect_err("Failed to create file.");
1764         });
1765     }
1766 
1767     #[test]
test_huge_l1_table()1768     fn test_huge_l1_table() {
1769         let mut header = valid_header();
1770         header[36] = 0x12;
1771         with_basic_file(&header, |disk_file: File| {
1772             QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect_err("Failed to create file.");
1773         });
1774     }
1775 
1776     #[test]
test_header_1_tb_file_min_cluster()1777     fn test_header_1_tb_file_min_cluster() {
1778         let mut header = test_huge_header();
1779         header[24] = 0;
1780         header[26] = 1;
1781         header[31] = 0;
1782         // 1 TB with the min cluster size makes the arrays too big, it should fail.
1783         with_basic_file(&header, |disk_file: File| {
1784             QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect_err("Failed to create file.");
1785         });
1786     }
1787 
1788     #[test]
test_header_1_tb_file()1789     fn test_header_1_tb_file() {
1790         let mut header = test_huge_header();
1791         // reset to 1 TB size.
1792         header[24] = 0;
1793         header[26] = 1;
1794         header[31] = 0;
1795         // set cluster_bits
1796         header[23] = 16;
1797         with_basic_file(&header, |disk_file: File| {
1798             let mut qcow =
1799                 QcowFile::from(disk_file, MAX_NESTING_DEPTH).expect("Failed to create file.");
1800             let value = 0x0000_0040_3f00_ffffu64;
1801             write_all_at(&mut qcow, &value.to_le_bytes(), 0x100_0000_0000 - 8)
1802                 .expect("failed to write data");
1803         });
1804     }
1805 
1806     #[test]
test_header_huge_num_refcounts()1807     fn test_header_huge_num_refcounts() {
1808         let mut header = valid_header();
1809         header[56..60].copy_from_slice(&[0x02, 0x00, 0xe8, 0xff]);
1810         with_basic_file(&header, |disk_file: File| {
1811             QcowFile::from(disk_file, MAX_NESTING_DEPTH)
1812                 .expect_err("Created disk with excessive refcount clusters");
1813         });
1814     }
1815 
1816     #[test]
test_header_huge_refcount_offset()1817     fn test_header_huge_refcount_offset() {
1818         let mut header = valid_header();
1819         header[48..56].copy_from_slice(&[0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00]);
1820         with_basic_file(&header, |disk_file: File| {
1821             QcowFile::from(disk_file, MAX_NESTING_DEPTH)
1822                 .expect_err("Created disk with excessive refcount offset");
1823         });
1824     }
1825 
1826     #[test]
write_read_start()1827     fn write_read_start() {
1828         with_basic_file(&valid_header(), |disk_file: File| {
1829             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1830             write_all_at(&mut q, b"test first bytes", 0).expect("Failed to write test string.");
1831             let mut buf = [0u8; 4];
1832             read_exact_at(&mut q, &mut buf, 0).expect("Failed to read.");
1833             assert_eq!(&buf, b"test");
1834         });
1835     }
1836 
1837     #[test]
write_read_start_backing()1838     fn write_read_start_backing() {
1839         let disk_file = basic_file(&valid_header());
1840         let mut backing = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1841         write_all_at(&mut backing, b"test first bytes", 0).expect("Failed to write test string.");
1842         let mut buf = [0u8; 4];
1843         let wrapping_disk_file = basic_file(&valid_header());
1844         let mut wrapping = QcowFile::from(wrapping_disk_file, MAX_NESTING_DEPTH).unwrap();
1845         wrapping.set_backing_file(Some(Box::new(backing)));
1846         read_exact_at(&mut wrapping, &mut buf, 0).expect("Failed to read.");
1847         assert_eq!(&buf, b"test");
1848     }
1849 
1850     #[test]
write_read_start_backing_overlap()1851     fn write_read_start_backing_overlap() {
1852         let disk_file = basic_file(&valid_header());
1853         let mut backing = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1854         write_all_at(&mut backing, b"test first bytes", 0).expect("Failed to write test string.");
1855         let wrapping_disk_file = basic_file(&valid_header());
1856         let mut wrapping = QcowFile::from(wrapping_disk_file, MAX_NESTING_DEPTH).unwrap();
1857         wrapping.set_backing_file(Some(Box::new(backing)));
1858         write_all_at(&mut wrapping, b"TEST", 0).expect("Failed to write second test string.");
1859         let mut buf = [0u8; 10];
1860         read_exact_at(&mut wrapping, &mut buf, 0).expect("Failed to read.");
1861         assert_eq!(&buf, b"TEST first");
1862     }
1863 
1864     #[test]
offset_write_read()1865     fn offset_write_read() {
1866         with_basic_file(&valid_header(), |disk_file: File| {
1867             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1868             let b = [0x55u8; 0x1000];
1869             write_all_at(&mut q, &b, 0xfff2000).expect("Failed to write test string.");
1870             let mut buf = [0u8; 4];
1871             read_exact_at(&mut q, &mut buf, 0xfff2000).expect("Failed to read.");
1872             assert_eq!(buf[0], 0x55);
1873         });
1874     }
1875 
1876     #[test]
write_zeroes_read()1877     fn write_zeroes_read() {
1878         with_basic_file(&valid_header(), |disk_file: File| {
1879             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1880             // Write some test data.
1881             let b = [0x55u8; 0x1000];
1882             write_all_at(&mut q, &b, 0xfff2000).expect("Failed to write test string.");
1883             // Overwrite the test data with zeroes.
1884             q.write_zeroes_all_at(0xfff2000, 0x200)
1885                 .expect("Failed to write zeroes.");
1886             // Verify that the correct part of the data was zeroed out.
1887             let mut buf = [0u8; 0x1000];
1888             read_exact_at(&mut q, &mut buf, 0xfff2000).expect("Failed to read.");
1889             assert_eq!(buf[0], 0);
1890             assert_eq!(buf[0x1FF], 0);
1891             assert_eq!(buf[0x200], 0x55);
1892             assert_eq!(buf[0xFFF], 0x55);
1893         });
1894     }
1895 
1896     #[test]
write_zeroes_full_cluster()1897     fn write_zeroes_full_cluster() {
1898         // Choose a size that is larger than a cluster.
1899         // valid_header uses cluster_bits = 12, which corresponds to a cluster size of 4096.
1900         const CHUNK_SIZE: usize = 4096 * 2 + 512;
1901         with_basic_file(&valid_header(), |disk_file: File| {
1902             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1903             // Write some test data.
1904             let b = [0x55u8; CHUNK_SIZE];
1905             write_all_at(&mut q, &b, 0).expect("Failed to write test string.");
1906             // Overwrite the full cluster with zeroes.
1907             q.write_zeroes_all_at(0, CHUNK_SIZE)
1908                 .expect("Failed to write zeroes.");
1909             // Verify that the data was zeroed out.
1910             let mut buf = [0u8; CHUNK_SIZE];
1911             read_exact_at(&mut q, &mut buf, 0).expect("Failed to read.");
1912             assert_eq!(buf[0], 0);
1913             assert_eq!(buf[CHUNK_SIZE - 1], 0);
1914         });
1915     }
1916 
1917     #[test]
write_zeroes_backing()1918     fn write_zeroes_backing() {
1919         let disk_file = basic_file(&valid_header());
1920         let mut backing = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1921         // Write some test data.
1922         let b = [0x55u8; 0x1000];
1923         write_all_at(&mut backing, &b, 0xfff2000).expect("Failed to write test string.");
1924         let wrapping_disk_file = basic_file(&valid_header());
1925         let mut wrapping = QcowFile::from(wrapping_disk_file, MAX_NESTING_DEPTH).unwrap();
1926         wrapping.set_backing_file(Some(Box::new(backing)));
1927         // Overwrite the test data with zeroes.
1928         // This should allocate new clusters in the wrapping file so that they can be zeroed.
1929         wrapping
1930             .write_zeroes_all_at(0xfff2000, 0x200)
1931             .expect("Failed to write zeroes.");
1932         // Verify that the correct part of the data was zeroed out.
1933         let mut buf = [0u8; 0x1000];
1934         read_exact_at(&mut wrapping, &mut buf, 0xfff2000).expect("Failed to read.");
1935         assert_eq!(buf[0], 0);
1936         assert_eq!(buf[0x1FF], 0);
1937         assert_eq!(buf[0x200], 0x55);
1938         assert_eq!(buf[0xFFF], 0x55);
1939     }
1940     #[test]
test_header()1941     fn test_header() {
1942         with_basic_file(&valid_header(), |disk_file: File| {
1943             let q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1944             assert_eq!(q.virtual_size(), 0x20_0000_0000);
1945         });
1946     }
1947 
1948     #[test]
read_small_buffer()1949     fn read_small_buffer() {
1950         with_basic_file(&valid_header(), |disk_file: File| {
1951             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1952             let mut b = [5u8; 16];
1953             read_exact_at(&mut q, &mut b, 1000).expect("Failed to read.");
1954             assert_eq!(0, b[0]);
1955             assert_eq!(0, b[15]);
1956         });
1957     }
1958 
1959     #[test]
replay_ext4()1960     fn replay_ext4() {
1961         with_basic_file(&valid_header(), |disk_file: File| {
1962             let mut q = QcowFile::from(disk_file, MAX_NESTING_DEPTH).unwrap();
1963             const BUF_SIZE: usize = 0x1000;
1964             let mut b = [0u8; BUF_SIZE];
1965 
1966             struct Transfer {
1967                 pub write: bool,
1968                 pub addr: u64,
1969             }
1970 
1971             // Write transactions from mkfs.ext4.
1972             let xfers: Vec<Transfer> = vec![
1973                 Transfer {
1974                     write: false,
1975                     addr: 0xfff0000,
1976                 },
1977                 Transfer {
1978                     write: false,
1979                     addr: 0xfffe000,
1980                 },
1981                 Transfer {
1982                     write: false,
1983                     addr: 0x0,
1984                 },
1985                 Transfer {
1986                     write: false,
1987                     addr: 0x1000,
1988                 },
1989                 Transfer {
1990                     write: false,
1991                     addr: 0xffff000,
1992                 },
1993                 Transfer {
1994                     write: false,
1995                     addr: 0xffdf000,
1996                 },
1997                 Transfer {
1998                     write: false,
1999                     addr: 0xfff8000,
2000                 },
2001                 Transfer {
2002                     write: false,
2003                     addr: 0xffe0000,
2004                 },
2005                 Transfer {
2006                     write: false,
2007                     addr: 0xffce000,
2008                 },
2009                 Transfer {
2010                     write: false,
2011                     addr: 0xffb6000,
2012                 },
2013                 Transfer {
2014                     write: false,
2015                     addr: 0xffab000,
2016                 },
2017                 Transfer {
2018                     write: false,
2019                     addr: 0xffa4000,
2020                 },
2021                 Transfer {
2022                     write: false,
2023                     addr: 0xff8e000,
2024                 },
2025                 Transfer {
2026                     write: false,
2027                     addr: 0xff86000,
2028                 },
2029                 Transfer {
2030                     write: false,
2031                     addr: 0xff84000,
2032                 },
2033                 Transfer {
2034                     write: false,
2035                     addr: 0xff89000,
2036                 },
2037                 Transfer {
2038                     write: false,
2039                     addr: 0xfe7e000,
2040                 },
2041                 Transfer {
2042                     write: false,
2043                     addr: 0x100000,
2044                 },
2045                 Transfer {
2046                     write: false,
2047                     addr: 0x3000,
2048                 },
2049                 Transfer {
2050                     write: false,
2051                     addr: 0x7000,
2052                 },
2053                 Transfer {
2054                     write: false,
2055                     addr: 0xf000,
2056                 },
2057                 Transfer {
2058                     write: false,
2059                     addr: 0x2000,
2060                 },
2061                 Transfer {
2062                     write: false,
2063                     addr: 0x4000,
2064                 },
2065                 Transfer {
2066                     write: false,
2067                     addr: 0x5000,
2068                 },
2069                 Transfer {
2070                     write: false,
2071                     addr: 0x6000,
2072                 },
2073                 Transfer {
2074                     write: false,
2075                     addr: 0x8000,
2076                 },
2077                 Transfer {
2078                     write: false,
2079                     addr: 0x9000,
2080                 },
2081                 Transfer {
2082                     write: false,
2083                     addr: 0xa000,
2084                 },
2085                 Transfer {
2086                     write: false,
2087                     addr: 0xb000,
2088                 },
2089                 Transfer {
2090                     write: false,
2091                     addr: 0xc000,
2092                 },
2093                 Transfer {
2094                     write: false,
2095                     addr: 0xd000,
2096                 },
2097                 Transfer {
2098                     write: false,
2099                     addr: 0xe000,
2100                 },
2101                 Transfer {
2102                     write: false,
2103                     addr: 0x10000,
2104                 },
2105                 Transfer {
2106                     write: false,
2107                     addr: 0x11000,
2108                 },
2109                 Transfer {
2110                     write: false,
2111                     addr: 0x12000,
2112                 },
2113                 Transfer {
2114                     write: false,
2115                     addr: 0x13000,
2116                 },
2117                 Transfer {
2118                     write: false,
2119                     addr: 0x14000,
2120                 },
2121                 Transfer {
2122                     write: false,
2123                     addr: 0x15000,
2124                 },
2125                 Transfer {
2126                     write: false,
2127                     addr: 0x16000,
2128                 },
2129                 Transfer {
2130                     write: false,
2131                     addr: 0x17000,
2132                 },
2133                 Transfer {
2134                     write: false,
2135                     addr: 0x18000,
2136                 },
2137                 Transfer {
2138                     write: false,
2139                     addr: 0x19000,
2140                 },
2141                 Transfer {
2142                     write: false,
2143                     addr: 0x1a000,
2144                 },
2145                 Transfer {
2146                     write: false,
2147                     addr: 0x1b000,
2148                 },
2149                 Transfer {
2150                     write: false,
2151                     addr: 0x1c000,
2152                 },
2153                 Transfer {
2154                     write: false,
2155                     addr: 0x1d000,
2156                 },
2157                 Transfer {
2158                     write: false,
2159                     addr: 0x1e000,
2160                 },
2161                 Transfer {
2162                     write: false,
2163                     addr: 0x1f000,
2164                 },
2165                 Transfer {
2166                     write: false,
2167                     addr: 0x21000,
2168                 },
2169                 Transfer {
2170                     write: false,
2171                     addr: 0x22000,
2172                 },
2173                 Transfer {
2174                     write: false,
2175                     addr: 0x24000,
2176                 },
2177                 Transfer {
2178                     write: false,
2179                     addr: 0x40000,
2180                 },
2181                 Transfer {
2182                     write: false,
2183                     addr: 0x0,
2184                 },
2185                 Transfer {
2186                     write: false,
2187                     addr: 0x3000,
2188                 },
2189                 Transfer {
2190                     write: false,
2191                     addr: 0x7000,
2192                 },
2193                 Transfer {
2194                     write: false,
2195                     addr: 0x0,
2196                 },
2197                 Transfer {
2198                     write: false,
2199                     addr: 0x1000,
2200                 },
2201                 Transfer {
2202                     write: false,
2203                     addr: 0x2000,
2204                 },
2205                 Transfer {
2206                     write: false,
2207                     addr: 0x3000,
2208                 },
2209                 Transfer {
2210                     write: false,
2211                     addr: 0x0,
2212                 },
2213                 Transfer {
2214                     write: false,
2215                     addr: 0x449000,
2216                 },
2217                 Transfer {
2218                     write: false,
2219                     addr: 0x48000,
2220                 },
2221                 Transfer {
2222                     write: false,
2223                     addr: 0x48000,
2224                 },
2225                 Transfer {
2226                     write: false,
2227                     addr: 0x448000,
2228                 },
2229                 Transfer {
2230                     write: false,
2231                     addr: 0x44a000,
2232                 },
2233                 Transfer {
2234                     write: false,
2235                     addr: 0x48000,
2236                 },
2237                 Transfer {
2238                     write: false,
2239                     addr: 0x48000,
2240                 },
2241                 Transfer {
2242                     write: true,
2243                     addr: 0x0,
2244                 },
2245                 Transfer {
2246                     write: true,
2247                     addr: 0x448000,
2248                 },
2249                 Transfer {
2250                     write: true,
2251                     addr: 0x449000,
2252                 },
2253                 Transfer {
2254                     write: true,
2255                     addr: 0x44a000,
2256                 },
2257                 Transfer {
2258                     write: true,
2259                     addr: 0xfff0000,
2260                 },
2261                 Transfer {
2262                     write: true,
2263                     addr: 0xfff1000,
2264                 },
2265                 Transfer {
2266                     write: true,
2267                     addr: 0xfff2000,
2268                 },
2269                 Transfer {
2270                     write: true,
2271                     addr: 0xfff3000,
2272                 },
2273                 Transfer {
2274                     write: true,
2275                     addr: 0xfff4000,
2276                 },
2277                 Transfer {
2278                     write: true,
2279                     addr: 0xfff5000,
2280                 },
2281                 Transfer {
2282                     write: true,
2283                     addr: 0xfff6000,
2284                 },
2285                 Transfer {
2286                     write: true,
2287                     addr: 0xfff7000,
2288                 },
2289                 Transfer {
2290                     write: true,
2291                     addr: 0xfff8000,
2292                 },
2293                 Transfer {
2294                     write: true,
2295                     addr: 0xfff9000,
2296                 },
2297                 Transfer {
2298                     write: true,
2299                     addr: 0xfffa000,
2300                 },
2301                 Transfer {
2302                     write: true,
2303                     addr: 0xfffb000,
2304                 },
2305                 Transfer {
2306                     write: true,
2307                     addr: 0xfffc000,
2308                 },
2309                 Transfer {
2310                     write: true,
2311                     addr: 0xfffd000,
2312                 },
2313                 Transfer {
2314                     write: true,
2315                     addr: 0xfffe000,
2316                 },
2317                 Transfer {
2318                     write: true,
2319                     addr: 0xffff000,
2320                 },
2321             ];
2322 
2323             for xfer in &xfers {
2324                 if xfer.write {
2325                     write_all_at(&mut q, &b, xfer.addr).expect("Failed to write.");
2326                 } else {
2327                     read_exact_at(&mut q, &mut b, xfer.addr).expect("Failed to read.");
2328                 }
2329             }
2330         });
2331     }
2332 
2333     #[test]
combo_write_read()2334     fn combo_write_read() {
2335         with_default_file(1024 * 1024 * 1024 * 256, |mut qcow_file| {
2336             const NUM_BLOCKS: usize = 555;
2337             const BLOCK_SIZE: usize = 0x1_0000;
2338             const OFFSET: u64 = 0x1_0000_0020;
2339             let data = [0x55u8; BLOCK_SIZE];
2340             let mut readback = [0u8; BLOCK_SIZE];
2341             for i in 0..NUM_BLOCKS {
2342                 let seek_offset = OFFSET + (i as u64) * (BLOCK_SIZE as u64);
2343                 write_all_at(&mut qcow_file, &data, seek_offset)
2344                     .expect("Failed to write test data.");
2345                 // Read back the data to check it was written correctly.
2346                 read_exact_at(&mut qcow_file, &mut readback, seek_offset).expect("Failed to read.");
2347                 for (orig, read) in data.iter().zip(readback.iter()) {
2348                     assert_eq!(orig, read);
2349                 }
2350             }
2351             // Check that address 0 is still zeros.
2352             read_exact_at(&mut qcow_file, &mut readback, 0).expect("Failed to read.");
2353             for read in readback.iter() {
2354                 assert_eq!(*read, 0);
2355             }
2356             // Check the data again after the writes have happened.
2357             for i in 0..NUM_BLOCKS {
2358                 let seek_offset = OFFSET + (i as u64) * (BLOCK_SIZE as u64);
2359                 read_exact_at(&mut qcow_file, &mut readback, seek_offset).expect("Failed to read.");
2360                 for (orig, read) in data.iter().zip(readback.iter()) {
2361                     assert_eq!(orig, read);
2362                 }
2363             }
2364 
2365             assert_eq!(qcow_file.first_zero_refcount().unwrap(), None);
2366         });
2367     }
2368 
2369     #[test]
rebuild_refcounts()2370     fn rebuild_refcounts() {
2371         with_basic_file(&valid_header(), |mut disk_file: File| {
2372             let header = QcowHeader::new(&mut disk_file).expect("Failed to create Header.");
2373             let cluster_size = 65536;
2374             let mut raw_file =
2375                 QcowRawFile::from(disk_file, cluster_size).expect("Failed to create QcowRawFile.");
2376             QcowFile::rebuild_refcounts(&mut raw_file, header)
2377                 .expect("Failed to rebuild recounts.");
2378         });
2379     }
2380 
2381     #[test]
nested_qcow()2382     fn nested_qcow() {
2383         let tmp_dir = TempDir::new().unwrap();
2384 
2385         // A file `backing` is backing a qcow file `qcow.l1`, which in turn is backing another
2386         // qcow file.
2387         let backing_file_path = tmp_dir.path().join("backing");
2388         let _backing_file = OpenOptions::new()
2389             .read(true)
2390             .write(true)
2391             .create(true)
2392             .open(&backing_file_path)
2393             .unwrap();
2394 
2395         let level1_qcow_file_path = tmp_dir.path().join("qcow.l1");
2396         let level1_qcow_file = OpenOptions::new()
2397             .read(true)
2398             .write(true)
2399             .create(true)
2400             .open(&level1_qcow_file_path)
2401             .unwrap();
2402         let _level1_qcow_file = QcowFile::new_from_backing(
2403             level1_qcow_file,
2404             backing_file_path.to_str().unwrap(),
2405             1000, /* allow deep nesting */
2406         )
2407         .unwrap();
2408 
2409         let level2_qcow_file = tempfile().unwrap();
2410         let _level2_qcow_file = QcowFile::new_from_backing(
2411             level2_qcow_file,
2412             level1_qcow_file_path.to_str().unwrap(),
2413             1000, /* allow deep nesting */
2414         )
2415         .expect("failed to create level2 qcow file");
2416     }
2417 
2418     #[test]
io_seek()2419     fn io_seek() {
2420         with_default_file(1024 * 1024 * 10, |mut qcow_file| {
2421             // Cursor should start at 0.
2422             assert_eq!(qcow_file.seek(SeekFrom::Current(0)).unwrap(), 0);
2423 
2424             // Seek 1 MB from start.
2425             assert_eq!(
2426                 qcow_file.seek(SeekFrom::Start(1024 * 1024)).unwrap(),
2427                 1024 * 1024
2428             );
2429 
2430             // Rewind 1 MB + 1 byte (past beginning) - seeking to a negative offset is an error and
2431             // should not move the cursor.
2432             qcow_file
2433                 .seek(SeekFrom::Current(-(1024 * 1024 + 1)))
2434                 .expect_err("negative offset seek should fail");
2435             assert_eq!(qcow_file.seek(SeekFrom::Current(0)).unwrap(), 1024 * 1024);
2436 
2437             // Seek to last byte.
2438             assert_eq!(
2439                 qcow_file.seek(SeekFrom::End(-1)).unwrap(),
2440                 1024 * 1024 * 10 - 1
2441             );
2442 
2443             // Seek to EOF.
2444             assert_eq!(qcow_file.seek(SeekFrom::End(0)).unwrap(), 1024 * 1024 * 10);
2445 
2446             // Seek past EOF is not allowed.
2447             qcow_file
2448                 .seek(SeekFrom::End(1))
2449                 .expect_err("seek past EOF should fail");
2450         });
2451     }
2452 
2453     #[test]
io_write_read()2454     fn io_write_read() {
2455         with_default_file(1024 * 1024 * 10, |mut qcow_file| {
2456             const BLOCK_SIZE: usize = 0x1_0000;
2457             let data_55 = [0x55u8; BLOCK_SIZE];
2458             let data_aa = [0xaau8; BLOCK_SIZE];
2459             let mut readback = [0u8; BLOCK_SIZE];
2460 
2461             qcow_file.write_all(&data_55).unwrap();
2462             assert_eq!(
2463                 qcow_file.seek(SeekFrom::Current(0)).unwrap(),
2464                 BLOCK_SIZE as u64
2465             );
2466 
2467             qcow_file.write_all(&data_aa).unwrap();
2468             assert_eq!(
2469                 qcow_file.seek(SeekFrom::Current(0)).unwrap(),
2470                 BLOCK_SIZE as u64 * 2
2471             );
2472 
2473             // Read BLOCK_SIZE of just 0xaa.
2474             assert_eq!(
2475                 qcow_file
2476                     .seek(SeekFrom::Current(-(BLOCK_SIZE as i64)))
2477                     .unwrap(),
2478                 BLOCK_SIZE as u64
2479             );
2480             qcow_file.read_exact(&mut readback).unwrap();
2481             assert_eq!(
2482                 qcow_file.seek(SeekFrom::Current(0)).unwrap(),
2483                 BLOCK_SIZE as u64 * 2
2484             );
2485             for (orig, read) in data_aa.iter().zip(readback.iter()) {
2486                 assert_eq!(orig, read);
2487             }
2488 
2489             // Read BLOCK_SIZE of just 0x55.
2490             qcow_file.rewind().unwrap();
2491             qcow_file.read_exact(&mut readback).unwrap();
2492             for (orig, read) in data_55.iter().zip(readback.iter()) {
2493                 assert_eq!(orig, read);
2494             }
2495 
2496             // Read BLOCK_SIZE crossing between the block of 0x55 and 0xaa.
2497             qcow_file
2498                 .seek(SeekFrom::Start(BLOCK_SIZE as u64 / 2))
2499                 .unwrap();
2500             qcow_file.read_exact(&mut readback).unwrap();
2501             for (orig, read) in data_55[BLOCK_SIZE / 2..]
2502                 .iter()
2503                 .chain(data_aa[..BLOCK_SIZE / 2].iter())
2504                 .zip(readback.iter())
2505             {
2506                 assert_eq!(orig, read);
2507             }
2508         });
2509     }
2510 }
2511