If a request includes only zeroes, use efficient zero method instead of
sending the zeroes over the wire.
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
examples/Makefile.am | 1 +
examples/copy-libev.c | 68 ++++++++++++++++++++++++++++++++++---------
2 files changed, 55 insertions(+), 14 deletions(-)
diff --git a/examples/Makefile.am b/examples/Makefile.am
index a8286a3..27d2ead 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -224,6 +224,7 @@ copy_libev_SOURCES = \
copy-libev.c \
$(NULL)
copy_libev_CPPFLAGS = \
+ -I$(top_srcdir)/common/include \
-I$(top_srcdir)/include \
$(NULL)
copy_libev_CFLAGS = \
diff --git a/examples/copy-libev.c b/examples/copy-libev.c
index 70a9811..d9fb2c7 100644
--- a/examples/copy-libev.c
+++ b/examples/copy-libev.c
@@ -27,6 +27,8 @@
#include <ev.h>
+#include "iszero.h"
+
/* These values depend on the enviroment tested.
*
* For shared storage using direct I/O:
@@ -79,9 +81,12 @@ static int64_t offset;
static int64_t written;
static bool debug;
+static void start_request(struct request *r);
static void start_read(struct request *r);
+static void start_write(struct request *r);
+static void start_zero(struct request *r);
static int read_completed(void *user_data, int *error);
-static int write_completed(void *user_data, int *error);
+static int request_completed(void *user_data, int *error);
static inline int
get_fd(struct connection *c)
@@ -104,16 +109,25 @@ get_events(struct connection *c)
return events;
}
+/* Start async copy or zero request. */
static void
-start_read(struct request *r)
+start_request(struct request *r)
{
- int64_t cookie;
-
assert (offset < size);
r->length = MIN (REQUEST_SIZE, size - offset);
r->offset = offset;
+ start_read (r);
+
+ offset += r->length;
+}
+
+static void
+start_read(struct request *r)
+{
+ int64_t cookie;
+
DEBUG ("start read offset=%ld len=%ld", r->offset, r->length);
cookie = nbd_aio_pread (
@@ -123,38 +137,64 @@ start_read(struct request *r)
0);
if (cookie == -1)
FAIL ("Cannot start read: %s", nbd_get_error ());
-
- offset += r->length;
}
static int
read_completed (void *user_data, int *error)
{
struct request *r = (struct request *)user_data;
+
+ DEBUG ("read completed offset=%ld len=%ld", r->offset, r->length);
+
+ if (is_zero (r->data, r->length))
+ start_zero (r);
+ else
+ start_write (r);
+
+ return 1;
+}
+
+static void
+start_write(struct request *r)
+{
int64_t cookie;
- DEBUG ("read completed, starting write offset=%ld len=%ld",
- r->offset, r->length);
+ DEBUG ("start write offset=%ld len=%ld", r->offset, r->length);
cookie = nbd_aio_pwrite (
dst.nbd, r->data, r->length, r->offset,
- (nbd_completion_callback) { .callback=write_completed,
+ (nbd_completion_callback) { .callback=request_completed,
.user_data=r },
0);
if (cookie == -1)
FAIL ("Cannot start write: %s", nbd_get_error ());
+}
- return 1;
+static void
+start_zero(struct request *r)
+{
+ int64_t cookie;
+
+ DEBUG ("start zero offset=%ld len=%ld", r->offset, r->length);
+
+ cookie = nbd_aio_zero (
+ dst.nbd, r->length, r->offset,
+ (nbd_completion_callback) { .callback=request_completed,
+ .user_data=r },
+ 0);
+ if (cookie == -1)
+ FAIL ("Cannot start zero: %s", nbd_get_error ());
}
+/* Called when async copy or zero request completed. */
static int
-write_completed (void *user_data, int *error)
+request_completed (void *user_data, int *error)
{
struct request *r = (struct request *)user_data;
written += r->length;
- DEBUG ("write completed offset=%ld len=%ld", r->offset, r->length);
+ DEBUG ("request completed offset=%ld len=%ld", r->offset,
r->length);
if (written == size) {
/* The last write completed. Stop all watchers and break out
@@ -168,7 +208,7 @@ write_completed (void *user_data, int *error)
/* If we have data to read, start a new read. */
if (offset < size)
- start_read(r);
+ start_request(r);
return 1;
}
@@ -249,7 +289,7 @@ main (int argc, char *argv[])
if (r->data == NULL)
FAIL ("Cannot allocate buffer: %s", strerror (errno));
- start_read(r);
+ start_request(r);
}
/* Start watching events on src and dst handles. */
--
2.26.2