diff mbox series

[v5,14/22] parallels: Preserve extensions cluster for non-transient extensions

Message ID 20240311181850.73013-15-alexander.ivanov@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series parallels: Add full dirty bitmap support | expand

Commit Message

Alexander Ivanov March 11, 2024, 6:18 p.m. UTC
There could be non-transient extensions that require presence of the
extensions cluster during work. Mark extensions cluster as used at
extensions loading end nullify l1 tables of dirty bitmaps.
Use this cluster at dirty bitmap saving if it exists.

Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
---
 block/parallels-ext.c | 49 ++++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/block/parallels-ext.c b/block/parallels-ext.c
index 2d839006a4..1ec23aa1e7 100644
--- a/block/parallels-ext.c
+++ b/block/parallels-ext.c
@@ -122,7 +122,7 @@  finish:
  */
 static BdrvDirtyBitmap * GRAPH_RDLOCK
 parallels_load_bitmap(BlockDriverState *bs, uint8_t *data, size_t data_size,
-                      Error **errp)
+                      int64_t ext_off, Error **errp)
 {
     int ret;
     ParallelsDirtyBitmapFeature bf;
@@ -130,6 +130,7 @@  parallels_load_bitmap(BlockDriverState *bs, uint8_t *data, size_t data_size,
     BdrvDirtyBitmap *bitmap;
     QemuUUID uuid;
     char uuidstr[UUID_STR_LEN];
+    int64_t l1_off;
     int i;
 
     if (data_size < sizeof(bf)) {
@@ -171,16 +172,29 @@  parallels_load_bitmap(BlockDriverState *bs, uint8_t *data, size_t data_size,
 
     ret = parallels_load_bitmap_data(bs, l1_table, bf.l1_size, bitmap, errp);
     if (ret < 0) {
-        bdrv_release_dirty_bitmap(bitmap);
-        return NULL;
+        goto err;
+    }
+
+    if (!(bs->open_flags & BDRV_O_RDWR)) {
+        return bitmap;
+    }
+
+    l1_off = ext_off + sizeof(ParallelsDirtyBitmapFeature);
+    ret = bdrv_pwrite_zeroes(bs->file, l1_off,
+                             bf.l1_size * sizeof(uint64_t), 0);
+    if (ret < 0) {
+        goto err;
     }
 
     return bitmap;
+err:
+    bdrv_release_dirty_bitmap(bitmap);
+    return NULL;
 }
 
 static int GRAPH_RDLOCK
-parallels_parse_format_extension(BlockDriverState *bs, uint8_t *ext_cluster,
-                                 Error **errp)
+parallels_parse_format_extension(BlockDriverState *bs, int64_t ext_off,
+                                 uint8_t *ext_cluster, Error **errp)
 {
     BDRVParallelsState *s = bs->opaque;
     int ret;
@@ -259,7 +273,8 @@  parallels_parse_format_extension(BlockDriverState *bs, uint8_t *ext_cluster,
                  */
                 break;
             }
-            bitmap = parallels_load_bitmap(bs, pos, fh.data_size, errp);
+            bitmap = parallels_load_bitmap(bs, pos, fh.data_size,
+                                           ext_off + pos - ext_cluster, errp);
             if (!bitmap) {
                 goto fail;
             }
@@ -298,7 +313,11 @@  int parallels_read_format_extension(BlockDriverState *bs,
         goto out;
     }
 
-    ret = parallels_parse_format_extension(bs, ext_cluster, errp);
+    ret = parallels_parse_format_extension(bs, ext_off, ext_cluster, errp);
+    if (ret == 0) {
+        ret = parallels_mark_used(bs, s->used_bmap, s->used_bmap_size,
+                                  ext_off, 1);
+    }
 
 out:
     qemu_vfree(ext_cluster);
@@ -429,8 +448,6 @@  parallels_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
     size_t hash_len = 0;
     int ret;
 
-    s->header->ext_off = 0;
-
     if (!bdrv_has_named_bitmaps(bs)) {
         return 0;
     }
@@ -447,11 +464,15 @@  parallels_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
         parallels_save_bitmap(bs, bitmap, &pos, &remaining);
     }
 
-    header_off = parallels_allocate_host_clusters(bs, &alloc_size);
-    if (header_off < 0) {
-        error_report("Can't save dirty bitmap: cluster allocation error");
-        ret = header_off;
-        goto end;
+    if (s->header->ext_off) {
+        header_off = le64_to_cpu(s->header->ext_off) << BDRV_SECTOR_BITS;
+    } else {
+        header_off = parallels_allocate_host_clusters(bs, &alloc_size);
+        if (header_off < 0) {
+            error_report("Can't save dirty bitmap: cluster allocation error");
+            ret = header_off;
+            goto end;
+        }
     }
 
     ret = qcrypto_hash_bytes(QCRYPTO_HASH_ALG_MD5,