diff options
author | Dylan Reid <dgreid@chromium.org> | 2018-09-04 17:35:15 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-19 15:40:05 -0700 |
commit | 39401ff269cf74e0eaedbd7d0bff510ed01e4782 (patch) | |
tree | 2e107aab4abc3bdb1f38f784f501e9bd00ca799b /qcow | |
parent | 579bd2cf0e59c86779bc113734d583590341301c (diff) | |
download | crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar.gz crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar.bz2 crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar.lz crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar.xz crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.tar.zst crosvm-39401ff269cf74e0eaedbd7d0bff510ed01e4782.zip |
qcow: Add accessors for more file state
Being able to access the state of the qcow file makes debugging easier. These functions will be used from a helper program in the following commit. Change-Id: I1db7ddaeaff1c83363513a2c55c44a1825833634 Signed-off-by: Dylan Reid <dgreid@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1207454 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'qcow')
-rw-r--r-- | qcow/src/qcow.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/qcow/src/qcow.rs b/qcow/src/qcow.rs index a60f731..3129203 100644 --- a/qcow/src/qcow.rs +++ b/qcow/src/qcow.rs @@ -31,7 +31,9 @@ pub enum Error { CompressedBlocksNotSupported, GettingFileSize(io::Error), GettingRefcount(refcount::Error), + EvictingCache(io::Error), InvalidClusterSize, + InvalidIndex, InvalidL1TableOffset, InvalidMagic, InvalidOffset(u64), @@ -39,7 +41,9 @@ pub enum Error { NoRefcountClusters, OpeningFile(io::Error), ReadingHeader(io::Error), + ReadingPointers(io::Error), ReadingRefCounts(io::Error), + ReadingRefCountBlock(refcount::Error), SeekingFile(io::Error), SettingRefcountRefcount(io::Error), SizeTooSmallForNumberOfClusters, @@ -385,6 +389,60 @@ impl QcowFile { Ok(qcow) } + /// Returns the `QcowHeader` for this file. + pub fn header(&self) -> &QcowHeader { + &self.header + } + + /// Returns the L1 lookup table for this file. This is only useful for debugging. + pub fn l1_table(&self) -> &[u64] { + &self.l1_table + } + + /// Returns an L2_table of cluster addresses, only used for debugging. + pub fn l2_table(&mut self, l1_index: usize) -> Result<Option<&[u64]>> { + let l2_addr_disk = *self.l1_table.get(l1_index).ok_or(Error::InvalidIndex)?; + + if l2_addr_disk == 0 { + // Reading from an unallocated cluster will return zeros. + return Ok(None); + } + + if !self.l2_cache.contains_key(&l1_index) { + // Not in the cache. + let table = VecCache::from_vec( + Self::read_l2_cluster(&mut self.raw_file, l2_addr_disk) + .map_err(Error::ReadingPointers)?, + ); + let l1_table = &mut self.l1_table; + let raw_file = &mut self.raw_file; + self.l2_cache + .insert(l1_index, table, |index, evicted| { + raw_file.write_pointer_table( + l1_table[index], + evicted.get_values(), + CLUSTER_USED_FLAG, + ) + }) + .map_err(Error::EvictingCache)?; + } + + // The index must exist as it was just inserted if it didn't already. + Ok(Some(self.l2_cache.get(&l1_index).unwrap().get_values())) + } + + /// Returns the refcount table for this file. This is only useful for debugging. + pub fn ref_table(&self) -> &[u64] { + &self.refcounts.ref_table() + } + + /// Returns the `index`th refcount block from the file. + pub fn refcount_block(&mut self, index: usize) -> Result<Option<&[u16]>> { + self.refcounts + .refcount_block(&mut self.raw_file, index) + .map_err(Error::ReadingRefCountBlock) + } + /// Returns the first cluster in the file with a 0 refcount. Used for testing. pub fn first_zero_refcount(&mut self) -> Result<Option<u64>> { let file_size = self |