<div dir="ltr">Hi Andrei,<div><br></div><div>thank you.</div><div><br></div><div>So we can start working on fixing bugs in order for the zdtm tests to pass sending patches against </div><div><a href="https://github.com/avagin/criu/tree/remote">https://github.com/avagin/criu/tree/remote</a> ?<br></div><div><br></div><div>cheers,</div><div>rodrigo</div></div><div class="gmail_extra"><br><div class="gmail_quote">2018-05-15 7:49 GMT+01:00 Andrei Vagin <span dir="ltr"><<a href="mailto:avagin@virtuozzo.com" target="_blank">avagin@virtuozzo.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
I rebased these patches and added a few minor fixes:<br>
<a href="https://github.com/avagin/criu/tree/remote" rel="noreferrer" target="_blank">https://github.com/avagin/<wbr>criu/tree/remote</a><br>
<div><div class="h5"><br>
On Mon, May 14, 2018 at 01:29:47AM +0100, rodrigo-bruno wrote:<br>
> From: Rodrigo Bruno <<a href="mailto:rbruno@gsd.inesc-id.pt">rbruno@gsd.inesc-id.pt</a>><br>
> <br>
> ---<br>
> criu/img-remote.c | 93 +++++++++++++++++++++++++++++-<wbr>---------<br>
> criu/include/img-remote.h | 28 ++++++++++--<br>
> 2 files changed, 93 insertions(+), 28 deletions(-)<br>
> <br>
> diff --git a/criu/img-remote.c b/criu/img-remote.c<br>
> index f812c52d..70db71e2 100644<br>
> --- a/criu/img-remote.c<br>
> +++ b/criu/img-remote.c<br>
> @@ -470,8 +470,6 @@ static struct rimage *new_remote_image(char *path, char *snapshot_id)<br>
> buf->nbytes = 0;<br>
> INIT_LIST_HEAD(&(rimg->buf_<wbr>head));<br>
> list_add_tail(&(buf->l), &(rimg->buf_head));<br>
> - rimg->curr_sent_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> - rimg->curr_sent_bytes = 0;<br>
> <br>
> if (pthread_mutex_init(&(rimg-><wbr>in_use), NULL) != 0) {<br>
> pr_err("Remote image in_use mutex init failed\n");<br>
> @@ -498,8 +496,6 @@ static struct rimage *clear_remote_image(struct rimage *rimg)<br>
> <br>
> list_entry(rimg->buf_head.<wbr>next, struct rbuf, l)->nbytes = 0;<br>
> rimg->size = 0;<br>
> - rimg->curr_sent_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> - rimg->curr_sent_bytes = 0;<br>
> <br>
> pthread_mutex_unlock(&(rimg-><wbr>in_use));<br>
> <br>
> @@ -669,18 +665,43 @@ err:<br>
> return NULL;<br>
> }<br>
> <br>
> +<br>
> +int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool close_fd)<br>
> +{<br>
> + int ret;<br>
> + struct roperation *op = malloc(sizeof(struct roperation));<br>
> + bzero(op, sizeof(struct roperation));<br>
> + op->fd = fd;<br>
> + op->rimg = rimg;<br>
> + op->size = size;<br>
> + op->flags = flags;<br>
> + op->close_fd = close_fd;<br>
> + op->curr_recv_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> + while ((ret = recv_image_async(op)) < 0)<br>
> + if (ret != EAGAIN && ret != EWOULDBLOCK)<br>
> + return -1;<br>
> + return ret;<br>
> +}<br>
> +<br>
> /* Note: size is a limit on how much we want to read from the socket. Zero means<br>
> * read until the socket is closed.<br>
> */<br>
> -int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool close_fd)<br>
> +int64_t recv_image_async(struct roperation *op)<br>
> {<br>
> - struct rbuf *curr_buf = NULL;<br>
> + int fd = op->fd;<br>
> + struct rimage *rimg = op->rimg;<br>
> + uint64_t size = op->size;<br>
> + int flags = op->flags;<br>
> + bool close_fd = op->close_fd;<br>
> + struct rbuf *curr_buf = op->curr_recv_buf;<br>
> int n;<br>
> <br>
> - if (flags == O_APPEND)<br>
> - curr_buf = list_entry(rimg->buf_head.<wbr>prev, struct rbuf, l);<br>
> - else<br>
> - curr_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> + if (curr_buf == NULL) {<br>
> + if (flags == O_APPEND)<br>
> + curr_buf = list_entry(rimg->buf_head.<wbr>prev, struct rbuf, l);<br>
> + else<br>
> + curr_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> + }<br>
> <br>
> while (1) {<br>
> n = read(fd,<br>
> @@ -712,6 +733,8 @@ int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool c<br>
> close(fd);<br>
> return rimg->size;<br>
> }<br>
> + } else if (errno == EAGAIN || errno == EWOULDBLOCK) {<br>
> + return errno;<br>
> } else {<br>
> pr_perror("Read on %s:%s socket failed",<br>
> rimg->path, rimg->snapshot_id);<br>
> @@ -724,37 +747,59 @@ int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool c<br>
> <br>
> int64_t send_image(int fd, struct rimage *rimg, int flags, bool close_fd)<br>
> {<br>
> + int ret;<br>
> + struct roperation *op = malloc(sizeof(struct roperation));<br>
> + bzero(op, sizeof(struct roperation));<br>
> + op->fd = fd;<br>
> + op->rimg = rimg;<br>
> + op->flags = flags;<br>
> + op->close_fd = close_fd;<br>
> + op->curr_sent_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> + while ((ret = send_image_async(op)) < 0)<br>
> + if (ret != EAGAIN && ret != EWOULDBLOCK)<br>
> + return -1;<br>
> + return ret;<br>
> +}<br>
> <br>
> - int n, nblocks = 0;<br>
> +int64_t send_image_async(struct roperation *op)<br>
> +{<br>
> + int fd = op->fd;<br>
> + struct rimage *rimg = op->rimg;<br>
> + int flags = op->flags;<br>
> + bool close_fd = op->close_fd;<br>
> + int n;<br>
> <br>
> if (flags != O_APPEND) {<br>
> - rimg->curr_sent_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> - rimg->curr_sent_bytes = 0;<br>
> + op->curr_sent_buf = list_entry(rimg->buf_head.<wbr>next, struct rbuf, l);<br>
> + op->curr_sent_bytes = 0;<br>
> }<br>
> <br>
> while (1) {<br>
> n = send(<br>
> fd,<br>
> - rimg->curr_sent_buf->buffer + rimg->curr_sent_bytes,<br>
> - min(BUF_SIZE, rimg->curr_sent_buf->nbytes) - rimg->curr_sent_bytes,<br>
> + op->curr_sent_buf->buffer + op->curr_sent_bytes,<br>
> + min(BUF_SIZE, op->curr_sent_buf->nbytes) - op->curr_sent_bytes,<br>
> MSG_NOSIGNAL);<br>
> if (n > -1) {<br>
> - rimg->curr_sent_bytes += n;<br>
> - if (rimg->curr_sent_bytes == BUF_SIZE) {<br>
> - rimg->curr_sent_buf =<br>
> - list_entry(rimg->curr_sent_<wbr>buf->l.next, struct rbuf, l);<br>
> - nblocks++;<br>
> - rimg->curr_sent_bytes = 0;<br>
> - } else if (rimg->curr_sent_bytes == rimg->curr_sent_buf->nbytes) {<br>
> + op->curr_sent_bytes += n;<br>
> + if (op->curr_sent_bytes == BUF_SIZE) {<br>
> + op->curr_sent_buf =<br>
> + list_entry(op->curr_sent_buf-><wbr>l.next, struct rbuf, l);<br>
> + op->nblocks++;<br>
> + op->curr_sent_bytes = 0;<br>
> + } else if (op->curr_sent_bytes == op->curr_sent_buf->nbytes) {<br>
> if (close_fd)<br>
> close(fd);<br>
> - return nblocks*BUF_SIZE + rimg->curr_sent_buf->nbytes;<br>
> + return op->nblocks*BUF_SIZE + op->curr_sent_buf->nbytes;<br>
> }<br>
> } else if (errno == EPIPE || errno == ECONNRESET) {<br>
> pr_warn("Connection for %s:%s was closed early than expected\n",<br>
> rimg->path, rimg->snapshot_id);<br>
> return 0;<br>
> - } else {<br>
> + } else if (errno == EAGAIN || errno == EWOULDBLOCK) {<br>
> + return errno;<br>
> + }<br>
> + else {<br>
> pr_perror("Write on %s:%s socket failed",<br>
> rimg->path, rimg->snapshot_id);<br>
> return -1;<br>
> diff --git a/criu/include/img-remote.h b/criu/include/img-remote.h<br>
> index 1771d310..0947e7f0 100644<br>
> --- a/criu/include/img-remote.h<br>
> +++ b/criu/include/img-remote.h<br>
> @@ -36,10 +36,6 @@ struct rimage {<br>
> char snapshot_id[PATHLEN];<br>
> struct list_head l;<br>
> struct list_head buf_head;<br>
> - /* Used to track already sent buffers when the image is appended. */<br>
> - struct rbuf *curr_sent_buf;<br>
> - /* Similar to the previous field. Number of bytes sent in 'curr_sent_buf'. */<br>
> - int curr_sent_bytes;<br>
> uint64_t size; /* number of bytes */<br>
> pthread_mutex_t in_use; /* Only one operation at a time, per image. */<br>
> };<br>
> @@ -57,6 +53,28 @@ struct wthread {<br>
> sem_t wakeup_sem;<br>
> };<br>
> <br>
> +/* Structure that describes the state of a remote operation on remote images. */<br>
> +struct roperation {<br>
> + /* File descriptor being used. */<br>
> + int fd;<br>
> + /* Remote image being used. */<br>
> + struct rimage *rimg;<br>
> + /* Flags for the operation. */<br>
> + int flags;<br>
> + /* If fd should be closed when the operation is done. */<br>
> + bool close_fd;<br>
> + /* Note: recv operation only. How much bytes should be received. */<br>
> + uint64_t size;<br>
> + /* Note: recv operation only. Buffer being writen. */<br>
> + struct rbuf *curr_recv_buf;<br>
> + /* Note: send operation only. Number of blocks already sent. */<br>
> + int nblocks;<br>
> + /* Note: send operation only. Pointer to buffer being sent. */<br>
> + struct rbuf *curr_sent_buf;<br>
> + /* Note: send operation only. Number of bytes sent in 'curr_send_buf. */<br>
> + uint64_t curr_sent_bytes;<br>
> +};<br>
> +<br>
> /* This variable is used to indicate when the dump is finished. */<br>
> extern bool finished;<br>
> /* This is the proxy to cache TCP socket FD. */<br>
> @@ -80,7 +98,9 @@ void *accept_remote_image_<wbr>connections(void *ptr);<br>
> <br>
> int64_t forward_image(struct rimage *rimg);<br>
> int64_t send_image(int fd, struct rimage *rimg, int flags, bool image_check);<br>
> +int64_t send_image_async(struct roperation *op);<br>
> int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool image_check);<br>
> +int64_t recv_image_async(struct roperation *op);<br>
> <br>
> int64_t read_remote_header(int fd, char *snapshot_id, char *path, int *open_mode, uint64_t *size);<br>
> int64_t write_remote_header(int fd, char *snapshot_id, char *path, int open_mode, uint64_t size);<br>
> -- <br>
> 2.17.0<br>
> <br>
</div></div>> ______________________________<wbr>_________________<br>
> CRIU mailing list<br>
> <a href="mailto:CRIU@openvz.org">CRIU@openvz.org</a><br>
> <a href="https://lists.openvz.org/mailman/listinfo/criu" rel="noreferrer" target="_blank">https://lists.openvz.org/<wbr>mailman/listinfo/criu</a><br>
</blockquote></div><br></div>