diff --git a/crtools.c b/crtools.c index 50bc89808..cf8ea623c 100644 --- a/crtools.c +++ b/crtools.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) int log_inited = 0; int log_level = 0; - static const char short_opts[] = "dsf:t:p:hcD:o:n:vxVr:jl"; + static const char short_opts[] = "dsRf:t:p:hcD:o:n:vxVr:jl"; BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE); @@ -90,6 +90,7 @@ int main(int argc, char *argv[]) { "tree", required_argument, 0, 't' }, { "pid", required_argument, 0, 'p' }, { "leave-stopped", no_argument, 0, 's' }, + { "leave-running", no_argument, 0, 'R' }, { "restore-detached", no_argument, 0, 'd' }, { "contents", no_argument, 0, 'c' }, { "file", required_argument, 0, 'f' }, @@ -113,6 +114,7 @@ int main(int argc, char *argv[]) { "page-server", no_argument, 0, 50}, { "address", required_argument, 0, 51}, { "port", required_argument, 0, 52}, + { "snapshot", optional_argument, 0, 53}, { }, }; @@ -124,6 +126,9 @@ int main(int argc, char *argv[]) case 's': opts.final_state = TASK_STOPPED; break; + case 'R': + opts.final_state = TASK_ALIVE; + break; case 'x': opts.ext_unix_sk = true; break; @@ -256,6 +261,10 @@ int main(int argc, char *argv[]) case 'l': opts.handle_file_locks = true; break; + case 53: + opts.mem_snapshot = true; + opts.snap_parent = optarg; + break; case 'V': pr_msg("Version: %s\n", version); return 0; @@ -275,6 +284,9 @@ int main(int argc, char *argv[]) return ret; } + if (opts.mem_snapshot) + pr_info("Will do snapshot from %s\n", opts.snap_parent); + ret = open_image_dir(); if (ret < 0) { pr_perror("can't open currect directory"); @@ -355,8 +367,10 @@ usage: pr_msg(" -t|--tree checkpoint/restore the whole process tree identified by pid\n"); pr_msg(" -d|--restore-detached detach after restore\n"); pr_msg(" -s|--leave-stopped leave tasks in stopped state after checkpoint instead of killing them\n"); + pr_msg(" -R|--leave-running leave tasks in running state after checkpoint\n"); pr_msg(" -D|--images-dir directory where to put images to\n"); pr_msg(" --pidfile [FILE] write a pid of a root task in this file\n"); + pr_msg(" --snapshot <[DIR]> create snapshot (relative to DIR images if given)\n"); pr_msg("\n* Special resources support:\n"); pr_msg(" -x|--%s allow external unix connections\n", USK_EXT_PARAM); diff --git a/image.c b/image.c index 6a0376cac..4f74bde46 100644 --- a/image.c +++ b/image.c @@ -325,7 +325,29 @@ int open_image_dir(void) close(fd); + if (opts.snap_parent) { + ret = symlink(opts.snap_parent, CR_PARENT_LINK); + if (ret < 0) { + pr_perror("Can't link parent snapshot."); + goto err; + } + + fd = open(CR_PARENT_LINK, O_RDONLY); + if (fd < 0) { + pr_perror("Can't open parent snapshot."); + goto err; + } + + ret = install_service_fd(PARENT_FD_OFF, fd); + + close(fd); + } + return ret; + +err: + close_image_dir(); + return -1; } void close_image_dir(void) diff --git a/include/crtools.h b/include/crtools.h index 206710dee..62611cabc 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -117,6 +117,8 @@ struct cr_options { struct list_head scripts; bool use_page_server; struct sockaddr_in ps_addr; + bool mem_snapshot; + char *snap_parent; }; extern struct cr_options opts; @@ -131,10 +133,13 @@ enum sfd_type { PROC_FD_OFF, CTL_TTY_OFF, SELF_STDIN_OFF, + PARENT_FD_OFF, SERVICE_FD_MAX }; +#define CR_PARENT_LINK "parent" + extern int clone_service_fd(int id); extern int init_service_fd(void); extern int get_service_fd(enum sfd_type type); diff --git a/protobuf/pagemap.proto b/protobuf/pagemap.proto index d10516799..6d644eff7 100644 --- a/protobuf/pagemap.proto +++ b/protobuf/pagemap.proto @@ -5,4 +5,5 @@ message pagemap_head { message pagemap_entry { required uint64 vaddr = 1; required uint32 nr_pages = 2; + optional bool in_parent = 3; }