All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joshua Otto <jtotto@uwaterloo.ca>
To: xen-devel@lists.xenproject.org
Cc: wei.liu2@citrix.com, andrew.cooper3@citrix.com,
	ian.jackson@eu.citrix.com, czylin@uwaterloo.ca,
	Joshua Otto <jtotto@uwaterloo.ca>,
	imhy.yang@gmail.com, hjarmstr@uwaterloo.ca
Subject: [PATCH RFC 13/20] libxc/migration: add try_read_record()
Date: Mon, 27 Mar 2017 05:06:25 -0400	[thread overview]
Message-ID: <1490605592-12189-14-git-send-email-jtotto@uwaterloo.ca> (raw)
In-Reply-To: <1490605592-12189-1-git-send-email-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 | 67 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxc/xc_sr_common.h | 39 +++++++++++++++++++++++++++
 4 files changed, 124 insertions(+), 5 deletions(-)

diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 72e6242..2c53b22 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..b762775 100644
--- a/tools/libxc/xc_sr_common.c
+++ b/tools/libxc/xc_sr_common.c
@@ -147,6 +147,73 @@ 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;
+        else
+            assert(rrctx->offset == sizeof(rrctx->rhdr));
+    }
+
+    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 ee463d9..b52355d 100644
--- a/tools/libxc/xc_sr_common.h
+++ b/tools/libxc/xc_sr_common.h
@@ -394,6 +394,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.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-03-27  9:12 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-27  9:06 [PATCH RFC 00/20] Add postcopy live migration support Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 01/20] tools: rename COLO 'postcopy' to 'aftercopy' Joshua Otto
2017-03-28 16:34   ` Wei Liu
2017-04-11  6:19     ` Zhang Chen
2017-03-27  9:06 ` [PATCH RFC 02/20] libxc/xc_sr: parameterise write_record() on fd Joshua Otto
2017-03-28 18:53   ` Andrew Cooper
2017-03-31 14:19   ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 03/20] libxc/xc_sr_restore.c: use write_record() in send_checkpoint_dirty_pfn_list() Joshua Otto
2017-03-28 18:56   ` Andrew Cooper
2017-03-31 14:19   ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 04/20] libxc/xc_sr_save.c: add WRITE_TRIVIAL_RECORD_FN() Joshua Otto
2017-03-28 19:03   ` Andrew Cooper
2017-03-30  4:28     ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 05/20] libxc/xc_sr: factor out filter_pages() Joshua Otto
2017-03-28 19:27   ` Andrew Cooper
2017-03-30  4:42     ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 06/20] libxc/xc_sr: factor helpers out of handle_page_data() Joshua Otto
2017-03-28 19:52   ` Andrew Cooper
2017-03-30  4:49     ` Joshua Otto
2017-04-12 15:16       ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 07/20] migration: defer precopy policy to libxl Joshua Otto
2017-03-29 18:54   ` Jennifer Herbert
2017-03-30  5:28     ` Joshua Otto
2017-03-29 20:18   ` Andrew Cooper
2017-03-30  5:19     ` Joshua Otto
2017-04-12 15:16       ` Wei Liu
2017-04-18 17:56         ` Ian Jackson
2017-03-27  9:06 ` [PATCH RFC 08/20] libxl/migration: add precopy tuning parameters Joshua Otto
2017-03-29 21:08   ` Andrew Cooper
2017-03-30  6:03     ` Joshua Otto
2017-04-12 15:37       ` Wei Liu
2017-04-27 22:51         ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 09/20] libxc/xc_sr_save: introduce save batch types Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 10/20] libxc/xc_sr_save.c: initialise rec.data before free() Joshua Otto
2017-03-28 19:59   ` Andrew Cooper
2017-03-29 17:47     ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 11/20] libxc/migration: correct hvm record ordering specification Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 12/20] libxc/migration: specify postcopy live migration Joshua Otto
2017-03-27  9:06 ` Joshua Otto [this message]
2017-04-12 15:16   ` [PATCH RFC 13/20] libxc/migration: add try_read_record() Wei Liu
2017-03-27  9:06 ` [PATCH RFC 14/20] libxc/migration: implement the sender side of postcopy live migration Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 15/20] libxc/migration: implement the receiver " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 16/20] libxl/libxl_stream_write.c: track callback chains with an explicit phase Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 17/20] libxl/libxl_stream_read.c: " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 18/20] libxl/migration: implement the sender side of postcopy live migration Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 19/20] libxl/migration: implement the receiver " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 20/20] tools: expose postcopy live migration support in libxl and xl Joshua Otto
2017-03-28 14:41 ` [PATCH RFC 00/20] Add postcopy live migration support Wei Liu
2017-03-30  4:13   ` Joshua Otto
2017-03-31 14:19     ` Wei Liu
2017-03-29 22:50 ` Andrew Cooper
2017-03-31  4:51   ` Joshua Otto
2017-04-12 15:38     ` Wei Liu

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=1490605592-12189-14-git-send-email-jtotto@uwaterloo.ca \
    --to=jtotto@uwaterloo.ca \
    --cc=andrew.cooper3@citrix.com \
    --cc=czylin@uwaterloo.ca \
    --cc=hjarmstr@uwaterloo.ca \
    --cc=ian.jackson@eu.citrix.com \
    --cc=imhy.yang@gmail.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.