From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ross Lagerwall Subject: [PATCH v3 5/6] tools/libxl: Extend datacopier to support reading into a buffer Date: Mon, 16 Mar 2015 13:29:53 +0000 Message-ID: <1426512594-11585-5-git-send-email-ross.lagerwall@citrix.com> References: <1426512594-11585-1-git-send-email-ross.lagerwall@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1426512594-11585-1-git-send-email-ross.lagerwall@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Ross Lagerwall , Wei Liu , Ian Jackson , Ian Campbell , Andrew Cooper List-Id: xen-devel@lists.xenproject.org Currently a datacopier may source its data from an fd or local buffer, but its destination must be an fd. For migration v2, libxl needs to read from the migration stream into a local buffer. Implement a "read into local buffer" mode, invoked when readbuf is set and writefd is -1. On success, the callback passes the number of bytes read. Signed-off-by: Ross Lagerwall [Rewrite commit message] Signed-off-by: Andrew Cooper CC: Ian Campbell CC: Ian Jackson CC: Wei Liu --- tools/libxl/libxl_aoutils.c | 59 +++++++++++++++++++++++++++----------------- tools/libxl/libxl_internal.h | 8 ++++-- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c index dff5d71..a5a10fb 100644 --- a/tools/libxl/libxl_aoutils.c +++ b/tools/libxl/libxl_aoutils.c @@ -134,7 +134,7 @@ static void datacopier_check_state(libxl__egc *egc, libxl__datacopier_state *dc) STATE_AO_GC(dc->ao); int rc; - if (dc->used) { + if (dc->used && !dc->readbuf) { if (!libxl__ev_fd_isregistered(&dc->towrite)) { rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); @@ -148,7 +148,7 @@ static void datacopier_check_state(libxl__egc *egc, libxl__datacopier_state *dc) } else if (!libxl__ev_fd_isregistered(&dc->toread) || dc->bytes_to_read == 0) { /* we have had eof */ - datacopier_callback(egc, dc, 0, 0); + datacopier_callback(egc, dc, 0, dc->readbuf ? dc->used : 0); return; } else { /* nothing buffered, but still reading */ @@ -216,25 +216,31 @@ static void datacopier_readable(libxl__egc *egc, libxl__ev_fd *ev, } assert(revents & POLLIN); for (;;) { - while (dc->used >= dc->maxsz) { - libxl__datacopier_buf *rm = LIBXL_TAILQ_FIRST(&dc->bufs); - dc->used -= rm->used; - assert(dc->used >= 0); - LIBXL_TAILQ_REMOVE(&dc->bufs, rm, entry); - free(rm); - } + libxl__datacopier_buf *buf = NULL; + int r; + + if (dc->readbuf) { + r = read(ev->fd, dc->readbuf + dc->used, dc->bytes_to_read); + } else { + while (dc->used >= dc->maxsz) { + libxl__datacopier_buf *rm = LIBXL_TAILQ_FIRST(&dc->bufs); + dc->used -= rm->used; + assert(dc->used >= 0); + LIBXL_TAILQ_REMOVE(&dc->bufs, rm, entry); + free(rm); + } - libxl__datacopier_buf *buf = - LIBXL_TAILQ_LAST(&dc->bufs, libxl__datacopier_bufs); - if (!buf || buf->used >= sizeof(buf->buf)) { - buf = malloc(sizeof(*buf)); - if (!buf) libxl__alloc_failed(CTX, __func__, 1, sizeof(*buf)); - buf->used = 0; - LIBXL_TAILQ_INSERT_TAIL(&dc->bufs, buf, entry); - } - int r = read(ev->fd, buf->buf + buf->used, + buf = LIBXL_TAILQ_LAST(&dc->bufs, libxl__datacopier_bufs); + if (!buf || buf->used >= sizeof(buf->buf)) { + buf = malloc(sizeof(*buf)); + if (!buf) libxl__alloc_failed(CTX, __func__, 1, sizeof(*buf)); + buf->used = 0; + LIBXL_TAILQ_INSERT_TAIL(&dc->bufs, buf, entry); + } + r = read(ev->fd, buf->buf + buf->used, min_t(size_t, sizeof(buf->buf) - buf->used, (dc->bytes_to_read == -1) ? SIZE_MAX : dc->bytes_to_read)); + } if (r < 0) { if (errno == EINTR) continue; if (errno == EWOULDBLOCK) break; @@ -257,9 +263,11 @@ static void datacopier_readable(libxl__egc *egc, libxl__ev_fd *ev, return; } } - buf->used += r; + if (!dc->readbuf) { + buf->used += r; + assert(buf->used <= sizeof(buf->buf)); + } dc->used += r; - assert(buf->used <= sizeof(buf->buf)); if (dc->bytes_to_read > 0) dc->bytes_to_read -= r; if (dc->bytes_to_read == 0) @@ -318,15 +326,20 @@ int libxl__datacopier_start(libxl__datacopier_state *dc) libxl__datacopier_init(dc); + assert(dc->readfd >= 0 || dc->writefd >= 0); + assert(!(dc->readbuf && dc->bytes_to_read == -1)); + if (dc->readfd >= 0) { rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable, dc->readfd, POLLIN); if (rc) goto out; } - rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, - dc->writefd, POLLOUT); - if (rc) goto out; + if (dc->writefd >= 0) { + rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, + dc->writefd, POLLOUT); + if (rc) goto out; + } return 0; diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 58ac658..931c00c 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -2524,8 +2524,9 @@ typedef struct libxl__datacopier_buf libxl__datacopier_buf; /* onwrite==1 means failure happened when writing, logged, errnoval is valid * onwrite==0 means failure happened when reading - * errnoval==0 means we got eof and all data was written - * errnoval!=0 means we had a read error, logged + * errnoval>=0 means we got eof and all data was written or number of bytes + * written when in read mode + * errnoval<0 means we had a read error, logged * onwrite==-1 means some other internal failure, errnoval not valid, logged * If we get POLLHUP, we call callback_pollhup(..., onwrite, -1); * or if callback_pollhup==0 this is an internal failure, as above. @@ -2550,6 +2551,9 @@ struct libxl__datacopier_state { FILE *log; /* gets a copy of everything */ libxl__datacopier_callback *callback; libxl__datacopier_callback *callback_pollhup; + void *readbuf; /* Set this to read data into it without writing to an + fd. The buffer should be at least as large as the + bytes_to_read parameter, which should not be -1. */ /* remaining fields are private to datacopier */ libxl__ev_fd toread, towrite; ssize_t used; -- 2.1.0