xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Joshua Otto <joshua.t.otto@gmail.com>
To: xen-devel@lists.xenproject.org
Cc: andrew.cooper3@citrix.com, wei.liu2@citrix.com,
	Joshua Otto <jtotto@uwaterloo.ca>
Subject: [PATCH RFC v2 13/23] libxc/migration: add try_read_record()
Date: Sun, 17 Jun 2018 03:18:24 -0700	[thread overview]
Message-ID: <1529230714-30455-14-git-send-email-joshua.t.otto@gmail.com> (raw)
In-Reply-To: <1529230714-30455-1-git-send-email-joshua.t.otto@gmail.com>

From: Joshua Otto <jtotto@uwaterloo.ca>

Enable non-blocking migration record reads by adding a helper routine that
manages the context of a record read across multiple invocations as the record's
data becomes available over time.

Signed-off-by: Joshua Otto <jtotto@uwaterloo.ca>
---
 tools/libxc/xc_private.c   | 21 +++++++++++----
 tools/libxc/xc_private.h   |  2 ++
 tools/libxc/xc_sr_common.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxc/xc_sr_common.h | 39 ++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index f395594..b33d02f 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -633,26 +633,37 @@ void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits)
     }
 }
 
-int read_exact(int fd, void *data, size_t size)
+int try_read_exact(int fd, void *data, size_t size, size_t *offset)
 {
-    size_t offset = 0;
     ssize_t len;
 
-    while ( offset < size )
+    assert(offset);
+    *offset = 0;
+    while ( *offset < size )
     {
-        len = read(fd, (char *)data + offset, size - offset);
+        len = read(fd, (char *)data + *offset, size - *offset);
         if ( (len == -1) && (errno == EINTR) )
             continue;
         if ( len == 0 )
             errno = 0;
         if ( len <= 0 )
             return -1;
-        offset += len;
+        *offset += len;
     }
 
     return 0;
 }
 
+int read_exact(int fd, void *data, size_t size)
+{
+    size_t offset;
+    int rc;
+
+    rc = try_read_exact(fd, data, size, &offset);
+    assert(rc == -1 || offset == size);
+    return rc;
+}
+
 int write_exact(int fd, const void *data, size_t size)
 {
     size_t offset = 0;
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 1c27b0f..aaae344 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -384,6 +384,8 @@ int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu);
 
 /* Return 0 on success; -1 on error setting errno. */
 int read_exact(int fd, void *data, size_t size); /* EOF => -1, errno=0 */
+/* Like read_exact(), but stores the length read before error to *offset. */
+int try_read_exact(int fd, void *data, size_t size, size_t *offset);
 int write_exact(int fd, const void *data, size_t size);
 int writev_exact(int fd, const struct iovec *iov, int iovcnt);
 
diff --git a/tools/libxc/xc_sr_common.c b/tools/libxc/xc_sr_common.c
index 090b5fd..c37fe1f 100644
--- a/tools/libxc/xc_sr_common.c
+++ b/tools/libxc/xc_sr_common.c
@@ -147,6 +147,71 @@ int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec)
     return 0;
 };
 
+int try_read_record(struct xc_sr_read_record_context *rrctx, int fd,
+                    struct xc_sr_record *rec)
+{
+    int rc;
+    xc_interface *xch = rrctx->ctx->xch;
+    size_t offset_out, dataoff, datasz;
+
+    /* If the header isn't yet complete, attempt to finish it first. */
+    if ( rrctx->offset < sizeof(rrctx->rhdr) )
+    {
+        rc = try_read_exact(fd, (char *)&rrctx->rhdr + rrctx->offset,
+                            sizeof(rrctx->rhdr) - rrctx->offset, &offset_out);
+        rrctx->offset += offset_out;
+
+        if ( rc )
+            return rc;
+    }
+
+    datasz = ROUNDUP(rrctx->rhdr.length, REC_ALIGN_ORDER);
+
+    if ( datasz )
+    {
+        if ( !rrctx->data )
+        {
+            rrctx->data = malloc(datasz);
+
+            if ( !rrctx->data )
+            {
+                ERROR("Unable to allocate %zu bytes for record (0x%08x, %s)",
+                      datasz, rrctx->rhdr.type,
+                      rec_type_to_str(rrctx->rhdr.type));
+                return -1;
+            }
+        }
+
+        dataoff = rrctx->offset - sizeof(rrctx->rhdr);
+        rc = try_read_exact(fd, (char *)rrctx->data + dataoff, datasz - dataoff,
+                            &offset_out);
+        rrctx->offset += offset_out;
+
+        if ( rc == -1 )
+        {
+            /* Differentiate between expected and fatal errors. */
+            if ( (errno != EAGAIN) && (errno != EWOULDBLOCK) )
+            {
+                free(rrctx->data);
+                rrctx->data = NULL;
+                PERROR("Failed to read %zu bytes for record (0x%08x, %s)",
+                       datasz, rrctx->rhdr.type,
+                       rec_type_to_str(rrctx->rhdr.type));
+            }
+
+            return rc;
+        }
+    }
+
+    /* Success!  Fill in the output record structure. */
+    rec->type   = rrctx->rhdr.type;
+    rec->length = rrctx->rhdr.length;
+    rec->data   = rrctx->data;
+    rrctx->data = NULL;
+
+    return 0;
+}
+
 int validate_pages_record(struct xc_sr_context *ctx, struct xc_sr_record *rec,
                           uint32_t expected_type)
 {
diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h
index fc82e71..ce72e0d 100644
--- a/tools/libxc/xc_sr_common.h
+++ b/tools/libxc/xc_sr_common.h
@@ -399,6 +399,45 @@ static inline int write_record(struct xc_sr_context *ctx, int fd,
 int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec);
 
 /*
+ * try_read_record() (prototype below) reads a record from a _non-blocking_
+ * stream over the course of one or more invocations.  Context for the record
+ * read is maintained in an xc_sr_read_record_context.
+ *
+ * The protocol is:
+ * - call read_record_init() on an uninitialized or previously-destroyed
+ *   read-record context prior to using it to read a record
+ * - call try_read_record() with this initialized context one or more times
+ *   - rc < 0 and errno == EAGAIN/EWOULDBLOCK => try again
+ *   - rc < 0 otherwise => failure
+ *   - rc == 0 => a complete record has been read, and is filled into
+ *     try_read_record()'s rec argument
+ * - after either failure or completion of a record, destroy the context with
+ *   read_record_destroy()
+ */
+struct xc_sr_read_record_context
+{
+    struct xc_sr_context *ctx;
+    size_t offset;
+    struct xc_sr_rhdr rhdr;
+    void *data;
+};
+
+static inline void read_record_init(struct xc_sr_read_record_context *rrctx,
+                                    struct xc_sr_context *ctx)
+{
+    *rrctx = (struct xc_sr_read_record_context) { .ctx = ctx };
+}
+
+int try_read_record(struct xc_sr_read_record_context *rrctx, int fd,
+                    struct xc_sr_record *rec);
+
+static inline void read_record_destroy(struct xc_sr_read_record_context *rrctx)
+{
+    free(rrctx->data);
+    rrctx->data = NULL;
+}
+
+/*
  * Given a record of one of the page data types, validate it by:
  * - checking its actual type against its specific expected type
  * - sanity checking its actual length against its claimed length
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-06-17 10:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-17 10:18 [PATCH RFC v2 00/23] Design document and performance evaluation for post-copy live migration Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 01/23] tools: rename COLO 'postcopy' to 'aftercopy' Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 02/23] libxc/xc_sr: parameterise write_record() on fd Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 03/23] libxc/xc_sr_restore.c: use write_record() in send_checkpoint_dirty_pfn_list() Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 04/23] libxc/xc_sr: naming correction: mfns -> gfns Joshua Otto
2018-07-05 15:12   ` Wei Liu
2018-06-17 10:18 ` [PATCH RFC v2 05/23] libxc/xc_sr_restore: introduce generic 'pages' records Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 06/23] libxc/xc_sr_restore: factor helpers out of handle_page_data() Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 07/23] libxc/migration: tidy the xc_domain_save()/restore() interface Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 08/23] libxc/migration: defer precopy policy to a callback Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 09/23] libxl/migration: wire up the precopy policy RPC callback Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 10/23] libxc/xc_sr_save: introduce save batch types Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 11/23] libxc/migration: correct hvm record ordering specification Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 12/23] libxc/migration: specify postcopy live migration Joshua Otto
2018-06-17 10:18 ` Joshua Otto [this message]
2018-06-17 10:18 ` [PATCH RFC v2 14/23] libxc/migration: implement the sender side of " Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 15/23] libxc/migration: implement the receiver " Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 16/23] libxl/libxl_stream_write.c: track callback chains with an explicit phase Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 17/23] libxl/libxl_stream_read.c: " Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 18/23] libxl/migration: implement the sender side of postcopy live migration Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 19/23] libxl/migration: implement the receiver " Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 20/23] tools: expose postcopy live migration support in libxl and xl Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 21/23] xen/mem_paging: move paging op arguments into a union Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 22/23] xen/mem_paging: add a populate_evicted paging op Joshua Otto
2018-06-17 10:18 ` [PATCH RFC v2 23/23] libxc/xc_sr_restore.c: use populate_evicted() Joshua Otto
2021-06-02 11:20 ` [Xen-devel] [PATCH RFC v2 00/23] Design document and performance evaluation for post-copy live migration Olaf Hering

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1529230714-30455-14-git-send-email-joshua.t.otto@gmail.com \
    --to=joshua.t.otto@gmail.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jtotto@uwaterloo.ca \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).