[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