[RFC 1/2] block/qcow2-cache: Introduce qcow2_write_l2_entry()

zhangjiaji via posted 2 patches 3 weeks, 1 day ago
Maintainers: Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>
[RFC 1/2] block/qcow2-cache: Introduce qcow2_write_l2_entry()
Posted by zhangjiaji via 3 weeks, 1 day ago
From: Zhu Yangyang <zhuyangyang14@huawei.com>

This function will be used in the next optimization patch to flush
only the actually changed portion of the qcow2 L2 Table cache,
instead of flushing the entire L2 Table cache.

Signed-off-by: Zhu Yangyang <zhuyangyang14@h-partners.com>
---
 block/qcow2-cache.c | 33 ++++++++++++++++++++++++++++++---
 block/qcow2.h       |  2 ++
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 23d9588b08..b5378d003d 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -180,7 +180,8 @@ qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
 }
 
 static int GRAPH_RDLOCK
-qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
+qcow2_cache_entry_flush_part(BlockDriverState *bs, Qcow2Cache *c, int i,
+                             int l2_index, int nb_clusters)
 {
     BDRVQcow2State *s = bs->opaque;
     int ret = 0;
@@ -226,8 +227,21 @@ qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
         BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
     }
 
-    ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->table_size,
-                      qcow2_cache_get_table_addr(c, i), 0);
+    if (l2_index < 0) {
+        ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->table_size,
+                          qcow2_cache_get_table_addr(c, i), 0);
+    } else {
+        /* Only flush the actual dirty portions. */
+        int64_t l2_offset = l2_index * l2_entry_size(s);
+        int64_t l2_bytes = nb_clusters * l2_entry_size(s);
+
+        int64_t aligned_offset = QEMU_ALIGN_DOWN(l2_offset, BDRV_SECTOR_SIZE);
+        int64_t aligned_end = QEMU_ALIGN_UP(l2_offset + l2_bytes, BDRV_SECTOR_SIZE);
+        ret = bdrv_pwrite(bs->file, c->entries[i].offset + aligned_offset,
+                          aligned_end - aligned_offset,
+                          qcow2_cache_get_table_addr(c, i) + aligned_offset, 0);
+    }
+
     if (ret < 0) {
         return ret;
     }
@@ -237,6 +251,19 @@ qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
     return 0;
 }
 
+static int GRAPH_RDLOCK
+qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
+{
+    return qcow2_cache_entry_flush_part(bs, c, i, -1, 0);
+}
+
+int qcow2_write_l2_entry(BlockDriverState *bs, Qcow2Cache *c, void *l2_tabel,
+                         int l2_index, int nb_clusters)
+{
+    int l2 = qcow2_cache_get_table_idx(c, l2_tabel);
+    return qcow2_cache_entry_flush_part(bs, c, l2, l2_index, nb_clusters);
+}
+
 int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c)
 {
     BDRVQcow2State *s = bs->opaque;
diff --git a/block/qcow2.h b/block/qcow2.h
index a9e3481c6e..b0ba2e1996 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -1001,6 +1001,8 @@ qcow2_cache_create(BlockDriverState *bs, int num_tables, unsigned table_size);
 int qcow2_cache_destroy(Qcow2Cache *c);
 
 void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
+int qcow2_write_l2_entry(BlockDriverState *bs, Qcow2Cache *c, void *l2_tabel,
+                         int l2_index, int nb_clusters)
 int GRAPH_RDLOCK qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
 int GRAPH_RDLOCK qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
 int GRAPH_RDLOCK qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
-- 
2.33.0