qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v7 07/11] qcow2: track guest io requests in data_file


From: Vladimir Sementsov-Ogievskiy
Subject: [PATCH v7 07/11] qcow2: track guest io requests in data_file
Date: Sat, 4 Sep 2021 19:24:24 +0300

We are going to fix a bug of reallocating host cluster that are under
guest operation. For this we need to track these operations.

So, we create BlockReq objects during guest writing and reading data.

That's important for synchronization with further host clusters
reallocation code that we create BlockReq object in same s->lock
critical section where we get an offset.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 block/qcow2.c | 58 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 8aa5679fe9..aefe6558b6 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2212,6 +2212,8 @@ typedef struct Qcow2AioTask {
     QEMUIOVector *qiov;
     uint64_t qiov_offset;
     QCowL2Meta *l2meta; /* only for write */
+
+    BlockReq *req;
 } Qcow2AioTask;
 
 static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task);
@@ -2224,7 +2226,8 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
                                        uint64_t bytes,
                                        QEMUIOVector *qiov,
                                        size_t qiov_offset,
-                                       QCowL2Meta *l2meta)
+                                       QCowL2Meta *l2meta,
+                                       BlockReq *req)
 {
     Qcow2AioTask local_task;
     Qcow2AioTask *task = pool ? g_new(Qcow2AioTask, 1) : &local_task;
@@ -2239,6 +2242,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
         .bytes = bytes,
         .qiov_offset = qiov_offset,
         .l2meta = l2meta,
+        .req = req,
     };
 
     trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
@@ -2260,7 +2264,8 @@ static coroutine_fn int 
qcow2_co_preadv_task(BlockDriverState *bs,
                                              uint64_t host_offset,
                                              uint64_t offset, uint64_t bytes,
                                              QEMUIOVector *qiov,
-                                             size_t qiov_offset)
+                                             size_t qiov_offset,
+                                             BlockReq *req)
 {
     BDRVQcow2State *s = bs->opaque;
     int ret;
@@ -2300,6 +2305,12 @@ static coroutine_fn int 
qcow2_co_preadv_task(BlockDriverState *bs,
         g_assert_not_reached();
     }
 
+    if (req) {
+        WITH_QEMU_LOCK_GUARD(&s->lock) {
+            reqlist_free_req(req);
+        }
+    }
+
     return ret;
 }
 
@@ -2311,7 +2322,7 @@ static coroutine_fn int 
qcow2_co_preadv_task_entry(AioTask *task)
 
     return qcow2_co_preadv_task(t->bs, t->subcluster_type,
                                 t->host_offset, t->offset, t->bytes,
-                                t->qiov, t->qiov_offset);
+                                t->qiov, t->qiov_offset, t->req);
 }
 
 static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
@@ -2327,6 +2338,8 @@ static coroutine_fn int 
qcow2_co_preadv_part(BlockDriverState *bs,
     AioTaskPool *aio = NULL;
 
     while (bytes != 0 && aio_task_pool_status(aio) == 0) {
+        BlockReq *req = NULL;
+
         /* prepare next request */
         cur_bytes = MIN(bytes, INT_MAX);
         if (s->crypto) {
@@ -2336,7 +2349,7 @@ static coroutine_fn int 
qcow2_co_preadv_part(BlockDriverState *bs,
 
         qemu_co_mutex_lock(&s->lock);
         ret = qcow2_get_host_offset(bs, offset, &cur_bytes,
-                                    &host_offset, &type, NULL);
+                                    &host_offset, &type, &req);
         qemu_co_mutex_unlock(&s->lock);
         if (ret < 0) {
             goto out;
@@ -2354,7 +2367,7 @@ static coroutine_fn int 
qcow2_co_preadv_part(BlockDriverState *bs,
             }
             ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, type,
                                  host_offset, offset, cur_bytes,
-                                 qiov, qiov_offset, NULL);
+                                 qiov, qiov_offset, NULL, req);
             if (ret < 0) {
                 goto out;
             }
@@ -2523,7 +2536,8 @@ static coroutine_fn int 
qcow2_co_pwritev_task(BlockDriverState *bs,
                                               uint64_t offset, uint64_t bytes,
                                               QEMUIOVector *qiov,
                                               uint64_t qiov_offset,
-                                              QCowL2Meta *l2meta)
+                                              QCowL2Meta *l2meta,
+                                              BlockReq *req)
 {
     int ret;
     BDRVQcow2State *s = bs->opaque;
@@ -2582,6 +2596,9 @@ out_unlocked:
 
 out_locked:
     qcow2_handle_l2meta(bs, &l2meta, false);
+
+    reqlist_free_req(req);
+
     qemu_co_mutex_unlock(&s->lock);
 
     qemu_vfree(crypt_buf);
@@ -2597,7 +2614,7 @@ static coroutine_fn int 
qcow2_co_pwritev_task_entry(AioTask *task)
 
     return qcow2_co_pwritev_task(t->bs, t->host_offset,
                                  t->offset, t->bytes, t->qiov, t->qiov_offset,
-                                 t->l2meta);
+                                 t->l2meta, t->req);
 }
 
 static coroutine_fn int qcow2_co_pwritev_part(
@@ -2615,6 +2632,7 @@ static coroutine_fn int qcow2_co_pwritev_part(
     trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
 
     while (bytes != 0 && aio_task_pool_status(aio) == 0) {
+        BlockReq *req;
 
         l2meta = NULL;
 
@@ -2630,7 +2648,7 @@ static coroutine_fn int qcow2_co_pwritev_part(
         qemu_co_mutex_lock(&s->lock);
 
         ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes,
-                                      &host_offset, &l2meta, NULL);
+                                      &host_offset, &l2meta, &req);
         if (ret < 0) {
             goto out_locked;
         }
@@ -2638,6 +2656,7 @@ static coroutine_fn int qcow2_co_pwritev_part(
         ret = qcow2_pre_write_overlap_check(bs, 0, host_offset,
                                             cur_bytes, true);
         if (ret < 0) {
+            reqlist_free_req(req);
             goto out_locked;
         }
 
@@ -2648,7 +2667,7 @@ static coroutine_fn int qcow2_co_pwritev_part(
         }
         ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
                              host_offset, offset,
-                             cur_bytes, qiov, qiov_offset, l2meta);
+                             cur_bytes, qiov, qiov_offset, l2meta, req);
         l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
         if (ret < 0) {
             goto fail_nometa;
@@ -4045,6 +4064,7 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
     qemu_co_mutex_lock(&s->lock);
 
     while (bytes != 0) {
+        BlockReq *req = NULL;
         uint64_t copy_offset = 0;
         QCow2SubclusterType type;
         /* prepare next request */
@@ -4052,7 +4072,7 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
         cur_write_flags = write_flags;
 
         ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes,
-                                    &copy_offset, &type, NULL);
+                                    &copy_offset, &type, &req);
         if (ret < 0) {
             goto out;
         }
@@ -4080,6 +4100,7 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
             break;
 
         case QCOW2_SUBCLUSTER_COMPRESSED:
+            reqlist_free_req(req);
             ret = -ENOTSUP;
             goto out;
 
@@ -4096,6 +4117,7 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
                                       dst, dst_offset,
                                       cur_bytes, read_flags, cur_write_flags);
         qemu_co_mutex_lock(&s->lock);
+        reqlist_free_req(req);
         if (ret < 0) {
             goto out;
         }
@@ -4129,6 +4151,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs,
     qemu_co_mutex_lock(&s->lock);
 
     while (bytes != 0) {
+        BlockReq *req;
 
         l2meta = NULL;
 
@@ -4139,7 +4162,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs,
          * the refcnt, without copying user data.
          * Or if src->bs == dst->bs->backing->bs, we could copy by discarding. 
*/
         ret = qcow2_alloc_host_offset(bs, dst_offset, &cur_bytes,
-                                      &host_offset, &l2meta, NULL);
+                                      &host_offset, &l2meta, &req);
         if (ret < 0) {
             goto fail;
         }
@@ -4147,6 +4170,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs,
         ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes,
                                             true);
         if (ret < 0) {
+            reqlist_free_req(req);
             goto fail;
         }
 
@@ -4154,6 +4178,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs,
         ret = bdrv_co_copy_range_to(src, src_offset, s->data_file, host_offset,
                                     cur_bytes, read_flags, write_flags);
         qemu_co_mutex_lock(&s->lock);
+        reqlist_free_req(req);
         if (ret < 0) {
             goto fail;
         }
@@ -4565,6 +4590,7 @@ qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
     ssize_t out_len;
     uint8_t *buf, *out_buf;
     uint64_t cluster_offset;
+    BlockReq *req = NULL;
 
     assert(bytes == s->cluster_size || (bytes < s->cluster_size &&
            (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS)));
@@ -4594,7 +4620,7 @@ qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
 
     qemu_co_mutex_lock(&s->lock);
     ret = qcow2_alloc_compressed_cluster_offset(bs, offset, out_len,
-                                                &cluster_offset, NULL);
+                                                &cluster_offset, &req);
     if (ret < 0) {
         qemu_co_mutex_unlock(&s->lock);
         goto fail;
@@ -4614,6 +4640,11 @@ qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
 success:
     ret = 0;
 fail:
+    if (req) {
+        WITH_QEMU_LOCK_GUARD(&s->lock) {
+            reqlist_free_req(req);
+        }
+    }
     qemu_vfree(buf);
     g_free(out_buf);
     return ret;
@@ -4676,7 +4707,8 @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
         }
 
         ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_compressed_task_entry,
-                             0, 0, offset, chunk_size, qiov, qiov_offset, 
NULL);
+                             0, 0, offset, chunk_size, qiov, qiov_offset, NULL,
+                             NULL);
         if (ret < 0) {
             break;
         }
-- 
2.29.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]