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(a)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