[Libguestfs] [PATCH libnbd] examples: copy-libev: Simplify extents handling

Nir Soffer nirsof at gmail.com
Fri Apr 23 20:20:09 UTC 2021


Using the libnbd format, pair of uint32_t per extent makes the code
harder to understand. Add extent struct and convert the extent entries
to simpler extent array.

Signed-off-by: Nir Soffer <nsoffer at redhat.com>
---
 examples/copy-libev.c | 59 +++++++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 25 deletions(-)

diff --git a/examples/copy-libev.c b/examples/copy-libev.c
index 2e39465..c6ae5be 100644
--- a/examples/copy-libev.c
+++ b/examples/copy-libev.c
@@ -91,25 +91,23 @@ struct request {
     enum request_state state;
 };
 
+struct extent {
+    uint32_t length;
+    bool zero;
+};
+
 static struct ev_loop *loop;
 static ev_prepare prepare;
 static struct connection src;
 static struct connection dst;
 static struct request requests[MAX_REQUESTS];
 
-/* List of extents received from source server. Using the same format returned
- * by libnbd, array of uint32_t pairs. The first item is the length of the
- * extent, and the second is the extent flags.
- *
- * The number of extents is extents_len / 2. extents_pos is the index of the
- * current extent.
- *
- * extents_in_progress flag is set when we start asynchronous block status
- * request.
- */
-static uint32_t *extents;
+/* List of extents received from source server. */
+static struct extent *extents;
 static size_t extents_len;
 static size_t extents_pos;
+
+/* Set when we start asynchronous block status request. */
 static bool extents_in_progress;
 
 static int64_t size;
@@ -191,15 +189,26 @@ extent_callback (void *user_data, const char *metacontext, uint64_t offset,
         return 1;
     }
 
-    extents = malloc (nr_entries * sizeof *extents);
+    /* Libnbd returns uint32_t pair (length, flags) for each extent. */
+    extents_len = nr_entries / 2;
+
+    extents = malloc (extents_len * sizeof *extents);
     if (extents == NULL)
         FAIL ("Cannot allocated extents: %s", strerror (errno));
 
-    memcpy (extents, entries, nr_entries * sizeof *extents);
-    extents_len = nr_entries;
+    /* Copy libnbd entries to extents array. */
+    for (int i = 0, j = 0; i < extents_len; i++, j=i*2) {
+        extents[i].length = entries[j];
+
+        /* Libnbd exposes both ZERO and HOLE flags. We care only about
+         * ZERO status, meaning we can copy this extent using efficinet
+         * zero method.
+         */
+        extents[i].zero = (entries[j + 1] & LIBNBD_STATE_ZERO) != 0;
+    }
 
     DEBUG ("r%d: received %d extents for %s",
-           r->index, nr_entries / 2, metacontext);
+           r->index, extents_len, metacontext);
 
     return 1;
 }
@@ -278,7 +287,7 @@ next_extent (struct request *r)
 
     assert (extents);
 
-    is_zero = extents[extents_pos + 1] & LIBNBD_STATE_ZERO;
+    is_zero = extents[extents_pos].zero;
 
     /* Zero can be much faster, so try to zero entire extent. */
     if (is_zero && dst.can_zero)
@@ -288,30 +297,30 @@ next_extent (struct request *r)
 
     while (length < limit) {
         DEBUG ("e%d: offset=%ld len=%ld zero=%d",
-               extents_pos / 2, offset, extents[extents_pos], is_zero);
+               extents_pos, offset, extents[extents_pos].length, is_zero);
 
         /* If this extent is too large, steal some data from it to
          * complete the request.
          */
-        if (length + extents[extents_pos] > limit) {
+        if (length + extents[extents_pos].length > limit) {
             uint32_t stolen = limit - length;
 
-            extents[extents_pos] -= stolen;
+            extents[extents_pos].length -= stolen;
             length += stolen;
             break;
         }
 
         /* Consume the entire extent and start looking at the next one. */
-        length += extents[extents_pos];
-        extents[extents_pos] = 0;
+        length += extents[extents_pos].length;
+        extents[extents_pos].length = 0;
 
-        if (extents_pos + 2 == extents_len)
+        if (extents_pos + 1 == extents_len)
             break;
 
-        extents_pos += 2;
+        extents_pos++;
 
         /* If next extent is different, we are done. */
-        if ((extents[extents_pos + 1] & LIBNBD_STATE_ZERO) != is_zero)
+        if (extents[extents_pos].zero != is_zero)
             break;
     }
 
@@ -326,7 +335,7 @@ next_extent (struct request *r)
 
     offset += length;
 
-    if (extents_pos + 2 == extents_len && extents[extents_pos] == 0) {
+    if (extents_pos + 1 == extents_len && extents[extents_pos].length == 0) {
         /* Processed all extents, clear extents. */
         DEBUG ("r%d: consumed all extents offset=%ld", r->index, offset);
         free (extents);
-- 
2.26.3




More information about the Libguestfs mailing list