<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Aug 3, 2016 at 12:42 PM, Mike Rapoport <span dir="ltr"><<a href="mailto:rppt@linux.vnet.ibm.com" target="_blank">rppt@linux.vnet.ibm.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>On Tue, Aug 02, 2016 at 04:39:37PM +0000, Katerina Koukiou wrote:<br>
> This patch introduces --remote option and image-proxy/image-cache processes.<br>
> This leaves user the option to decide if the checkpoint data are to be stored<br>
> on disk or sent through socket to the image-proxy.<br>
> The latter forwards the data to the destination node where image-cache receives<br>
> them.<br>
><br>
> The overall communication is performed as follows:<br>
> rc_node CRIU dump -> (sends images using a local socket) ->Â Â Â image-proxy<br>
>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â |<br>
>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â V<br>
> dst_node: CRIU restore <- (receives images from a local socket)Â Â <- image-cache<br>
><br>
> Running criu with --remote option is like this:<br>
><br>
> dst_node# criu image-cache --port <port> -o /tmp/image-cache.log<br>
> --local-cache-path <local_cache_path> ...<br>
> dst_node# criu restore --remote -o /tmp/image-cache.log<br>
> --local-cache-path <local_cache_path> ...<br>
> src_node# criu image-proxy --port <port> --address <dst_node> -o /tmp/image-proxy.log<br>
> --local-proxy-path <local_proxy_path> ...<br>
> src_node# criu dump -t <pid> --remote -o /tmp/dump.log<br>
> --local-proxy-path <local_proxy_path> ...<br>
><br>
> Signed-off-by: Rodrigo Bruno <rbruno at <a href="http://gsd.inesc-id.pt" rel="noreferrer" target="_blank">gsd.inesc-id.pt</a>><br>
> Signed-off-by: Katerina Koukiou <<a href="mailto:k.koukiou@gmail.com" target="_blank">k.koukiou@gmail.com</a>><br>
> ---<br>
> criu/Makefile.crtools    |  4 +<br>
> criu/cr-dump.c        | 15 +++<br>
> criu/crtools.c        | 30 ++++-<br>
> criu/image-desc.c      |  4 +-<br>
> criu/image.c         | 26 ++++-<br>
> criu/img-remote.c      | 272 +++++++++++++++++++++++++++++++++++++++++++<br>
> criu/include/cr_options.h  |  3 +<br>
> criu/include/image.h     |  1 +<br>
>Â criu/include/protobuf-desc.h |Â Â 4 +<br>
> criu/include/util.h     |  1 +<br>
> criu/page-xfer.c       | 27 ++++-<br>
> criu/pagemap.c        | 48 ++++++--<br>
> criu/protobuf-desc.c     |  1 +<br>
> criu/util.c         | 15 +++<br>
> images/Makefile       |  1 +<br>
> images/remote-image.proto  | 20 ++++<br>
>Â 16 files changed, 449 insertions(+), 23 deletions(-)<br>
>Â create mode 100644 criu/img-remote.c<br>
>Â create mode 100644 images/remote-image.proto<br>
><br>
> diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools<br>
> index 2665f92..8189960 100644<br>
> --- a/criu/Makefile.crtools<br>
> +++ b/criu/Makefile.crtools<br>
> @@ -26,6 +26,10 @@ obj-y           += files-reg.o<br>
> obj-y            += fsnotify.o<br>
> obj-y            += image-desc.o<br>
> obj-y            += image.o<br>
> +obj-y            += img-remote.o<br>
> +obj-y            += img-proxy.o<br>
> +obj-y            += img-cache.o<br>
> +obj-y            += img-remote-proto.o<br>
> obj-y            += ipc_ns.o<br>
> obj-y            += irmap.o<br>
> obj-y            += kcmp-ids.o<br>
> diff --git a/criu/cr-dump.c b/criu/cr-dump.c<br>
> index be83bec..a8b5ab6 100644<br>
> --- a/criu/cr-dump.c<br>
> +++ b/criu/cr-dump.c<br>
> @@ -84,6 +84,8 @@<br>
><br>
>Â #include "asm/dump.h"<br>
><br>
> +#include "img-remote.h"<br>
> +<br>
>Â static char loc_buf[PAGE_SIZE];<br>
><br>
>Â void free_mappings(struct vm_area_list *vma_area_list)<br>
> @@ -1483,6 +1485,11 @@ int cr_pre_dump_tasks(pid_t pid)<br>
>Â Â Â Â struct pstree_item *item;<br>
>Â Â Â Â int ret = -1;<br>
><br>
> +Â Â Â if (opts.remote && push_snapshot_id() < 0) {<br>
> +Â Â Â Â Â Â Â pr_err("Failed to push image namespace.\n");<br>
> +Â Â Â Â Â Â Â goto err;<br>
> +Â Â Â }<br>
> +<br>
>Â Â Â Â root_item = alloc_pstree_item();<br>
>Â Â Â Â if (!root_item)<br>
>Â Â Â Â Â Â Â Â goto err;<br>
> @@ -1613,6 +1620,9 @@ static int cr_dump_finish(int ret)<br>
><br>
>Â Â Â Â close_service_fd(CR_PROC_FD_OFF);<br>
><br>
> +Â Â Â if (opts.remote)<br>
> +Â Â Â Â Â Â Â finish_remote_dump();<br>
> +<br>
<br>
</div></div>Please take care of possible errors.<br>
Would it be correct to call finish_remote_dump even is ret != 0?<br>
And, what happens if finish_remote_dump fails?<br></blockquote><div>Fixed that. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div><br>
>Â Â Â Â if (ret) {<br>
>Â Â Â Â Â Â Â Â pr_err("Dumping FAILED.\n");<br>
>Â Â Â Â } else {<br>
> @@ -1633,6 +1643,11 @@ int cr_dump_tasks(pid_t pid)<br>
>Â Â Â Â pr_info("Dumping processes (pid: %d)\n", pid);<br>
>Â Â Â Â pr_info("========================================\n");<br>
><br>
> +Â Â Â if (opts.remote && push_snapshot_id() < 0) {<br>
> +Â Â Â Â Â Â Â pr_err("Failed to push image namespace.\n");<br>
> +Â Â Â Â Â Â Â goto err;<br>
> +Â Â Â }<br>
> +<br>
>Â Â Â Â root_item = alloc_pstree_item();<br>
>Â Â Â Â if (!root_item)<br>
>Â Â Â Â Â Â Â Â goto err;<br>
> diff --git a/criu/crtools.c b/criu/crtools.c<br>
> index a0b2fc9..4efca16 100644<br>
> --- a/criu/crtools.c<br>
> +++ b/criu/crtools.c<br>
> @@ -48,6 +48,7 @@<br>
><br>
>Â #include "setproctitle.h"<br>
>Â #include "sysctl.h"<br>
> +#include "img-remote.h"<br>
><br>
>Â struct cr_options opts;<br>
><br>
> @@ -72,6 +73,10 @@ void init_opts(void)<br>
>Â Â Â Â opts.ghost_limit = DEFAULT_GHOST_LIMIT;<br>
>Â Â Â Â opts.timeout = DEFAULT_TIMEOUT;<br>
>Â Â Â Â opts.empty_ns = 0;<br>
> +Â Â Â opts.addr = DEFAULT_CACHE_HOST;<br>
> +Â Â Â opts.port = DEFAULT_CACHE_PORT;<br>
> +Â Â Â opts.local_cache_path = DEFAULT_IMG_PATH;<br>
> +Â Â Â opts.local_proxy_path = DEFAULT_IMG_PATH;<br>
>Â }<br>
><br>
>Â static int parse_join_ns(const char *ptr)<br>
> @@ -279,6 +284,9 @@ int main(int argc, char *argv[], char *envp[])<br>
>        { "cgroup-props-file",     required_argument,   0, 1081 },<br>
>        { "cgroup-dump-controller",   required_argument,   0, 1082 },<br>
>        { SK_INFLIGHT_PARAM,      no_argument,      0, 1083 },<br>
> +       { "remote",           no_argument,      0, 1084 },<br>
> +       { "local-cache-path",      required_argument,   0, 1085 },<br>
> +       { "local-proxy-path",      required_argument,   0, 1086 },<br>
>Â Â Â Â Â Â Â Â { },<br>
>Â Â Â Â };<br>
><br>
> @@ -587,6 +595,15 @@ int main(int argc, char *argv[], char *envp[])<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_msg("Will skip in-flight TCP connections\n");<br>
>Â Â Â Â Â Â Â Â Â Â Â Â opts.tcp_skip_in_flight = true;<br>
>Â Â Â Â Â Â Â Â Â Â Â Â break;<br>
> +Â Â Â Â Â Â Â case 1084:<br>
> +Â Â Â Â Â Â Â Â Â Â Â opts.remote = true;<br>
> +Â Â Â Â Â Â Â Â Â Â Â break;<br>
> +Â Â Â Â Â Â Â case 1085:<br>
> +Â Â Â Â Â Â Â Â Â Â Â opts.local_cache_path = optarg;<br>
> +Â Â Â Â Â Â Â Â Â Â Â break;<br>
> +Â Â Â Â Â Â Â case 1086:<br>
> +Â Â Â Â Â Â Â Â Â Â Â opts.local_proxy_path = optarg;<br>
> +Â Â Â Â Â Â Â Â Â Â Â break;<br>
>Â Â Â Â Â Â Â Â case 'V':<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_msg("Version: %s\n", CRIU_VERSION);<br>
>Â Â Â Â Â Â Â Â Â Â Â Â if (strcmp(CRIU_GITID, "0"))<br>
> @@ -727,6 +744,12 @@ int main(int argc, char *argv[], char *envp[])<br>
>Â Â Â Â if (!strcmp(argv[optind], "page-server"))<br>
>Â Â Â Â Â Â Â Â return cr_page_server(opts.daemon_mode, -1) > 0 ? 0 : 1;<br>
><br>
> +Â Â Â if (!strcmp(argv[optind], "image-cache"))<br>
> +Â Â Â Â Â Â Â return image_cache(opts.local_cache_path, opts.port);<br>
> +<br>
> +Â Â Â if (!strcmp(argv[optind], "image-proxy"))<br>
> +Â Â Â Â Â Â Â return image_proxy(opts.local_proxy_path, opts.addr, opts.port);<br>
> +<br>
>Â Â Â Â if (!strcmp(argv[optind], "service"))<br>
>Â Â Â Â Â Â Â Â return cr_service(opts.daemon_mode);<br>
><br>
> @@ -753,6 +776,8 @@ usage:<br>
>Â "Â criu page-server\n"<br>
>Â "Â criu service [<options>]\n"<br>
>Â "Â criu dedup\n"<br>
> +"Â criu image-cache [<options>]\n"<br>
> +"Â criu image-proxy [<options>]\n"<br>
>Â "\n"<br>
>Â "Commands:\n"<br>
> " dump      checkpoint a process/tree identified by pid\n"<br>
> @@ -765,6 +790,8 @@ usage:<br>
> " dedup     remove duplicates in memory dump\n"<br>
> " cpuinfo dump  writes cpu information into image file\n"<br>
> " cpuinfo check validates cpu information read from image file\n"<br>
> +" image-cache  launch destination-side cache for images sent from the source-side\n"<br>
> +" image-proxy  launch source-side proxy to sent images to the destination-side\n"<br>
>Â Â Â Â );<br>
><br>
>Â Â Â Â if (usage_error) {<br>
> @@ -791,6 +818,7 @@ usage:<br>
>Â "Â Â Â Â Â Â Â Â Â Â Â Â restore making it the parent of the restored process\n"<br>
>Â "Â --freeze-cgroup\n"<br>
>Â "Â Â Â Â Â Â Â Â Â Â Â Â use cgroup freezer to collect processes\n"<br>
> +" --remote       dump/restore images directly to/from remote node using image-proxy/image-cache\n"<br>
>Â "\n"<br>
>Â "* Special resources support:\n"<br>
>Â "Â -x|--" USK_EXT_PARAM "inode,.." "Â Â Â allow external unix connections (optionally can be assign socket's inode that allows one-sided dump)\n"<br>
> @@ -900,7 +928,7 @@ usage:<br>
>Â "\n"<br>
>Â "Page/Service server options:\n"<br>
>Â "Â --address ADDRÂ Â Â Â address of server or service\n"<br>
> -"Â --port PORTÂ Â Â Â Â Â port of page server\n"<br>
> +"Â --port PORTÂ Â Â Â Â Â port of page serve or service\n"<br>
> " -d|--daemon      run in the background after creating socket\n"<br>
>Â "\n"<br>
>Â "Other options:\n"<br>
> diff --git a/criu/image-desc.c b/criu/image-desc.c<br>
> index 2b31354..e146ef8 100644<br>
> --- a/criu/image-desc.c<br>
> +++ b/criu/image-desc.c<br>
> @@ -102,13 +102,13 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {<br>
>Â Â Â Â [CR_FD_STATS] = {<br>
>        .fmt  = "stats-%s",<br>
>        .magic = STATS_MAGIC,<br>
> -Â Â Â Â Â Â Â .oflags = O_SERVICE,<br>
> +Â Â Â Â Â Â Â .oflags = O_SERVICE | O_FORCE_LOCAL,<br>
>Â Â Â Â },<br>
><br>
>Â Â Â Â [CR_FD_IRMAP_CACHE] = {<br>
>        .fmt  = "irmap-cache",<br>
>        .magic = IRMAP_CACHE_MAGIC,<br>
> -Â Â Â Â Â Â Â .oflags = O_SERVICE,<br>
> +Â Â Â Â Â Â Â .oflags = O_SERVICE | O_FORCE_LOCAL,<br>
>Â Â Â Â },<br>
><br>
>Â Â Â Â [CR_FD_FILE_LOCKS_PID] = {<br>
> diff --git a/criu/image.c b/criu/image.c<br>
> index a3bb285..d5ecea2 100644<br>
> --- a/criu/image.c<br>
> +++ b/criu/image.c<br>
> @@ -13,6 +13,7 @@<br>
>Â #include "protobuf.h"<br>
>Â #include "images/inventory.pb-c.h"<br>
>Â #include "images/pagemap.pb-c.h"<br>
> +#include "img-remote.h"<br>
><br>
>Â bool ns_per_id = false;<br>
>Â bool img_common_magic = true;<br>
> @@ -309,9 +310,26 @@ static int do_open_image(struct cr_img *img, int dfd, int type, unsigned long of<br>
>Â {<br>
>Â Â Â Â int ret, flags;<br>
><br>
> -Â Â Â flags = oflags & ~(O_NOBUF | O_SERVICE);<br>
> +Â Â Â flags = oflags & ~(O_NOBUF | O_SERVICE | O_FORCE_LOCAL);<br>
><br>
> -Â Â Â ret = openat(dfd, path, flags, CR_FD_PERM);<br>
> +Â Â Â if (opts.remote && !(oflags & O_FORCE_LOCAL)) {<br>
> +Â Â Â Â Â Â Â char *snapshot_id = NULL;<br>
> +<br>
> +Â Â Â Â Â Â Â snapshot_id = get_snapshot_id_from_idx(dfd);<br>
> +<br>
> +Â Â Â Â Â Â Â if (snapshot_id == NULL)<br>
> +Â Â Â Â Â Â Â Â Â Â Â ret = -1;<br>
> +Â Â Â Â Â Â Â else if (flags == O_RDONLY) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_info("do_open_remote_image RDONLY path=%s snapshot_id=%s\n",<br>
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â path, snapshot_id);<br>
<br>
</div></div>IMHO, pr_debug will suffice here<br>
<span><br>
> +Â Â Â Â Â Â Â Â Â Â Â ret = read_remote_image_connection(snapshot_id, path);<br>
> +Â Â Â Â Â Â Â } else {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_info("do_open_remote_image WDONLY path=%s snapshot_id=%s\n",<br>
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â path, snapshot_id);<br>
<br>
</span>and here<br></blockquote><div>Right, changed these. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div><br>
> +Â Â Â Â Â Â Â Â Â Â Â ret = write_remote_image_connection(snapshot_id, path, O_WRONLY);<br>
> +Â Â Â Â Â Â Â }<br>
> +Â Â Â } else<br>
> +Â Â Â Â Â Â Â ret = openat(dfd, path, flags, CR_FD_PERM);<br>
>Â Â Â Â if (ret < 0) {<br>
>Â Â Â Â Â Â Â Â if (!(flags & O_CREAT) && (errno == ENOENT)) {<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_info("No %s image\n", path);<br>
> @@ -413,7 +431,9 @@ int open_image_dir(char *dir)<br>
>Â Â Â Â close(fd);<br>
>Â Â Â Â fd = ret;<br>
><br>
> -Â Â Â if (opts.img_parent) {<br>
> +Â Â Â if (opts.remote) {<br>
> +Â Â Â Â Â Â Â init_snapshot_id(dir);<br>
> +Â Â Â } else if (opts.img_parent) {<br>
>Â Â Â Â Â Â Â Â ret = symlinkat(opts.img_parent, fd, CR_PARENT_LINK);<br>
>Â Â Â Â Â Â Â Â if (ret < 0 && errno != EEXIST) {<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_perror("Can't link parent snapshot");<br>
> diff --git a/criu/img-remote.c b/criu/img-remote.c<br>
> new file mode 100644<br>
> index 0000000..05f3666<br>
> --- /dev/null<br>
> +++ b/criu/img-remote.c<br>
> @@ -0,0 +1,272 @@<br>
> +#include <unistd.h><br>
> +#include <stdlib.h><br>
> +#include <sys/types.h><br>
> +#include <sys/socket.h><br>
> +#include <netinet/in.h><br>
> +#include <netdb.h><br>
> +#include "xmalloc.h"<br>
> +#include "criu-log.h"<br>
> +#include "img-remote.h"<br>
> +#include "img-remote-proto.h"<br>
> +#include "images/remote-image.pb-c.h"<br>
> +#include "protobuf-desc.h"<br>
> +#include <fcntl.h><br>
> +#include "servicefd.h"<br>
> +#include "compiler.h"<br>
> +#include "cr_options.h"<br>
> +<br>
> +#define PB_LOCAL_IMAGE_SIZE PATHLEN<br>
> +<br>
> +static char *snapshot_id;<br>
> +<br>
> +LIST_HEAD(snapshot_head);<br>
> +<br>
> +/* A snapshot is a dump or pre-dump operation. Each snapshot is identified by an<br>
> + * ID which corresponds to the working directory specefied by the user.<br>
> + */<br>
> +struct snapshot {<br>
> +Â Â Â char snapshot_id[PATHLEN];<br>
> +Â Â Â struct list_head l;<br>
> +};<br>
> +<br>
> +struct snapshot *new_snapshot(char *snapshot_id)<br>
> +{<br>
> +Â Â Â struct snapshot *s = malloc(sizeof(struct snapshot));<br>
> +<br>
> +Â Â Â if (!s)<br>
> +Â Â Â Â Â Â Â pr_perror("Failed to allocate snapshot structure");<br>
<br>
</div></div>Shouldn't we propagate allocation error?<br>
<span><br>
> +Â Â Â strncpy(s->snapshot_id, snapshot_id, PATHLEN);<br>
<br>
</span>because this fill SIGSEGV otherwise ;-)<span></span></blockquote><div>Â <br>Fixed that. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span>
> +Â Â Â return s;<br>
> +}<br>
> +<br>
> +void add_snapshot(struct snapshot *snapshot)<br>
> +{<br>
> +Â Â Â list_add_tail(&(snapshot->l), &snapshot_head);<br>
> +}<br>
> +<br>
> +static char *get_local_img_path(void)<br>
> +{<br>
> +Â Â Â static char *local_img_path = NULL;<br>
> +<br>
> +Â Â Â if (local_img_path != NULL)<br>
> +Â Â Â Â Â Â Â return local_img_path;<br>
> +<br>
> +Â Â Â if (strcmp(opts.local_cache_path, DEFAULT_IMG_PATH))<br>
> +Â Â Â Â Â Â Â local_img_path = opts.local_cache_path;<br>
> +Â Â Â else if (strcmp(opts.local_proxy_path, DEFAULT_IMG_PATH))<br>
> +Â Â Â Â Â Â Â local_img_path = opts.local_proxy_path;<br>
> +<br>
<br>
</span>It seems that if user will pass DEFAULT_IMG_PATH in opts.local_cache_path<br>
and in opts.local_proxy_path, the local_img_path will remain NULL...<br>
<span><br></span></blockquote><div>Fixed that. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span>
> +Â Â Â return local_img_path;<br>
> +}<br>
> +<br>
> +int read_remote_image_connection(char *snapshot_id, char *path)<br>
> +{<br>
> +Â Â Â int error;<br>
> +Â Â Â int sockfd = setup_UNIX_client_socket(get_local_img_path());<br>
> +<br>
> +Â Â Â if (sockfd < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Error opening local connection for %s:%s", path, snapshot_id);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â if (write_header(sockfd, snapshot_id, path, O_RDONLY) < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Error writing header for %s:%s", path, snapshot_id);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â if (read_reply_header(sockfd, &error) < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Error reading reply header for %s:%s", path, snapshot_id);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +Â Â Â errno = error;<br>
<br>
</span>Can you please explain why do you assign errno value?<br>
<div><div><br></div></div></blockquote><div>Yes, the code is not mine; I just rebased it. But I can tell you what I understand.<br></div><div>In criu/image.c when an image does not exist read_remote_image_connection<br></div><div>returns -1. In image.c we want to handle this case separately when <br>read_remote_image_connection returns -1 but the reason is error code ENOENT.<br>Then because read_reply_header does not assign errno but error variable,<br></div><div>we do the "errno = error" assignment by ourselves.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>
> +Â Â Â if (!error)<br>
> +Â Â Â Â Â Â Â return sockfd;<br>
> +Â Â Â else if (error == ENOENT) {<br>
> +Â Â Â Â Â Â Â pr_info("Image does not exist (%s:%s)\n", path, snapshot_id);<br>
> +Â Â Â Â Â Â Â close(sockfd);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +Â Â Â pr_perror("Unexpected error returned: %d (%s:%s)\n", error, path, snapshot_id);<br>
> +Â Â Â close(sockfd);<br>
> +Â Â Â return -1;<br>
> +}<br>
> +<br>
> +int write_remote_image_connection(char *snapshot_id, char *path, int flags)<br>
> +{<br>
> +Â Â Â int sockfd = setup_UNIX_client_socket(get_local_img_path());<br>
> +<br>
> +Â Â Â if (sockfd < 0)<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +<br>
> +Â Â Â if (write_header(sockfd, snapshot_id, path, flags) < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Error writing header for %s:%s", path, snapshot_id);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +Â Â Â return sockfd;<br>
> +}<br>
> +<br>
> +int finish_remote_dump(void)<br>
> +{<br>
> +Â Â Â pr_info("Dump side is calling finish\n");<br>
> +Â Â Â int fd = write_remote_image_connection(NULL_SNAPSHOT_ID, DUMP_FINISH, O_WRONLY);<br>
> +<br>
> +Â Â Â if (fd == -1) {<br>
> +Â Â Â Â Â Â Â pr_perror("Unable to open finish dump connection");<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â close(fd);<br>
> +Â Â Â return 0;<br>
> +}<br>
> +<br>
> +int skip_remote_bytes(int fd, unsigned long len)<br>
> +{<br>
> +Â Â Â static char buf[4096];<br>
> +Â Â Â int n = 0;<br>
> +Â Â Â unsigned long curr = 0;<br>
> +<br>
> +Â Â Â for (; curr < len; ) {<br>
> +Â Â Â Â Â Â Â n = read(fd, buf, min(len - curr, (unsigned long)4096));<br>
> +Â Â Â Â Â Â Â if (n == 0) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_perror("Unexpected end of stream (skipping %lx/%lx bytes)",<br>
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â curr, len);<br>
> +Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â Â Â Â Â } else if (n > 0) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â curr += n;<br>
> +Â Â Â Â Â Â Â } else {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_perror("Error while skipping bytes from stream (%lx/%lx)",<br>
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â curr, len);<br>
> +Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â Â Â Â Â }<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â if (curr != len) {<br>
> +Â Â Â Â Â Â Â pr_perror("Unable to skip the current number of bytes: %lx instead of %lx",<br>
> +Â Â Â Â Â Â Â Â Â Â Â curr, len);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +Â Â Â return 0;<br>
> +}<br>
> +<br>
> +static int pull_snapshot_ids(void)<br>
> +{<br>
> +Â Â Â int n, sockfd;<br>
> +Â Â Â SnapshotIdEntry *ls;<br>
> +Â Â Â struct snapshot *s = NULL;<br>
> +<br>
> +Â Â Â sockfd = read_remote_image_connection(NULL_SNAPSHOT_ID, PARENT_IMG);<br>
> +<br>
> +Â Â Â /* The connection was successful but there is not file. */<br>
> +Â Â Â if (sockfd < 0 && errno == ENOENT)<br>
> +Â Â Â Â Â Â Â return 0;<br>
> +Â Â Â else if (sockfd < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Unable to open snapshot id read connection");<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â while (1) {<br>
> +Â Â Â Â Â Â Â n = pb_read_obj(sockfd, (void **)&ls, PB_SNAPSHOT_ID);<br>
> +Â Â Â Â Â Â Â if (!n) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â close(sockfd);<br>
> +Â Â Â Â Â Â Â Â Â Â Â return n;<br>
> +Â Â Â Â Â Â Â } else if (n < 0) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_perror("Unable to read remote snapshot ids");<br>
> +Â Â Â Â Â Â Â Â Â Â Â close(sockfd);<br>
> +Â Â Â Â Â Â Â Â Â Â Â return n;<br>
> +Â Â Â Â Â Â Â }<br>
> +<br>
> +Â Â Â Â Â Â Â s = new_snapshot(ls->snapshot_id);<br>
> +Â Â Â Â Â Â Â if (!s) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â pr_perror("Unable create new snapshot structure");<br>
> +Â Â Â Â Â Â Â Â Â Â Â close(sockfd);<br>
> +Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â Â Â Â Â }<br>
> +Â Â Â Â Â Â Â add_snapshot(s);<br>
> +Â Â Â Â Â Â Â pr_info("[read_snapshot ids] parent = %s\n", ls->snapshot_id);<br>
> +Â Â Â }<br>
> +Â Â Â free(ls);<br>
> +Â Â Â close(sockfd);<br>
> +Â Â Â return n;<br>
> +}<br>
> +<br>
> +int push_snapshot_id(void)<br>
> +{<br>
> +Â Â Â int n;<br>
> +Â Â Â SnapshotIdEntry rn = SNAPSHOT_ID_ENTRY__INIT;<br>
> +Â Â Â int sockfd = write_remote_image_connection(NULL_SNAPSHOT_ID, PARENT_IMG, O_APPEND);<br>
> +<br>
> +Â Â Â if (sockfd < 0) {<br>
> +Â Â Â Â Â Â Â pr_perror("Unable to open snapshot id push connection");<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â rn.snapshot_id = xmalloc(sizeof(char) * PATHLEN);<br>
> +Â Â Â if (!rn.snapshot_id) {<br>
> +Â Â Â Â Â Â Â pr_perror("Unable to allocate snapshot id buffer");<br>
> +Â Â Â Â Â Â Â close(sockfd);<br>
> +Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â }<br>
> +Â Â Â strncpy(rn.snapshot_id, snapshot_id, PATHLEN);<br>
> +<br>
> +Â Â Â n = pb_write_obj(sockfd, &rn, PB_SNAPSHOT_ID);<br>
> +<br>
> +Â Â Â xfree(rn.snapshot_id);<br>
> +Â Â Â close(sockfd);<br>
> +Â Â Â return n;<br>
> +}<br>
> +<br>
> +void init_snapshot_id(char *si)<br>
> +{<br>
> +Â Â Â snapshot_id = si;<br>
> +}<br>
> +<br>
> +char *get_curr_snapshot_id(void)<br>
> +{<br>
> +Â Â Â return snapshot_id;<br>
> +}<br>
> +<br>
> +int get_curr_snapshot_id_idx(void)<br>
> +{<br>
> +Â Â Â struct snapshot *si;<br>
> +Â Â Â int idx = 0;<br>
> +<br>
> +Â Â Â if (list_empty(&snapshot_head))<br>
> +Â Â Â Â Â Â Â pull_snapshot_ids();<br>
> +<br>
> +Â Â Â list_for_each_entry(si, &snapshot_head, l) {<br>
> +Â Â Â if (!strncmp(si->snapshot_id, snapshot_id, PATHLEN))<br>
> +Â Â Â Â Â Â Â Â Â Â Â return idx;<br>
> +Â Â Â Â Â Â Â idx++;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â pr_perror("Error, could not find current snapshot id (%s) fd", snapshot_id);<br>
> +Â Â Â return -1;<br>
> +}<br>
> +<br>
> +char *get_snapshot_id_from_idx(int idx)<br>
> +{<br>
> +Â Â Â struct snapshot *si;<br>
> +<br>
> +Â Â Â if (list_empty(&snapshot_head))<br>
> +Â Â Â Â Â Â Â pull_snapshot_ids();<br>
> +<br>
> +Â Â Â /* Note: if idx is the service fd then we need the current<br>
> +Â Â Â * snapshot_id idx. Else we need a parent snapshot_id idx.<br>
> +Â Â Â */<br>
> +Â Â Â if (idx == get_service_fd(IMG_FD_OFF))<br>
> +Â Â Â Â Â Â Â idx = get_curr_snapshot_id_idx();<br>
> +<br>
> +Â Â Â list_for_each_entry(si, &snapshot_head, l) {<br>
> +Â Â Â Â Â Â Â if (!idx)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return si->snapshot_id;<br>
> +Â Â Â Â Â Â Â idx--;<br>
> +Â Â Â }<br>
> +<br>
> +Â Â Â pr_perror("Error, could not find snapshot id for idx %d", idx);<br>
> +Â Â Â return NULL;<br>
> +}<br>
> +<br>
> +int get_curr_parent_snapshot_id_idx(void)<br>
> +{<br>
> +Â Â Â return get_curr_snapshot_id_idx() - 1;<br>
> +}<br>
> diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h<br>
> index 8eeadc9..ada8369 100644<br>
> --- a/criu/include/cr_options.h<br>
> +++ b/criu/include/cr_options.h<br>
> @@ -111,6 +111,9 @@ struct cr_options {<br>
>    unsigned int      empty_ns;<br>
>    bool          tcp_skip_in_flight;<br>
>    char          *work_dir;<br>
> +   bool          remote;<br>
> +   char          *local_cache_path;<br>
> +   char          *local_proxy_path;<br>
>Â };<br>
><br>
>Â extern struct cr_options opts;<br>
> diff --git a/criu/include/image.h b/criu/include/image.h<br>
> index 65b7b0a..9ba6ab8 100644<br>
> --- a/criu/include/image.h<br>
> +++ b/criu/include/image.h<br>
> @@ -104,6 +104,7 @@ extern bool img_common_magic;<br>
>Â #define O_DUMPÂ Â Â Â Â Â Â Â (O_WRONLY | O_CREAT | O_TRUNC)<br>
>Â #define O_SHOWÂ Â Â Â Â Â Â Â (O_RDONLY | O_NOBUF)<br>
>Â #define O_RSTRÂ Â Â Â Â Â Â Â (O_RDONLY)<br>
> +#define O_FORCE_LOCALÂ Â (O_SYNC)<br>
><br>
>Â struct cr_img {<br>
>Â Â Â Â union {<br>
> diff --git a/criu/include/protobuf-desc.h b/criu/include/protobuf-desc.h<br>
> index 6c76b49..43ac534 100644<br>
> --- a/criu/include/protobuf-desc.h<br>
> +++ b/criu/include/protobuf-desc.h<br>
> @@ -59,6 +59,10 @@ enum {<br>
>    PB_BINFMT_MISC,     /* 50 */<br>
>Â Â Â Â PB_TTY_DATA,<br>
>Â Â Â Â PB_AUTOFS,<br>
> +   PB_REMOTE_IMAGE,    /* Header for images sent from proxy to cache.*/<br>
> +   PB_LOCAL_IMAGE,     /* Header for reading/writing images from/to proxy or cache. */<br>
> +   PB_LOCAL_IMAGE_REPLY,  /* Header for reading/writing images reply. */<br>
> +   PB_SNAPSHOT_ID,     /* Contains a single id. Used for reading/writing ids from proxy or cache. */<br>
><br>
>Â Â Â Â /* PB_AUTOGEN_STOP */<br>
><br>
> diff --git a/criu/include/util.h b/criu/include/util.h<br>
> index 5b7cad1..63be0ea 100644<br>
> --- a/criu/include/util.h<br>
> +++ b/criu/include/util.h<br>
> @@ -259,6 +259,7 @@ FILE *fopenat(int dirfd, char *path, char *cflags);<br>
>Â void split(char *str, char token, char ***out, int *n);<br>
><br>
>Â int fd_has_data(int lfd);<br>
> +size_t read_into_buffer(int fd, char *buff, size_t size);<br>
><br>
>Â int make_yard(char *path);<br>
><br>
> diff --git a/criu/page-xfer.c b/criu/page-xfer.c<br>
> index 7978227..3c668d7 100644<br>
> --- a/criu/page-xfer.c<br>
> +++ b/criu/page-xfer.c<br>
> @@ -17,6 +17,8 @@<br>
>Â #include "protobuf.h"<br>
>Â #include "images/pagemap.pb-c.h"<br>
><br>
> +#include "img-remote.h"<br>
> +<br>
>Â static int page_server_sk = -1;<br>
><br>
>Â struct page_server_iov {<br>
> @@ -288,7 +290,9 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id)<br>
>Â Â Â Â Â Â Â Â Â Â Â Â goto out;<br>
><br>
>Â Â Â Â Â Â Â Â xfer->parent = xmalloc(sizeof(*xfer->parent));<br>
> -Â Â Â Â Â Â Â if (!xfer->parent) {<br>
> +Â Â Â Â Â Â Â if (!xfer->parent && opts.remote) {<br>
> +Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â Â Â Â Â } else if (!xfer->parent) {<br>
<br>
</div></div>I think using<br>
<br>
        if (!xfer->parent) {<br>
            if (!opts.remote)<br>
                close(pfd);<br>
            return -1;<br>
        }<br>
<br>
is little bit less obscure.<br>
<div><div><br></div></div></blockquote><div>You are right. Changed this. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>
>Â Â Â Â Â Â Â Â Â Â Â Â close(pfd);<br>
>Â Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
>Â Â Â Â Â Â Â Â }<br>
> @@ -298,10 +302,12 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id)<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_perror("No parent image found, though parent directory is set");<br>
>Â Â Â Â Â Â Â Â Â Â Â Â xfree(xfer->parent);<br>
>Â Â Â Â Â Â Â Â Â Â Â Â xfer->parent = NULL;<br>
> -Â Â Â Â Â Â Â Â Â Â Â close(pfd);<br>
> +Â Â Â Â Â Â Â Â Â Â Â if (!opts.remote)<br>
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â close(pfd);<br>
>Â Â Â Â Â Â Â Â Â Â Â Â goto out;<br>
>Â Â Â Â Â Â Â Â }<br>
> -Â Â Â Â Â Â Â close(pfd);<br>
> +Â Â Â Â Â Â Â if (!opts.remote)<br>
> +Â Â Â Â Â Â Â Â Â Â Â close(pfd);<br>
>Â Â Â Â }<br>
><br>
>Â out:<br>
> @@ -406,9 +412,16 @@ int check_parent_local_xfer(int fd_type, int id)<br>
>Â Â Â Â struct stat st;<br>
>Â Â Â Â int ret, pfd;<br>
><br>
> -Â Â Â pfd = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);<br>
> -Â Â Â if (pfd < 0 && errno == ENOENT)<br>
> -Â Â Â Â Â Â Â return 0;<br>
> +Â Â Â if (opts.remote) {<br>
> +Â Â Â Â Â Â Â pfd = get_curr_parent_snapshot_id_idx();<br>
> +Â Â Â Â Â Â Â pr_err("Unable to get parent snapsgot id");<br>
> +Â Â Â Â Â Â Â if (pfd == -1)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> +Â Â Â } else {<br>
> +Â Â Â Â Â Â Â pfd = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);<br>
> +Â Â Â Â Â Â Â if (pfd < 0 && errno == ENOENT)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return 0;<br>
> +Â Â Â }<br>
><br>
>Â Â Â Â snprintf(path, sizeof(path), imgset_template[fd_type].fmt, id);<br>
>Â Â Â Â ret = fstatat(pfd, path, &st, 0);<br>
> @@ -470,6 +483,8 @@ int check_parent_page_xfer(int fd_type, long id)<br>
>Â {<br>
>Â Â Â Â if (opts.use_page_server)<br>
>Â Â Â Â Â Â Â Â return check_parent_server_xfer(fd_type, id);<br>
> +Â Â Â else if (opts.remote)<br>
> +Â Â Â Â Â Â Â return get_curr_parent_snapshot_id_idx() == -1 ? 0 : 1;<br>
>Â Â Â Â else<br>
>Â Â Â Â Â Â Â Â return check_parent_local_xfer(fd_type, id);<br>
>Â }<br>
> diff --git a/criu/pagemap.c b/criu/pagemap.c<br>
> index dbe9cc4..693f967 100644<br>
> --- a/criu/pagemap.c<br>
> +++ b/criu/pagemap.c<br>
> @@ -11,6 +11,8 @@<br>
>Â #include "protobuf.h"<br>
>Â #include "images/pagemap.pb-c.h"<br>
><br>
> +#include "img-remote.h"<br>
> +<br>
>Â #ifndef SEEK_DATA<br>
>Â #define SEEK_DATAÂ Â 3<br>
>Â #define SEEK_HOLEÂ Â 4<br>
> @@ -124,11 +126,18 @@ int dedup_one_iovec(struct page_read *pr, struct iovec *iov)<br>
>Â static int get_pagemap(struct page_read *pr, struct iovec *iov)<br>
>Â {<br>
>Â Â Â Â PagemapEntry *pe;<br>
> +Â Â Â int ret;<br>
><br>
> -Â Â Â if (pr->curr_pme >= pr->nr_pmes)<br>
> -Â Â Â Â Â Â Â return 0;<br>
> +Â Â Â if (opts.remote) {<br>
> +Â Â Â Â Â Â Â ret = pb_read_one_eof(pr->pmi, &pe, PB_PAGEMAP);<br>
> +Â Â Â Â Â Â Â if (ret <= 0)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return ret;<br>
> +Â Â Â } else {<br>
> +Â Â Â Â Â Â Â if (pr->curr_pme >= pr->nr_pmes)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return 0;<br>
><br>
> -Â Â Â pe = pr->pmes[pr->curr_pme];<br>
> +Â Â Â Â Â Â Â pe = pr->pmes[pr->curr_pme];<br>
> +Â Â Â }<br>
><br>
>Â Â Â Â pagemap2iovec(pe, iov);<br>
><br>
> @@ -261,7 +270,7 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,<br>
>Â Â Â Â Â Â Â Â off_t current_vaddr = lseek(fd, pr->pi_off, SEEK_SET);<br>
><br>
>Â Â Â Â Â Â Â Â pr_debug("\tpr%u Read page from self %lx/%"PRIx64"\n", pr->id, pr->cvaddr, current_vaddr);<br>
> -Â Â Â Â Â Â Â ret = read(fd, buf, len);<br>
> +Â Â Â Â Â Â Â ret = read_into_buffer(fd, buf, len);<br>
>Â Â Â Â Â Â Â Â if (ret != len) {<br>
>Â Â Â Â Â Â Â Â Â Â Â Â pr_perror("Can't read mapping page %d", ret);<br>
>Â Â Â Â Â Â Â Â Â Â Â Â return -1;<br>
> @@ -314,7 +323,7 @@ static void close_page_read(struct page_read *pr)<br>
>Â Â Â Â if (pr->pi)<br>
>Â Â Â Â Â Â Â Â close_image(pr->pi);<br>
><br>
> -Â Â Â if (pr->pmes)<br>
> +Â Â Â if (!opts.remote && pr->pmes)<br>
>Â Â Â Â Â Â Â Â free_pagemaps(pr);<br>
>Â }<br>
><br>
> @@ -323,9 +332,24 @@ static int try_open_parent(int dfd, int pid, struct page_read *pr, int pr_flags)<br>
>Â Â Â Â int pfd, ret;<br>
>Â Â Â Â struct page_read *parent = NULL;<br>
><br>
> -Â Â Â pfd = openat(dfd, CR_PARENT_LINK, O_RDONLY);<br>
> -Â Â Â if (pfd < 0 && errno == ENOENT)<br>
> -Â Â Â Â Â Â Â goto out;<br>
> +Â Â Â if (opts.remote) {<br>
> +Â Â Â Â Â Â Â /* Note: we are replacing a real directory FD for a snapshot_id<br>
> +Â Â Â Â Â Â Â * index. Since we need the parent of the current snapshot_id,<br>
> +Â Â Â Â Â Â Â * we want the current snapshot_id index minus one. It is<br>
> +Â Â Â Â Â Â Â * possible that dfd is already a snapshot_id index. We test it<br>
> +Â Â Â Â Â Â Â * by comparing it to the service FD. When opening an image (see<br>
> +Â Â Â Â Â Â Â * do_open_image) we convert the snapshot_id index into a real<br>
> +Â Â Â Â Â Â Â * snapshot_id.<br>
> +Â Â Â Â Â Â Â */<br>
> +Â Â Â Â Â Â Â pfd = dfd == get_service_fd(IMG_FD_OFF) ?<br>
> +Â Â Â Â Â Â Â Â Â Â Â get_curr_snapshot_id_idx() - 1 : dfd - 1;<br>
> +Â Â Â Â Â Â Â if (pfd < 0)<br>
> +Â Â Â Â Â Â Â Â Â Â Â goto out;<br>
> +Â Â Â } else {<br>
> +Â Â Â Â Â Â Â pfd = openat(dfd, CR_PARENT_LINK, O_RDONLY);<br>
> +Â Â Â Â Â Â Â if (pfd < 0 && errno == ENOENT)<br>
> +Â Â Â Â Â Â Â Â Â Â Â goto out;<br>
> +Â Â Â }<br>
><br>
>Â Â Â Â parent = xmalloc(sizeof(*parent));<br>
>Â Â Â Â if (!parent)<br>
> @@ -348,7 +372,8 @@ out:<br>
>Â err_free:<br>
>Â Â Â Â xfree(parent);<br>
>Â err_cl:<br>
> -Â Â Â close(pfd);<br>
> +Â Â Â if (!opts.remote)<br>
> +Â Â Â Â Â Â Â close(pfd);<br>
>Â Â Â Â return -1;<br>
>Â }<br>
><br>
> @@ -458,7 +483,7 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)<br>
>Â Â Â Â Â Â Â Â return -1;<br>
>Â Â Â Â }<br>
><br>
> -Â Â Â if (init_pagemaps(pr)) {<br>
> +Â Â Â if (!opts.remote && init_pagemaps(pr)) {<br>
<br>
</div></div>Is there anything that prevents using init_pagemaps with opts.remote?<br>
Why cannot we just read the entire pagemap from the socket as we read it<br>
from local file?<br></blockquote><div>Â </div><div>I hadn't commented it out at start, but got an error. I am not sure what the exact problem is.<br></div><div>The thing is that img_raw_size(pr->pmi) inside init_pagemaps returns 0; <br></div><div>Tell me if you understand why that happens.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div><br>
>Â Â Â Â Â Â Â Â close_page_read(pr);<br>
>Â Â Â Â Â Â Â Â return -1;<br>
>Â Â Â Â }<br>
> @@ -467,7 +492,8 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)<br>
>Â Â Â Â pr->put_pagemap = put_pagemap;<br>
>Â Â Â Â pr->read_pages = read_pagemap_page;<br>
>Â Â Â Â pr->close = close_page_read;<br>
> -Â Â Â pr->seek_page = seek_pagemap_page;<br>
> +Â Â Â if (!opts.remote)<br>
> +Â Â Â Â Â Â Â pr->seek_page = seek_pagemap_page;<br>
>Â Â Â Â pr->id = ids++;<br>
><br>
>Â Â Â Â pr_debug("Opened page read %u (parent %u)\n",<br>
> diff --git a/criu/protobuf-desc.c b/criu/protobuf-desc.c<br>
> index 9352a76..c1850f9 100644<br>
> --- a/criu/protobuf-desc.c<br>
> +++ b/criu/protobuf-desc.c<br>
> @@ -64,6 +64,7 @@<br>
>Â #include "images/seccomp.pb-c.h"<br>
>Â #include "images/binfmt-misc.pb-c.h"<br>
>Â #include "images/autofs.pb-c.h"<br>
> +#include "images/remote-image.pb-c.h"<br>
><br>
>Â struct cr_pb_message_desc cr_pb_descs[PB_MAX];<br>
><br>
> diff --git a/criu/util.c b/criu/util.c<br>
> index c44d900..5e2f400 100644<br>
> --- a/criu/util.c<br>
> +++ b/criu/util.c<br>
> @@ -1184,3 +1184,18 @@ int setup_tcp_client(char *addr)<br>
><br>
>Â Â Â Â return sk;<br>
>Â }<br>
> +<br>
> +size_t read_into_buffer(int fd, char *buff, size_t size)<br>
> +{<br>
<br>
</div></div>Can you please explain why this wrapper is required?<br></blockquote><div>Actually it's not. It's only used one time. I moved the code.<br></div><div>So, thanks for the comments.<br></div><div>I 'll resend the patches with the above fixes, and rebased on<br></div><div>criu-dev, not master. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div><br>
> +Â Â Â size_t n = 0;<br>
> +Â Â Â size_t curr = 0;<br>
> +<br>
> +Â Â Â while (1) {<br>
> +       n = read(fd, buff + curr, size - curr);<br>
> +Â Â Â Â Â Â Â if (n < 1)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return n;<br>
> +Â Â Â Â Â Â Â curr += n;<br>
> +Â Â Â Â Â Â Â if (curr == size)<br>
> +Â Â Â Â Â Â Â Â Â Â Â return size;<br>
> +Â Â Â }<br>
> +}<br>
> diff --git a/images/Makefile b/images/Makefile<br>
> index cf50794..3753d62 100644<br>
> --- a/images/Makefile<br>
> +++ b/images/Makefile<br>
> @@ -60,6 +60,7 @@ proto-obj-y += binfmt-misc.o<br>
> proto-obj-y += time.o<br>
> proto-obj-y += sysctl.o<br>
> proto-obj-y += autofs.o<br>
> +proto-obj-y += remote-image.o<br>
><br>
>Â CFLAGSÂ Â Â Â Â Â Â Â += -iquote $(obj)/<br>
><br>
> diff --git a/images/remote-image.proto b/images/remote-image.proto<br>
> new file mode 100644<br>
> index 0000000..1212627<br>
> --- /dev/null<br>
> +++ b/images/remote-image.proto<br>
> @@ -0,0 +1,20 @@<br>
> +message local_image_entry {<br>
> +   required string name      = 1;<br>
> +   required string snapshot_id   = 2;<br>
> +   required uint32 open_mode    = 3;<br>
> +}<br>
> +<br>
> +message remote_image_entry {<br>
> +   required string name      = 1;<br>
> +   required string snapshot_id   = 2;<br>
> +   required uint32 open_mode    = 3;<br>
> +   required uint64 size      = 4;<br>
> +}<br>
> +<br>
> +message local_image_reply_entry {<br>
> +   required uint32 error      = 1;<br>
> +}<br>
> +<br>
> +message snapshot_id_entry {<br>
> +   required string snapshot_id   = 1;<br>
> +}<br>
> --<br>
> 2.7.3<br>
><br>
</div></div>> _______________________________________________<br>
> CRIU mailing list<br>
> <a href="mailto:CRIU@openvz.org" target="_blank">CRIU@openvz.org</a><br>
> <a href="https://lists.openvz.org/mailman/listinfo/criu" rel="noreferrer" target="_blank">https://lists.openvz.org/mailman/listinfo/criu</a><br>
><br>
<br>
</blockquote></div><br></div></div>