[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