2013-07-18 21:47:11 +04:00
|
|
|
#include "version.h"
|
2014-06-17 21:10:46 +04:00
|
|
|
#include <sys/prctl.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/types.h>
|
2013-12-18 01:04:40 +04:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
2014-06-17 21:10:46 +04:00
|
|
|
#include <signal.h>
|
criu: almost fix building on Alpine Linux
It seems that the different libc (musl) which Alpine Linux uses produces
different errors than the usual glibc. This patch fixes most include
errors. Two errors are not yet resolved on Alpine Linux's libc (musl):
* proc_parse.c: In function 'parse_posix_timers':
proc_parse.c:2125:34: error: 'SIGEV_THREAD_ID' undeclared (first use in this function)
timer->spt.it_sigev_notify = SIGEV_THREAD_ID;
proc_parse.c:2125:34: note: each undeclared identifier is reported only once for each function it appears in
Seems difficult to fix as including <linux/signal.h>, which provides
this #define, generates more different error messages related to
time.h and linux/time.h collisions. It is not yet clear if additional
guards would help in the header files.
* fsnotify.c: In function 'open_by_handle':
fsnotify.c:107:9: error: implicit declaration of function 'open_by_handle_at' [-Werror=implicit-function-declaration]
return open_by_handle_at(fd, arg, O_PATH);
The function open_by_handle_at() is not provided by Alpine Linux's
libc (musl).
This patch resolves the following errors/warnings and has been tested on
RHEL7(x86_64/powerpc64le) and Fedora 24:
cr-service.c: In function 'cr_service':
cr-service.c:1082:26: error: passing argument 2 of 'accept' from incompatible pointer type [-Werror=incompatible-pointer-types]
sk = accept(server_fd, &client_addr, &client_addr_len);
^
In file included from /usr/include/fortify/sys/socket.h:20:0,
from cr-service.c:11:
/usr/include/sys/socket.h:301:5: note: expected 'struct sockaddr * restrict' but argument is of type 'struct sockaddr_un *'
int accept (int, struct sockaddr *__restrict, socklen_t *__restrict);
^
cc1: all warnings being treated as errors
files.c: In function 'open_transport_fd':
files.c:845:19: error: passing argument 2 of 'bind' from incompatible pointer type [-Werror=incompatible-pointer-types]
ret = bind(sock, &saddr, sun_len);
^
In file included from /usr/include/fortify/sys/socket.h:20:0,
from files.c:12:
/usr/include/sys/socket.h:298:5: note: expected 'const struct sockaddr *' but argument is of type 'struct sockaddr_un *'
int bind (int, const struct sockaddr *, socklen_t);
^
cc1: all warnings being treated as errors
In file included from fsnotify.c:18:0:
/usr/include/sys/poll.h:1:2: error: #warning redirecting incorrect #include <sys/poll.h> to <poll.h> [-Werror=cpp]
#warning redirecting incorrect #include <sys/poll.h> to <poll.h>
^
cc1: all warnings being treated as errors
In file included from /root/criu/criu/include/timerfd.h:7:0,
from /root/criu/criu/include/restorer.h:18,
from arch/x86/crtools.c:16:
/root/criu/criu/include/files.h:43:14: error: field 'stat' has incomplete type
struct stat stat;
In file included from arch/x86/vdso-pie.c:6:0:
/root/criu/criu/include/syscall.h:22:66: error: unknown type name 'loff_t'
extern long sys_pread (unsigned int fd, char *buf, size_t count, loff_t pos) ;
^
/root/criu/criu/include/syscall.h:83:31: error: unknown type name 'clockid_t'
extern long sys_timer_create (clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id
^
/root/criu/criu/include/syscall.h:88:38: error: unknown type name 'clockid_t'
extern long sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp) ;
^
In file included from netfilter.c:5:0:
/usr/include/wait.h:1:2: error: #warning redirecting incorrect #include <wait.h> to <sys/wait.h> [-Werror=cpp]
#warning redirecting incorrect #include <wait.h> to <sys/wait.h>
^
cc1: all warnings being treated as errors
pie/restorer.c: In function '__export_restore_task':
pie/restorer.c:1276:23: error: 'LOCK_EX' undeclared (first use in this function)
ret = sys_flock(fd, LOCK_EX);
^
pie/restorer.c:1276:23: note: each undeclared identifier is reported only once for each function it appears in
pie/restorer.c:1310:23: error: 'LOCK_UN' undeclared (first use in this function)
ret = sys_flock(fd, LOCK_UN);
^
sk-unix.c: In function 'open_unixsk_standalone':
sk-unix.c:1169:19: error: passing argument 2 of 'connect' from incompatible pointer type [-Werror=incompatible-pointer-types]
if (connect(sk, &addr, sizeof(addr.sun_family))) {
^
In file included from /usr/include/fortify/sys/socket.h:20:0,
from sk-unix.c:1:
/usr/include/sys/socket.h:299:5: note: expected 'const struct sockaddr *' but argument is of type 'struct sockaddr_un *'
int connect (int, const struct sockaddr *, socklen_t);
^
cc1: all warnings being treated as errors
c/criu.c: In function 'criu_local_set_parent_images':
c/criu.c:169:26: error: implicit declaration of function 'strdup' [-Werror=implicit-function-declaration]
opts->rpc->parent_img = strdup(path);
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2016-07-05 21:45:34 +03:00
|
|
|
#include <string.h>
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
#include "criu.h"
|
|
|
|
#include "rpc.pb-c.h"
|
|
|
|
#include "cr-service-const.h"
|
2013-07-18 21:47:11 +04:00
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
#define CR_DEFAULT_SERVICE_BIN "criu"
|
|
|
|
|
2013-09-14 15:00:17 +04:00
|
|
|
const char *criu_lib_version = CRIU_VERSION;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2015-07-31 15:57:00 +03:00
|
|
|
struct criu_opts {
|
|
|
|
CriuOpts *rpc;
|
|
|
|
int (*notify)(char *action, criu_notify_arg_t na);
|
|
|
|
enum criu_service_comm service_comm;
|
|
|
|
union {
|
|
|
|
char *service_address;
|
|
|
|
int service_fd;
|
|
|
|
char *service_binary;
|
|
|
|
};
|
|
|
|
int swrk_pid;
|
|
|
|
};
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
static criu_opts *global_opts;
|
2013-12-18 01:04:40 +04:00
|
|
|
static int saved_errno;
|
|
|
|
|
2015-07-16 15:42:00 +03:00
|
|
|
void criu_local_set_service_comm(criu_opts *opts, enum criu_service_comm comm)
|
|
|
|
{
|
|
|
|
opts->service_comm = comm;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_service_comm(enum criu_service_comm comm)
|
|
|
|
{
|
|
|
|
criu_local_set_service_comm(global_opts, comm);
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_local_set_service_address(criu_opts *opts, char *path)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
|
|
|
if (path)
|
2015-07-16 15:42:00 +03:00
|
|
|
opts->service_address = path;
|
2013-12-18 01:04:40 +04:00
|
|
|
else
|
2015-07-16 15:42:00 +03:00
|
|
|
opts->service_address = CR_DEFAULT_SERVICE_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_service_address(char *path)
|
|
|
|
{
|
|
|
|
criu_local_set_service_address(global_opts, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_local_set_service_fd(criu_opts *opts, int fd)
|
|
|
|
{
|
|
|
|
opts->service_fd = fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_service_fd(int fd)
|
|
|
|
{
|
|
|
|
criu_local_set_service_fd(global_opts, fd);
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
void criu_local_set_service_binary(criu_opts *opts, char *path)
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
opts->service_binary = path;
|
|
|
|
else
|
|
|
|
opts->service_binary = CR_DEFAULT_SERVICE_BIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_service_binary(char *path)
|
|
|
|
{
|
|
|
|
criu_local_set_service_binary(global_opts, path);
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_init_opts(criu_opts **o)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_opts *opts = NULL;
|
|
|
|
CriuOpts *rpc = NULL;
|
|
|
|
|
|
|
|
opts = *o;
|
|
|
|
|
2015-07-21 13:27:00 +03:00
|
|
|
if (opts) {
|
|
|
|
if (opts->rpc)
|
|
|
|
criu_opts__free_unpacked(opts->rpc, NULL);
|
|
|
|
|
|
|
|
free(opts);
|
|
|
|
opts = NULL;
|
|
|
|
}
|
2015-07-15 04:45:02 +03:00
|
|
|
|
|
|
|
rpc = malloc(sizeof(CriuOpts));
|
|
|
|
if (rpc == NULL) {
|
|
|
|
perror("Can't allocate memory for criu RPC opts");
|
|
|
|
return -1;
|
2014-06-25 19:22:21 +04:00
|
|
|
}
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_opts__init(rpc);
|
|
|
|
|
|
|
|
opts = malloc(sizeof(criu_opts));
|
|
|
|
if (opts == NULL) {
|
2013-12-18 01:04:40 +04:00
|
|
|
perror("Can't allocate memory for criu opts");
|
2015-07-21 13:27:00 +03:00
|
|
|
criu_opts__free_unpacked(rpc, NULL);
|
2013-12-18 01:04:40 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc = rpc;
|
|
|
|
opts->notify = NULL;
|
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
opts->service_comm = CRIU_COMM_BIN;
|
|
|
|
opts->service_address = CR_DEFAULT_SERVICE_BIN;
|
2015-07-16 15:42:00 +03:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
*o = opts;
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_init_opts(void)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_init_opts(&global_opts);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_notify_cb(criu_opts *opts, int (*cb)(char *action, criu_notify_arg_t na))
|
2014-06-25 19:22:21 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->notify = cb;
|
|
|
|
opts->rpc->has_notify_scripts = true;
|
|
|
|
opts->rpc->notify_scripts = true;
|
2014-06-25 19:22:21 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_notify_cb(int (*cb)(char *action, criu_notify_arg_t na))
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_notify_cb(global_opts, cb);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2014-06-26 13:58:53 +04:00
|
|
|
int criu_notify_pid(criu_notify_arg_t na)
|
|
|
|
{
|
|
|
|
return na->has_pid ? na->pid : 0;
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_pid(criu_opts *opts, int pid)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_pid = true;
|
|
|
|
opts->rpc->pid = pid;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_pid(int pid)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_pid(global_opts, pid);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_images_dir_fd(criu_opts *opts, int fd)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->images_dir_fd = fd;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_images_dir_fd(int fd)
|
2014-06-25 17:15:57 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_images_dir_fd(global_opts, fd);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_parent_images(criu_opts *opts, char *path)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->parent_img = strdup(path);
|
2014-06-25 17:15:57 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_parent_images(char *path)
|
2014-06-25 17:15:57 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_parent_images(global_opts, path);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_track_mem(criu_opts *opts, bool track_mem)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_track_mem = true;
|
|
|
|
opts->rpc->track_mem = track_mem;
|
2014-06-25 17:15:57 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_track_mem(bool track_mem)
|
2014-06-25 17:15:57 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_track_mem(global_opts, track_mem);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_auto_dedup(criu_opts *opts, bool auto_dedup)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_auto_dedup = true;
|
|
|
|
opts->rpc->auto_dedup = auto_dedup;
|
2014-06-25 17:15:57 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_auto_dedup(bool auto_dedup)
|
2014-06-25 17:15:57 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_auto_dedup(global_opts, auto_dedup);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_force_irmap(criu_opts *opts, bool force_irmap)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_force_irmap = true;
|
|
|
|
opts->rpc->force_irmap = force_irmap;
|
2014-06-25 17:15:57 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_force_irmap(bool force_irmap)
|
2014-06-25 17:15:57 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_force_irmap(global_opts, force_irmap);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_link_remap(criu_opts *opts, bool link_remap)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_link_remap = true;
|
|
|
|
opts->rpc->link_remap = link_remap;
|
2014-06-25 17:15:57 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_link_remap(bool link_remap)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_link_remap(global_opts, link_remap);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_work_dir_fd(criu_opts *opts, int fd)
|
2014-02-04 18:27:20 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_work_dir_fd = true;
|
|
|
|
opts->rpc->work_dir_fd = fd;
|
2014-02-04 18:27:20 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_work_dir_fd(int fd)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_work_dir_fd(global_opts, fd);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_leave_running(criu_opts *opts, bool leave_running)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_leave_running = true;
|
|
|
|
opts->rpc->leave_running = leave_running;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_leave_running(bool leave_running)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_leave_running(global_opts, leave_running);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_ext_unix_sk(criu_opts *opts, bool ext_unix_sk)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_ext_unix_sk = true;
|
|
|
|
opts->rpc->ext_unix_sk = ext_unix_sk;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_ext_unix_sk(bool ext_unix_sk)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_ext_unix_sk(global_opts, ext_unix_sk);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-29 14:05:50 +03:00
|
|
|
int criu_local_add_unix_sk(criu_opts *opts, unsigned int inode)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
UnixSk **a, *u;
|
|
|
|
|
|
|
|
/*if caller forgot enable ext_unix_sk option we do it*/
|
|
|
|
if (!opts->rpc->has_ext_unix_sk) {
|
|
|
|
criu_local_set_ext_unix_sk(opts, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*if user disabled ext_unix_sk and try to add unixsk inode after that*/
|
|
|
|
if (opts->rpc->has_ext_unix_sk && !opts->rpc->ext_unix_sk) {
|
|
|
|
if (opts->rpc->n_unix_sk_ino > 0) {
|
|
|
|
free(opts->rpc->unix_sk_ino);
|
|
|
|
opts->rpc->n_unix_sk_ino = 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = malloc(sizeof(*u));
|
|
|
|
if (!u)
|
|
|
|
goto er;
|
|
|
|
unix_sk__init(u);
|
|
|
|
|
|
|
|
u->inode = inode;
|
|
|
|
|
|
|
|
nr = opts->rpc->n_unix_sk_ino + 1;
|
|
|
|
a = realloc(opts->rpc->unix_sk_ino, nr * sizeof(u));
|
|
|
|
if (!a)
|
|
|
|
goto er_u;
|
|
|
|
|
|
|
|
a[nr - 1] = u;
|
|
|
|
opts->rpc->unix_sk_ino = a;
|
|
|
|
opts->rpc->n_unix_sk_ino = nr;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
er_u:
|
|
|
|
free(u);
|
|
|
|
er:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_add_unix_sk(unsigned int inode)
|
|
|
|
{
|
|
|
|
return criu_local_add_unix_sk(global_opts, inode);
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_tcp_established(criu_opts *opts, bool tcp_established)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_tcp_established = true;
|
|
|
|
opts->rpc->tcp_established = tcp_established;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_tcp_established(bool tcp_established)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_tcp_established(global_opts, tcp_established);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2016-06-20 23:15:00 +03:00
|
|
|
void criu_local_set_tcp_skip_in_flight(criu_opts *opts, bool tcp_skip_in_flight)
|
|
|
|
{
|
|
|
|
opts->rpc->has_tcp_skip_in_flight = true;
|
|
|
|
opts->rpc->tcp_skip_in_flight = tcp_skip_in_flight;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_tcp_skip_in_flight(bool tcp_skip_in_flight)
|
|
|
|
{
|
|
|
|
criu_local_set_tcp_skip_in_flight(global_opts, tcp_skip_in_flight);
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_evasive_devices(criu_opts *opts, bool evasive_devices)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_evasive_devices = true;
|
|
|
|
opts->rpc->evasive_devices = evasive_devices;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_evasive_devices(bool evasive_devices)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_evasive_devices(global_opts, evasive_devices);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_shell_job(criu_opts *opts, bool shell_job)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_shell_job = true;
|
|
|
|
opts->rpc->shell_job = shell_job;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_shell_job(bool shell_job)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_shell_job(global_opts, shell_job);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_file_locks(criu_opts *opts, bool file_locks)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_file_locks = true;
|
|
|
|
opts->rpc->file_locks = file_locks;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_file_locks(bool file_locks)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_file_locks(global_opts, file_locks);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_log_level(criu_opts *opts, int log_level)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_log_level = true;
|
|
|
|
opts->rpc->log_level = log_level;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_log_level(int log_level)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_log_level(global_opts, log_level);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_root(criu_opts *opts, char *root)
|
2014-03-19 21:59:00 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->root = strdup(root);
|
2014-03-19 21:59:00 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_root(char *root)
|
2014-08-06 22:23:00 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_root(global_opts, root);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_manage_cgroups(criu_opts *opts, bool manage)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_manage_cgroups = true;
|
|
|
|
opts->rpc->manage_cgroups = manage;
|
2014-08-06 22:23:00 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_manage_cgroups(bool manage)
|
2015-04-21 10:33:55 -06:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_manage_cgroups(global_opts, manage);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-08-06 15:39:00 +03:00
|
|
|
void criu_local_set_manage_cgroups_mode(criu_opts *opts, enum criu_cg_mode mode)
|
2015-08-05 21:02:00 +03:00
|
|
|
{
|
|
|
|
opts->rpc->has_manage_cgroups_mode = true;
|
2015-08-06 15:39:00 +03:00
|
|
|
opts->rpc->manage_cgroups_mode = (CriuCgMode)mode;
|
2015-08-05 21:02:00 +03:00
|
|
|
}
|
|
|
|
|
2015-08-06 15:39:00 +03:00
|
|
|
void criu_set_manage_cgroups_mode(enum criu_cg_mode mode)
|
2015-08-05 21:02:00 +03:00
|
|
|
{
|
|
|
|
criu_local_set_manage_cgroups_mode(global_opts, mode);
|
|
|
|
}
|
|
|
|
|
2016-06-10 18:53:00 +03:00
|
|
|
void criu_local_set_freeze_cgroup(criu_opts *opts, char *name)
|
|
|
|
{
|
|
|
|
opts->rpc->freeze_cgroup = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_freeze_cgroup(char *name)
|
|
|
|
{
|
|
|
|
criu_local_set_freeze_cgroup(global_opts, name);
|
|
|
|
}
|
|
|
|
|
2016-06-17 14:22:00 +03:00
|
|
|
void criu_local_set_timeout(criu_opts *opts, unsigned int timeout)
|
|
|
|
{
|
|
|
|
opts->rpc->timeout = timeout;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_timeout(unsigned int timeout)
|
|
|
|
{
|
|
|
|
criu_local_set_timeout(global_opts, timeout);
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_auto_ext_mnt(criu_opts *opts, bool val)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_auto_ext_mnt = true;
|
|
|
|
opts->rpc->auto_ext_mnt = val;
|
2015-04-21 10:33:55 -06:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_auto_ext_mnt(bool val)
|
2015-04-21 10:33:55 -06:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_auto_ext_mnt(global_opts, val);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_ext_sharing(criu_opts *opts, bool val)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_ext_sharing = true;
|
|
|
|
opts->rpc->ext_sharing = val;
|
2015-04-21 10:33:55 -06:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_ext_sharing(bool val)
|
2015-04-21 10:33:55 -06:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_ext_sharing(global_opts, val);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_ext_masters(criu_opts *opts, bool val)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_ext_masters = true;
|
|
|
|
opts->rpc->ext_masters = val;
|
2015-04-21 10:33:55 -06:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_ext_masters(bool val)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_ext_masters(global_opts, val);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_log_file(criu_opts *opts, char *log_file)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->log_file = strdup(log_file);
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_log_file(char *log_file)
|
2014-02-28 18:59:55 +04:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_log_file(global_opts, log_file);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
void criu_local_set_cpu_cap(criu_opts *opts, unsigned int cap)
|
2015-07-13 14:55:00 +03:00
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->has_cpu_cap = true;
|
|
|
|
opts->rpc->cpu_cap = cap;
|
2014-02-28 18:59:55 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
void criu_set_cpu_cap(unsigned int cap)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
criu_local_set_cpu_cap(global_opts, cap);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_set_exec_cmd(criu_opts *opts, int argc, char *argv[])
|
2014-03-22 20:14:00 +04:00
|
|
|
{
|
|
|
|
int i;
|
2014-03-27 16:43:00 +04:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->n_exec_cmd = argc;
|
|
|
|
opts->rpc->exec_cmd = malloc((argc) * sizeof(char *));
|
2014-03-27 16:43:00 +04:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
if (opts->rpc->exec_cmd) {
|
2014-03-27 16:43:00 +04:00
|
|
|
for (i = 0; i < argc; i++) {
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->exec_cmd[i] = strdup(argv[i]);
|
|
|
|
if (!opts->rpc->exec_cmd[i]) {
|
2014-03-27 16:43:00 +04:00
|
|
|
while (i > 0)
|
2015-07-15 04:45:02 +03:00
|
|
|
free(opts->rpc->exec_cmd[i--]);
|
|
|
|
free(opts->rpc->exec_cmd);
|
|
|
|
opts->rpc->n_exec_cmd = 0;
|
|
|
|
opts->rpc->exec_cmd = NULL;
|
2014-03-27 16:43:00 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return -ENOMEM;
|
2014-03-22 20:14:00 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_set_exec_cmd(int argc, char *argv[])
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_set_exec_cmd(global_opts, argc, argv);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_add_ext_mount(criu_opts *opts, char *key, char *val)
|
2014-06-25 17:34:17 +04:00
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
ExtMountMap **a, *m;
|
|
|
|
|
|
|
|
m = malloc(sizeof(*m));
|
|
|
|
if (!m)
|
|
|
|
goto er;
|
2014-07-31 19:51:00 +04:00
|
|
|
ext_mount_map__init(m);
|
|
|
|
|
2014-06-25 17:34:17 +04:00
|
|
|
m->key = strdup(key);
|
|
|
|
if (!m->key)
|
|
|
|
goto er_n;
|
|
|
|
m->val = strdup(val);
|
|
|
|
if (!m->val)
|
|
|
|
goto er_k;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
nr = opts->rpc->n_ext_mnt + 1;
|
|
|
|
a = realloc(opts->rpc->ext_mnt, nr * sizeof(m));
|
2014-06-25 17:34:17 +04:00
|
|
|
if (!a)
|
|
|
|
goto er_v;
|
|
|
|
|
|
|
|
a[nr - 1] = m;
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->ext_mnt = a;
|
|
|
|
opts->rpc->n_ext_mnt = nr;
|
2014-06-25 17:34:17 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
er_v:
|
|
|
|
free(m->val);
|
|
|
|
er_k:
|
|
|
|
free(m->key);
|
|
|
|
er_n:
|
|
|
|
free(m);
|
|
|
|
er:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_add_ext_mount(char *key, char *val)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_add_ext_mount(global_opts, key, val);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_add_cg_root(criu_opts *opts, char *ctrl, char *path)
|
2014-08-22 16:12:05 +04:00
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
CgroupRoot **a, *root;
|
|
|
|
|
|
|
|
root = malloc(sizeof(*root));
|
|
|
|
if (!root)
|
|
|
|
goto er;
|
|
|
|
cgroup_root__init(root);
|
|
|
|
|
|
|
|
if (ctrl) {
|
|
|
|
root->ctrl = strdup(ctrl);
|
|
|
|
if (!root->ctrl)
|
|
|
|
goto er_r;
|
|
|
|
}
|
|
|
|
|
|
|
|
root->path = strdup(path);
|
|
|
|
if (!root->path)
|
|
|
|
goto er_c;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
nr = opts->rpc->n_cg_root + 1;
|
|
|
|
a = realloc(opts->rpc->cg_root, nr * sizeof(root));
|
2014-08-22 16:12:05 +04:00
|
|
|
if (!a)
|
|
|
|
goto er_p;
|
|
|
|
|
|
|
|
a[nr - 1] = root;
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->cg_root = a;
|
|
|
|
opts->rpc->n_cg_root = nr;
|
2014-08-22 16:12:05 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
er_p:
|
|
|
|
free(root->path);
|
|
|
|
er_c:
|
|
|
|
if (root->ctrl)
|
|
|
|
free(root->ctrl);
|
|
|
|
er_r:
|
|
|
|
free(root);
|
|
|
|
er:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2015-07-13 14:55:00 +03:00
|
|
|
|
|
|
|
int criu_add_cg_root(char *ctrl, char *path)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_add_cg_root(global_opts, ctrl, path);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_add_veth_pair(criu_opts *opts, char *in, char *out)
|
2014-06-25 17:37:50 +04:00
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
CriuVethPair **a, *p;
|
|
|
|
|
|
|
|
p = malloc(sizeof(*p));
|
|
|
|
if (!p)
|
|
|
|
goto er;
|
2014-07-31 19:51:00 +04:00
|
|
|
criu_veth_pair__init(p);
|
|
|
|
|
2014-06-25 17:37:50 +04:00
|
|
|
p->if_in = strdup(in);
|
|
|
|
if (!p->if_in)
|
|
|
|
goto er_p;
|
|
|
|
p->if_out = strdup(out);
|
|
|
|
if (!p->if_out)
|
|
|
|
goto er_i;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
nr = opts->rpc->n_veths + 1;
|
|
|
|
a = realloc(opts->rpc->veths, nr * sizeof(p));
|
2014-06-25 17:37:50 +04:00
|
|
|
if (!a)
|
|
|
|
goto er_o;
|
|
|
|
|
|
|
|
a[nr - 1] = p;
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->veths = a;
|
|
|
|
opts->rpc->n_veths = nr;
|
2014-06-25 17:37:50 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
er_o:
|
|
|
|
free(p->if_out);
|
|
|
|
er_i:
|
|
|
|
free(p->if_in);
|
|
|
|
er_p:
|
|
|
|
free(p);
|
|
|
|
er:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_add_veth_pair(char *in, char *out)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_add_veth_pair(global_opts, in, out);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_add_enable_fs(criu_opts *opts, char *fs)
|
2015-05-06 12:22:00 +03:00
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
char *str = NULL;
|
|
|
|
char **ptr = NULL;
|
|
|
|
|
|
|
|
str = strdup(fs);
|
|
|
|
if (!str)
|
|
|
|
goto err;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
nr = opts->rpc->n_enable_fs + 1;
|
|
|
|
ptr = realloc(opts->rpc->enable_fs, nr * sizeof(*ptr));
|
2015-05-06 12:22:00 +03:00
|
|
|
if (!ptr)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
ptr[nr - 1] = str;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->n_enable_fs = nr;
|
|
|
|
opts->rpc->enable_fs = ptr;
|
2015-05-06 12:22:00 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (str)
|
|
|
|
free(str);
|
|
|
|
if (ptr)
|
|
|
|
free(ptr);
|
|
|
|
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_add_enable_fs(char *fs)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_add_enable_fs(global_opts, fs);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_add_skip_mnt(criu_opts *opts, char *mnt)
|
2015-05-06 12:22:00 +03:00
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
char *str = NULL;
|
|
|
|
char **ptr = NULL;
|
|
|
|
|
|
|
|
str = strdup(mnt);
|
|
|
|
if (!str)
|
|
|
|
goto err;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
nr = opts->rpc->n_skip_mnt + 1;
|
|
|
|
ptr = realloc(opts->rpc->skip_mnt, nr * sizeof(*ptr));
|
2015-05-06 12:22:00 +03:00
|
|
|
if (!ptr)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
ptr[nr - 1] = str;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
opts->rpc->n_skip_mnt = nr;
|
|
|
|
opts->rpc->skip_mnt = ptr;
|
2015-05-06 12:22:00 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (str)
|
|
|
|
free(str);
|
|
|
|
if (ptr)
|
|
|
|
free(ptr);
|
|
|
|
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2015-09-16 07:27:00 +03:00
|
|
|
int criu_local_add_irmap_path(criu_opts *opts, char *path)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
char *my_path;
|
|
|
|
char **m;
|
|
|
|
|
|
|
|
if (!opts)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
my_path = strdup(path);
|
|
|
|
if (!my_path)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
nr = opts->rpc->n_irmap_scan_paths + 1;
|
|
|
|
m = realloc(opts->rpc->irmap_scan_paths, nr * sizeof(*m));
|
|
|
|
if (!m)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
m[nr - 1] = my_path;
|
|
|
|
|
|
|
|
opts->rpc->n_irmap_scan_paths = nr;
|
|
|
|
opts->rpc->irmap_scan_paths = m;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (my_path)
|
|
|
|
free(my_path);
|
|
|
|
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2016-05-30 18:49:00 +03:00
|
|
|
int criu_local_add_cg_props(criu_opts *opts, char *stream)
|
|
|
|
{
|
|
|
|
char *new;
|
|
|
|
|
|
|
|
new = strdup(stream);
|
|
|
|
if (!new)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
free(opts->rpc->cgroup_props);
|
|
|
|
opts->rpc->cgroup_props = new;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_local_add_cg_props_file(criu_opts *opts, char *path)
|
|
|
|
{
|
|
|
|
char *new;
|
|
|
|
|
|
|
|
new = strdup(path);
|
|
|
|
if (!new)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
free(opts->rpc->cgroup_props_file);
|
|
|
|
opts->rpc->cgroup_props_file = new;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_local_add_cg_dump_controller(criu_opts *opts, char *name)
|
|
|
|
{
|
|
|
|
char **new;
|
|
|
|
size_t nr;
|
|
|
|
|
2016-06-01 15:22:00 +03:00
|
|
|
nr = opts->rpc->n_cgroup_dump_controller + 1;
|
|
|
|
new = realloc(opts->rpc->cgroup_dump_controller, nr * sizeof(char *));
|
2016-05-30 18:49:00 +03:00
|
|
|
if (!new)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2016-06-01 15:22:00 +03:00
|
|
|
new[opts->rpc->n_cgroup_dump_controller] = strdup(name);
|
|
|
|
if (!new[opts->rpc->n_cgroup_dump_controller])
|
2016-05-30 18:49:00 +03:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2016-06-01 15:22:00 +03:00
|
|
|
opts->rpc->n_cgroup_dump_controller = nr;
|
|
|
|
opts->rpc->cgroup_dump_controller = new;
|
2016-05-30 18:49:00 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_add_skip_mnt(char *mnt)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_add_skip_mnt(global_opts, mnt);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-08-10 17:20:50 +03:00
|
|
|
void criu_local_set_ghost_limit(criu_opts *opts, unsigned int limit)
|
|
|
|
{
|
|
|
|
opts->rpc->has_ghost_limit = true;
|
|
|
|
opts->rpc->ghost_limit = limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
void criu_set_ghost_limit(unsigned int limit)
|
|
|
|
{
|
|
|
|
criu_local_set_ghost_limit(global_opts, limit);
|
|
|
|
}
|
|
|
|
|
2015-09-16 07:27:00 +03:00
|
|
|
int criu_add_irmap_path(char *path)
|
|
|
|
{
|
|
|
|
return criu_local_add_irmap_path(global_opts, path);
|
|
|
|
}
|
|
|
|
|
2016-10-13 16:07:00 +03:00
|
|
|
int criu_local_add_inherit_fd(criu_opts *opts, int fd, char *key)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
InheritFd **a, *f;
|
|
|
|
|
|
|
|
/* Inheriting is only supported with swrk mode */
|
|
|
|
if (opts->service_comm != CRIU_COMM_BIN)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
f = malloc(sizeof(*f));
|
|
|
|
if (!f)
|
|
|
|
goto er;
|
|
|
|
inherit_fd__init(f);
|
|
|
|
|
|
|
|
f->fd = fd;
|
|
|
|
f->key = strdup(key);
|
|
|
|
if (!f->key)
|
|
|
|
goto er_f;
|
|
|
|
|
|
|
|
nr = opts->rpc->n_inherit_fd + 1;
|
|
|
|
a = realloc(opts->rpc->inherit_fd, nr * sizeof(f));
|
|
|
|
if (!a)
|
|
|
|
goto err_k;
|
|
|
|
|
|
|
|
a[nr - 1] = f;
|
|
|
|
opts->rpc->inherit_fd = a;
|
|
|
|
opts->rpc->n_inherit_fd = nr;
|
|
|
|
return 0;
|
|
|
|
err_k:
|
|
|
|
free(f->key);
|
|
|
|
er_f:
|
|
|
|
free(f);
|
|
|
|
er:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_add_inherit_fd(int fd, char *key)
|
|
|
|
{
|
|
|
|
return criu_local_add_inherit_fd(global_opts, fd, key);
|
|
|
|
}
|
|
|
|
|
2016-10-21 21:10:00 +03:00
|
|
|
int criu_local_add_external(criu_opts *opts, char *key)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
char **a, *e = NULL;
|
|
|
|
|
|
|
|
e = strdup(key);
|
|
|
|
if (!e)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
nr = opts->rpc->n_external + 1;
|
|
|
|
a = realloc(opts->rpc->external, nr * sizeof(*a));
|
|
|
|
if (!a)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
a[nr - 1] = e;
|
|
|
|
opts->rpc->external = a;
|
|
|
|
opts->rpc->n_external = nr;
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if (e)
|
|
|
|
free(e);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_add_external(char *key)
|
|
|
|
{
|
|
|
|
return criu_local_add_external(global_opts, key);
|
|
|
|
}
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
static CriuResp *recv_resp(int socket_fd)
|
|
|
|
{
|
2015-11-13 17:10:08 +03:00
|
|
|
unsigned char *buf = NULL;
|
2013-12-18 01:04:40 +04:00
|
|
|
int len;
|
|
|
|
CriuResp *msg = 0;
|
|
|
|
|
2015-04-21 16:09:09 +03:00
|
|
|
len = recv(socket_fd, NULL, 0, MSG_TRUNC | MSG_PEEK);
|
2013-12-18 01:04:40 +04:00
|
|
|
if (len == -1) {
|
2015-04-21 16:09:09 +03:00
|
|
|
perror("Can't read request");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2015-11-13 17:10:08 +03:00
|
|
|
buf = malloc(len);
|
|
|
|
if (!buf) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
perror("Can't receive response");
|
|
|
|
goto err;
|
|
|
|
}
|
2015-04-21 16:09:09 +03:00
|
|
|
|
|
|
|
len = recv(socket_fd, buf, len, MSG_TRUNC);
|
|
|
|
if (len == -1) {
|
|
|
|
perror("Can't read request");
|
2013-12-18 01:04:40 +04:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg = criu_resp__unpack(NULL, len, buf);
|
|
|
|
if (!msg) {
|
|
|
|
perror("Failed unpacking response");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2015-11-13 17:10:08 +03:00
|
|
|
free(buf);
|
2013-12-18 01:04:40 +04:00
|
|
|
return msg;
|
|
|
|
err:
|
2015-11-13 17:10:08 +03:00
|
|
|
free(buf);
|
2013-12-18 01:04:40 +04:00
|
|
|
saved_errno = errno;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int send_req(int socket_fd, CriuReq *req)
|
|
|
|
{
|
2015-04-21 16:09:09 +03:00
|
|
|
unsigned char *buf;
|
2013-12-18 01:04:40 +04:00
|
|
|
int len;
|
|
|
|
|
|
|
|
len = criu_req__get_packed_size(req);
|
|
|
|
|
2015-11-13 17:10:08 +03:00
|
|
|
buf = malloc(len);
|
|
|
|
if (!buf) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
perror("Can't send request");
|
|
|
|
goto err;
|
|
|
|
}
|
2015-04-21 16:09:09 +03:00
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
if (criu_req__pack(req, buf) != len) {
|
|
|
|
perror("Failed packing request");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(socket_fd, buf, len) == -1) {
|
|
|
|
perror("Can't send request");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2015-11-13 17:10:08 +03:00
|
|
|
free(buf);
|
2013-12-18 01:04:40 +04:00
|
|
|
return 0;
|
|
|
|
err:
|
2015-11-13 17:10:08 +03:00
|
|
|
free(buf);
|
2013-12-18 01:04:40 +04:00
|
|
|
saved_errno = errno;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:22:21 +04:00
|
|
|
static int send_notify_ack(int socket_fd, int ret)
|
|
|
|
{
|
|
|
|
int send_ret;
|
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__NOTIFY;
|
|
|
|
req.has_notify_success = true;
|
|
|
|
req.notify_success = (ret == 0);
|
|
|
|
|
|
|
|
send_ret = send_req(socket_fd, &req);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're failing the notification then report
|
|
|
|
* back the original error code (and it will be
|
|
|
|
* propagated back to user).
|
|
|
|
*
|
|
|
|
* If the notification was OK, then report the
|
|
|
|
* result of acking it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return ret ? : send_ret;
|
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
static void swrk_wait(criu_opts *opts)
|
|
|
|
{
|
2015-07-30 16:40:22 -04:00
|
|
|
if (opts->service_comm == CRIU_COMM_BIN)
|
|
|
|
waitpid(opts->swrk_pid, NULL, 0);
|
2015-07-30 16:40:21 -04:00
|
|
|
}
|
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
static int swrk_connect(criu_opts *opts, bool d)
|
2015-07-30 16:40:21 -04:00
|
|
|
{
|
|
|
|
int sks[2], pid, ret = -1;
|
|
|
|
|
|
|
|
if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sks))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
if (pid < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (pid == 0) {
|
|
|
|
sigset_t mask;
|
|
|
|
char fds[11];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unblock SIGCHLD.
|
|
|
|
*
|
|
|
|
* The caller of this function is supposed to have
|
|
|
|
* this signal blocked. Otherwise it risks to get
|
|
|
|
* into situation, when this routine is not yet
|
|
|
|
* returned, but the restore subtree exits and
|
|
|
|
* emits the SIGCHLD.
|
|
|
|
*
|
|
|
|
* In turn, unblocked SIGCHLD is required to make
|
|
|
|
* criu restoration process work -- it catches
|
|
|
|
* subtasks restore errors in this handler.
|
|
|
|
*/
|
|
|
|
|
|
|
|
sigemptyset(&mask);
|
|
|
|
sigaddset(&mask, SIGCHLD);
|
|
|
|
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
|
|
|
|
|
|
|
close(sks[0]);
|
|
|
|
sprintf(fds, "%d", sks[1]);
|
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
if (d)
|
|
|
|
if (daemon(0, 1)) {
|
|
|
|
perror("Can't detach for a self-dump");
|
|
|
|
goto child_err;
|
|
|
|
}
|
|
|
|
|
|
|
|
pid = getpid();
|
|
|
|
if (write(sks[1], &pid, sizeof(pid)) != sizeof(pid)) {
|
|
|
|
perror("Can't write swrk pid");
|
|
|
|
goto child_err;
|
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
execlp(opts->service_binary, opts->service_binary, "swrk", fds, NULL);
|
2015-07-30 16:40:21 -04:00
|
|
|
perror("Can't exec criu swrk");
|
2015-10-12 12:50:04 +03:00
|
|
|
child_err:
|
|
|
|
close(sks[1]);
|
2015-07-30 16:40:21 -04:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(sks[1]);
|
2015-10-12 12:50:04 +03:00
|
|
|
|
|
|
|
if (read(sks[0], &pid, sizeof(pid)) != sizeof(pid)) {
|
|
|
|
perror("Can't read swrk pid");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
opts->swrk_pid = pid;
|
|
|
|
ret = sks[0];
|
2015-10-12 12:50:04 +03:00
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
out:
|
|
|
|
return ret;
|
2015-10-12 12:50:04 +03:00
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
err:
|
|
|
|
close(sks[0]);
|
|
|
|
close(sks[1]);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
static int criu_connect(criu_opts *opts, bool d)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
|
|
|
int fd, ret;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
socklen_t addr_len;
|
|
|
|
|
2015-07-16 15:42:00 +03:00
|
|
|
if (opts->service_comm == CRIU_COMM_FD)
|
|
|
|
return opts->service_fd;
|
2015-07-30 16:40:22 -04:00
|
|
|
else if (opts->service_comm == CRIU_COMM_BIN)
|
2015-10-12 12:50:04 +03:00
|
|
|
return swrk_connect(opts, d);
|
2015-07-16 15:42:00 +03:00
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
|
|
|
|
if (fd < 0) {
|
|
|
|
saved_errno = errno;
|
|
|
|
perror("Can't create socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sun_family = AF_LOCAL;
|
|
|
|
|
2015-10-09 11:11:00 +03:00
|
|
|
strncpy(addr.sun_path, opts->service_address, sizeof(addr.sun_path));
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2015-10-09 11:11:00 +03:00
|
|
|
addr_len = strlen(opts->service_address) + sizeof(addr.sun_family);
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
ret = connect(fd, (struct sockaddr *) &addr, addr_len);
|
|
|
|
if (ret < 0) {
|
|
|
|
saved_errno = errno;
|
|
|
|
perror("Can't connect to socket");
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
static int send_req_and_recv_resp_sk(int fd, criu_opts *opts, CriuReq *req, CriuResp **resp)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
2014-06-17 21:09:25 +04:00
|
|
|
int ret = 0;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
if (send_req(fd, req) < 0) {
|
2014-06-25 19:22:21 +04:00
|
|
|
ret = -ECOMM;
|
2013-12-18 01:04:40 +04:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:22:21 +04:00
|
|
|
again:
|
2013-12-18 01:04:40 +04:00
|
|
|
*resp = recv_resp(fd);
|
|
|
|
if (!*resp) {
|
|
|
|
perror("Can't receive response");
|
2014-06-25 19:22:21 +04:00
|
|
|
ret = -ECOMM;
|
2013-12-18 01:04:40 +04:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:22:21 +04:00
|
|
|
if ((*resp)->type == CRIU_REQ_TYPE__NOTIFY) {
|
2015-07-15 04:45:02 +03:00
|
|
|
if (opts->notify)
|
|
|
|
ret = opts->notify((*resp)->notify->script, (*resp)->notify);
|
2014-06-25 19:22:21 +04:00
|
|
|
|
|
|
|
ret = send_notify_ack(fd, ret);
|
|
|
|
if (!ret)
|
|
|
|
goto again;
|
|
|
|
else
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
if ((*resp)->type != req->type) {
|
|
|
|
if ((*resp)->type == CRIU_REQ_TYPE__EMPTY &&
|
|
|
|
(*resp)->success == false)
|
2014-06-25 19:22:21 +04:00
|
|
|
ret = -EINVAL;
|
2013-12-18 01:04:40 +04:00
|
|
|
else {
|
|
|
|
perror("Unexpected response type");
|
2014-06-25 19:22:21 +04:00
|
|
|
ret = -EBADMSG;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-11 22:55:17 +02:00
|
|
|
if ((*resp)->has_cr_errno)
|
|
|
|
saved_errno = (*resp)->cr_errno;
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
exit:
|
2014-06-25 19:22:21 +04:00
|
|
|
return ret;
|
2014-06-17 21:09:25 +04:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
static int send_req_and_recv_resp(criu_opts *opts, CriuReq *req, CriuResp **resp)
|
2014-06-17 21:09:25 +04:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int ret = 0;
|
2015-10-12 12:50:04 +03:00
|
|
|
bool d = false;
|
|
|
|
|
|
|
|
if (req->type == CRIU_REQ_TYPE__DUMP && req->opts->has_pid == false)
|
|
|
|
d = true;
|
2014-06-17 21:09:25 +04:00
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
fd = criu_connect(opts, d);
|
2014-06-17 21:09:25 +04:00
|
|
|
if (fd < 0) {
|
|
|
|
perror("Can't connect to criu");
|
2014-07-29 21:06:00 +04:00
|
|
|
ret = -ECONNREFUSED;
|
2014-06-17 21:09:25 +04:00
|
|
|
} else {
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp_sk(fd, opts, req, resp);
|
2013-12-18 01:04:40 +04:00
|
|
|
close(fd);
|
2014-06-17 21:09:25 +04:00
|
|
|
}
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2014-06-17 21:09:25 +04:00
|
|
|
return ret;
|
2013-12-18 01:04:40 +04:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_check(criu_opts *opts)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
CriuResp *resp = NULL;
|
|
|
|
|
|
|
|
saved_errno = 0;
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__CHECK;
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp(opts, &req, &resp);
|
2013-12-18 01:04:40 +04:00
|
|
|
if (ret)
|
|
|
|
goto exit;
|
|
|
|
|
2013-12-18 15:50:27 +04:00
|
|
|
ret = resp->success ? 0 : -EBADE;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
exit:
|
|
|
|
if (resp)
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
swrk_wait(opts);
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
errno = saved_errno;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_check(void)
|
|
|
|
{
|
|
|
|
return criu_local_check(global_opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
int criu_local_dump(criu_opts *opts)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
CriuResp *resp = NULL;
|
|
|
|
|
|
|
|
saved_errno = 0;
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__DUMP;
|
2015-07-15 04:45:02 +03:00
|
|
|
req.opts = opts->rpc;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp(opts, &req, &resp);
|
2013-12-18 01:04:40 +04:00
|
|
|
if (ret)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (resp->success) {
|
|
|
|
if (resp->dump->has_restored && resp->dump->restored)
|
|
|
|
ret = 1;
|
|
|
|
else
|
|
|
|
ret = 0;
|
|
|
|
} else
|
2013-12-18 15:50:27 +04:00
|
|
|
ret = -EBADE;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
exit:
|
|
|
|
if (resp)
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
swrk_wait(opts);
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
errno = saved_errno;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_dump(void)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_dump(global_opts);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_dump_iters(criu_opts *opts, int (*more)(criu_predump_info pi))
|
2014-06-26 18:52:34 +04:00
|
|
|
{
|
|
|
|
int ret = -1, fd = -1, uret;
|
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
CriuResp *resp = NULL;
|
|
|
|
|
|
|
|
saved_errno = 0;
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__PRE_DUMP;
|
2015-07-15 04:45:02 +03:00
|
|
|
req.opts = opts->rpc;
|
2014-06-26 18:52:34 +04:00
|
|
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
/*
|
|
|
|
* Self-dump in iterable manner is tricky and
|
|
|
|
* not supported for the moment.
|
|
|
|
*
|
|
|
|
* Calls w/o iteration callback is, well, not
|
|
|
|
* allowed either.
|
|
|
|
*/
|
2015-07-15 04:45:02 +03:00
|
|
|
if (!opts->rpc->has_pid || !more)
|
2014-06-26 18:52:34 +04:00
|
|
|
goto exit;
|
|
|
|
|
|
|
|
ret = -ECONNREFUSED;
|
2015-10-12 12:50:04 +03:00
|
|
|
fd = criu_connect(opts, false);
|
2014-06-26 18:52:34 +04:00
|
|
|
if (fd < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
while (1) {
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp_sk(fd, opts, &req, &resp);
|
2014-06-26 18:52:34 +04:00
|
|
|
if (ret)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (!resp->success) {
|
|
|
|
ret = -EBADE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
uret = more(NULL);
|
|
|
|
if (uret < 0) {
|
|
|
|
ret = uret;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
|
|
|
|
if (uret == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__DUMP;
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp_sk(fd, opts, &req, &resp);
|
2014-06-26 18:52:34 +04:00
|
|
|
if (!ret)
|
|
|
|
ret = (resp->success ? 0 : -EBADE);
|
|
|
|
exit:
|
|
|
|
if (fd >= 0)
|
|
|
|
close(fd);
|
|
|
|
if (resp)
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
swrk_wait(opts);
|
|
|
|
|
2014-06-26 18:52:34 +04:00
|
|
|
errno = saved_errno;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_dump_iters(int (*more)(criu_predump_info pi))
|
|
|
|
{
|
|
|
|
return criu_local_dump_iters((void *)global_opts, more);
|
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_restore(criu_opts *opts)
|
2013-12-18 01:04:40 +04:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
CriuResp *resp = NULL;
|
|
|
|
|
|
|
|
saved_errno = 0;
|
|
|
|
|
|
|
|
req.type = CRIU_REQ_TYPE__RESTORE;
|
2015-07-15 04:45:02 +03:00
|
|
|
req.opts = opts->rpc;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
ret = send_req_and_recv_resp(opts, &req, &resp);
|
2013-12-18 01:04:40 +04:00
|
|
|
if (ret)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if (resp->success)
|
|
|
|
ret = resp->restore->pid;
|
|
|
|
else
|
2013-12-18 15:50:27 +04:00
|
|
|
ret = -EBADE;
|
2013-12-18 01:04:40 +04:00
|
|
|
|
|
|
|
exit:
|
|
|
|
if (resp)
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
swrk_wait(opts);
|
|
|
|
|
2013-12-18 01:04:40 +04:00
|
|
|
errno = saved_errno;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-06-17 21:10:46 +04:00
|
|
|
|
2015-07-13 14:55:00 +03:00
|
|
|
int criu_restore(void)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_restore(global_opts);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:45:02 +03:00
|
|
|
int criu_local_restore_child(criu_opts *opts)
|
2014-06-17 21:10:46 +04:00
|
|
|
{
|
2015-07-30 16:40:21 -04:00
|
|
|
int sk, ret = -1;
|
2015-07-30 16:40:22 -04:00
|
|
|
enum criu_service_comm saved_comm;
|
|
|
|
char *saved_comm_data;
|
|
|
|
bool save_comm;
|
2014-06-17 21:10:46 +04:00
|
|
|
CriuReq req = CRIU_REQ__INIT;
|
|
|
|
CriuResp *resp = NULL;
|
|
|
|
|
2015-07-30 16:40:22 -04:00
|
|
|
/*
|
|
|
|
* restore_child is not possible with criu running as a system
|
|
|
|
* service, so we need to switch comm method to CRIU_COMM_BIN.
|
|
|
|
* We're doing so because of the backward compatibility, and we
|
|
|
|
* should probably consider requiring CRIU_COMM_BIN to be set by
|
|
|
|
* user at some point.
|
|
|
|
*/
|
|
|
|
save_comm = (opts->service_comm != CRIU_COMM_BIN);
|
|
|
|
if (save_comm) {
|
|
|
|
/* Save comm */
|
|
|
|
saved_comm = opts->service_comm;
|
|
|
|
saved_comm_data = opts->service_address;
|
|
|
|
|
|
|
|
opts->service_comm = CRIU_COMM_BIN;
|
|
|
|
opts->service_binary = CR_DEFAULT_SERVICE_BIN;
|
|
|
|
}
|
|
|
|
|
2015-10-12 12:50:04 +03:00
|
|
|
sk = swrk_connect(opts, false);
|
2015-07-30 16:40:22 -04:00
|
|
|
if (save_comm) {
|
|
|
|
/* Restore comm */
|
|
|
|
opts->service_comm = saved_comm;
|
|
|
|
opts->service_address = saved_comm_data;
|
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
if (sk < 0)
|
|
|
|
return -1;
|
2014-06-17 21:10:46 +04:00
|
|
|
|
2015-07-30 16:40:20 -04:00
|
|
|
saved_errno = 0;
|
|
|
|
|
2014-06-17 21:10:46 +04:00
|
|
|
req.type = CRIU_REQ_TYPE__RESTORE;
|
2015-07-15 04:45:02 +03:00
|
|
|
req.opts = opts->rpc;
|
2014-06-17 21:10:46 +04:00
|
|
|
|
2014-09-10 15:46:06 +04:00
|
|
|
req.opts->has_rst_sibling = true;
|
|
|
|
req.opts->rst_sibling = true;
|
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
ret = send_req_and_recv_resp_sk(sk, opts, &req, &resp);
|
2014-06-17 21:10:46 +04:00
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
swrk_wait(opts);
|
2014-06-17 21:10:46 +04:00
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
ret = resp->success ? resp->restore->pid : -EBADE;
|
|
|
|
criu_resp__free_unpacked(resp, NULL);
|
|
|
|
}
|
|
|
|
|
2015-07-30 16:40:21 -04:00
|
|
|
close(sk);
|
2015-07-30 16:40:20 -04:00
|
|
|
errno = saved_errno;
|
2014-06-17 21:10:46 +04:00
|
|
|
return ret;
|
|
|
|
}
|
2015-07-13 14:55:00 +03:00
|
|
|
|
|
|
|
int criu_restore_child(void)
|
|
|
|
{
|
2015-07-15 04:45:02 +03:00
|
|
|
return criu_local_restore_child(global_opts);
|
2015-07-13 14:55:00 +03:00
|
|
|
}
|