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