[CRIU] [PATCH 4/5] lib: add check/dump/restore

Ruslan Kuprieiev kupruser at gmail.com
Tue Dec 10 10:11:43 PST 2013


Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
 lib/criu.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/criu.h |  50 +++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 lib/criu.h

diff --git a/lib/criu.c b/lib/criu.c
index 2bd224e..b9ff842 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -1,3 +1,289 @@
 #include "version.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "criu.h"
+#include "rpc.pb-c.h"
+#include "cr-service-const.h"
 
 const char *criu_lib_version = CRIU_VERSION;
+
+static char *service_address = CR_DEFAULT_SERVICE_ADDRESS;
+static CriuOpts *opts;
+
+void criu_set_service_address(char *path)
+{
+	if (path)
+		service_address = path;
+	else
+		service_address = CR_DEFAULT_SERVICE_ADDRESS;
+}
+
+int criu_init_opts(void)
+{
+	if (opts)
+		criu_opts__free_unpacked(opts, NULL);
+
+	opts = malloc(sizeof(CriuOpts));
+	if (opts == NULL) {
+		perror("Can't allocate memory for criu opts");
+		return -1;
+	}
+
+	criu_opts__init(opts);
+	return 0;
+}
+
+void criu_set_pid(int pid)
+{
+	opts->has_pid	= true;
+	opts->pid	= pid;
+}
+
+void criu_set_images_dir_fd(int fd)
+{
+	opts->images_dir_fd = fd;
+}
+
+void criu_set_leave_running(bool leave_running)
+{
+	opts->has_leave_running	= true;
+	opts->leave_running	= leave_running;
+}
+
+void criu_set_ext_unix_sk(bool ext_unix_sk)
+{
+	opts->has_ext_unix_sk	= true;
+	opts->ext_unix_sk	= ext_unix_sk;
+}
+
+void criu_set_tcp_established(bool tcp_established)
+{
+	opts->has_tcp_established	= true;
+	opts->tcp_established		= tcp_established;
+}
+
+void criu_set_evasive_devices(bool evasive_devices)
+{
+	opts->has_evasive_devices	= true;
+	opts->evasive_devices		= evasive_devices;
+}
+
+void criu_set_shell_job(bool shell_job)
+{
+	opts->has_shell_job	= true;
+	opts->shell_job		= shell_job;
+}
+
+void criu_set_file_locks(bool file_locks)
+{
+	opts->has_file_locks	= true;
+	opts->file_locks	= file_locks;
+}
+
+void criu_set_log_level(int log_level)
+{
+	opts->has_log_level	= true;
+	opts->log_level		= log_level;
+}
+
+void criu_set_log_file(char *log_file)
+{
+	opts->log_file = strdup(log_file);
+}
+
+static CriuResp *recv_resp(int socket_fd)
+{
+	unsigned char buf[CR_MAX_MSG_SIZE];
+	int len;
+	CriuResp *msg = 0;
+
+	len = read(socket_fd, buf, CR_MAX_MSG_SIZE);
+	if (len == -1) {
+		perror("Can't read response");
+		return NULL;
+	}
+
+	msg = criu_resp__unpack(NULL, len, buf);
+	if (!msg) {
+		perror("Failed unpacking response");
+		return NULL;
+	}
+
+	return msg;
+}
+
+static int send_req(int socket_fd, CriuReq *req)
+{
+	unsigned char buf[CR_MAX_MSG_SIZE];
+	int len;
+
+	len = criu_req__get_packed_size(req);
+
+	if (criu_req__pack(req, buf) != len) {
+		perror("Failed packing request");
+		return -1;
+	}
+
+	if (write(socket_fd, buf, len)  == -1) {
+		perror("Can't send request");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int criu_connect(void)
+{
+	int fd, ret;
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+
+	fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	if (fd < 0) {
+		perror("Can't create socket");
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_LOCAL;
+
+	strcpy(addr.sun_path, service_address);
+
+	addr_len = strlen(addr.sun_path) + sizeof(addr.sun_family);
+
+	ret = connect(fd, (struct sockaddr *) &addr, addr_len);
+	if (ret < 0) {
+		perror("Can't connect to socket");
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
+
+static int send_req_and_recv_resp(CriuReq *req, CriuResp **resp)
+{
+	int fd;
+	int ret	= 0;
+
+	fd = criu_connect();
+	if (fd < 0) {
+		perror("Can't connect to criu");
+		ret = ECONNREFUSED;
+		goto exit;
+	}
+
+	if (send_req(fd, req) < 0) {
+		ret = ECOMM;
+		goto exit;
+	}
+
+	*resp = recv_resp(fd);
+	if (!*resp) {
+		perror("Can't receive response");
+		ret = ECOMM;
+		goto exit;
+	}
+
+	if ((*resp)->type != req->type) {
+		if ((*resp)->type == CRIU_REQ_TYPE__EMPTY &&
+		    (*resp)->success == false)
+			ret = EINVAL;
+		else {
+			perror("Unexpected response type");
+			ret = EBADMSG;
+		}
+	}
+
+exit:
+	if (fd > 0)
+		close(fd);
+
+	return ret;
+}
+
+int criu_check(void)
+{
+	int ret = -1;
+	int err = 0;
+	CriuReq req	= CRIU_REQ__INIT;
+	CriuResp *resp	= NULL;
+
+	req.type	= CRIU_REQ_TYPE__CHECK;
+
+	err = send_req_and_recv_resp(&req, &resp);
+	if (err)
+		goto exit;
+
+	ret = resp->success ? 0 : -1;
+
+exit:
+	criu_resp__free_unpacked(resp, NULL);
+
+	if (err)
+		errno = err;
+
+	return ret;
+}
+
+int criu_dump(void)
+{
+	int ret = -1;
+	int err = 0;
+	CriuReq req	= CRIU_REQ__INIT;
+	CriuResp *resp	= NULL;
+
+	req.type	= CRIU_REQ_TYPE__DUMP;
+	req.opts	= opts;
+
+	err = send_req_and_recv_resp(&req, &resp);
+	if (err)
+		goto exit;
+
+	if (resp->success) {
+		if (resp->dump->has_restored && resp->dump->restored)
+			ret = 1;
+		else
+			ret = 0;
+	}
+
+exit:
+	criu_resp__free_unpacked(resp, NULL);
+
+	if (err)
+		errno = err;
+
+	return ret;
+}
+
+int criu_restore(void)
+{
+	int ret = -1;
+	int err = 0;
+	CriuReq req	= CRIU_REQ__INIT;
+	CriuResp *resp	= NULL;
+
+	req.type	= CRIU_REQ_TYPE__RESTORE;
+	req.opts	= opts;
+
+	err = send_req_and_recv_resp(&req, &resp);
+	if (err)
+		goto exit;
+
+	if (resp->success)
+		ret = resp->restore->pid;
+
+exit:
+	criu_resp__free_unpacked(resp, NULL);
+
+	if (err)
+		errno = err;
+
+	return ret;
+}
diff --git a/lib/criu.h b/lib/criu.h
new file mode 100644
index 0000000..37f6f32
--- /dev/null
+++ b/lib/criu.h
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2013 Parallels, Inc. (www.parallels.com).
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * (LGPL) version 2.1 which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl-2.1.html
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, you can find it here:
+ * www.gnu.org/licenses/lgpl.html
+ */
+
+#ifndef __CRIU_LIB_H__
+#define __CRIU_LIB_H__
+
+#include <stdbool.h>
+
+void criu_set_service_address(char *path);
+
+int criu_init_opts(void); /* must be called before using any criu_set* functions down below */
+void criu_set_pid(int pid);
+void criu_set_images_dir_fd(int fd); /* must be set for dump/restore */
+void criu_set_leave_running(bool leave_running);
+void criu_set_ext_unix_sk(bool ext_unix_sk);
+void criu_set_tcp_established(bool tcp_established);
+void criu_set_evasive_devices(bool evasive_devices);
+void criu_set_shell_job(bool shell_job);
+void criu_set_file_locks(bool file_locks);
+void criu_set_log_level(int log_level);
+void criu_set_log_file(char *log_file);
+
+/* On error functions down below return -1 and errno set approprietly:
+ * ECONNREFUSED		-- Unable to connect to criu
+ * ECOMM		-- Unable to send/recv msg to/from criu
+ * EINVAL		-- CRIU doesn't support this type of request.
+ *			   You should probably update criu.
+ * EBADMSG		-- Unexpected response from criu.
+ *		           You should probably update criu.
+ */
+int criu_check(void);
+int criu_dump(void);
+int criu_restore(void);
+
+#endif /* __CRIU_LIB_H__ */
-- 
1.8.3.2



More information about the CRIU mailing list