Blame SOURCES/kvm-nbd-server-send-more-than-one-extent-of-base-allocat.patch

7711c0
From 6f48ea5b06bd3f566d51996f447c205452c6ee70 Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Fri, 22 Mar 2019 03:22:21 +0100
7711c0
Subject: [PATCH 054/163] nbd/server: send more than one extent of
7711c0
 base:allocation context
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190322032241.8111-9-jsnow@redhat.com>
7711c0
Patchwork-id: 85100
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 08/28] nbd/server: send more than one extent of base:allocation context
7711c0
Bugzilla: 1691563
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
7711c0
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
7711c0
This is necessary for efficient block-status export, for clients which
7711c0
support it.  (qemu is not yet such a client, but could become one.)
7711c0
7711c0
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
Message-Id: <20180704112302.471456-3-vsementsov@virtuozzo.com>
7711c0
[eblake: grammar tweaks]
7711c0
Signed-off-by: Eric Blake <eblake@redhat.com>
7711c0
(cherry picked from commit fb7afc797e071f2616e1ccc849b39fe43e7033bf)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 nbd/server.c | 79 +++++++++++++++++++++++++++++++++++++++++++++---------------
7711c0
 1 file changed, 60 insertions(+), 19 deletions(-)
7711c0
7711c0
diff --git a/nbd/server.c b/nbd/server.c
7711c0
index a8ddc4a..a9fec45 100644
7711c0
--- a/nbd/server.c
7711c0
+++ b/nbd/server.c
7711c0
@@ -1844,37 +1844,68 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
7711c0
     return ret;
7711c0
 }
7711c0
 
7711c0
-static int blockstatus_to_extent_be(BlockDriverState *bs, uint64_t offset,
7711c0
-                                    uint64_t bytes, NBDExtent *extent)
7711c0
+/*
7711c0
+ * Populate @extents from block status. Update @bytes to be the actual
7711c0
+ * length encoded (which may be smaller than the original), and update
7711c0
+ * @nb_extents to the number of extents used.
7711c0
+ *
7711c0
+ * Returns zero on success and -errno on bdrv_block_status_above failure.
7711c0
+ */
7711c0
+static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
7711c0
+                                  uint64_t *bytes, NBDExtent *extents,
7711c0
+                                  unsigned int *nb_extents)
7711c0
 {
7711c0
-    uint64_t remaining_bytes = bytes;
7711c0
+    uint64_t remaining_bytes = *bytes;
7711c0
+    NBDExtent *extent = extents, *extents_end = extents + *nb_extents;
7711c0
+    bool first_extent = true;
7711c0
 
7711c0
+    assert(*nb_extents);
7711c0
     while (remaining_bytes) {
7711c0
         uint32_t flags;
7711c0
         int64_t num;
7711c0
         int ret = bdrv_block_status_above(bs, NULL, offset, remaining_bytes,
7711c0
                                           &num, NULL, NULL);
7711c0
+
7711c0
         if (ret < 0) {
7711c0
             return ret;
7711c0
         }
7711c0
 
7711c0
         flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
7711c0
                 (ret & BDRV_BLOCK_ZERO      ? NBD_STATE_ZERO : 0);
7711c0
+        offset += num;
7711c0
+        remaining_bytes -= num;
7711c0
 
7711c0
-        if (remaining_bytes == bytes) {
7711c0
+        if (first_extent) {
7711c0
             extent->flags = flags;
7711c0
+            extent->length = num;
7711c0
+            first_extent = false;
7711c0
+            continue;
7711c0
         }
7711c0
 
7711c0
-        if (flags != extent->flags) {
7711c0
-            break;
7711c0
+        if (flags == extent->flags) {
7711c0
+            /* extend current extent */
7711c0
+            extent->length += num;
7711c0
+        } else {
7711c0
+            if (extent + 1 == extents_end) {
7711c0
+                break;
7711c0
+            }
7711c0
+
7711c0
+            /* start new extent */
7711c0
+            extent++;
7711c0
+            extent->flags = flags;
7711c0
+            extent->length = num;
7711c0
         }
7711c0
+    }
7711c0
 
7711c0
-        offset += num;
7711c0
-        remaining_bytes -= num;
7711c0
+    extents_end = extent + 1;
7711c0
+
7711c0
+    for (extent = extents; extent < extents_end; extent++) {
7711c0
+        cpu_to_be32s(&extent->flags);
7711c0
+        cpu_to_be32s(&extent->length);
7711c0
     }
7711c0
 
7711c0
-    cpu_to_be32s(&extent->flags);
7711c0
-    extent->length = cpu_to_be32(bytes - remaining_bytes);
7711c0
+    *bytes -= remaining_bytes;
7711c0
+    *nb_extents = extents_end - extents;
7711c0
 
7711c0
     return 0;
7711c0
 }
7711c0
@@ -1910,21 +1941,29 @@ static int nbd_co_send_extents(NBDClient *client, uint64_t handle,
7711c0
 /* Get block status from the exported device and send it to the client */
7711c0
 static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
7711c0
                                     BlockDriverState *bs, uint64_t offset,
7711c0
-                                    uint32_t length, bool last,
7711c0
-                                    uint32_t context_id, Error **errp)
7711c0
+                                    uint32_t length, bool dont_fragment,
7711c0
+                                    bool last, uint32_t context_id,
7711c0
+                                    Error **errp)
7711c0
 {
7711c0
     int ret;
7711c0
-    NBDExtent extent;
7711c0
+    unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BITMAP_EXTENTS;
7711c0
+    NBDExtent *extents = g_new(NBDExtent, nb_extents);
7711c0
+    uint64_t final_length = length;
7711c0
 
7711c0
-    ret = blockstatus_to_extent_be(bs, offset, length, &extent);
7711c0
+    ret = blockstatus_to_extents(bs, offset, &final_length, extents,
7711c0
+                                 &nb_extents);
7711c0
     if (ret < 0) {
7711c0
+        g_free(extents);
7711c0
         return nbd_co_send_structured_error(
7711c0
                 client, handle, -ret, "can't get block status", errp);
7711c0
     }
7711c0
 
7711c0
-    return nbd_co_send_extents(client, handle, &extent, 1,
7711c0
-                               be32_to_cpu(extent.length), last,
7711c0
-                               context_id, errp);
7711c0
+    ret = nbd_co_send_extents(client, handle, extents, nb_extents,
7711c0
+                              final_length, last, context_id, errp);
7711c0
+
7711c0
+    g_free(extents);
7711c0
+
7711c0
+    return ret;
7711c0
 }
7711c0
 
7711c0
 /*
7711c0
@@ -2232,10 +2271,12 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
7711c0
             (client->export_meta.base_allocation ||
7711c0
              client->export_meta.bitmap))
7711c0
         {
7711c0
+            bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE;
7711c0
+
7711c0
             if (client->export_meta.base_allocation) {
7711c0
                 ret = nbd_co_send_block_status(client, request->handle,
7711c0
                                                blk_bs(exp->blk), request->from,
7711c0
-                                               request->len,
7711c0
+                                               request->len, dont_fragment,
7711c0
                                                !client->export_meta.bitmap,
7711c0
                                                NBD_META_ID_BASE_ALLOCATION,
7711c0
                                                errp);
7711c0
@@ -2248,7 +2289,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
7711c0
                 ret = nbd_co_send_bitmap(client, request->handle,
7711c0
                                          client->exp->export_bitmap,
7711c0
                                          request->from, request->len,
7711c0
-                                         request->flags & NBD_CMD_FLAG_REQ_ONE,
7711c0
+                                         dont_fragment,
7711c0
                                          true, NBD_META_ID_DIRTY_BITMAP, errp);
7711c0
                 if (ret < 0) {
7711c0
                     return ret;
7711c0
-- 
7711c0
1.8.3.1
7711c0