summary refs log tree commit diff
path: root/qcow/src/refcount.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2018-09-27 09:34:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-09-27 19:44:09 -0700
commit46f70e8c1679e0758683112db45fec590beb5b5b (patch)
tree3cc425784407ad13a5bf95d20effe37790237507 /qcow/src/refcount.rs
parenteaaf3e17e68e2a08012b23adb99b2a80b14a21f5 (diff)
downloadcrosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar.gz
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar.bz2
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar.lz
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar.xz
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.tar.zst
crosvm-46f70e8c1679e0758683112db45fec590beb5b5b.zip
qcow: optimize sync_caches to avoid extra writes
Track the clean/dirty state of the L1 table and the refcount table to
avoid writing them out and doing an extra fsyncdata() if nothing has
changed.

BUG=None
TEST=Manually verify strace output contains only the expected fsyncs

Change-Id: I20bdd250024039a5b4142605462a8977ced1efcc
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1247442
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'qcow/src/refcount.rs')
-rw-r--r--qcow/src/refcount.rs26
1 files changed, 20 insertions, 6 deletions
diff --git a/qcow/src/refcount.rs b/qcow/src/refcount.rs
index 96b5e0c..13906a1 100644
--- a/qcow/src/refcount.rs
+++ b/qcow/src/refcount.rs
@@ -29,7 +29,7 @@ pub type Result<T> = std::result::Result<T, Error>;
 /// Represents the refcount entries for an open qcow file.
 #[derive(Debug)]
 pub struct RefCount {
-    ref_table: Vec<u64>,
+    ref_table: VecCache<u64>,
     refcount_table_offset: u64,
     refblock_cache: CacheMap<VecCache<u16>>,
     refcount_block_entries: u64, // number of refcounts in a cluster.
@@ -48,8 +48,11 @@ impl RefCount {
         refcount_block_entries: u64,
         cluster_size: u64,
     ) -> io::Result<RefCount> {
-        let ref_table =
-            raw_file.read_pointer_table(refcount_table_offset, refcount_table_entries, None)?;
+        let ref_table = VecCache::from_vec(raw_file.read_pointer_table(
+            refcount_table_offset,
+            refcount_table_entries,
+            None,
+        )?);
         Ok(RefCount {
             ref_table,
             refcount_table_offset,
@@ -134,8 +137,19 @@ impl RefCount {
     }
 
     /// Flush the refcount table that keeps the address of the refcounts blocks.
-    pub fn flush_table(&mut self, raw_file: &mut QcowRawFile) -> io::Result<()> {
-        raw_file.write_pointer_table(self.refcount_table_offset, &self.ref_table, 0)
+    /// Returns true if the table changed since the previous `flush_table()` call.
+    pub fn flush_table(&mut self, raw_file: &mut QcowRawFile) -> io::Result<bool> {
+        if self.ref_table.dirty() {
+            raw_file.write_pointer_table(
+                self.refcount_table_offset,
+                &self.ref_table.get_values(),
+                0,
+            )?;
+            self.ref_table.mark_clean();
+            Ok(true)
+        } else {
+            Ok(false)
+        }
     }
 
     /// Gets the refcount for a cluster with the given address.
@@ -167,7 +181,7 @@ impl RefCount {
 
     /// Returns the refcount table for this file. This is only useful for debugging.
     pub fn ref_table(&self) -> &[u64] {
-        &self.ref_table
+        &self.ref_table.get_values()
     }
 
     /// Returns the refcounts stored in the given block.