[CRIU] [PATCH 2/3] lib: add check/dump/restore
Pavel Emelyanov
xemul at parallels.com
Mon Dec 9 11:23:10 PST 2013
Very good. A couple of comments inline.
> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
> ---
> lib/criu.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/criu.h | 50 +++++++++++
> 2 files changed, 333 insertions(+)
> create mode 100644 lib/criu.h
>
> diff --git a/lib/criu.c b/lib/criu.c
> index 2bd224e..6f996df 100644
> --- a/lib/criu.c
> +++ b/lib/criu.c
> @@ -1,3 +1,286 @@
> #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"
> +
> +#define MAX_MSG_SIZE 1024
> +#define CR_DEFAULT_SERVICE_ADDRESS "/var/run/criu_service.socket"
Put them into separate header, that would be included in both crtools and libcriu.
>
> 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[MAX_MSG_SIZE];
> + int len;
> + CriuResp *msg = 0;
> +
> + len = read(socket_fd, buf, 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[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 exchange(CriuReq *req, CriuResp **resp)
Bad name for function.
> +{
> + 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;
> + }
> + goto exit;
Excessive goto;
> + }
> +
> +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 = exchange(&req, &resp);
> + if (err)
> + goto exit;
> +
> + ret = resp->success ? 0 : -1;
> +
> +exit:
> + criu_resp__free_unpacked(resp, NULL);
> +
> + errno = err;
errno should be updated only if reporting error
> + 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 = exchange(&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);
> +
> + errno = err;
Same here
> + 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 = exchange(&req, &resp);
> + if (err)
> + goto exit;
> +
> + if (resp->success)
> + ret = resp->restore->pid;
> +
> +exit:
> + criu_resp__free_unpacked(resp, NULL);
> +
> + errno = err;
And here
> + 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__ */
>
More information about the CRIU
mailing list